Java 使用S/MIME对文件进行签名和加密

Java 使用S/MIME对文件进行签名和加密,java,openssl,bouncycastle,encryption-asymmetric,smime,Java,Openssl,Bouncycastle,Encryption Asymmetric,Smime,我目前正在尝试修改一些脚本,我们使用这些脚本来使用OpenSSL和S/MIME(使用Java和BouncyCastle)对xml文件进行加密/解密 对文件进行签名和加密的命令: openssl smime -sign -signer Pub1.crt -inkey Priv.key -in foo.xml | openssl smime -encrypt -out foo.xml.smime Pub2.crt Pub1.crt 这将生成一个包含xml文件的签名和加密smime文件。目前,在使用

我目前正在尝试修改一些脚本,我们使用这些脚本来使用OpenSSL和S/MIME(使用Java和BouncyCastle)对xml文件进行加密/解密

对文件进行签名和加密的命令:

openssl smime -sign -signer Pub1.crt -inkey Priv.key -in foo.xml | openssl smime -encrypt -out foo.xml.smime Pub2.crt Pub1.crt
这将生成一个包含xml文件的签名和加密smime文件。目前,在使用OpenSSL库的linux下,使用一组shell脚本可以实现这一点。将来,我们希望将这个过程集成到Java应用程序中

我发现使用BouncyCastle库应该可以实现这一点(请参阅)。这里的答案提供了两个Java类,展示了如何使用BouncyCastle和S/MIME对电子邮件进行签名和加密。与我们的OpenSSL命令相比,在我们的方法中似乎不需要签署加密电子邮件所需的许多东西

我们生成的文件中的更多元信息:

签名文件

MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----709621D94E0377688356FAAE5A2C1321"
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
Content-Transfer-Encoding: base64
加密文件

MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----709621D94E0377688356FAAE5A2C1321"
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
Content-Transfer-Encoding: base64

甚至可以像我们使用OpenSSL那样对简单文件进行签名和加密吗?我目前对签名和解密的了解还不是很高,所以请原谅我没有提供代码示例。我想我需要的是更多的投入到我需要做的事情中,也许还有一些已经做过这件事的人的专业知识。我希望这是问这个问题的正确地方。如果没有,请纠正我。

我和你有一个类似的问题,但我设法解决了。我必须警告你,我对签名和加密的了解也不高。但是这个代码似乎对我有用

在我的例子中,我使用了来自globalsign的personalsign pro 3证书,之前我只是在java中调用openssl。但是,我想清理我的代码,并决定使用bouncy castle代替

 public static boolean signAllFiles(List<File> files) {
    Boolean signingSucceeded = true;
    KeyStore ks = null;
    char[] password = null;

    Security.addProvider(new BouncyCastleProvider());
    try {
        ks = KeyStore.getInstance("PKCS12");
        password = "yourpass".toCharArray();
        ks.load(new FileInputStream("full/path/to/your/original/certificate.pfx"), password);
    } catch (Exception e) {
        signingSucceeded = false;
    }

    // Get privatekey and certificate
    X509Certificate cert = null;
    PrivateKey privatekey = null;

    try {
        Enumeration<String> en = ks.aliases();
        String ALIAS = "";
        Vector<Object> vectaliases = new Vector<Object>();

        while (en.hasMoreElements())
            vectaliases.add(en.nextElement());
        String[] aliases = (String[])(vectaliases.toArray(new String[0]));
        for (int i = 0; i < aliases.length; i++)
            if (ks.isKeyEntry(aliases[i]))
            {
                ALIAS = aliases[i];
                break;
            }
        privatekey = (PrivateKey)ks.getKey(ALIAS, password);
        cert = (X509Certificate)ks.getCertificate(ALIAS);
        // publickey = ks.getCertificate(ALIAS).getPublicKey();
    } catch (Exception e) {
        signingSucceeded = false;
    }

    for (File source : files) {
        String fileName = "the/path/andNameOfYourOutputFile";

        try {
            // Reading files which need to be signed
            File fileToSign = source;
            byte[] buffer = new byte[(int)fileToSign.length()];
            DataInputStream in = new DataInputStream(new FileInputStream(fileToSign));
            in.readFully(buffer);
            in.close();

            // Generate signature
            ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
            certList.add(cert);
            Store<?> certs = new JcaCertStore(certList);
            CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();

            ContentSigner sha1signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(
                    privatekey);
            signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
                    new JcaDigestCalculatorProviderBuilder().build()).build(sha1signer, cert));
            signGen.addCertificates(certs);
            CMSTypedData content = new CMSProcessableByteArray(buffer);
            CMSSignedData signedData = signGen.generate(content, false);
            byte[] signeddata = signedData.getEncoded();

            // Write signature to Fi File
            FileOutputStream envfos = new FileOutputStream(fileName);
            byte[] outputString = Base64.encode(signeddata);
            int fullLines = (int)Math.floor(outputString.length / 64);
            for (int i = 0; i < fullLines; i++) {
                envfos.write(outputString, i * 64, 64);
                envfos.write("\r\n".getBytes());
            }

            envfos.write(outputString, fullLines * 64, outputString.length % 64);
            envfos.close();
        } catch (Exception e) {
            signingSucceeded = false;
        }
    }
    return signingSucceeded;
}
公共静态布尔信号文件(列表文件){
布尔符号成功=真;
密钥库ks=null;
char[]password=null;
addProvider(新的BouncyCastleProvider());
试一试{
ks=KeyStore.getInstance(“PKCS12”);
password=“yourpass.toCharArray();
加载(新文件输入流(“full/path/to/your/original/certificate.pfx”),密码);
}捕获(例外e){
签名成功=错误;
}
//获取私钥和证书
X509证书证书证书=空;
PrivateKey PrivateKey=null;
试一试{
枚举en=ks.alias();
字符串别名=”;
向量向量=新向量();
while(en.hasMoreElements())
添加(en.nextElement());
String[]别名=(String[])(vectaliases.toArray(新字符串[0]);
对于(int i=0;i

这只是签署文件的代码,希望对您有所帮助。

谢谢。这看起来很有希望,应该给我足够的建议来进一步研究这件事,等