我终于自己在安卓模拟器上测试了一下,得到了最终答案。一旦我意识到 PKCS7 只是一种存储形式,或者更确切地说是各种签名类型的容器,实际上就不难理解了。
应用内
调用返回CERT.RSA 文件中的第一个签名。这是一个嵌入 X.509 证书的 PKCS7 文件,据我所知,它始终只是 android 应用程序的一个签名。
Signature sig = context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SIGNATURES).signatures[0];
从上面得到的这个Signature可以直接用来生成一个像这样的工作X.509-certificate(取自here):
byte[] rawCert = sig.toByteArray();
InputStream certStream = new ByteArrayInputStream(rawCert);
CertificateFactory certFactory;
X509Certificate x509Cert;
try {
certFactory = CertificateFactory.getInstance("X509");
x509Cert = (X509Certificate) certFactory.generateCertificate(certStream);
//do stuff with your certificate
} catch(Exception ex) {
//handle exception
}
其他任何地方
如果您在自己的 android 应用程序之外拥有证书并且想要相同的字节流,由上面的函数提供,您可以使用这样的简单 Java 程序来做同样的事情:
FileInputStream is = new FileInputStream("CERT.RSA");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate c = (X509Certificate) cf.generateCertificates(is).toArray()[0];
byte[] rawCert = c.getEncoded();
此代码首先读取文件,创建CertificateFactory,然后是隔离PKCS7 容器中的第一个证书的重要步骤。然后c.getEncoded() 最终为您提供与上述方法完全相同的表示。
openssl
最后但并非最不重要的openssl-命令(取自here):
openssl pkcs7 -inform DER -in CERT.RSA -print_certs -text
它会给你一个包含信息的漂亮概述,最后
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
块。它包含与上面相同的数据。如果您解析此块的内容并使用 base64 对其进行解码,它将为您提供与上面两个示例完全相同的字节数组。