bouncycastle中的PKCS#7 SignedData问题

时间:2012-02-08 23:27:53

标签: cryptography openssl bouncycastle asn.1 smime

我在那里!

我有一个openssl生成的smime文件的问题。我需要解析(在BouncyCastle的帮助下)使用openssl生成的smime SignedData包。我用这个命令创建了一个例子:

openssl smime -sign -inkey Signer/signer_key.pem -in Signer/message.txt -text -out SMIME/signed.data -signer Signer/signer_cert.pem -certfile cacert.pem -outform smime

问题是我需要在流程中填写pkcs7 ASN.1结构,然后应用标准中描述的算法,可以在此处找到:pkcs7 signedData

ASN.1结构如下:

SignedData ::= SEQUENCE { version Version, 
                          digestAlgorithms DigestAlgorithmIdentifiers, 
                          contentInfo ContentInfo, 
                          certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
                          crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
                          signerInfos SignerInfos }

SignerInfo ::= SEQUENCE { version Version, 
                          issuerAndSerialNumber IssuerAndSerialNumber, 
                          digestAlgorithm DigestAlgorithmIdentifier, 
                          authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
                          digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
                          encryptedDigest EncryptedDigest, 
                          unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }

签名验证中出现问题。在标准中说是

  

消息摘要计算过程的结果取决于      signedAttrs字段是否存在。当田地不存在时      结果只是所描述的内容的消息摘要      以上。但是,当字段存在时,结果就是消息      摘要SignedAttrs值的完整DER编码      包含在signedAttrs字段中。

在smime包中我有明文,我正在计算它的摘要,并与从smime文件中读取encryptedDigest的结果进行比较,然后对其进行解密。假设它没有属性。但是对我来说很明显,不知何故,smime包中包含的签名不仅基于明文计算,还基于某些属性计算。我想知道的是通过在cleantext中附加必要的属性来使这项工作成为一种方法,以便两者的摘要等于从SMIME包中读取的encryptedDigest字段。

以下是我正在使用的主要内容。为了简化,我删除了(大量)调试部分,并放置了一些英文评论,取代了葡萄牙语。我认为理解它很简单,但如果有人对此感兴趣,我可以发布我的整个代码。

    package signedData;

import PKCS7.SignedData;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.security.MessageDigest;
import java.security.Security;
import java.security.cert.CertStore;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.mail.smime.SMIMESigned;
import org.bouncycastle.util.Store;
import sun.misc.BASE64Encoder;


public class Main {

    public static void main(String[] args) {

        String ksFile = "Recipient/ks_recipient", ks_type = "JCEKS", key_alias = "recipient_pkcs12", cert_alias = "cacert", algorithm, provider = "BC";
        byte[] encrypted, encrypted2,  decrypted, digest;
        Cifra cipher;
        Digest dgst;
        X509Certificate cert;
        Properties props;
        Session session;
        MimeMessage msg;
        SMIMESigned signed;
        SignerInformationStore signers;
        SignerInformation s;
        CertStore certs;
        Collection c;
        Iterator it, certIt;
        ByteArrayOutputStream baos;
        ObjectOutputStream oos;


        if( args.length == 1) {

            /**
             * args[0] - SMIME's Path file
             */


            try {

                props = System.getProperties();
                session = Session.getDefaultInstance(props);

                msg = new MimeMessage(session, new FileInputStream(args[0]));
                signed = new SMIMESigned((MimeMultipart) msg.getContent());

                /* Putting information from various parties ( contained in the SMIME package) in a Collection, in order to process the information from each individually */
                signers = signed.getSignerInfos();
                c = signers.getSigners();

                /* Read certificates from SMIME package */
                certs =   (CertStore) signed.getCertificatesAndCRLs("Collection", provider);


                /* Iterate through the signers */
                it = c.iterator();

                while(it.hasNext()) {

                    /* Isolate each signer information */
                    s = (SignerInformation) it.next();

                    Collection certCollection = certs.getCertificates(s.getSID());

                    /* Iterate through this chain's certificates */
                    certIt = certCollection.iterator();
                    cert = (X509Certificate) certIt.next();


                    /* Verify signer certificate with CA */
                    if(Certificate_Handler.verifyCertificate( RW_KeyStore.getCertificate(ksFile, ks_type, cert_alias), cert, Security.getProvider(provider))) {

                        /* Read encryption algorithm identifier from SMIME package */
                        algorithm = Gadgets.getBC_Algorithm(s.getEncryptionAlgOID());

                        /* Read encrypted signature bytes */
                        encrypted = s.toASN1Structure().getEncryptedDigest().getOctets();

                        /* Create an instance of Digest, which is responsible for computing message digests */
                        dgst = new Digest(Gadgets.getBC_DigestAlgorithm(s.getDigestAlgOID()), provider);

                        /* Specify the encryption algorithm */
                        cipher = new Cifra(algorithm, provider);

                        // decrypt digest
                        decrypted = cipher.decifrar(encrypted2, cert.getPublicKey());


                        /* Compute plaintext digest */
                        digest = dgst.computeMessageDigest(((String) signed.getContent().getContent()).getBytes());

                        /* Verify signature */
                        if( MessageDigest.isEqual(decrypted, digest) )
                            System.out.println("check");
                        else
                            System.out.println("fail");
                    }
                    else
                        throw new Exception("Invalid Certificate");
                }
            }
            catch (Exception ex) {

                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        else
            System.err.println("Invalid parameter number: " + args.length);
    }
}

现在是一个SMIME文件的例子,这是我实际使用的文件:

    MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha1"; boundary="----BF337FE7381F86CE88DBE2ED7A24396E"

This is an S/MIME signed message

------BF337FE7381F86CE88DBE2ED7A24396E
Content-Type: text/plain

Executive Mansion,
Washington, August 22, 1862.

Hon. Horace Greeley:
Dear Sir.

I have just read yours of the 19th. addressed to myself through the New-York Tribune. If there be in it any statements, or assumptions of fact, which I may know to be erroneous, I do not, now and here, controvert them. If there be in it any inferences which I may believe to be falsely drawn, I do not now and here, argue against them. If there be perceptable in it an impatient and dictatorial tone, I waive it in deference to an old friend, whose heart I have always supposed to be right.

As to the policy I "seem to be pursuing" as you say, I have not meant to leave any one in doubt.

I would save the Union. I would save it the shortest way under the Constitution. The sooner the national authority can be restored; the nearer the Union will be "the Union as it was." If there be those who would not save the Union, unless they could at the same time save slavery, I do not agree with them. If there be those who would not save the Union unless they could at the same time destroy slavery, I do not agree with them. My paramount object in this struggle is to save the Union, and is not either to save or to destroy slavery. If I could save the Union without freeing any slave I would do it, and if I could save it by freeing all the slaves I would do it; and if I could save it by freeing some and leaving others alone I would also do that. What I do about slavery, and the colored race, I do because I believe it helps to save the Union; and what I forbear, I forbear because I do not believe it would help to save the Union. I shall do less whenever I shall believe what I am doing hurts the cause, and I shall do more whenever I shall believe doing more will help the cause. I shall try to correct errors when shown to be errors; and I shall adopt new views so fast as they shall appear to be true views.

I have here stated my purpose according to my view of official duty; and I intend no modification of my oft-expressed personal wish that all men every where could be free.

Yours,
A. Lincoln.
------BF337FE7381F86CE88DBE2ED7A24396E
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

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

------BF337FE7381F86CE88DBE2ED7A24396E--

1 个答案:

答案 0 :(得分:2)

我解决了。 (pkcs7)标准在计算摘要后创建一个辅助结构(DigestInfo)。

DigestInfo ::= SEQUENCE { digestAlgorithm DigestAlgorithmIdentifier, 
                          digest Digest }

在解密我从SMIME包中读取的EncryptedDigest后,结果是DigestInfo。

然后我计算signedAttributes的摘要(对于每个签名者):

SignerInformation.getSignedAttributes()

最后将结果放入DigestInfo。只有这样我才能检查签名的有效性。瞧,它正在发挥作用!

希望这可以帮助任何遇到与我相同问题的人,因为这真的是一个耗时的问题......