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:
		
							parent
							
								
									dc349c17a8
								
							
						
					
					
						commit
						7489cf6eff
					
				| @ -600,6 +600,21 @@ | |||||||
|             <artifactId>caffeine</artifactId> |             <artifactId>caffeine</artifactId> | ||||||
|             <version>${caffeine.version}</version> |             <version>${caffeine.version}</version> | ||||||
|         </dependency> |         </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> |     </dependencies> | ||||||
|     <repositories> |     <repositories> | ||||||
|         <repository> |         <repository> | ||||||
|  | |||||||
| @ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								libraries/src/main/resources/Baeldung.cer
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								libraries/src/main/resources/Baeldung.cer
									
									
									
									
									
										Normal 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----- | ||||||
							
								
								
									
										
											BIN
										
									
								
								libraries/src/main/resources/Baeldung.p12
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								libraries/src/main/resources/Baeldung.p12
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -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); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user