Skip to content

Commit 7489cf6

Browse files
nabylapivovarit
authored andcommitted
PR Bouncycastle article (eugenp#2882)
* Add bouncycastle depedencies * Add certificate and private key to resources folder * add bouncycastle code sample * Add bouncycastle test
1 parent dc349c1 commit 7489cf6

5 files changed

Lines changed: 199 additions & 0 deletions

File tree

libraries/pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,21 @@
600600
<artifactId>caffeine</artifactId>
601601
<version>${caffeine.version}</version>
602602
</dependency>
603+
<dependency>
604+
<groupId>org.bouncycastle</groupId>
605+
<artifactId>bcprov-jdk15on</artifactId>
606+
<version>1.58</version>
607+
</dependency>
608+
<dependency>
609+
<groupId>org.bouncycastle</groupId>
610+
<artifactId>bcprov-jdk15on</artifactId>
611+
<version>1.58</version>
612+
</dependency>
613+
<dependency>
614+
<groupId>org.bouncycastle</groupId>
615+
<artifactId>bcpkix-jdk15on</artifactId>
616+
<version>1.58</version>
617+
</dependency>
603618
</dependencies>
604619
<repositories>
605620
<repository>
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.baeldung.bouncycastle;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
5+
import java.security.PrivateKey;
6+
import java.security.cert.CertificateEncodingException;
7+
import java.security.cert.CertificateException;
8+
import java.security.cert.X509Certificate;
9+
import java.util.ArrayList;
10+
import java.util.Collection;
11+
import java.util.Iterator;
12+
import java.util.List;
13+
14+
import org.bouncycastle.asn1.ASN1InputStream;
15+
import org.bouncycastle.asn1.cms.ContentInfo;
16+
import org.bouncycastle.cert.X509CertificateHolder;
17+
import org.bouncycastle.cert.jcajce.JcaCertStore;
18+
import org.bouncycastle.cms.CMSAlgorithm;
19+
import org.bouncycastle.cms.CMSEnvelopedData;
20+
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
21+
import org.bouncycastle.cms.CMSException;
22+
import org.bouncycastle.cms.CMSProcessableByteArray;
23+
import org.bouncycastle.cms.CMSSignedData;
24+
import org.bouncycastle.cms.CMSSignedDataGenerator;
25+
import org.bouncycastle.cms.CMSTypedData;
26+
import org.bouncycastle.cms.KeyTransRecipientInformation;
27+
import org.bouncycastle.cms.RecipientInformation;
28+
import org.bouncycastle.cms.SignerInformation;
29+
import org.bouncycastle.cms.SignerInformationStore;
30+
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
31+
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
32+
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
33+
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
34+
import org.bouncycastle.cms.jcajce.JceKeyTransRecipient;
35+
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
36+
import org.bouncycastle.operator.ContentSigner;
37+
import org.bouncycastle.operator.OperatorCreationException;
38+
import org.bouncycastle.operator.OutputEncryptor;
39+
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
40+
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
41+
import org.bouncycastle.util.Store;
42+
43+
public class BouncyCastleCrypto {
44+
45+
public static byte[] signData(byte[] data, final X509Certificate signingCertificate, final PrivateKey signingKey)
46+
throws CertificateEncodingException, OperatorCreationException, CMSException, IOException {
47+
byte[] signedMessage = null;
48+
List<X509Certificate> certList = new ArrayList<X509Certificate>();
49+
CMSTypedData cmsData = new CMSProcessableByteArray(data);
50+
certList.add(signingCertificate);
51+
Store certs = new JcaCertStore(certList);
52+
CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator();
53+
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withRSA").build(signingKey);
54+
cmsGenerator.addSignerInfoGenerator(
55+
new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
56+
.build(contentSigner, signingCertificate));
57+
cmsGenerator.addCertificates(certs);
58+
CMSSignedData cms = cmsGenerator.generate(cmsData, true);
59+
signedMessage = cms.getEncoded();
60+
return signedMessage;
61+
}
62+
63+
public static boolean verifSignData(final byte[] signedData)
64+
throws CMSException, IOException, OperatorCreationException, CertificateException {
65+
ByteArrayInputStream bIn = new ByteArrayInputStream(signedData);
66+
ASN1InputStream aIn = new ASN1InputStream(bIn);
67+
CMSSignedData s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
68+
aIn.close();
69+
bIn.close();
70+
Store certs = s.getCertificates();
71+
SignerInformationStore signers = s.getSignerInfos();
72+
Collection<SignerInformation> c = signers.getSigners();
73+
SignerInformation signer = c.iterator().next();
74+
Collection<X509CertificateHolder> certCollection = certs.getMatches(signer.getSID());
75+
Iterator<X509CertificateHolder> certIt = certCollection.iterator();
76+
X509CertificateHolder certHolder = certIt.next();
77+
boolean verifResult = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certHolder));
78+
if (!verifResult) {
79+
return false;
80+
}
81+
return true;
82+
}
83+
84+
public static byte[] encryptData(final byte[] data, X509Certificate encryptionCertificate)
85+
throws CertificateEncodingException, CMSException, IOException {
86+
byte[] encryptedData = null;
87+
if (null != data && null != encryptionCertificate) {
88+
CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator();
89+
JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate);
90+
cmsEnvelopedDataGenerator.addRecipientInfoGenerator(jceKey);
91+
CMSTypedData msg = new CMSProcessableByteArray(data);
92+
OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC")
93+
.build();
94+
CMSEnvelopedData cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(msg, encryptor);
95+
encryptedData = cmsEnvelopedData.getEncoded();
96+
}
97+
return encryptedData;
98+
}
99+
100+
public static byte[] decryptData(final byte[] encryptedData, final PrivateKey decryptionKey) throws CMSException {
101+
byte[] decryptedData = null;
102+
if (null != encryptedData && null != decryptionKey) {
103+
CMSEnvelopedData envelopedData = new CMSEnvelopedData(encryptedData);
104+
Collection<RecipientInformation> recip = envelopedData.getRecipientInfos().getRecipients();
105+
KeyTransRecipientInformation recipientInfo = (KeyTransRecipientInformation) recip.iterator().next();
106+
JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(decryptionKey);
107+
decryptedData = recipientInfo.getContent(recipient);
108+
}
109+
return decryptedData;
110+
}
111+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
3+
BAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREw
4+
DwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRa
5+
MEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNh
6+
YmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
7+
ADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMh
8+
jozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oM
9+
AYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6Iujr
10+
CZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSj
11+
fs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IV
12+
whgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADAR
13+
BglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IB
14+
AQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1
15+
vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAP
16+
pHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhU
17+
CGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJt
18+
XJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxU
19+
ia7y5BL6uOa/4ShSV8pcJDYz
20+
-----END CERTIFICATE-----
2.44 KB
Binary file not shown.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.baeldung.bouncycastle;
2+
3+
import static org.junit.Assert.assertTrue;
4+
5+
import java.io.FileInputStream;
6+
import java.io.IOException;
7+
import java.security.KeyStore;
8+
import java.security.KeyStoreException;
9+
import java.security.NoSuchAlgorithmException;
10+
import java.security.NoSuchProviderException;
11+
import java.security.PrivateKey;
12+
import java.security.Security;
13+
import java.security.UnrecoverableKeyException;
14+
import java.security.cert.CertificateException;
15+
import java.security.cert.CertificateFactory;
16+
import java.security.cert.X509Certificate;
17+
18+
import org.bouncycastle.cms.CMSException;
19+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
20+
import org.bouncycastle.operator.OperatorCreationException;
21+
import org.junit.Test;
22+
23+
public class BouncyCastleLiveTest {
24+
25+
String certificatePath = "src/main/resources/Baeldung.cer";
26+
String privateKeyPath = "src/main/resources/Baeldung.p12";
27+
char[] p12Password = "password".toCharArray();
28+
char[] keyPassword = "password".toCharArray();
29+
30+
@Test
31+
public void givenCryptographicResource_whenOperationSuccess_returnTrue()
32+
throws CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException,
33+
KeyStoreException, UnrecoverableKeyException, CMSException, OperatorCreationException {
34+
Security.addProvider(new BouncyCastleProvider());
35+
36+
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
37+
X509Certificate certificate = (X509Certificate) certFactory
38+
.generateCertificate(new FileInputStream(certificatePath));
39+
KeyStore keystore = KeyStore.getInstance("PKCS12");
40+
keystore.load(new FileInputStream(privateKeyPath), p12Password);
41+
PrivateKey privateKey = (PrivateKey) keystore.getKey("baeldung", keyPassword);
42+
String secretMessage = "My password is 123456Seven";
43+
System.out.println("Original Message : " + secretMessage);
44+
byte[] stringToEncrypt = secretMessage.getBytes();
45+
byte[] encryptedData = BouncyCastleCrypto.encryptData(stringToEncrypt, certificate);
46+
byte[] rawData = BouncyCastleCrypto.decryptData(encryptedData, privateKey);
47+
String decryptedMessage = new String(rawData);
48+
assertTrue(decryptedMessage.equals(secretMessage));
49+
byte[] signedData = BouncyCastleCrypto.signData(rawData, certificate, privateKey);
50+
Boolean check = BouncyCastleCrypto.verifSignData(signedData);
51+
assertTrue(check);
52+
}
53+
}

0 commit comments

Comments
 (0)