Unable to verify the Signature with two different mechanism

心已入冬 提交于 2021-02-11 12:41:01

问题


I have two clients,

  1. first client expect CMS/PKCS to verify signature
  2. second client expect only signature (EncryptedDigestMessage). Original file and certificate separately to verify signature

So, I want to create one method that should return the appropriate output based on format (PKCS or SignOnly)

public static byte[] digitalSign(byte[] fileContent , PrivateKey privkey , X509Certificate x509Certificate , String format) throws Exception{

        Security.addProvider(new BouncyCastleProvider());
        List<X509Certificate> certList = new ArrayList<X509Certificate>();
        CMSTypedData data = new CMSProcessableByteArray(fileContent);
        certList.add(x509Certificate);
        Store certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner sha1Signer = new JcaContentSignerBuilder("MD5WithRSA").setProvider("BC").build(privkey);
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(sha1Signer,x509Certificate));
        gen.addCertificates(certs);
        CMSSignedData signedData = gen.generate(data, true);
        
        //based on the format this method should return expected byte[]
        if(format.equals("PKCS")){//should return CMS/PKCS package
            return signedData.getEncoded();
        }else{//should return only Signature (Encrypted Digest of fileContent)
            SignerInformation signer = signedData.getSignerInfos().getSigners().iterator().next();
            return signer.getSignature();// returns the Signature
        }
    }

I verified PKCS using below method. signature is verified it returns true.

//CMS/PKCS signature verification
    public static boolean verfySignaturePKCS(byte[] cmsSignedBytes ) throws Exception{
        boolean result = false;
        Security.addProvider(new BouncyCastleProvider());
        CMSSignedData cms =new CMSSignedData(cmsSignedBytes );
        Store<X509CertificateHolder> certificates = cms.getCertificates();
        
        SignerInformationStore signerInfos = cms.getSignerInfos();
        Collection<SignerInformation> signers = signerInfos.getSigners();
        Iterator<SignerInformation> iterator = signers.iterator();
        while (iterator.hasNext()) { 
            SignerInformation signer = iterator.next(); 
            Collection<X509CertificateHolder> certCollection = certificates.getMatches(signer.getSID()); 
            Iterator<X509CertificateHolder> certIt = certCollection.iterator(); 
            X509CertificateHolder certHolder = certIt.next(); 
            X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
            
            if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert))) {
                result = true; 
            }
        }
        return result;
    }

To verify that SignOnly data, I'm using normal Java security MessageDigest and Cipher classes.

parameters:

  1. signedData--> Signature
  2. fileBytes--> Original File content
  3. cert--> X509Certificate to decrypt the signature

method process:

  1. generate messageHash from original file content
  2. decrypt Signature with cert and get the decryptedMessageHash
  3. compare messageHash and decryptedMessageHash

In this way decrypt signature is going well without error. So I understand this is correct signature which is signed by my privatekey related to the given certificate. but, both messageHash and decryptedMessageHash having different data.

    public static boolean verifySignOnly(byte[] signedData,byte[] fileBytes ,X509Certificate cert) throws Exception{
        Security.addProvider(new BouncyCastleProvider());
        MessageDigest md = MessageDigest.getInstance("MD5" , "BC");
        byte[] messageHash = md.digest(fileBytes);
        Cipher cipher = Cipher.getInstance("RSA" , "BC");
        cipher.init(Cipher.DECRYPT_MODE, cert);
        byte[] decryptedMessageHash = cipher.doFinal(signedData);
        return Arrays.equals(decryptedMessageHash, messageHash);
        
    }

Can anyone explain what mistake I made?

来源:https://stackoverflow.com/questions/63287608/unable-to-verify-the-signature-with-two-different-mechanism

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!