当使用较新版本的Bouncy Castle时,SMIME无法被接收者验证 [英] SMIME can't be validated by receiver when using newer version of Bouncy Castle

查看:204
本文介绍了当使用较新版本的Bouncy Castle时,SMIME无法被接收者验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用BC加密和签名一个SMIME消息以供AS2使用。我们的代码工作正常,一个绝对古老的弹性城堡版本, bcmail-1.4:125 。升级到任何更新的消息的接收者(不是太古老的旋风服务器)无法验证消息。 (例如,maven中最早的v / em也是这样的,这些是没有API更改的版本(例如1.38)。



由于我们使用JDK 1.7 (和1.8),我一直在尝试将其更新为更新的BC,java邮件等。我已将所有弹性城堡升级到 bcmail-jdk15on:1.51 bcprov-jdk15on:1.51 以及java邮件,并按照 bcmail 包中的示例。然而,我仍然从Cyclone得到一个错误,说诚信检查失败



我相当肯定错误是我如何进行签名,当我禁用签名并且仅使用加密时它会正常处理,此外,我可以正确地从远程服务器收到一个签名的响应并验证签名,这是我如何得到错误消息(从




  • 证书由openssl / self signed / etc创建,存储在pkcs12文件

  • Unlimi
  • senderKey 是一个 BCRSAPrivateCrtKey

  • senderCert

    • org.bouncycastle.jcajce.provider。不对称x509.X509CertificateObject




失败:目前的代码是这样的,使用 bcmail-jdk15on:1.51 &等等

  SMIMESignedGenerator gen = new SMIMESignedGenerator(); 
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder()
.setProvider(BC)
.build(SHA1withRSA,senderKey,senderCert));
// gen.addCertificates(new JcaCertStore(list(senderCert)));旧v。不添加证书
MimeMultipart smime = gen.generate(part); // MimeBodyPart传入函数
MimeBodyPart tmpBody = new MimeBodyPart();
tmpBody.setContent(signedData);
tmpBody.setHeader(Content-Type,signedData.getContentType()

以前的工作代码看起来像这样,并使用 bcmail-1.4:1.25 。升级到1.3x也会在解密时导致另一端的失败jdk我运行,1.6 - 1.8)

  MimeBodyPart body = new MimeBodyPart(); 
body.setDataHandler(new DataHandler(new ByteArrayDataSource(bytes [],contentType,null);));
SMIMESignedGenerator sGen = new SMIMESignedGenerator();
// SHA1解析为1.3.14.3.2.26,FWIW
sGen.addSigner(senderKey,senderCert,getBouncyCastleAlgorithmId(SHA1));
MimeMultipart signedData = sGen.generate(part,BC);
//这是加密和流式传输,否问题有

常用设置代码

  byte [] data = Files.readAllBytes(filePath); 
MimeBodyPart part = new MimeBodyPart();
ByteArrayDataSou rce dataSource = new ByteArrayDataSource(data,application / EDIFACT,null);
part.setDataHandler(new DataHandler(dataSource));
part.setHeader(Content-Transfer-Encoding,8bit);
part.setHeader(Content-Type,application / EDIFACT);

我有一种感觉,它与我如何添加(或操纵) senderCert ,这是本地应用程序的X509。



更新



我已经使新代码更符合通过删除证书产生的旧版本:




  • 它不再包含签名消息中的证书。旧版本没有

  • 整个mime多部分内容现在正好与
  • 相同的长度(1095字节)
  • 格式(标题等)现在完全相同

  • 已签名的部分现在几乎相同。有一部分似乎根据时间(???)而变化,而且每次都会发生变化。我无法获取openssl来验证此消息,不知道为什么。



以下是示例输出,FWIW。 X-45454545 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- ------ = _ Part_1_1448572667.1409621469842
内容类型:应用程序/ EDIFACT
内容转移编码:8bit

这是一个测试

------ = _ Part_1_1448572667.1409621469842
内容类型:application / pkcs7-signature;命名= smime.p7s; smime-type = signed-data
Content-Transfer-Encoding:base64
Content-Disposition:attachment;文件名= smime.p7s
含量-描述:S / MIME加密签名

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIBpDCCAaAC
AQEwgZ4wgZAxCzAJBgNVBAYTAmNuMREwDwYDVQQIDAhzaGFuZ2hhaTESMBAGA1UEBwwJY2hhbmdu
aW5nMREwDwYDVQQKDAhwb3dlcmUyZTEOMAwGA1UECwwFaXRkZXYxEjAQBgNVBAMMCWFiLWNsaWVu
dDEjMCEGCSqGSIb3DQEJARYUYWItY2xpZW50QG15Q29ycC5jb20CCQClDAGwq37A / jAJBgUrDgMC
GgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQwOTAyMDEz
M [TA5] WjAjBgkqhkiG9w0BCQQxFgQUG6KkoqPBvE7Kd9dB0eop / aUTya0wDQYJKoZIhvcNAQEBBQAE
GYB [h9N4maow9aoTQ8QBGgXEYE + xgXSmRPy + ufIsMpuS0Yys / 1t3AfXSSI7WKgLMRKYXve8gdb4Gn
dqecHzkBwBq4hebt9YK + E30E6DpZpCwErsgDVaU / ExBA5gauPWneysy + s2bE5Y6pNZ7Qf3kGU5kI
UjlOF / LUNkCsgT5z //] 5N6QAAAAAAAA ==
------ = _ Part_1_1448572667.1409621469842--


解决方案

经过大量调试和转储文件等,我证明它与摘要计算。在签名身体部分的特定位置是内容MIC(摘要的base64)。不知怎的,这个价值与对方没有一致...



一旦我这样做了,还有更多的时间与谷歌,我终于出现了有关sourceforge的更多信息确认这一点。有用的,因为它提到了我的具体版本的BC。引用:


问题是BC> = 1.27将规范化
不会与content- 200新新新新旗新新新新旗旗新新旗新新旗200新新200 200 200 200 200 200 200:45新新新旗旗新1992 200 200 200 200 -40 200 200 -40 -40 200 200 -40 -40 200 200 -40 200 200 -40 -40 200 200 -40 200 200 -40 -40 200 200 -40 -40 200 200 -40 -40 200 200 -40 -40 200 200 -40 -40 200 200 200 -40 -40 200 200 -40 200 200 -40 200 200 -40 200 200 200 -40 200 200 -40 -40 200 200 -40 200 200 -40 -40 200 200 -40 -40 200 200 -40 -40 200 200 X-在计算MIC之前,应将消息转换为
canonical形式。
文本消息的规范表单是由CR,LF指示EOL。 rfc是
无声的其他内容类型的规范形式是什么。许多
S / MIME实现(例如,openssl,1.27之后的Bouncy Castle)
不正确地假设除了
之外的所有消息的规范形式,与内容传输编码二进制文件一起发送的是每个LF $新新新新旗新新新新旗新新旗新新旗新新旗新新旗新新旗旗哨旗新新新旗新新旗旗哨派旗新新新旗新新旗旗哨旗新新旗新新旗新新旗旗新1992 200 200新新新新旗新新旗旗新1992 200 200新新新新旗新新旗旗新1992 200 200新新新新旗新新旗200新新新新旗新新旗旗哨式新新200新新旗新新旗旗200新新新新旗新新新新旗新新旗新新旗200新新新旗200 200旗新新旗旗新1992新新新旗新新旗旗新1992 200 200新新新旗新新旗旗新1992新新新新旗新新200新新新旗200 200旗新新旗旗新1992新新新旗新新旗200新新新200新新旗新新200新200新新新旗200新新新旗200新新新旗新200新新旗新新200新新旗新200新新旗新新200新新旗新200新新旗新新200新新旗新新200新新旗新200新新旗新新200新新旗新200新200新新旗新200新200新新200新新旗新新200新新旗新新200新新旗新新200新新200新新新旗200新新新200新新200新新旗新新200新新旗新新200新新200新新旗新新200新新新新旗新新新新旗新新旗新新旗旗新新旗新新旗旗新新旗新新旗旗新新旗新新旗旗新新旗新新旗旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗2001-新新新旗200新新新旗200新新新旗200新新新旗200新新新旗200新新新旗200新新新200旗哨StrEC旗新新旗新新200新200新新旗新新旗200新新新旗200新新200旗哨StrEC新旗p > MIME Body Part 我已经通过手动执行JCA路由,轻量级路由以及CMS路由验证了相同的结果(在服务器上失败)。



有了这些信息,我对发件人进行了简单的更改....

  MimeBody零件部分= // ..使mime body部分从文件
part.setHeader(Content-Transfer-Encoding,binary);新新旗新新新旗新新旗新新旗新新旗旗新新旗新新旗旗新新旗新新旗旗新新旗新200新新旗新新旗旗新新旗新200新新旗旗新新旗旗新200 200 200 200 200 200 CEolololol。 )
似乎没有效果:

  gen = SMIMESignedGenerator(binary); //没有,即使文档说要设置这个

我的最终签名功能看起来像这样,任何感兴趣的人:

  SMIMESignedGenerator gen = new SMIMESignedGenerator(); 
SignerInfoGenerator sigGen = new JcaSimpleSignerInfoGeneratorBuilder()
.setProvider(BC)
.build(SHA1withRSA,senderKey,senderCert);
gen.addSignerInfoGenerator(sigGen);
MimeMultipart smime = gen.generate(part);
MimeBodyPart tmpBody = new MimeBodyPart();
tmpBody.setContent(smime);
tmpBody.setHeader(Content-Type,smime.getContentType());
return tmpBody;

原始文件只是一行:

 这是一个测试

被签名的输入是这个:

 内容类型:application / EDIFACT 
Content-Transfer-Encoding:binary

这是一个测试

调试信息:

 数据字节:
436F6E74656E742D547970653A206170706C69636174696F6E2F454449464143540D0
A436F6E74656E742D5472616E736665722D456E636F64696E673A2062696E6172790D
0A0D0A74686973206973206120746573740A

消化MIC:{
的algorithmId: 1.3.14.3.2.26
摘要字节:CEC2C6614A481DFDF45C801FD6F2A51BC53D3FDF
digest base64:zsLGYUpIHf30XIAf1vKlG8U9P98 =
}
pre>

这不附加签名,或添加任何功能,并使用v1 x509证书。我可以改变那些东西,现在这一切都在工作了。



我真的希望这一切都更加透明... BC内部是间接的间接,虽然我明白为什么。它比旧版内部还好。我不能说我没有找到很多例子,但是BC测试用例似乎并不是最好的(例如,我找不到一个根据预期的摘要值进行验证的例子SMIME'ing,也许我错过了)


I am using BC to encrypt and sign an SMIME message for use with AS2. The code we have works fine with an absolutely ancient version of bouncy castle, bcmail-1.4:125. Upgrading to anything newer causes the receiver of the message (not too ancient Cyclone server) to fail to verify the message. (e.g. the earliest v in maven causes this too. These are the versions without API changes (e.g. 1.38).

Since we use JDK 1.7 (and 1.8), I've been trying to update this to a newer version of BC, java-mail, etc. I've upgraded all of bouncy castle to bcmail-jdk15on:1.51 and bcprov-jdk15on:1.51, along with java mail, and followed the examples in the bcmail package. However, I am still getting an error from Cyclone saying integrity-check-failed.

I am fairly certain the error is with how I am doing signing. When I disable signing and only use encryption it processes correctly. Also, I can correctly receive a signed response from the remote server and verify the signature, which is how I get the error message out (from content-disposition on the MimeMultiPart).

  • The certificates are created by openssl/self signed/etc, stored in pkcs12 file
  • Unlimited strength policies are in place
  • senderKey is a BCRSAPrivateCrtKey
  • senderCert
    • org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject

Failing: The current code is this, using bcmail-jdk15on:1.51 & etc

SMIMESignedGenerator gen = new SMIMESignedGenerator();
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder()
           .setProvider("BC")
           .build("SHA1withRSA", senderKey, senderCert));
// gen.addCertificates(new JcaCertStore(list(senderCert))); old v. doesn't add certs
MimeMultipart smime = gen.generate(part); // MimeBodyPart passed in to function
MimeBodyPart tmpBody = new MimeBodyPart();
tmpBody.setContent(signedData);
tmpBody.setHeader("Content-Type", signedData.getContentType()

Previously working code looks like this and uses bcmail-1.4:1.25. Upgrading to 1.3x also causes a failure on the other end when decrypting (irrespective of which jdk I run on, 1.6 - 1.8)

MimeBodyPart body = new MimeBodyPart();
body.setDataHandler(new DataHandler(new ByteArrayDataSource(bytes[], contentType, null);));
SMIMESignedGenerator sGen = new SMIMESignedGenerator();
// SHA1 resolves to "1.3.14.3.2.26", FWIW
sGen.addSigner(senderKey, senderCert, getBouncyCastleAlgorithmId("SHA1"));
MimeMultipart signedData = sGen.generate(part, "BC");
// this is then encrypted & streamed, no issues there

Common Setup Code

byte[] data = Files.readAllBytes(filePath);
MimeBodyPart part = new MimeBodyPart();
ByteArrayDataSource dataSource = new ByteArrayDataSource(data, "application/EDIFACT", null);
part.setDataHandler(new DataHandler(dataSource));
part.setHeader("Content-Transfer-Encoding", "8bit");
part.setHeader("Content-Type", "application/EDIFACT");

I have a feeling it has something to do with how I am adding (or manipulating) the senderCert, which is the local application's X509.

Update

I've made the new code more in-line with what the old produces by removing the certificate:

  • It no longer includes the cert in the signed message. old version didn't
  • The entire mime multi-part content is now exactly the same length (1095 bytes) as before
  • The format (headers, etc) is now exactly the same
  • The signed part is now nearly identical. There is a portion that seems to vary based on the time (???), though, and that changes each time. I can't get openssl to verify this message yet, no idea why.

Here is sample output, FWIW. The text in [] is the only part that changes.

------=_Part_1_1448572667.1409621469842
Content-Type: application/EDIFACT
Content-Transfer-Encoding: 8bit

this is a test

------=_Part_1_1448572667.1409621469842
Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Cryptographic Signature

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIBpDCCAaAC
AQEwgZ4wgZAxCzAJBgNVBAYTAmNuMREwDwYDVQQIDAhzaGFuZ2hhaTESMBAGA1UEBwwJY2hhbmdu
aW5nMREwDwYDVQQKDAhwb3dlcmUyZTEOMAwGA1UECwwFaXRkZXYxEjAQBgNVBAMMCWFiLWNsaWVu
dDEjMCEGCSqGSIb3DQEJARYUYWItY2xpZW50QG15Q29ycC5jb20CCQClDAGwq37A/jAJBgUrDgMC
GgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQwOTAyMDEz
M[TA5]WjAjBgkqhkiG9w0BCQQxFgQUG6KkoqPBvE7Kd9dB0eop/aUTya0wDQYJKoZIhvcNAQEBBQAE
gYB[h9N4maow9aoTQ8QBGgXEYE+xgXSmRPy+ufIsMpuS0Yys/1t3AfXSSI7WKgLMRKYXve8gdb4Gn
dqecHzkBwBq4hebt9YK+E30E6DpZpCwErsgDVaU/ExBA5gauPWneysy+s2bE5Y6pNZ7Qf3kGU5kI
UjlOF/LUNkCsgT5z//]5N6QAAAAAAAA==
------=_Part_1_1448572667.1409621469842--

解决方案

After a lot of debugging and dumping of files and so on, I proved that it had soemething to do with the digest calculation. In a specific location in the signed body part is the content MIC (base64 of the digest). Somehow this value did not match what the other side did...

Once I had that, and some more time with google, I finally turned up more information on sourceforge confirming this. Helpful since it mentions my specific version of BC. To quote:

The problem is that BC >= 1.27 will "canonicalize" all messages that are not sent with content-transfer-encoding binary.

What does this mean?

In the S/MIME rfc it says that all messages should be converted to a "canonical" form before computing the MIC. The "canonical" form for text messages is that EOL is indicated by CR, LF. The rfc's are silent on what the canonical form for other content types is. Many S/MIME implementations (e.g. openssl, Bouncy Castle after 1.27) incorrectly assume that the canonical form for all messages except those sent with content-transfer-encoding binary is that every LF should be preceeded by a CR.

So if a BC 1.25 used sends a message including bare LF characters then the MIC validation will fail if the message is received by an application using BC >= 1.27, or openssl smime, or many other S/MIME implementations.

OpenAS2 should be fixed to use content-transfer-encoding binary.

This only appears to work if you set the encoding on the MIME Body Part I had verified the same results (that failed on the server) by doing the JCA route manually, the lightweight route, and also the CMS route.

With that information I made a simple change to the sender....

MimeBodyPart part = //.. make mime body part from file
part.setHeader("Content-Transfer-Encoding", "binary");

The funny part about this is that changing anything to do with the SMIMESignedGenerator() seems to have no effect:

gen = SMIMESignedGenerator("binary");  // nothing, even though the docs say to set this

My final signing function looks like this, for anyone interested:

SMIMESignedGenerator gen = new SMIMESignedGenerator();
SignerInfoGenerator sigGen = new JcaSimpleSignerInfoGeneratorBuilder()
        .setProvider(BC)
        .build("SHA1withRSA", senderKey, senderCert);
gen.addSignerInfoGenerator(sigGen);
MimeMultipart smime = gen.generate(part);
MimeBodyPart tmpBody = new MimeBodyPart();
tmpBody.setContent(smime);
tmpBody.setHeader("Content-Type", smime.getContentType());
return tmpBody;

The original file is just one line:

this is a test

The input that gets signed is this:

Content-Type: application/EDIFACT
Content-Transfer-Encoding: binary

this is a test

Debugging info:

data bytes:
436F6E74656E742D547970653A206170706C69636174696F6E2F454449464143540D0
A436F6E74656E742D5472616E736665722D456E636F64696E673A2062696E6172790D
0A0D0A74686973206973206120746573740A

digest mic: {
   "algorithmId":   "1.3.14.3.2.26"
   "digest bytes":  "CEC2C6614A481DFDF45C801FD6F2A51BC53D3FDF"
   "digest base64": "zsLGYUpIHf30XIAf1vKlG8U9P98="
}

Not this does not attach the signature, or add any capabilities, and uses a v1 x509 cert. I may change that stuff now that this is all working again.

I really do wish all this was more transparent... BC internally is indirection upon indirection, though I understand why. It's still better internally than the old version. I can't say that I haven't found a lot of examples, but the BC test cases don't seem the best (e.g. I couldn't find one that verified against an expected digest value after SMIME'ing. maybe I missed it)

这篇关于当使用较新版本的Bouncy Castle时,SMIME无法被接收者验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆