SMIME cannot be verified by the recipient when using a newer version of Bouncy Castle

I am using BC to encrypt and sign a SMIME message for use with AS2. The code that we have to work perfectly with the old version completely invigorating castle bcmail-1.4:125

. Upgrading to something new causes the recipient of the message (the not-too-old Cyclone server) to be unable to validate the message. (for example, the earliest v in maven also calls this. These are the unchanged versions of the API (for example 1.38).

Since we are using JDK 1.7 (and 1.8) I am trying to upgrade to a newer version of BC, java mail, etc. I have updated all bouncy castles to bcmail-jdk15on:1.51

and bcprov-jdk15on:1.51

as well as java post and follow the examples in the package bcmail

. However, I am still getting a message from Cyclone saying integrity-check-failed

.

I'm pretty sure the error is related to how I sign up. When I disable signing and only use encryption, it handles correctly. Also, I can get the signed response correctly from the remote server and verify the signature from where I am getting the error (from content on MimeMultiPart).

  • Certificates are generated using openssl / self signed / etc saved in pkcs12 file
  • Unlimited strength strategies
  • senderKey

    is an BCRSAPrivateCrtKey

  • senderCert

    • org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject

Bad luck : the current code is 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 crashes on the other end when decrypting (no matter which jdk I run, 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

      

General installation 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 to do with the way I add (or manipulate) senderCert

which is an X509 local application.

Update

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

  • It no longer includes the certificate in the signed message. old version not
  • All information about multiplayer multiplayer is now the same length (1095 bytes) still
  • The format (headers, etc.) is now exactly the same
  • The signed part is now almost identical. However, there is a part that seems to change with time (???) and that changes every time. I can't get openssl to check this post, but don't know why.

Here's a 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--

      

+3


source to share


1 answer


After a lot of debugging and dumping files, etc., I proved that it was about digest computation. At a specific place in the signed body part, there is MIC (digest base64) content. Somehow this meaning did not match what the other side did ...

Once I had this, and some more time with Google, I finally brought up more information on the source forge confirming this. Helpful as it mentions my specific BC version. Quote:

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

What does it mean?

S / MIME rfc says that all messages must be converted to "canonical" form before calculating the MIC. The "canonical" form for text messages is that EOL stands for CR, LF. RFCs are not to mention the canonical form for other types of content. Many S / MIMEs (e.g. openssl, Bouncy Castle after 1.27) incorrectly assume that the canonical form for all messages other than those sent with binary content encoding is that every LF must precede a CR.

So, if BC 1.25 is in use, sends a message that includes bare LF characters, then the MIC confirmation will fail if the message is received by the application using BC> = 1.27 or openssl smime or many other S / MIME implementations.

OpenAS2 needs to be patched to use binary content transfer encoding.

This only works if you have set the encoding on the MIME body part . I verified the same results (which failed on the server) by doing the JCA route manually, the light route and also the CMS route.

With this 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 thing about this is that changing anything related SMIMESignedGenerator()

doesn't seem to have any 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 entry that subscribes is as follows:

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

this is a test

      

Debug information:

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 features and uses the v1 x509 certificate. I can change this now that it all works again.

I really want the whole thing to be more transparent ... BC is intrinsically indirect by indirection, although I understand why. It is still better than the old version. I can't say that I haven't found many examples, but the BC tests don't seem to be the best (for example, I couldn't find one that checked for the expected digest value after SMIME'ing. I may have missed this)

+2


source







All Articles