PKCS#7加密信封签名验证错误:消息哈希

时间:2013-06-25 11:02:30

标签: java cryptography pkcs#7 iaik-jce

我想提交一个关于加密标准PKCS#7的问题。 我有一个文件" PATH_DOC_NF1"我必须创建一个PKCS#7加密信封。 使用KeyStore和AIK-JCE(基于Java的加密服务提供程序)。

我拥有的X.509证书如下:

  

版本:3
  编号:231944
  签名算法:sha1WithRSAEncryption(1.2.840.113549.1.1.5)
  发行人:CN = .........,OU = .........,O = ......,C = IT
  之前有效:Fri Apr 01 09:20:15 CEST 2011
        不是之后:Tue Apr 01 09:20:13 CEST 2014
  主题:CN = TRANTN59T46H703C-001,OU = ......,O = .........,C = IT
  Sun RSA公钥,1024位
    模数:......
    公众指数:...
  证书指纹(MD5):............
  证书指纹(SHA-1):............

     

扩展程序:4

运行下面的代码:

public static void main(String[] args) {

    Path path = Paths.get(PATH_DOC_NF1);
    try {
        byte[] data = Files.readAllBytes(path);
        Security.addProvider(new IAIK()); 

        KeyStore ks = KeyStore.getInstance("IAIKKeyStore", "IAIK");
        InputStream is = new FileInputStream(PATH_KEYSTORE_TELEMACO);
        X509Certificate certX509;
        PrivateKey pk;

        String pathout=PATH_DOC_NF1+".p7m";

        File file = new File(pathout);

        if (file.exists()){
            System.out.println("Il file " + pathout +" esiste");
        }else if (file.createNewFile()){
            System.out.println("Il file " + pathout +" E' stato creato");
        }else{
            System.out.println("Il file " + pathout +" non puo' essere creato");
        }
        ByteArrayInputStream in = new ByteArrayInputStream(data);

        if (ks != null){
            ks.load(is, KEY_PASSWORD_TELEMACO);
            Enumeration<String> aliases = ks.aliases();
            for (; aliases.hasMoreElements(); ) {
                String alias = aliases.nextElement();
                if(ks.isKeyEntry(alias)){
                    pk = (PrivateKey) ks.getKey(alias,KEY_PASSWORD_TELEMACO);
                    Certificate[] chain = ks.getCertificateChain(alias);
                    certX509 = (X509Certificate) chain[0];


                    MessageDigest digestEngine = MessageDigest.getInstance("SHA");

                    ByteArrayOutputStream contentBuffer = new ByteArrayOutputStream();

                    byte[] contentHash = digestEngine.digest(data);

                    contentBuffer.close();

                    SignedData signedData = new SignedData(contentBuffer.toByteArray(), SignedData.IMPLICIT);

                    signedData.setCertificates(new X509Certificate[] { certX509 });

                    SignerInfo signerInfo = new SignerInfo(new IssuerAndSerialNumber(certX509), AlgorithmID.sha, null);

                    Attribute[] authenticatedAttributes = {
                            new Attribute(ObjectID.contentType,new ASN1Object[] {ObjectID.pkcs7_data}),
                            new Attribute(ObjectID.signingTime,new ASN1Object[] {new ChoiceOfTime().toASN1Object()}),
                            new Attribute(ObjectID.messageDigest,new ASN1Object[] {new OCTET_STRING(contentHash)})
                    };

                    signerInfo.setAuthenticatedAttributes(authenticatedAttributes);

                    byte[] toBeSigned = DerCoder.encode(ASN.createSetOf(authenticatedAttributes, true));

                    MessageDigest md = MessageDigest.getInstance("SHA");

                    byte[] hashToBeSigned = md.digest(toBeSigned);

                    DigestInfo digestInfoEngine = new DigestInfo(AlgorithmID.sha1WithRSAEncryption, hashToBeSigned);
                    byte[] toBeEncrypted = digestInfoEngine.toByteArray();


                    Signature sign = Signature.getInstance("RSA");
                    sign.initSign(pk);

                    sign.update(toBeEncrypted);
                    byte[] signatureValue = sign.sign();

                    signerInfo.setEncryptedDigest(signatureValue);

                    signedData.addSignerInfo(signerInfo);

                    OutputStream signatureOutput = new FileOutputStream(pathout);

                    ContentInfoStream cis = new ContentInfoStream(signedData);
                    BufferedOutputStream bos = new BufferedOutputStream(signatureOutput);

                    Base64OutputStream b64Out = new Base64OutputStream(bos);

                    cis.writeTo(b64Out);
                    b64Out.close();
                    in.close();

                    /****VERIFY_SIGN******/

                    InputStream encodedStream;

                    encodedStream = new FileInputStream(pathout);
                    ASN1InputStream asn1 = new ASN1InputStream(encodedStream);
                    ContentInfoStream cis2 = new ContentInfoStream(asn1);

                    SignedDataStream signedData2;

                    if (cis.getContentType().equals(ObjectID.cms_signedData)){

                        signedData2 = (SignedDataStream)cis2.getContent();  
                        InputStream contentStream = signedData2.getInputStream();

                        byte[] read = new byte[10240];

                        int byteRead;
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();

                        while((byteRead = contentStream.read(read)) > 0){
                            baos.write(read,0,byteRead);
                        }

                        SignerInfo[] signerInfos = signedData2.getSignerInfos();
                        System.out.println(pathout+"\n\n"+signerInfos[0].toString());

                        for (int i=0; i < signerInfos.length; i++){
                            try
                            {
                                X509Certificate signerCertificate = signedData.verify(i);
                            }
                            catch (SignatureException ex)
                            {
                                try {
                                    System.out.println("Signature ERROR from signer with certificate: "+signedData.getCertificate(signerInfos[i].getIssuerAndSerialNumber()));

                                } catch (PKCSException e) {
                                    e.printStackTrace();
                                }
                                ex.printStackTrace();
                            }
                        }
                    }
                    else
                    {
                        System.out.println("errore, ci aspettiamo un SignedData");
                    }
                }
            }
        }


    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (CodingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (SignatureException e) {
        e.printStackTrace();
    } catch (PKCSException e) {
        e.printStackTrace();
    }

}

我收到以下错误:

  

java.security.SignatureException:签名验证错误:消息哈希!
      at iaik.pkcs.pkcs7.SignedDataStream.verify(Unknown Source)
      在message.PKCS7.main(PKCS7.java:183)

为了完整性,我插入了创建的Signinfo:

  

版本:1
  序列号:231944
  发行人:CN = .........,OU = .........,O = ......,C = IT
  digest_algorithm:SHA(1.3.14.3.2.26)
  digest_encryption_algorithm:rsaEncryption(1.2.840.113549.1.1.1)
  encrypted_digest:128字节[7E:B4:19:95:77 ...]
  authenticated_attributes:
  的contentType:
  OBJECT ID = PKCS#7数据
  signingTime:
  UTCTime = 130625105430Z
  消息摘要:
  OCTET STRING = 20字节:C8:2C:9A:77:2E ...

有人可以帮助我吗?

0 个答案:

没有答案