书读百遍其义自现,知识点多复习,看到的越多,理解的也越是深刻。也许此时我看到的点是点,十天半个月之后回头看时可能就是新的点或者线了,写博客也是,越写越深刻。
遇到KeyAttestation在gms中的错误
在cts中有一个针对keystore模块的测试项目,错误项开始,截图如下:
为什么会有这部分的错误呢? 如果设备没有从Google申请过Attestation keybox并且安装到设备中的话,cts中这部分的keystore的测试项都会失败。cts测试不过,说明设备目前运行的os状态不满足Android的CDD要求。
那什么是Google Attestation keybox
出身
Attestation Keybox
作用
它为应用程序开发者提供了一种使用加密密钥进行加密和验证的方法;Keystore将密钥保留在应用程序的进程空间之外,保证密钥不会因为程序被破坏或者其它渠道被泄密。另外,需要加密设备还为设备中的密钥库密钥提供了基于硬件的安全性保障,将密钥材料完全保留在Android系统之外,即使Liux内核泄漏也不会泄漏密钥材料。
部署
Attestation Key在Android7开始被添加,Android8及后面的版本开始强要求,需要平台(例如,高通、联发科)拥有硬件支持的keystore。GMS认证中的cts/keystore 模块会进行测试。
包含Attestation key的文件又称作为Attestation Keybox,需要从Google进行申请(申请前需要提供设备的具体信息:fingerprint:branch/device/product:xxx)。 Google会将Attestation keybox文件加密之后回传给设备制造商。设备制造商拿到加密后的文件解密后得到attestation_key_xxxx.xml 文件,attestation_key_xxxx.xml具体格式请参考和部署步骤和命令请参考:Android Basis - Google Keybox-CSDN博客
三种算法
DSA,ECDSA,RSA;
Digital Signature Algorithm -> 是一种数字签名算法,是NIST(美国的一个机构)于1991年制定的数字签名规范,只能被用于数字签名。
Elliptic Curve DSA -> 是一种利用椭圆曲线密码来实现的数字签名算法。
RSA-> 是一种公钥密码算法,由三位开发者的名字的首字母组成。RSA可以被用于公钥密码和数字签名。
RSA使用步骤
生产密钥对、加密、解密;
问题
1. 什么是数字签名?
数字签名相当于现实世界中的盖章、签字的功能在计算机世界中进行实现的技术。使用数字签名可以识别篡改和伪装,还可以防止否认。
数字签名通常有两种方法,直接对密文进行签名,或者是对密文的散列值进行签名。显然,通常搜我们使用后者。
2. 什么是.pem 格式?
pem格式的RSA、DSA或ECDSA私钥文件通常不包含公钥。PEM(Privacy-Enhanced Mail)是一种常见的文件格式,用于存储加密的私钥和证书(从Attestation Keybox文件可以看出)。在PEM格式中,私钥和公钥可以分别存储在不同的文件中,也可以将它们合并到同一个文件中。
私钥文件通常以"-----BEGIN PRIVATE KEY-----"开头,以"-----END PRIVATE KEY-----"结尾。它包含了用于加密和解密数据的关键信息。
公钥文件通常以"-----BEGIN PUBLIC KEY-----"开头,以"-----END PUBLIC KEY-----"结尾。它包含了用于验证签名和加密数据的关键信息。
3. 什么是证书?
举个例子,要开车就得先考驾照,驾照上有本人的照片、姓名、联系方式、有效期等等,并由公安机关盖章。我们只要看到驾照,就可以知道公安局认定此人具有驾驶车辆的资格。
公钥证书:public-key certificate certificate. 里面有姓名、组织、邮箱以及此人公钥,并由认证机构施加数字签名。只要看到公钥证书,我们就可以知道认证机构认定该公钥的确属于此人。公钥证书也称之为证书。
4.Attestation Keybox中私钥和证书的作用
现在回想一下keybox中的私钥和证书的作用。密钥用来解密被公钥加过密的数据,而证书以及证书中的公钥可以用于鉴权和加密数据。
CTS中keystore的错误分析
android.cts.keystore.KeyAttestationTest#testDeviceIdAttestation
在没有看源码之前,可以大胆猜测一下,这里的CTS测试项中testDeviceIdAttestation就是去读取系统中的证书,并发送给google来确认设备是否是google授权的设备。
另外,可以猜测cts能够提取出证书中包含的公钥,并判断公钥和私钥的具体关系。以上是大胆猜测,下面便是小心验证猜测
secp256r1
secp256r1是一种用于加密的椭圆曲线(Elliptic Curve Digital Signature Algorithm, ECDSA)密钥对生成算法,也被称为NIST P-256曲线。它是一种公钥密码学算法,用于生成数字签名和公钥加密。ECDSA是一种基于椭圆曲线密码学的数字签名算法,而secp256r1是ECDSA算法中常用的一种曲线参数。这种算法和曲线参数被广泛用于各种加密和安全通信协议中,包括但不限于比特币等加密货币的交易验证
disgest
在密码学中,digest(摘要)是一个将数据(如文件、消息等)经过哈希运算后得到的结果。Digest在密码学中的应用非常广泛,特别是在区块链技术中,它用于确保区块数据的完整性和不可篡改性。此外,digest与加密的区别在于加密是将数据转换为只有拥有密钥的人才能解密的形式,而digest是通过哈希函数将数据转换为固定长度的摘要,用于验证数据的完整性和真实性。
ID_TYPE_IMEI
ID_TYPE_IMEI通常是指设备标识类型,它代表的是国际移动设备身份码(IMEI)。在某些上下文中,如物联网、身份验证或安全系统中,IMEI可能是用于证明设备真实性和唯一性的关键信息。当涉及到Attestation(证书绑定或证明服务)时,ID_TYPE_IMEI可能会被用于生成基于硬件特征(如IMEI)的可信度证明,即证明该设备确实拥有特定的IMEI,并且其状态未被篡改。这种类型的attribution常常出现在需要硬件绑定的场景,比如手机设备管理或防伪应用。
代码理解
/*** Performs attestation of the device's identifiers. This method returns a certificate chain* whose first element contains the requested device identifiers in an extension. The device's* manufacturer, model, brand, device and product are always also included in the attestation.* If the device supports attestation in secure hardware, the chain will be rooted at a* trustworthy CA key. Otherwise, the chain will be rooted at an untrusted certificate. See* <a href="https://developer.android.com/training/articles/security-key-attestation.html">* Key Attestation</a> for the format of the certificate extension.* <p>* Attestation will only be successful when all of the following are true:* 1) The device has been set up to support device identifier attestation at the factory.* 2) The user has not permanently disabled device identifier attestation.* 3) You have permission to access the device identifiers you are requesting attestation for.* <p>* For privacy reasons, you cannot distinguish between (1) and (2). If attestation is* unsuccessful, the device may not support it in general or the user may have permanently* disabled it.** @param context the context to use for retrieving device identifiers.* @param idTypes the types of device identifiers to attest.* @param attestationChallenge a blob to include in the certificate alongside the device* identifiers.** @return a certificate chain containing the requested device identifiers in the first element** @exception SecurityException if you are not permitted to obtain an attestation of the* device's identifiers.* @exception DeviceIdAttestationException if the attestation operation fails.*/@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)@NonNull public static X509Certificate[] attestDeviceIds(Context context,@NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throwsDeviceIdAttestationException {if (attestationChallenge == null) {throw new NullPointerException("Missing attestation challenge");}if (idTypes == null) {throw new NullPointerException("Missing id types");}String keystoreAlias = generateRandomAlias();KeyGenParameterSpec.Builder builder =new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN).setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")).setDigests(KeyProperties.DIGEST_SHA256).setAttestationChallenge(attestationChallenge);if (idTypes != null) {builder.setAttestationIds(idTypes);builder.setDevicePropertiesAttestationIncluded(true);}try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");keyPairGenerator.initialize(builder.build());keyPairGenerator.generateKeyPair();KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");keyStore.load(null);Certificate[] certs = keyStore.getCertificateChain(keystoreAlias);X509Certificate[] certificateChain =Arrays.copyOf(certs, certs.length, X509Certificate[].class);keyStore.deleteEntry(keystoreAlias);return certificateChain;} catch (SecurityException e) {throw e;} catch (Exception e) {// If a DeviceIdAttestationException was previously wrapped with some other type,// let's throw the original exception instead of wrapping it yet again.if (e.getCause() instanceof DeviceIdAttestationException) {throw (DeviceIdAttestationException) e.getCause();}// Illegal argument errors are wrapped up by a ProviderException. Catch those so that// we can unwrap them into a more meaningful exception type for the caller.if (e instanceof ProviderException&& e.getCause() instanceof IllegalArgumentException) {throw (IllegalArgumentException) e.getCause();}throw new DeviceIdAttestationException("Unable to perform attestation", e);}}
加密相关的内容看起来比较费劲,从代码注释上能够看出,测试case从设备中获取证书,并将证书中的相关信息返回。那么证书中有哪些信息呢?在申请attestation keybox时候,我提供了设备的fingerprint,而fingerprint中包含了manufacture/prodcut/device 等等信息