【问题标题】:Replicate OpenSSL command to sign a file in Java复制 OpenSSL 命令以在 Java 中对文件进行签名
【发布时间】:2016-04-15 21:25:00
【问题描述】:

我需要对文件进行签名,到目前为止,我使用的 openssl 运行良好(文件已签名并验证)。

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 文件)时,它显示“文件已签名但无法验证”。我觉得我接近解决方案,但我不知道我做错了什么。

有人可以帮我弄清楚我缺少什么来验证文件吗?

PS;证书来自 SSL 证书 (GoDaddy),bundleCertificate.crt 是 GoDaddy 捆绑证书。

【问题讨论】:

    标签: java ssl openssl bouncycastle sign


    【解决方案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();
    }
    

    【讨论】:

    • 请说明您的原始代码存在什么问题,以及新版本如何修复它。
    猜你喜欢
    • 2022-10-01
    • 2011-07-05
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多