PR Bouncycastle article (#2882)

* Add bouncycastle depedencies

* Add certificate and private key to resources folder

* add bouncycastle code sample

* Add bouncycastle test
This commit is contained in:
nabyla 2017-10-27 10:46:29 +01:00 committed by Grzegorz Piwowarek
parent dc349c17a8
commit 7489cf6eff
5 changed files with 199 additions and 0 deletions

View File

@ -600,6 +600,21 @@
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.58</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.58</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.58</version>
</dependency>
</dependencies>
<repositories>
<repository>

View File

@ -0,0 +1,111 @@
package com.baeldung.bouncycastle;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.KeyTransRecipientInformation;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipient;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
public class BouncyCastleCrypto {
public static byte[] signData(byte[] data, final X509Certificate signingCertificate, final PrivateKey signingKey)
throws CertificateEncodingException, OperatorCreationException, CMSException, IOException {
byte[] signedMessage = null;
List<X509Certificate> certList = new ArrayList<X509Certificate>();
CMSTypedData cmsData = new CMSProcessableByteArray(data);
certList.add(signingCertificate);
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withRSA").build(signingKey);
cmsGenerator.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
.build(contentSigner, signingCertificate));
cmsGenerator.addCertificates(certs);
CMSSignedData cms = cmsGenerator.generate(cmsData, true);
signedMessage = cms.getEncoded();
return signedMessage;
}
public static boolean verifSignData(final byte[] signedData)
throws CMSException, IOException, OperatorCreationException, CertificateException {
ByteArrayInputStream bIn = new ByteArrayInputStream(signedData);
ASN1InputStream aIn = new ASN1InputStream(bIn);
CMSSignedData s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
aIn.close();
bIn.close();
Store certs = s.getCertificates();
SignerInformationStore signers = s.getSignerInfos();
Collection<SignerInformation> c = signers.getSigners();
SignerInformation signer = c.iterator().next();
Collection<X509CertificateHolder> certCollection = certs.getMatches(signer.getSID());
Iterator<X509CertificateHolder> certIt = certCollection.iterator();
X509CertificateHolder certHolder = certIt.next();
boolean verifResult = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certHolder));
if (!verifResult) {
return false;
}
return true;
}
public static byte[] encryptData(final byte[] data, X509Certificate encryptionCertificate)
throws CertificateEncodingException, CMSException, IOException {
byte[] encryptedData = null;
if (null != data && null != encryptionCertificate) {
CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator();
JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate);
cmsEnvelopedDataGenerator.addRecipientInfoGenerator(jceKey);
CMSTypedData msg = new CMSProcessableByteArray(data);
OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC")
.build();
CMSEnvelopedData cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(msg, encryptor);
encryptedData = cmsEnvelopedData.getEncoded();
}
return encryptedData;
}
public static byte[] decryptData(final byte[] encryptedData, final PrivateKey decryptionKey) throws CMSException {
byte[] decryptedData = null;
if (null != encryptedData && null != decryptionKey) {
CMSEnvelopedData envelopedData = new CMSEnvelopedData(encryptedData);
Collection<RecipientInformation> recip = envelopedData.getRecipientInfos().getRecipients();
KeyTransRecipientInformation recipientInfo = (KeyTransRecipientInformation) recip.iterator().next();
JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(decryptionKey);
decryptedData = recipientInfo.getContent(recipient);
}
return decryptedData;
}
}

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
BAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREw
DwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRa
MEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNh
YmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMh
jozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oM
AYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6Iujr
CZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSj
fs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IV
whgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADAR
BglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IB
AQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1
vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAP
pHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhU
CGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJt
XJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxU
ia7y5BL6uOa/4ShSV8pcJDYz
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -0,0 +1,53 @@
package com.baeldung.bouncycastle;
import static org.junit.Assert.assertTrue;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.junit.Test;
public class BouncyCastleLiveTest {
String certificatePath = "src/main/resources/Baeldung.cer";
String privateKeyPath = "src/main/resources/Baeldung.p12";
char[] p12Password = "password".toCharArray();
char[] keyPassword = "password".toCharArray();
@Test
public void givenCryptographicResource_whenOperationSuccess_returnTrue()
throws CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException,
KeyStoreException, UnrecoverableKeyException, CMSException, OperatorCreationException {
Security.addProvider(new BouncyCastleProvider());
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
X509Certificate certificate = (X509Certificate) certFactory
.generateCertificate(new FileInputStream(certificatePath));
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(privateKeyPath), p12Password);
PrivateKey privateKey = (PrivateKey) keystore.getKey("baeldung", keyPassword);
String secretMessage = "My password is 123456Seven";
System.out.println("Original Message : " + secretMessage);
byte[] stringToEncrypt = secretMessage.getBytes();
byte[] encryptedData = BouncyCastleCrypto.encryptData(stringToEncrypt, certificate);
byte[] rawData = BouncyCastleCrypto.decryptData(encryptedData, privateKey);
String decryptedMessage = new String(rawData);
assertTrue(decryptedMessage.equals(secretMessage));
byte[] signedData = BouncyCastleCrypto.signData(rawData, certificate, privateKey);
Boolean check = BouncyCastleCrypto.verifSignData(signedData);
assertTrue(check);
}
}