PKCS#7 Encryption and Decryption

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

PKCS#7 Encryption and Decryption

arvindpurohit
Hi All,

I want to encrypt and decrypt data using PKCS#7
Can anybody please help me.
I think CMSEncryptedGenerator  class i need to use, but i am not getting any document how to use it.
Code snippet will be a great help to me. 


Thanks A  Lot
Arvind
Reply | Threaded
Open this post in threaded view
|

Re: PKCS#7 Encryption and Decryption

David Hook-2

There are plenty of examples in the test class sources.

For general info on the library also start with:

http://www.bouncycastle.org/documentation.html

and

http://www.bouncycastle.org/wiki/display/JA1/BC+Version+2+APIs


Regards,

David

On 20/06/12 15:45, Arvind Purohit wrote:
Hi All,

I want to encrypt and decrypt data using PKCS#7
Can anybody please help me.
I think CMSEncryptedGenerator  class i need to use, but i am not getting any document how to use it.
Code snippet will be a great help to me. 


Thanks A  Lot
Arvind

Reply | Threaded
Open this post in threaded view
|

Re: AES/GCM with Associated Data

Hanson Char
Hi,

I don't seem to find any example of performing authenticated encryption with associated data in the BC (1.4.7) library/example.  So I went ahead and try to come up with some sample code in the form of a unit test below.  Can someone have a look to see if I am using the classes in the right way ?

Thanks,
Hanson

package org.bouncycastle.crypto.modes;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.junit.Test;

/**
 * @author Hanson Char
 */
public class GCMBlockCipherTest {
    private static final SecureRandom rand = new SecureRandom();
    private static final int MAC_SIZE = 128;
    private static final byte[] keybytes = new byte[16*2];
    private static final byte[] nouncebytes = new byte[16];
    private static final KeyParameter key = new KeyParameter(keybytes);
    private static final byte[] associatedText = "Some Associated Text".getBytes(StandardCharsets.UTF_8);
    private static final byte[] plaintext = "Some plaintext".getBytes(StandardCharsets.UTF_8);

    

    static {
         rand.nextBytes(keybytes); // a random key   
         rand.nextBytes(nouncebytes); // a random nounce
    }

    @Test
    public void testGCMEncryptDecryptWithAD() throws IllegalStateException, InvalidCipherTextException {
        System.out.println("plaintext: " + hex(plaintext));
        AEADParameters params = new AEADParameters(key, MAC_SIZE, nouncebytes, associatedText);
        byte[] ciphertext = encrypt(plaintext, params);
        System.out.println("ciphertext: " + hex(ciphertext));
        byte[] decrypted = decrypt(ciphertext, params);
        System.out.println("decrypted: " + hex(decrypted));
        System.out.println("nouce: " + hex(nouncebytes));
        assertTrue(Arrays.equals(plaintext, decrypted));
    }

    @Test(expected=InvalidCipherTextException.class)
    public void testNounceMismatch() throws IllegalStateException, InvalidCipherTextException {
        AEADParameters params = new AEADParameters(key, MAC_SIZE, nouncebytes, associatedText);
        byte[] ciphertext = encrypt(plaintext, params);
        AEADParameters params2 = new AEADParameters(key, MAC_SIZE, new byte[16], associatedText);
        try {
            decrypt(ciphertext, params2);
            fail();
        } catch(InvalidCipherTextException ex) {
            ex.getMessage().contains("mac check in GCM failed");
            throw ex;
        }
    }

    

    @Test(expected=InvalidCipherTextException.class)
    public void testADMismatch() throws IllegalStateException, InvalidCipherTextException {
        AEADParameters params = new AEADParameters(key, MAC_SIZE, nouncebytes, associatedText);
        byte[] ciphertext = encrypt(plaintext, params);
        AEADParameters params2 = new AEADParameters(key, MAC_SIZE, nouncebytes, new byte[16]);
        try {
            decrypt(ciphertext, params2);
            fail();
        } catch(InvalidCipherTextException ex) {
            ex.getMessage().contains("mac check in GCM failed");
            throw ex;
        }
    }

    private byte[] encrypt(byte[] plaintext, AEADParameters params) throws InvalidCipherTextException {
        GCMBlockCipher gcm = new GCMBlockCipher(new AESEngine());
        gcm.init(true, params);
        int outsize = gcm.getOutputSize(plaintext.length);
        byte[] out = new byte[outsize];
        int offOut = gcm.processBytes(plaintext, 0, plaintext.length, out, 0);
        gcm.doFinal(out, offOut);
        return out;
    }

    private byte[] decrypt(byte[] ciphertext, AEADParameters params) throws InvalidCipherTextException {
        GCMBlockCipher gcm = new GCMBlockCipher(new AESEngine());
        gcm.init(false, params);
        int outsize2 = gcm.getOutputSize(ciphertext.length);
        byte[] out2 = new byte[outsize2];
        int offOut = gcm.processBytes(ciphertext, 0, ciphertext.length, out2, 0);
        gcm.doFinal(out2, offOut);
        return out2;
    }

    private static String hex(byte[] values) {
        return new HexBinaryAdapter().marshal(values);
    }
}

Reply | Threaded
Open this post in threaded view
|

Re: PKCS#7 Encryption and Decryption

arvindpurohit
In reply to this post by David Hook-2
Thanks David,

I am using book Beginning cryptography with java and found example to encrypt and sign
But when i am trying to write this encrypted data to file and  read and decrypt and verify sign from file it is giving me this exception
org.bouncycastle.cms.CMSException: message-digest attribute value does not match calculated value

My code is below
======== Part 1 ====================
public class Test {
    private static final char[] KEY_STORE_PASSWORD = "123456".toCharArray();
    private static final long VALIDITY_PERIOD = 365 * 24 * 60 * 60 * 1000;
    private static final char[] KEY_PASSWORD = "keyPassword".toCharArray();
    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";
    public static void main(String[] args)  {
        try{
        // CREATE KEY STORE
        KeyStore keyStore = createKeyStore();
        // STEP 1. ENCRYPT AND SIGN
        byte[] step1Data = encryptData(keyStore, PLAIN_TEXT.getBytes());
        CMSSignedData cmsSignedData = signData(keyStore,step1Data);
        new File("D:\\pkcs7\\encrypted-file.p7b");
        FileOutputStream fileOuputStream = new FileOutputStream("D:\\pkcs7\\encrypted-file.p7b");
        fileOuputStream.write(cmsSignedData.getEncoded());
        fileOuputStream.flush();
        fileOuputStream.close();
        // STEP 2. READ ENCRYPTED DATA AND VERIFY SIGN AND DECRYPT IT
        File file =new File("D:\\pkcs7\\encrypted-file.p7b");
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] encryptedAndSignedByte = new byte[(int)file.length()];
        fileInputStream.read(encryptedAndSignedByte );
        fileInputStream.close();
        cmsSignedData =  new CMSSignedData(encryptedAndSignedByte);
        if( verifyData(keyStore, cmsSignedData) == true ){
            decryptData(keyStore,encryptedAndSignedByte);
        }
        }catch (Exception e) {
            e.printStackTrace();
        }
}
/**
     * This method will encrypt data
     */
    private static byte[] encryptData(KeyStore keyStore, byte[] plainData) throws Exception {
        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,
                KEY_PASSWORD);
        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        X509Certificate cert = (X509Certificate) chain[0];
        // set up the generator
        CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();
        gen.addKeyTransRecipient(cert);
        // create the enveloped-data object
        CMSProcessable data = new CMSProcessableByteArray(plainData);
        CMSEnvelopedData enveloped = gen.generate(data,
                CMSEnvelopedDataGenerator.AES128_CBC, "BC");
        return  enveloped.getEncoded();
    }
    private static byte[] decryptData(KeyStore keyStore,byte[] encryptedData) throws Exception{
        CMSEnvelopedDataParser envelopedDataParser = new CMSEnvelopedDataParser(new ByteArrayInputStream(encryptedData));
        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,KEY_PASSWORD);
        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        X509Certificate cert = (X509Certificate) chain[0];
        CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedData);
        RecipientId recId = new RecipientId();
        recId.setSerialNumber(cert.getSerialNumber());
        recId.setIssuer(cert.getIssuerX500Principal().getEncoded());
        RecipientInformationStore recipients = enveloped.getRecipientInfos();
        RecipientInformation recipient = recipients.get(recId);
        if (recipient != null) {
            // decrypt the data
            byte[] recData = recipient.getContent(key, "BC");
            System.out.println(new String(recData));
            return recData;
        } else {
            System.out.println("could not find a matching recipient");
        }
        return null;
    }
    private static CMSSignedData signData(KeyStore keyStore,byte[] encryptedData ) 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(encryptedData);
        CMSSignedData signed = gen.generate(data, "BC");
        // recreate
        signed = new CMSSignedData(data, signed.getEncoded());
        return signed;
    }
    private static boolean verifyData(KeyStore keyStore, CMSSignedData signed)
            throws Exception {
        X509Certificate rootCert = (X509Certificate) keyStore.getCertificate(ROOT_ALIAS);
        if (isValidSignature(signed, rootCert)) {
            return true;
        } else {
        }
        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.
     */
    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);
    }


From: David Hook <[hidden email]>
To: "[hidden email]" <[hidden email]>
Sent: Thursday, 21 June 2012 2:46 AM
Subject: Re: [dev-crypto] PKCS#7 Encryption and Decryption


There are plenty of examples in the test class sources.

For general info on the library also start with:

http://www.bouncycastle.org/documentation.html

and

http://www.bouncycastle.org/wiki/display/JA1/BC+Version+2+APIs


Regards,

David

On 20/06/12 15:45, Arvind Purohit wrote:
Hi All,

I want to encrypt and decrypt data using PKCS#7
Can anybody please help me.
I think CMSEncryptedGenerator  class i need to use, but i am not getting any document how to use it.
Code snippet will be a great help to me. 


Thanks A  Lot
Arvind



Reply | Threaded
Open this post in threaded view
|

Re: PKCS#7 Encryption and Decryption

arvindpurohit
In reply to this post by David Hook-2
Thanks David,

I am using book Beginning cryptography with java and found example to encrypt and sign
But when i am trying to write this encrypted data to file and  read and decrypt and verify sign from file it is giving me this exception
org.bouncycastle.cms.CMSException: message-digest attribute value does not match calculated value

==== My code part 2 ================

    public static KeyStore createKeyStore() throws Exception {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null, null);
        X500PrivateCredential rootCredential = createRootCredential();
        X500PrivateCredential interCredential = createIntermediateCredential(
                rootCredential.getPrivateKey(), rootCredential.getCertificate());
        X500PrivateCredential endCredential = createEndEntityCredential(
                interCredential.getPrivateKey(),
                interCredential.getCertificate());
        keyStore.setCertificateEntry(rootCredential.getAlias(),
                rootCredential.getCertificate());
        keyStore.setKeyEntry(
                endCredential.getAlias(),
                endCredential.getPrivateKey(),
                KEY_PASSWORD,
                new Certificate[] { endCredential.getCertificate(),
                        interCredential.getCertificate(),
                        rootCredential.getCertificate() });
        keyStore.store(new FileOutputStream("d:\\pkcs7\\KeyStore.jks"),
                KEY_STORE_PASSWORD);
        return keyStore;
    }
    public static KeyPair generateRSAKeyPair() throws Exception {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
        kpGen.initialize(1024, new SecureRandom());
        return kpGen.generateKeyPair();
    }
    public static X509Certificate generateCertificate(KeyPair pair)
            throws Exception {
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setPublicKey(pair.getPublic());
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
    }
    public static X509Certificate generateRootCert(KeyPair pair)
            throws Exception {
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setPublicKey(pair.getPublic());
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
    }
    public static X509Certificate generateEndEntityCert(PublicKey entityKey,
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(caCert.getSubjectX500Principal());
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test End Certificate"));
        certGen.setPublicKey(entityKey);
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
                new AuthorityKeyIdentifierStructure(caCert));
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
                new SubjectKeyIdentifierStructure(entityKey));
        certGen.addExtension(X509Extensions.BasicConstraints, true,
                new BasicConstraints(false));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(
                KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

        return certGen.generateX509Certificate(caKey, "BC");
    }
    public static X500PrivateCredential createRootCredential() throws Exception {
        KeyPair rootPair = generateRSAKeyPair();
        X509Certificate rootCert = generateRootCert(rootPair);

        return new X500PrivateCredential(rootCert, rootPair.getPrivate(),
                ROOT_ALIAS);
    }
    public static X500PrivateCredential createIntermediateCredential(
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        KeyPair interPair = generateRSAKeyPair();
        X509Certificate interCert = generateIntermediateCert(
                interPair.getPublic(), caKey, caCert);

        return new X500PrivateCredential(interCert, interPair.getPrivate(),
                INTERMEDIATE_ALIAS);
    }
    public static X500PrivateCredential createEndEntityCredential(
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        KeyPair endPair = generateRSAKeyPair();
        X509Certificate endCert = generateEndEntityCert(endPair.getPublic(),
                caKey, caCert);

        return new X500PrivateCredential(endCert, endPair.getPrivate(),
                END_ENTITY_ALIAS);
    }
    public static X509Certificate generateIntermediateCert(PublicKey intKey,
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(caCert.getSubjectX500Principal());
        certGen.setNotBefore(new Date(System.currentTimeMillis()));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal(
                "CN=Test Intermediate Certificate"));
        certGen.setPublicKey(intKey);
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
                new AuthorityKeyIdentifierStructure(caCert));
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
                new SubjectKeyIdentifierStructure(intKey));
        certGen.addExtension(X509Extensions.BasicConstraints, true,
                new BasicConstraints(0));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(
                KeyUsage.digitalSignature | KeyUsage.keyCertSign
                        | KeyUsage.cRLSign));
        return certGen.generateX509Certificate(caKey, "BC");
    }
}



From: David Hook <[hidden email]>
To: "[hidden email]" <[hidden email]>
Sent: Thursday, 21 June 2012 2:46 AM
Subject: Re: [dev-crypto] PKCS#7 Encryption and Decryption


There are plenty of examples in the test class sources.

For general info on the library also start with:

http://www.bouncycastle.org/documentation.html

and

http://www.bouncycastle.org/wiki/display/JA1/BC+Version+2+APIs


Regards,

David

On 20/06/12 15:45, Arvind Purohit wrote:
Hi All,

I want to encrypt and decrypt data using PKCS#7
Can anybody please help me.
I think CMSEncryptedGenerator  class i need to use, but i am not getting any document how to use it.
Code snippet will be a great help to me. 


Thanks A  Lot
Arvind