Sign data using PKCS #7 in JAVA

前端 未结 2 1900
后悔当初
后悔当初 2020-12-30 07:05

I want to sign a text file (may be a .exe file or something else in the future) using PKCS#7 and verify the signature using Java.

  1. What do I need
相关标签:
2条回答
  • 2020-12-30 07:50

    I reckon you need the following 2 Bouncy Castle jars to generate the PKCS7 digital signature:

    • bcprov-jdk15on-147.jar (for JDK 1.5 - JDK 1.7)

    • bcmail-jdk15on-147.jar (for JDK 1.5 - JDK 1.7)

    You can download the Bouncy Castle jars from here.

    You need to setup your keystore with the public & private key pair. You need only the private key to generate the digital signature & the public key to verify it.

    Here's how you'd pkcs7 sign content (Exception handling omitted for brevity) :

    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.Security;
    import java.security.cert.Certificate;
    import java.security.cert.X509Certificate;
    import java.util.ArrayList;
    import java.util.List;
    import org.bouncycastle.cert.jcajce.JcaCertStore;
    import org.bouncycastle.cms.CMSProcessableByteArray;
    import org.bouncycastle.cms.CMSSignedData;
    import org.bouncycastle.cms.CMSSignedDataGenerator;
    import org.bouncycastle.cms.CMSTypedData;
    import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.operator.ContentSigner;
    import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
    import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
    import org.bouncycastle.util.Store;
    import org.bouncycastle.util.encoders.Base64;
    
    public final class PKCS7Signer {
    
        private static final String PATH_TO_KEYSTORE = "/path/to/keyStore";
        private static final String KEY_ALIAS_IN_KEYSTORE = "My_Private_Key";
        private static final String KEYSTORE_PASSWORD = "MyPassword";
        private static final String SIGNATUREALGO = "SHA1withRSA";
    
        public PKCS7Signer() {
        }
    
        KeyStore loadKeyStore() throws Exception {
    
            KeyStore keystore = KeyStore.getInstance("JKS");
            InputStream is = new FileInputStream(PATH_TO_KEYSTORE);
            keystore.load(is, KEYSTORE_PASSWORD.toCharArray());
            return keystore;
        }
    
        CMSSignedDataGenerator setUpProvider(final KeyStore keystore) throws Exception {
    
            Security.addProvider(new BouncyCastleProvider());
    
            Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(KEY_ALIAS_IN_KEYSTORE);
    
            final List<Certificate> certlist = new ArrayList<Certificate>();
    
            for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
                certlist.add(certchain[i]);
            }
    
            Store certstore = new JcaCertStore(certlist);
    
            Certificate cert = keystore.getCertificate(KEY_ALIAS_IN_KEYSTORE);
    
            ContentSigner signer = new JcaContentSignerBuilder(SIGNATUREALGO).setProvider("BC").
                    build((PrivateKey) (keystore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray())));
    
            CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    
            generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
                    build()).build(signer, (X509Certificate) cert));
    
            generator.addCertificates(certstore);
    
            return generator;
        }
    
        byte[] signPkcs7(final byte[] content, final CMSSignedDataGenerator generator) throws Exception {
    
            CMSTypedData cmsdata = new CMSProcessableByteArray(content);
            CMSSignedData signeddata = generator.generate(cmsdata, true);
            return signeddata.getEncoded();
        }
    
        public static void main(String[] args) throws Exception {
    
            PKCS7Signer signer = new PKCS7Signer();
            KeyStore keyStore = signer.loadKeyStore();
            CMSSignedDataGenerator signatureGenerator = signer.setUpProvider(keyStore);
            String content = "some bytes to be signed";
            byte[] signedBytes = signer.signPkcs7(content.getBytes("UTF-8"), signatureGenerator);
            System.out.println("Signed Encoded Bytes: " + new String(Base64.encode(signedBytes)));
        }
    }
    
    0 讨论(0)
  • 2020-12-30 07:57

    PKCS#7 is known as CMS now (Cryptographic Message Syntax), and you will need the Bouncy Castle PKIX libraries to create one. It has ample documentation and a well established mailing list.

    I won't supply code snippet, it is against house rules. Try yourself first.

    0 讨论(0)
提交回复
热议问题