application/x-pkcs7-mime with Bouncy Castle
Hi ,
I have to create a system to exchange a Message using S/Mime format. My system in in java and uses Bouncy Castle Library, the destination system use php open_ssl architecture.
The message is signed (DIGEST_SHA256 algorithm) and encrypted (RC2 algorithm) before sending .
The actual problem starts here.
The two system are not able to exchange the information, for example i can not read the message sent by the php system I've the error "org.bouncycastle.cms.CMSException: bad padding in message" during the decryption process in my system.
I tried to create the same message from the two system to see the differences.
In the process, while comparing the two message created by the two systems and i saw the following differences on the header:
My Message
MIME-Version: 1.0
Content-Type: application/pkcs7-mime; name="smime.p7m"; smime-type=enveloped-data
Content-Transfer-Encoding: base64
PhP System message
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; name="smime.p7m"
Content-Transfer-Encoding: base64
How can i create an application/x-pkcs7-mime S/Mime message with bouncy castle? are those diffrences can be the problem? Can anybody put me in the right direction to solve this problem? Some people tells me that the problem can be the private key that i use for the decryption but i think that the key is correct.
I post my code
Packing the message
public String pack(String message,String indMittente,String indDestinatario,X509Certificate mitCert,X509Certificate destCert,KeyPair chiavi) throws Exception
{
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage body = new MimeMessage(session);
body.setFrom(new InternetAddress(indDestinatario));
body.setRecipient(Message.RecipientType.TO, new InternetAddress(
indDestinatario));
body.setSubject("subject");
body.setContent(message, "text/plain");
body.saveChanges();
// the signing process starts from this line
SMIMECapabilityVector caps = new SMIMECapabilityVector();
caps.addCapability(SMIMECapability.aES256_CBC);
caps.addCapability(SMIMECapability.dES_EDE3_CBC);
caps.addCapability(SMIMECapability.rC2_CBC, 128);
ASN1EncodableVector attributes = new ASN1EncodableVector();
attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(
new IssuerAndSerialNumber(
new X509Name(mitCert.getIssuerDN().getName()),mitCert.getSerialNumber())));
attributes.add(new SMIMECapabilitiesAttribute(caps));
SMIMESignedGenerator signer = new SMIMESignedGenerator();
signer.addSigner(
chiavi.getPrivate(),
mitCert,
SMIMESignedGenerator.DIGEST_SHA256,
new AttributeTable(attributes), null);
List certList = new ArrayList();
certList.add(mitCert);
CertStore certs = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certList), "BC");
signer.addCertificatesAndCRLs(certs);
MimeMultipart mm = signer.generate(body, "BC");
// the encryption process of the signed message start from this line
SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
gen.addKeyTransRecipient(destCert);
MimeMessage test = new MimeMessage(session);
test.setContent(mm);
MimeBodyPart mp = gen.generate(test, SMIMEEnvelopedGenerator.RC2_CBC,40, "BC");
props = System.getProperties();
session = javax.mail.Session.getDefaultInstance(props, null);
InternetAddress fromUser = new InternetAddress(indMittente);
InternetAddress toUser = new InternetAddress(indDestinatario);
MimeMessage finalbody = new MimeMessage(session);
finalbody.setFrom(fromUser);
finalbody.setRecipient(javax.mail.Message.RecipientType.TO, toUser);
finalbody.setSubject("subject");
finalbody.setContent(mp.getContent(),mp.getContentType());
finalbody.saveChanges();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
finalbody.writeTo(bout);
return bout.toString();
}
unpacking the message
public String unpack(String message,X509Certificate dest, KeyPair chiavePrivata) throws Exception
{
ByteArrayInputStream inb = new ByteArrayInputStream(message.getBytes());
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage body = new MimeMessage(session,inb);
SMIMEEnveloped enveloped = new SMIMEEnveloped(body);
// look for our recipient identifier
RecipientInformationStore recipients = enveloped.getRecipientInfos();
RecipientInformation recipient ;
recipient = (RecipientInformation)recipients.getRecipients().iterator().next();
// decryption step
MimeBodyPart res = SMIMEUtil.toMimeBodyPart(recipient.getContent(chiavePrivata.getPrivate(), "BC"));
if (res.getContent() instanceof MimeMultipart)
{
MimeMultipart test = (MimeMultipart)res.getContent();
SMIMESigned signed = new SMIMESigned((MimeMultipart)res.getContent());
// verification step
if (!isValid(signed))
{
throw new Exception("Errore:Firma del messaggio non valida");
}
// content display step
MimeBodyPart content = signed.getContent();
return content.getContent().toString();
}
else
{
throw new Exception("Impossibile decifrare il messaggio");
}
}
awaiting for a valuable help.
Thank you