将 cms 包装到 MimeMessage 中



是否有一个工作示例可以让 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

终于解决了这个问题。您需要创建带有文本的 mimemessage 并签署 mimemessage 而不是文本。下面的狙击手供参考:

            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()));

然后将签名数据附加到 mimemessage 中,如下所示:

            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");

最新更新