如何在Java中使用.p12签署电子邮件?

时间:2019-06-27 08:14:48

标签: java digital-signature bouncycastle

我尝试使用充气城堡,但它说数字签名无效/无法在接收方验证。

我不想加密电子邮件,仅添加数字签名。

请参见下面的代码片段,其中我正在传递MimeMessage并返回签名的MimeMessage,然后使用Java邮件发件人发送该消息

        MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();

        mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
        mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
        mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
        mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
        mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");

        CommandMap.setDefaultCommandMap(mailcap);

        Security.addProvider(new BouncyCastleProvider());

        KeyStore ks = KeyStore.getInstance("PKCS12");
        File file = ResourceUtils.getFile(certificatePath);
        ks.load(new FileInputStream(file), certificatePassword.toCharArray());

        Enumeration<String> es = ks.aliases();
        String alias = "";
        boolean isAlias = false;
        while (es.hasMoreElements()) {
            alias = es.nextElement();

            if (isAlias = ks.isKeyEntry(alias)) {
                break;
            }
        }
        if (isAlias) {
            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(certificatePassword.toCharArray()));
            PrivateKey myPrivateKey = pkEntry.getPrivateKey();

            Certificate[] chain = ks.getCertificateChain(alias);
            chain[0].verify(chain[1].getPublicKey());

            SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
            capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
            capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
            capabilities.addCapability(SMIMECapability.dES_CBC);
            capabilities.addCapability(SMIMECapability.aES256_CBC);

            ASN1EncodableVector attributes = new ASN1EncodableVector();
            attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(
                    new IssuerAndSerialNumber(
                            new X500Name(((X509Certificate) chain[0])
                                    .getIssuerDN().getName()),
                            ((X509Certificate) chain[0]).getSerialNumber())));
            attributes.add(new SMIMECapabilitiesAttribute(capabilities));

            SMIMESignedGenerator signer = new SMIMESignedGenerator();
            signer.addSigner(
                    myPrivateKey,
                    (X509Certificate) chain[0],
                    "DSA".equals(myPrivateKey.getAlgorithm()) ? SMIMESignedGenerator.DIGEST_SHA1
                            : SMIMESignedGenerator.DIGEST_MD5,
                    new AttributeTable(attributes), null);

            List certList = new ArrayList();
            certList.add(chain[0]);
            CertStore certs = CertStore.getInstance("Collection",
                    new CollectionCertStoreParameters(certList), "BC");
            signer.addCertificatesAndCRLs(certs);

            MimeMultipart mm = signer.generate(mimeMessage, "BC");
            MimeMessage signedMessage = new MimeMessage(mimeMessage);

            signedMessage.setContent(mm);
            signedMessage.saveChanges();
            LOG.info("{EMAIL SIGNING] Successfully signed email");
            return signedMessage;

我能够阅读邮件,但邮件客户端显示错误,指出证书无效/已验证。

我遵循了this的示例

0 个答案:

没有答案