3

我有一个MailComposer,它构建一个 mime 消息并使用MailSigningService对正文部分(内容)进行数字签名。

签名在sign()buildSignedGenerator()方法中实现。

收到邮件后,邮件客户端检测到签名但抱怨邮件可能被篡改。邮件客户端能够显示证书,它显示所有证书(包括 CA)。

因此,要么基于 Bouncycastle 的签名实现没有正确完成,要么消息本身没有按应有的方式构建。任何提示这里可能会出现什么问题?

MailComposer.java

private MimeMessage buildMimeMessage(com.jumio.jump.domain.Message message, String[] recipients, String subject, Session session) throws MessagingException, IOException {

    MimeMultipart parts = buildContentParts(message);
    parts = (message.getSendOnBehalfOfDomain() != null) ? signContentParts(message, parts) : parts;

    return buildMimeMessage(message, recipients, subject, session, parts);
}

private MimeMessage buildMimeMessage(com.jumio.jump.domain.Message message, String[] recipients, String subject, Session session, MimeMultipart parts) throws MessagingException {
    MimeMessage mimeMessage = new MimeMessage(session);
    mimeMessage.setSubject(subject, "UTF-8");
    mimeMessage.setHeader("Content-ParamType", "text/html; charset=UTF-8");
    mimeMessage.setSentDate(new Date());
    mimeMessage.setFrom(buildFromEmailAddress(message));
    for (String recipient : recipients) {
        if (recipient == null) {
            continue;
        }
        InternetAddress addressTo = new InternetAddress(recipient);
        mimeMessage.addRecipient(Message.RecipientType.TO, addressTo);
    }
    mimeMessage.setContent(parts);
    return mimeMessage;
}

private MimeMultipart signContentParts(com.jumio.jump.domain.Message message, MimeMultipart contentParts)
        throws MessagingException {
    MimeBodyPart body = new MimeBodyPart();
    body.setContent(contentParts);
    MimeMultipart result;
    try {
        result = mailSigningService.sign(body, signerCertificate, certificateChain,
                privateKey);
    } catch (Exception e) {
        logger.error(String.format("Error signing message $s, sending unsigned", message), e);
        return contentParts;
    }
    return result;
}

MailSigningService.java

@Override
public MimeMultipart sign(MimeBodyPart mimeBodyPart, X509Certificate signerCertificate,
        Certificate[] caCertificateChain,  PrivateKey privateKey)
        throws SMIMEException, OperatorCreationException, CertificateEncodingException, NoSuchProviderException,
        NoSuchAlgorithmException, InvalidAlgorithmParameterException {
    Validate.notNull(signerCertificate, "Valid certificate required, check keystore and/or keystore " +
            "configuration");
    Validate.notNull(privateKey, "Valid private key required, check keystore and/or keystore configuration");

    SMIMESignedGenerator generator = buildSignedGenerator(signerCertificate, caCertificateChain, privateKey);
    return generator.generate(mimeBodyPart);
}


private SMIMESignedGenerator buildSignedGenerator(X509Certificate signerCertificate, Certificate[] caCertificateChain, PrivateKey privateKey)
        throws OperatorCreationException, CertificateEncodingException, NoSuchProviderException,
        NoSuchAlgorithmException, InvalidAlgorithmParameterException {

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

    ASN1EncodableVector attributes = new ASN1EncodableVector();
    attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(new IssuerAndSerialNumber(new X509Name(
            signerCertificate.getIssuerDN().getName()), signerCertificate.getSerialNumber())));
    attributes.add(new SMIMECapabilitiesAttribute(capabilities));

    SMIMESignedGenerator generator = new SMIMESignedGenerator();


    generator.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(SECURITY_PROVIDER_NAME)
            .setSignedAttributeGenerator(new AttributeTable(attributes)).build(SIGNER_ALGORITHM, privateKey,
                    signerCertificate));


    List<Certificate> certificates=new ArrayList<Certificate>();
    if (caCertificateChain !=null && caCertificateChain.length>0) {
        certificates.addAll(Arrays.asList(caCertificateChain));
    } else {
        certificates.add(signerCertificate);
    }
    Store certificateStore = new JcaCertStore(certificates);
    generator.addCertificates(certificateStore);
    return generator;
}
4

0 回答 0