是否存在让MimeMessage附加cms签名数据的有效示例?
我知道BouncyCastle随SMIMEEnvelopedGenerator一起提供,但我正在从卡中读取私钥,因此使用cms而不是smime。 我设法以签名数据的形式发送邮件,但是在解析签名消息的内容时返回空。
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] data = "Hello World!".getBytes();
//start sign
List certList = new ArrayList();
certList.add(cert);
Store certs = new JcaCertStore(certList);
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
ContentSigner sha1Signer =
new JcaContentSignerBuilder(
"SHA256withRSA").setProvider("MyProvider").build((PrivateKey) key);
JcaSignerInfoGeneratorBuilder signBuilder =
new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
gen.addSignerInfoGenerator(signBuilder.build(sha1Signer, (X509Certificate) cert));
gen.addCertificates(certs);
bos.reset();
OutputStream sigOut = gen.open(bos, true);
sigOut.write(data);
sigOut.close();
Log.e(TAG, " signature: " + new String(bos.toByteArray()));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ASN1InputStream asn1 = new ASN1InputStream(bos.toByteArray());
DEROutputStream dos = new DEROutputStream(out);
dos.writeObject(asn1.readObject());
Log.e(TAG, "asn1: " + new String(out.toByteArray()));
} catch (IOException e1) {
throw new SignatureException("Failed to generate signature", e1);
}
byte[] base64Sig = Base64.encode(out.toByteArray(), Base64.DEFAULT);
Log.e(TAG, "string encodedSig: \n" + new String(base64Sig));
CryptoUtils.parseContentType(out.toByteArray());
MimeBodyPart part = new MimeBodyPart(new InternetHeaders(), base64Sig);
part.addHeader("Content-Type", "application/pkcs7-mime; name=smime.p7m; smime-type=signed-data");
part.addHeader("Content-Disposition", "attachment; filename=smime.p7m");
part.addHeader("Content-Description", "S/MIME Cryptographic Signed Data");
part.addHeader("Content-Transfer-Encoding", "base64");
bos.reset();
part.writeTo(bos);
Log.e(TAG, "part: " + new String(bos.toByteArray()));
MimeMessage msg = new MimeMessage(getSession());
msg.setFrom(new InternetAddress("test@mail.com"));
msg.setRecipients(Message.RecipientType.TO, "test2@mail.com");
msg.setSentDate(new Date());
msg.setSubject("Subject");
msg.setContent(part, part.getContentType());
//end sign
bos.reset();
msg.writeTo(bos);
Log.e(TAG, "final: " + new String(bos.toByteArray()));
所以我Transport.send(msg),但是解密内容时返回的是空而不是Hello world
答案 0 :(得分:0)
最终解决了它。您需要使用文本创建模仿,并在模仿而不是文本上签名。下面的快照器可供参考:
MimeBodyPart m = new MimeBodyPart();
m.setText("Hello World!");
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(m);
MimeMessage mm = new MimeMessage(getSession());
mm.setContent(mimeMultipart);
bos.reset();
mm.writeTo(bos);
Log.e(TAG, "mm: " + new String(bos.toByteArray()));
List certList = new ArrayList();
certList.add(cert);
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner sha1Signer =
new JcaContentSignerBuilder(
"SHA256withRSA").setProvider("Your Provider").build((PrivateKey) key);
JcaSignerInfoGeneratorBuilder signBuilder =
new JcaSignerInfoGeneratorBuilder(new
JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
gen.addSignerInfoGenerator(signBuilder.build(sha1Signer, (X509Certificate)
cert));
gen.addCertificates(certs);
CMSSignedData signedData = gen.generate(new
CMSProcessableByteArray(bos.toByteArray()), true);
Log.e(TAG, " signature: " + new String(signedData.getEncoded()));
然后将签名的数据附加到模仿消息中,如下所示:
msg.setDataHandler(new DataHandler(new
ByteArrayDataSource(signedData.getEncoded()
还要添加相关的标题:
msg.addHeader("Content-Type", "application/pkcs7-mime; name=smime.p7m;
smime-type=signed-data");
msg.addHeader("Content-Disposition", "attachment; filename=smime.p7m");
msg.addHeader("Content-Description", "S/MIME Cryptographic Signed Data");