使用 Bouncy Castle 在 Java 中复制“openssl smime”?

Raj*_*Raj 3 java cryptography bouncycastle code-signing-certificate

我手上有个问题。我不懂 Java 的同事正在使用 OpenSSL 命令对文件进行签名,如下所示:

openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem \
  -inkey passkey.pem -in manifest.json -out signature -outform DER \
  -passin pass:12345
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这里有三个文件提供给 openssl 命令来生成签名。

现在我们想使用 Java 复制相同的功能,因为我们假设要签名的内容将是动态的并且本质上是服务器端的。我读到 BouncyCastle 是最佳选择。但我不确定如何使用该库。我对密码技术也不是很熟悉。我无法理解如何使用上面的所有三个文件来签署manifest.json.

如果有人可以引导我找到正确的代码或给我一个开始,我将非常感谢您的努力。

daz*_*ito 6

我还必须在 java 中复制 openssl 命令,这就是我完成它的方法。无需使用运行时。

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();
}
Run Code Online (Sandbox Code Playgroud)

这是我加载文件的方法:

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();
}
Run Code Online (Sandbox Code Playgroud)

这是我的文件映射:

myCrtFile.crt -> signerCertHolder
myKeyFile.key -> privateKeyInfo
bundleCertificate.crt -> certificateHolder
Run Code Online (Sandbox Code Playgroud)