我需要签署一个文件,到目前为止,我已经使用了工作正常的openssl
comman(文件经过签名和验证)。
openssl smime -sign -in unsigned.mobileconfig -out signed.mobileconfig -signer myCrtFile.crt -inkey myKeyFile.key -certfile bundleCertificate.crt -outform der -nodetach
但是现在我需要在运行时执行此操作,因此我需要以编程方式对文件进行签名。我使用BouncyCastle
,但我打开以切换到另一个图书馆。
我不熟练使用证书,而BouncyCastle
则更少。这就是我的意思。
从openssl命令到下面代码的相应文件是:
myCrtFile.crt -> signerCertHolder
myKeyFile.key -> privateKeyInfo
bundleCertificate.crt -> certificateHolder
public byte[] sign(String message) throws IOException, CMSException, OperatorCreationException, CertificateEncodingException, MessagingException, CertificateException {
Security.addProvider(new BouncyCastleProvider());
PrivateKeyInfo privateKeyInfo = loadInKey();
X509CertificateHolder signerCertHolder = loadSigner();
X509CertificateHolder certificateCertHolder = loadCertfile();
PrivateKey inKey = new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
X509Certificate signer = certificateConverter.getCertificate(signerCertHolder);
X509Certificate certificate = certificateConverter.getCertificate(certificateCertHolder);
List<X509Certificate> certificateList = new ArrayList();
certificateList.add(signer);
certificateList.add(certificate);
Store<?> certs = new JcaCertStore(certificateList);
ContentSigner sha1signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(inKey);
JcaSignerInfoGeneratorBuilder jcaSignerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build());
CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();
signGen.addSignerInfoGenerator(jcaSignerInfoGeneratorBuilder.build(sha1signer, certificate));
signGen.addCertificates(certs);
CMSTypedData content = new CMSProcessableByteArray(message.getBytes());
CMSSignedData signedData = signGen.generate(content, false);
byte[] signeddata = signedData.getEncoded();
return signeddata;
}
然后我将byte[]
保存到文件中。当我打开文件(它是MDM mobileConfig文件)时,它说&#34;文件已签名但无法验证&#34;。我觉得我接近解决方案,但我不知道自己做错了什么。
有人可以帮我弄清楚我错过了什么来验证文件吗?
PS;证书来自SSL证书(GoDaddy),bundleCertificate.crt
是GoDaddy捆绑证书。
答案 0 :(得分:1)
我设法签署了该文件。怀疑,我接近最终的解决方案。这是完整的代码。
public byte[] signMobileConfig(byte[] mobileconfig)
throws CertificateEncodingException, PEMException, FileNotFoundException, IOException, CertificateException, OperatorCreationException, CMSException {
Security.addProvider(new BouncyCastleProvider());
X509CertificateHolder caCertificate = loadCertfile();
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
X509Certificate serverCertificate = certificateConverter.getCertificate(loadSigner());
PrivateKeyInfo privateKeyInfo = loadInKey();
PrivateKey inKey = new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(inKey);
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
JcaDigestCalculatorProviderBuilder digestProviderBuilder = new JcaDigestCalculatorProviderBuilder().setProvider("BC");
JcaSignerInfoGeneratorBuilder generatotBuilder = new JcaSignerInfoGeneratorBuilder(digestProviderBuilder.build());
generator.addSignerInfoGenerator(generatotBuilder.build(sha1Signer, serverCertificate));
generator.addCertificate(new X509CertificateHolder(serverCertificate.getEncoded()));
generator.addCertificate(new X509CertificateHolder(caCertificate.getEncoded()));
CMSProcessableByteArray bytes = new CMSProcessableByteArray(mobileconfig);
CMSSignedData signedData = generator.generate(bytes, true);
return signedData.getEncoded();
}
以下是我加载文件的方式:
public X509CertificateHolder loadSigner() throws FileNotFoundException, IOException {
InputStream inputStream = externalResourcesFacade.getResourceAsStream("path/to/.crt");
PEMParser parser = new PEMParser(new InputStreamReader(inputStream));
return (X509CertificateHolder) parser.readObject();
}
public PrivateKeyInfo loadInKey() throws FileNotFoundException, IOException {
InputStream inputStream = externalResourcesFacade.getResourceAsStream("path/to/.key");
PEMParser parser = new PEMParser(new InputStreamReader(inputStream));
return (PrivateKeyInfo) parser.readObject();
}
public X509CertificateHolder loadCertfile() throws FileNotFoundException, IOException {
InputStream inputStream = externalResourcesFacade.getResourceAsStream("path/to/.crt");
PEMParser parser = new PEMParser(new InputStreamReader(inputStream));
return (X509CertificateHolder) parser.readObject();
}