我的代码依赖于sun.security来生成一个用于签名APK的PKCS7签名块:
private static void writeSignatureBlock(byte[] signatureBytes, X509Certificate publicKey, OutputStream out)
throws Exception {
SignerInfo signerInfo = new SignerInfo(new X500Name(publicKey.getIssuerX500Principal().getName()),
publicKey.getSerialNumber(), AlgorithmId.get("SHA1"), AlgorithmId.get("RSA"), signatureBytes);
PKCS7 pkcs7 = new PKCS7(new AlgorithmId[] { AlgorithmId.get("SHA1") },
new ContentInfo(ContentInfo.DATA_OID, null), new X509Certificate[] { publicKey },
new SignerInfo[] { signerInfo });
ByteArrayOutputStream o = new ByteArrayOutputStream();
pkcs7.encodeSignedData(o);
byte[] expected = o.toByteArray();
}我正在尝试用Bouncy castle替换它,因为较新的Java版本不喜欢访问sun的内部类。
为了在bouncy castle中复制这种行为,我尝试了以下代码:
List<java.security.cert.Certificate> certList = new ArrayList<java.security.cert.Certificate>();
java.security.cert.Certificate certificate = publicKey;
certList.add(certificate);
JcaCertStore certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addCertificates(certs);
final byte[] signedHash = signatureBytes;
ContentSigner nonSigner = new ContentSigner() {
@Override
public byte[] getSignature() {
return signedHash;
}
@Override
public OutputStream getOutputStream() {
return new ByteArrayOutputStream();
}
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WithRSA");
}
};
org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate
.getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded()));
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().build());
sigb.setDirectSignature(true);
gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert)));
CMSProcessableByteArray msg = new CMSProcessableByteArray(new byte[0]);
CMSSignedData signedData = gen.generate(msg, false);
byte[] bouncyCastle = signedData.getEncoded();生成的输出具有不同的长度,并且非常不同:
Expected length: 1489
BouncyCastle length: 1491```
Why do these outputs differ in length (if only the content would be different I'd assume I supplied the data in a wrong format)?发布于 2019-07-17 22:14:18
唯一的区别是Bouncycastle对证书主题中的某些字符串使用的编码与sun.*类略有不同。Bouncycastle更符合RFC3280,但RFC5280在一定程度上放宽了要求。任何一种编码都应该没问题。
发布于 2020-01-22 22:27:37
BouncyCastle的替代方案是来自Oracle的Osdt CERT库,可从Maven-Repository获得。Gradle依赖:
// https://mvnrepository.com/artifact/com.oracle.ojdbc/osdt_core
implementation "com.oracle.ojdbc:osdt_cert:19.3.0.0" Oracle库使用起来要简单得多,比Bouncy castle更简单。从现有的PKCS7格式生成X509 DER格式需要3行代码:
import oracle.security.crypto.cert.PKCS7;
import oracle.security.crypto.cert.X509;
byte[] certDER = <retrieve the X.509 certificate as DER encoded byte array>
X509 x509 = new X509(certAsDER);
PKCS7 pkcs7 = new PKCS7(x509);
byte pkcs7DER = pkcs7.getEncoded();https://stackoverflow.com/questions/57061591
复制相似问题