Java Can';使用BouncyCastle复制openssl命令

Java Can';使用BouncyCastle复制openssl命令,java,encryption,cryptography,bouncycastle,sign,Java,Encryption,Cryptography,Bouncycastle,Sign,我已经尝试了几周,使用bouncycastle和java复制一些openssl命令 在遵循了大量的示例并尝试了Stackoverflow中的大量示例之后,我仍然无法使其工作,这就是我现在寻求帮助的原因 我必须复制的openssl命令有: openssl smime -sign -in fileToSign.eml -out signedFile.step2 -passin pass:« password» -binary -nodetach -signer myprivatecert.pem -

我已经尝试了几周,使用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类型=有符号数据;name=“smime.p7m”内容传输编码: base64

Mijayayjkozihvcnaqcoijautcqe0cqexdzanbglghkgbzqmeagefadccntug CSQGSIB3DQEHAACCNSYEGJUIQ29UDGVUDC1UEXBLOBTBDWX0AXBHCNQVBWL4ZWQ7 CMJVDW5KYXJ5PITLS0TPR0LQT0xFTULGXZE1NDY4NTAWNDC4MTYICI0TLS0T LT1MT0DJUE9MX01JRL8XNTQ2ODUWMDQODE2DQPDB250ZW50LVR5CGU6IHRLEHQV WE1MOw0KbmFtZT0iUERBX1A5MDAxMjZfMDA1XzIwMTkwMTA3LjA5MzIwMF8wMDAw MV9JTKLULNHTBCI7IGZPBGVUYW1LPSJQREDKWMDEYNL8WMDVFMJAXOTAXMDCU MDkzMjAwXzAwMDAxX0lOSVQueG1sIg0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGlu ZzogYmFzZTY0DQoNClBEOTRiV3dnZG1WeWMybHZiajBpTVM0d0lpQmxibU52Wkds DVP6MGLWWLJHTFRNAVB6NDHUVWxHVMTGUFNxNW1MGX1YVHSCFLxEGWnCLbNbZHT VZVTYJNNK0NQEFDAWEP6YVC5DVBQSVPVHD2VM1WEWMYBHZIAJRLUEVODMNTOWTZ WFJSUGPJD01UA3RNRev0TurkVu1Azynck16UTZNRGM4TDBODMNTOWTZWFJSUGDV OfYRNBJMMXSU0C5EwiyumHkr1uRTWPBEE9TMHDNUZB3TJFRD09UB3PAM93TUR3

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

openssl smime -encrypt -in signedFile.step2 -out encryptedFile.P7M -outform DER -binary anotherpubliccertificate.pub.pem
此命令获取两个文件,一个是由上一个命令签名的文件,另一个是公共证书,与上一个命令中使用的文件不同

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

我在互联网上找到的任何一个例子都帮助我得到了一个看起来像之前这些例子的文件,甚至不接近

我希望有人能帮忙

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

->返回的签名文件与openssl生成的签名文件不一致

->同样,这不起作用,结果与我用openssl生成的加密文件不一致

->一直在关注整个教程,没有得到预期的结果

->签名文件也不对应

->该类生成的内容与我试图获取的内容相似,但我无法测试它的有效性,因为我必须对其进行加密,并且仍然无法使encrytion工作

->与上节课相同

->此加密方法返回的结果与openssl不同,因此无法正常工作

当然,我一直试图继续使用bouncycastle中的这些示例类,但没有成功

任何帮助都将不胜感激

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

CMSTypedData content = new CMSProcessableByteArray(buffer);
CMSSignedData signedData = signGen.generate(content, false);
byte[] signeddata = signedData.getEncoded();
getEncoded()方法返回的字节数组比发送给CMSSignedData的缓冲区小得多


有人知道原因吗

对于签名,您与org.bounchycastle.mail.smime.examples.CreateSignedMultipartMail的关系相当密切,除了

  • 它提供多部分数据,
    opensslsime
    没有;改为从
    CreateSignedMail
    开始

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

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

  • 默认情况下,它使用一些与openssl不同的SignedAttribute

对于加密(或者更准确地说是封装)
openssl smime-outform der
,尽管名称根本不做smime,但它做CMS(最初也被称为PKCS7)。Bouncy充分利用Java的OO优势,将非常相似但不相同的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();

比内容小吗?请参阅--
enclosure
(第二个参数)设置为
false
时,您告诉它不要在签名中包含内容(更准确地说是签名数据),它按照您的要求执行了操作。

将二进制格式解释为文本是愚蠢的;查找DER的含义。我知道DER的含义,谢谢,这并不能帮助我理解如何获得相似的文件。我写这些字符是为了举例说明它看起来像什么我想这就是为什么人类发明了十六进制。如果您理解DER,那么您就不会发布UTF-8解码。Mr零序。对于这类问题,你应该发布到目前为止你开发的代码。正如我在上面的问题上所说的,我尝试了很多示例,真的太多了,我不能发布我所做的一切,因为我尝试的一切都没有返回我必须得到的结果。我问这个问题的目的是希望有人能找到一种方法来得到这个结果,而不是展示我尝试过和失败过的一切,但我会编辑我的问题,并添加一些我尝试过的例子Hello,很抱歉我的回答太晚了,看来,多亏了你的回答,加密问题现在已经解决了!非常感谢您,您现在为签名救了我的命,我还不能尝试它,但我注意到smime文件的头与openssl生成的头有很大不同,当然这可能不重要,但下面是我要说的