繁体   English   中英

无法使用BouncyCastle重现openssl命令

[英]Can't reproduce openssl command with BouncyCastle

我已经尝试了几个星期,使用bouncycastle和java来重现一些openssl命令。

在跟踪了许多示例并尝试了Stackoverflow的许多示例之后,我仍然无法使其正常运行,这就是为什么现在要寻求帮助。

我必须重现的openssl命令是:

openssl smime -sign -in fileToSign.eml -out signedFile.step2 -passin pass:« password» -binary -nodetach -signer myprivatecert.pem -certfile mypubliccert.pem

这第一个命令需要3个文件,即要签名的文件,一个私有证书和一个公共证书。

它返回一个看起来像的文件:

MIME版本:1.0内容处置:附件; filename =“ smime.p7m”内容类型:application / x-pkcs7-mime; smime-type = signed-data; name =“ smime.p7m” Content-Transfer-Encoding:base64

MIJAYAYJKoZIhvcNAQcCoIJAUTCCQE0CAQExDzANBglghkgBZQMEAgEFADCCNTUG CSqGSIb3DQEHAaCCNSYEgjUiQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7 CmJvdW5kYXJ5PSItLS0tPUxPR0lQT0xfTUlGXzE1NDY4NTAwNDc4MTYiCi0tLS0t LT1MT0dJUE9MX01JRl8xNTQ2ODUwMDQ3ODE2DQpDb250ZW50LVR5cGU6IHRleHQv WE1MOw0KbmFtZT0iUERBX1A5MDAxMjZfMDA1XzIwMTkwMTA3LjA5MzIwMF8wMDAw MV9JTklULnhtbCI7IGZpbGVuYW1lPSJQREFfUDkwMDEyNl8wMDVfMjAxOTAxMDcu MDkzMjAwXzAwMDAxX0lOSVQueG1sIg0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGlu ZzogYmFzZTY0DQoNClBEOTRiV3dnZG1WeWMybHZiajBpTVM0d0lpQmxibU52Wkds dVp6MGlWVlJHTFRnaVB6NDhUVWxHVmtGUFNXNW1iMGx1YVhScFlXeGwNClBnbzhT VzVtYjNNK0NqeFdaWEp6YVc5dVBqSXVPVHd2Vm1WeWMybHZiajRLUEVodmNtOWtZ WFJsUGpJd01Ua3RNREV0TURkVU1EazYNCk16UTZNRGM4TDBodmNtOWtZWFJsUGdv OFUyRnBjMmxsU0c5eWIyUmhkR1UrTWpBeE9TMHdNUzB3TjFRd09Ub3pNam93TUR3 ...

我必须使用的第二个命令是:

openssl smime -encrypt -in signedFile.step2 -out encryptedFile.P7M -outform DER -binary anotherpubliccertificate.pub.pem

该命令使用2个文件,该文件由上一个命令签名,并带有一个公共证书,与上一个命令中使用的证书不同。

这将返回一个二进制文件,即从步骤2生成的加密文件。

我在互联网上找到的任何示例都帮助我获得了一个类似于以前的文件,甚至没有关闭。

我希望有人能帮帮忙

编辑到目前为止我尝试过或参考过的一些示例

Java中带有弹力城堡的签名文件->此操作返回的签名文件与使用openssl生成的签名文件不对应

使用Bouncy Castle提供程序进行AES加密/解密 ->再次,这不起作用,结果与我用openssl生成的加密文件不符

https://studylibfr.com/doc/3898805/cryptographie-avec-bouncy-castle---zenk- >一直在关注整个教程,没有得到预期的结果

X509 RSA弹性城堡符号并验证Java中的纯文本 ->签名文件也不对应

https://github.com/bcgit/bc-java/blob/master/mail/src/main/java/org/bouncycastle/mail/smime/examples/CreateSignedMultipartMail.java- >此类生成类似于以下内容的东西我正在尝试获取,但是我无法测试它的有效性,因为我必须对其进行加密,但仍然无法使加密工作

https://github.com/bcgit/bc-java/blob/master/mail/src/main/java/org/bouncycastle/mail/smime/examples/ReadSignedMail.java- >与上一课相同

https://github.com/bcgit/bc-java/blob/master/mail/src/main/java/org/bouncycastle/mail/smime/examples/SendSignedAndEncryptedMail.java- >这种加密方法不会返回结果与openssl相同,因此无法正常工作

可以肯定的是,我尝试继续使用Bouncycastle的这些示例类,但没有成功。

任何帮助,将不胜感激

编辑2以下问题的答案使用S / MIME签名并加密文件将返回Base64编码的文件,该文件可能与我使用openssl生成的文件相对应。 但是问题是我的入口文件大约25kb,生成的签名文件只有3kb,我不明白为什么,我注意到在这一行:

CMSTypedData content = new CMSProcessableByteArray(buffer);
CMSSignedData signedData = signGen.generate(content, false);
byte[] signeddata = signedData.getEncoded();

getEncoded()方法返回的字节数组比我发送到CMSSignedData的缓冲区小得多。

有人知道原因吗?

对于签名,您与org.bouncycastle.mail.smime.examples.CreateSignedMultipartMail相当接近,除了

  • 它会处理多部分数据openssl smime不会执行; CreateSignedMail开始

  • 它执行多部分签名 ,也称为清除签名, openssl smime也默认为,但-nodetach更改为嵌入式aka封装

  • 它包括完整的证书链,但是是一个自生成的证书链,长度只有2,而几乎所有“真实”证书都更长,而openssl默认情况下仅包括签名者证书

  • 默认情况下,它使用一些不同于openssl的签名属性

对于加密(或更确切地说是包围) openssl smime -outform der ,尽管该名称根本不执行SMIME,但它执行CMS(最初仍称为PKCS7)。 Bouncy使用Java的完全面向对象,将非常相似但不相同的CMS和SMIME放入相关但不相同的不同类中,因此您需要CMS类。

我将它们放在一起(加上最少的测试工具):

    // for test, (own) signing key+certchain and (peer) encryption cert in file
    KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(args[0]),args[1].toCharArray());
    PrivateKey signkey = (PrivateKey) ks.getKey(args[2], args[1].toCharArray());
    Certificate[] signcert = ks.getCertificateChain(args[2]);
    Certificate encrcert = ks.getCertificate(args[3]);
    // and data in file
    byte[] data = Files.readAllBytes(new File(args[4]).toPath());

    // adapted from org.bouncycastle.mail.smime.examples.CreateSignedMail 
    // OpenSSL uses this rather silly capability list; may not be needed 
    SMIMECapabilityVector       caps = new SMIMECapabilityVector();
    caps.addCapability(SMIMECapability.aES256_CBC);
    caps.addCapability(SMIMECapability.aES192_CBC);
    caps.addCapability(SMIMECapability.aES128_CBC);
    caps.addCapability(SMIMECapability.dES_EDE3_CBC);
    caps.addCapability(SMIMECapability.rC2_CBC, 128);
    caps.addCapability(SMIMECapability.rC2_CBC, 64);
    caps.addCapability(SMIMECapability.dES_CBC);
    caps.addCapability(SMIMECapability.rC2_CBC, 40);
    ASN1EncodableVector signedAttrs = new ASN1EncodableVector();
    signedAttrs.add(new SMIMECapabilitiesAttribute(caps));
    // Bouncy default adds RFC6211 in addition to standard ctype, stime, mdgst
    // and changing this is complicated; recipient _should_ ignore unneeded attr

    SMIMESignedGenerator gen = new SMIMESignedGenerator();
    gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder()//.setProvider("BC") not needed
        .setSignedAttributeGenerator(new AttributeTable(signedAttrs))
        .build("SHA1withRSA", signkey, (X509Certificate) signcert[0]) ); 
    // change sigalg if key not RSA and/or want better hash
    // OpenSSL by default includes only signer cert; recipient may want more
    gen.addCertificates(new JcaCertStore (Arrays.asList (new Certificate[]{signcert[0]}) ));

    MimeBodyPart msg = new MimeBodyPart();
    msg.setText(new String(data, "ISO-8859-1")); // OpenSSL doesn't know charsets
    ByteArrayOutputStream temp = new ByteArrayOutputStream();
    gen.generateEncapsulated(msg).writeTo(temp); // OpenSSL -nodetach is encapsulated
    // Bouncy uses BER here (unlike OpenSSL DER) 
    // and I don't see a simple way to change it but it _should_ not matter 
    byte[] signedblob = temp.toByteArray();

    // now CMS (not SMIME) enveloping
    CMSEnvelopedDataGenerator edgen = new CMSEnvelopedDataGenerator();
    edgen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate) encrcert));
    CMSEnvelopedData edmsg = edgen.generate( new CMSProcessableByteArray(signedblob),
            new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).build() );
    byte[] encrblob = edmsg.toASN1Structure().getEncoded(ASN1Encoding.DER); // OpenSSL is DER though std doesn't require it

    // for test, write to a file
    Files.write(new File(args[5]).toPath(), encrblob);

继续,“有人知道原因吗”

CMSSignedData signedData = signGen.generate(content, false);
byte[] signeddata = signedData.getEncoded();

小于内容? 请参见javadocencapsulate (第二个参数)设置为false您告诉它不要在签名中包含内容(更确切地说是SignedData),并且按要求进行了操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM