PKCS#7签名

时间:2012-06-22 09:17:43

标签: java cryptography bouncycastle public-key-encryption pkcs#7

当我们使用以下类对数据进行签名时,我应该写什么来验证签名 org.bouncycastle.cms.CMSSignedData org.bouncycastle.cms.CMSSignedDataGenerator

非常感谢

我已经编写了代码来实现这一点,但我得到了异常

public class T2 {
    public static String ROOT_ALIAS = "root";
    public static String INTERMEDIATE_ALIAS = "intermediate";
    public static String END_ENTITY_ALIAS = "end";
    public static String PLAIN_TEXT = "Hello World!123";
    private static final char[] KEY_PASSWORD = "keyPassword".toCharArray();

    public static CMSSignedData signData(KeyStore keyStore,
            byte[] plainTextToSign) throws Exception {
        // GET THE PRIVATE KEY
        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,
                KEY_PASSWORD);

        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        CertStore certsAndCRLs = CertStore.getInstance("Collection",
                new CollectionCertStoreParameters(Arrays.asList(chain)), "BC");
        X509Certificate cert = (X509Certificate) chain[0];

        // set up the generator
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addSigner(key, cert, CMSSignedDataGenerator.DIGEST_SHA224);
        gen.addCertificatesAndCRLs(certsAndCRLs);

        // create the signed-data object
        CMSProcessable data = new CMSProcessableByteArray(plainTextToSign);
        CMSSignedData signed = gen.generate(data, "BC");

        // recreate
        signed = new CMSSignedData(data, signed.getEncoded());
        // ContentInfo conInf = signed.getContentInfo();
        // CMSProcessable sigContent = signed.getSignedContent();

        new File("D:\\pkcs7\\encrypted-file.p7b");
        FileOutputStream fileOuputStream = new FileOutputStream(
                "D:\\pkcs7\\encrypted-file.p7b");
        fileOuputStream.write(signed.getEncoded());
        // fileOuputStream.flush();
        fileOuputStream.close();
        return signed;
    }

    public static boolean verifyData(KeyStore keyStore) throws Exception {

        File file = new File("D:\\pkcs7\\encrypted-file.p7b");
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] signedByte = new byte[(int) file.length()];
        fileInputStream.read(signedByte);
        fileInputStream.close();

        // verification step
        X509Certificate rootCert = (X509Certificate) keyStore
                .getCertificate(ROOT_ALIAS);

        CMSSignedData signed = new CMSSignedData(signedByte);
        if (isValidSignature(signed, rootCert)) {
            System.out.println("verification succeeded");
            return true;
        } else {
            System.out.println("verification failed");
        }
        return false;
    }

    /**
     * Take a CMS SignedData message and a trust anchor and determine if the
     * message is signed with a valid signature from a end entity entity
     * certificate recognized by the trust anchor rootCert.
     */
    @SuppressWarnings("rawtypes")
    private static boolean isValidSignature(CMSSignedData signedData,
            X509Certificate rootCert) throws Exception {

        boolean[] bArr = new boolean[2];
        bArr[0] = true;
        CertStore certsAndCRLs = signedData.getCertificatesAndCRLs(
                "Collection", "BC");
        SignerInformationStore signers = signedData.getSignerInfos();
        Iterator it = signers.getSigners().iterator();

        if (it.hasNext()) {
            SignerInformation signer = (SignerInformation) it.next();
            SignerId signerConstraints = signer.getSID();
            signerConstraints.setKeyUsage(bArr);
            PKIXCertPathBuilderResult result = buildPath(rootCert,
                    signer.getSID(), certsAndCRLs);
            return signer.verify(result.getPublicKey(), "BC");
        }

        return false;
    }

    /**
     * Build a path using the given root as the trust anchor, and the passed in
     * end constraints and certificate store.
     * <p>
     * Note: the path is built with revocation checking turned off.
     */
    public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert,
            X509CertSelector endConstraints, CertStore certsAndCRLs)
            throws Exception {
        CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
        PKIXBuilderParameters buildParams = new PKIXBuilderParameters(
                Collections.singleton(new TrustAnchor(rootCert, null)),
                endConstraints);

        buildParams.addCertStore(certsAndCRLs);
        buildParams.setRevocationEnabled(false);

        return (PKIXCertPathBuilderResult) builder.build(buildParams);
    }
}

1 个答案:

答案 0 :(得分:0)

当签名包装时,您不需要向文件写入任何内容 - 签名操作的产物是包含签名包的数据。请注意,处理原始无符号数据的应用程序无法直接处理此类签名数据。例如。如果使用包装PKCS#7 / CMS签名对PDF文档进行签名,则Adobe Reader将无法直接打开签名数据(直到签名被删除)。通过将签名数据提供给验证程序来验证签名。

使用分离签名时,签名操作的产品是签名块本身,您可以将其存储在单独的文件中,或作为备用数据流存储在某些文件系统上或数据库中的单独字段中。在这种情况下,您的原始数据保持不变。通过将原始数据和签名块馈送到验证过程来验证签名。