【问题标题】:Using Java 7 to Verify OpenSSL Generated S/MIME Digital Signature Files使用 Java 7 验证 OpenSSL 生成的 S/MIME 数字签名文件
【发布时间】:2015-02-11 16:13:10
【问题描述】:

我们有一个使用 OpenSSL 生成 S/MIME 数字签名的过程,该签名需要稍后使用 Java 7 进行验证。一方面,我们使用 OpenSSL 读取文本文件并生成签名的数字输出,稍后进行验证。

我们曾经使用 OpenSSL 进行验证,但现在我们需要 Java(注意:我们不能指望 OpenSSL 现在可用)。

我们用这个来签名:openssl smime -sign -inkey private.key -signer public.key -in ${f} > ${f}.signed 并用这个来验证:openssl smime -verify -noverify -in ${f}.signed

注意:verify 不验证证书,只检查签名/内容。

我需要将此过程的验证部分更改为 Java 应用程序,最好使用 Java 7(我认为现在已内置 JCE)。

示例输出类似于 ...

MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----185C6C544BB34D30B0835B915C158544"

This is an S/MIME signed message

------185C6C544BB34D30B0835B915C158544
Four score and seven years ago our fathers brought forth on this continent, a
new nation, conceived in Liberty, and dedicated to the proposition that all
men are created equal.

Now we are engaged in a great civil war, testing whether that nation, ...
------185C6C544BB34D30B0835B915C158544
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

MIIKAAYJKoZIhvcNAQcCoIIJ8TCCCe0CAQExDzANBglghkgBZQMEAgEFADALBgkq
hkiG9w0BBwGgggchMIIHHTCCBgWgAwIBAgIEUzuEpzANBgkqhkiG9w0BAQsFADCB
hzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEoMCYGA1UE
CxMfRGVwYXJ0bWVudCBvZiBIb21lbGFuZCBTZWN1cml0eTEiMCAGA1UECxMZQ2Vy
dGlm ...
... JIQeeE=

------185C6C544BB34D30B0835B915C158544--

签名算法是sha256WithRSAEncryption;例子...

openssl smime -pk7out -in message.signed | openssl pkcs7 -text -noout -print_certs
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1396409511 (0x533b84a7)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Corp, OU=Acme, OU=CA
        Validity
            Not Before: May 16 15:27:56 2014 GMT
            Not After : May 16 15:57:56 2015 GMT
        Subject: C=US, O=Corp, OU=Acme, OU=CBP, CN=foo.acme.corp.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:00:00:00:00:b1:b6:49:6e:ca:d7:61:07:a0:18:
                    ...
                    c9:de:ab:a7:2f:97:e4:f6:64:37:ec:3a:9d:ae:c0:
                    16:03
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Certificate Policies: 
                Policy: 2.16.840.1.101.3.2.1.3.8
...

我查看了很多很多示例,尝试了多个示例,但均未成功。我希望有一些资源可以与您分享,但到目前为止我所取得的成功至少不会有任何帮助。

【问题讨论】:

    标签: java openssl digital-signature


    【解决方案1】:

    这可以使用 Bouncy Castle Crypto API 来完成,您可以使用以下官方示例作为参考,https://github.com/bcgit/bc-java/blob/master/mail/src/main/java/org/bouncycastle/mail/smime/examples/ValidateSignedMail.java。

    对于一个更简单的示例来执行包括证书链在内的已签名电子邮件的完整验证,您可以使用org.bouncycastle:bcmail-jdk15on:1.52 执行类似的操作:

    import org.bouncycastle.cms.SignerInformation;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.mail.smime.validator.SignedMailValidator;
    
    import javax.mail.internet.MimeMessage;
    import java.io.FileInputStream;
    import java.security.KeyStore;
    import java.security.Security;
    import java.security.cert.PKIXParameters;
    
    public class SignedMailValidatorExample {
        public static void main(String[] args) throws Exception {
            Security.addProvider(new BouncyCastleProvider());
            FileInputStream signedEmailInputStream = new FileInputStream("signed_email.eml");
            MimeMessage signedEmailMimeMessage = new MimeMessage(null, signedEmailInputStream);
            KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(new FileInputStream("truststore.jks"), "changeit".toCharArray());
            PKIXParameters pkixParameters = new PKIXParameters(trustStore);
            pkixParameters.setRevocationEnabled(false);
            SignedMailValidator signedMailValidator = new SignedMailValidator(signedEmailMimeMessage, pkixParameters);
            boolean successfulValidation = true;
            for (SignerInformation signerInformation : signedMailValidator.getSignerInformationStore().getSigners()) {
                SignedMailValidator.ValidationResult signerValidationResult = signedMailValidator
                        .getValidationResult(signerInformation);
                if (!signerValidationResult.isValidSignature()) {
                    successfulValidation = false;
                    break;
                }
            }
            if (successfulValidation) {
                System.out.println("Signed email validated correctly.");
            } else {
                System.out.println("Signed email validation failed.");
            }
        }
    }
    

    truststore.jks 应包含一个 CA 证书(例如,颁发 CA),该证书链接到用于签署电子邮件的证书。现在,您可以使用https://keystore-explorer.org/ 等软件轻松创建此文件。

    【讨论】:

      猜你喜欢
      • 2014-05-04
      • 1970-01-01
      • 2011-06-24
      • 2011-04-25
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 2020-01-13
      相关资源
      最近更新 更多