Author: Paolo Lulli <paolo@lulli.net>
Refactoryng to return byte array
src/main/java/net/lulli/encrypt/Pems.java | 4 src/main/java/net/lulli/encrypt/pki/PkiEncryptionManager.java | 110 ++-- src/test/java/EncryptionTest.java | 65 +-
diff --git a/src/main/java/net/lulli/encrypt/Pems.java b/src/main/java/net/lulli/encrypt/Pems.java index a3b17952a3ddc7c7a3a0928a5b97084170b23cb5..6f818e6cba57f9a084e84c348663ed7334d89d50 100644 --- a/src/main/java/net/lulli/encrypt/Pems.java +++ b/src/main/java/net/lulli/encrypt/Pems.java @@ -76,7 +76,7 @@ byte[] encoded = Base64.getDecoder().decode(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); - return (PublicKey) keyFactory.generatePublic(keySpec); + return keyFactory.generatePublic(keySpec); } public static PrivateKey readPKCS8PrivateKey(String key) throws Exception { @@ -88,6 +88,6 @@ byte[] encoded = Base64.getDecoder().decode(privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); - return (PrivateKey) keyFactory.generatePrivate(keySpec); + return keyFactory.generatePrivate(keySpec); } } diff --git a/src/main/java/net/lulli/encrypt/pki/PkiEncryptionManager.java b/src/main/java/net/lulli/encrypt/pki/PkiEncryptionManager.java index 85744ba2155eb1b4aa28e6e07bb25a3a464391ae..0b876e9ddb57da97cdc24c45d4dc608663bdec2f 100644 --- a/src/main/java/net/lulli/encrypt/pki/PkiEncryptionManager.java +++ b/src/main/java/net/lulli/encrypt/pki/PkiEncryptionManager.java @@ -1,23 +1,22 @@ -/* +/* * This file is part of cert-encoder * Copyright (c) 2024 Paolo Lulli. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.lulli.encrypt.pki; -import net.lulli.encrypt.Pems; import org.bouncycastle.cert.jcajce.JcaCertStore; import org.bouncycastle.cms.*; import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; @@ -25,7 +24,6 @@ import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; 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; @@ -33,19 +31,19 @@ import org.bouncycastle.util.encoders.Base64; import java.io.*; import java.nio.file.Files; -import java.nio.file.Paths; import java.security.KeyStore; import java.security.PrivateKey; -import java.security.PublicKey; import java.security.Security; import java.security.cert.X509Certificate; import java.util.ArrayList; public class PkiEncryptionManager { public static final PkiEncryptionManager INSTANCE = new PkiEncryptionManager(); - private PkiEncryptionManager() {} - public void signFile(File fileToSign) { + private PkiEncryptionManager() { + } + + private void signFile(File fileToSign) { try { char[] password = "yourpass".toCharArray(); String certificateAlias = ""; @@ -62,7 +60,7 @@ String signatureFileName = fileToSign.getName().toString() + ".signature"; byte[] buffer = loadFileIntoBuffer(fileToSign); - byte[] signeddata = generateSignature(cert, cert.getPublicKey(), privatekey, buffer); + byte[] signeddata = sign(cert, privatekey, buffer); writeSignatureToFile(signatureFileName, signeddata); } catch (Exception e) { @@ -82,61 +80,75 @@ throw new IllegalStateException(e.getMessage()); } } - private static byte[] generateSignature(X509Certificate cert, PublicKey publicKey, PrivateKey privatekey, byte[] buffer) { + public byte[] sign(X509Certificate cert, PrivateKey privatekey, byte[] buffer) { try { + Security.addProvider(new BouncyCastleProvider()); ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); certList.add(cert); Store<?> certs = new JcaCertStore(certList); - CMSSignedDataGenerator signGen = new CMSSignedDataGenerator(); + var cmsSignedDataGenerator = new CMSSignedDataGenerator(); - ContentSigner sha1signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privatekey); - signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1signer, cert)); - signGen.addCertificates(certs); - CMSTypedData content = new CMSProcessableByteArray(buffer); - CMSSignedData signedData = signGen.generate(content, false); - byte[] signeddata = signedData.getEncoded(); - return signeddata; + var sha1signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privatekey); + cmsSignedDataGenerator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1signer, cert)); + cmsSignedDataGenerator.addCertificates(certs); + var cmsProcessableByteArray = new CMSProcessableByteArray(buffer); + var cmsSignedData = cmsSignedDataGenerator.generate(cmsProcessableByteArray, false); + return cmsSignedData.getEncoded(); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } - public byte[] encryptData(byte[] data, X509Certificate encryptionCertificate) { + public byte[] encrypt(byte[] data, X509Certificate x509Certificate) { try { Security.addProvider(new BouncyCastleProvider()); - if (null != data && null != encryptionCertificate) { - var cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator(); - - //JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate); - cmsEnvelopedDataGenerator.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(encryptionCertificate).setProvider("BC")); - var cmsProcessableByteArray = new CMSProcessableByteArray(data); - var outputEncryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build(); - var cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(cmsProcessableByteArray, outputEncryptor); - return cmsEnvelopedData.getEncoded(); + if ((null == data) || (null == x509Certificate)) { + throw new IllegalStateException("Null parameters"); } - return null; + var cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator(); + cmsEnvelopedDataGenerator.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(x509Certificate).setProvider("BC")); + + var cmsProcessableByteArray = new CMSProcessableByteArray(data); + var outputEncryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build(); + var cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(cmsProcessableByteArray, outputEncryptor); + return cmsEnvelopedData.getEncoded(); + } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } + public byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) { + try { + var decryptedStream = decryptToInputStream(privateKey, encryptedData); + return decryptedStream.readAllBytes(); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage()); + } + } - public void decryptCms(PrivateKey privateKey, byte[] encryptedData, String destinationFile) { + public void decryptToFile(PrivateKey privateKey, byte[] encryptedData, String destinationFile) { try { var decryptedDestination = new File(destinationFile); - //byte[] encryptedData = Files.readAllBytes(encrypted.toPath()); + var decryptedStream = decryptToInputStream(privateKey, encryptedData); + + Files.copy(decryptedStream, decryptedDestination.toPath()); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage()); + } + } + private InputStream decryptToInputStream(PrivateKey privateKey, byte[] encryptedData) { + try { + Security.addProvider(new BouncyCastleProvider()); var cmsEnvelopedDataParser = new CMSEnvelopedDataParser(encryptedData); var singleRecipient = getSingleRecipient(cmsEnvelopedDataParser); var jceKeyTransEnvelopedRecipient = new JceKeyTransEnvelopedRecipient(privateKey); - try (InputStream decryptedStream = singleRecipient.getContentStream(jceKeyTransEnvelopedRecipient).getContentStream()) { - Files.copy(decryptedStream, decryptedDestination.toPath()); - } + return singleRecipient.getContentStream(jceKeyTransEnvelopedRecipient).getContentStream(); - System.out.println(String.format("Decrypted to file :'%s'", decryptedDestination.getAbsolutePath())); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } @@ -177,20 +189,4 @@ } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } - - /* - public static void main(String[] args) throws Exception { - var plainText = "this is a sample text"; - X509Certificate x509Certificate = Pems.certificateFromFile("/home/plulli/.x509crypt/local/certs/local.crt"); - //var enc = EncDec.encrypt(plainText, x509Certificate.getPublicKey().getEncoded()); - byte[] enc = encryptData(plainText.getBytes(), x509Certificate); - System.out.printf("Cleartext: [%s]\n Encrypted: [%s]\n", plainText, new String(enc)); - - Files.write(Paths.get("/tmp/output2.txt.enc"), enc); - - PrivateKey privateKey = Pems.privateKeyFromFile("/home/plulli/.x509crypt/local/certs/local.key"); - decryptCms(privateKey, enc, "/tmp/output2.txt"); - } - - */ } diff --git a/src/test/java/EncryptionTest.java b/src/test/java/EncryptionTest.java index 00f3020f5e095a5a2fabbd5c8e79cc91afd4daef..c21b639281ae888c6a4eeafef15427f13b453ca1 100644 --- a/src/test/java/EncryptionTest.java +++ b/src/test/java/EncryptionTest.java @@ -1,33 +1,29 @@ -/* +/* * This file is part of cert-encoder * Copyright (c) 2024 Paolo Lulli. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import net.lulli.encrypt.Pems; import net.lulli.encrypt.pki.PkiEncryptionManager; import net.lulli.encrypt.symmetric.SymmetricEncryptionManager; -import org.junit.Ignore; import org.junit.Test; import java.io.File; -import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; import java.util.Arrays; public class EncryptionTest { @@ -35,37 +31,56 @@ @Test public void symmetricEncryptDecrypt() { var symmetricEncryptionManager = SymmetricEncryptionManager.INSTANCE; - var plainTest = "This is some long cleartext"; + var plainText = "This is some long cleartext"; var key = "abcdefghijklmnopqrstuvz".getBytes(Charset.forName("UTF-8")); - byte[] encrypted = symmetricEncryptionManager.encrypt(plainTest, key); - + byte[] encrypted = symmetricEncryptionManager.encrypt(plainText, key); byte[] decrypted = symmetricEncryptionManager.decrypt(encrypted, key); - assert Arrays.equals(plainTest.getBytes(), decrypted); + assert Arrays.equals(plainText.getBytes(), decrypted); } - @Test public void pkiEncryptDecrypt() throws Exception { var pkiEncryptionManager = PkiEncryptionManager.INSTANCE; - File outputEncryptedFile = File.createTempFile("pkiEncrDecr.", ".enc"); - File outputDencryptedFile = File.createTempFile("pkiEncrDecr", ".dec"); + var outputEncryptedFile = File.createTempFile("pkiEncrDecr.", ".enc"); + var outputDencryptedFile = File.createTempFile("pkiEncrDecr", ".dec"); var plainText = "this is a sample text"; - String certString = Files.readString(Paths.get(getClass().getResource("local.crt").toURI()), Charset.forName("utf-8")); + var certString = Files.readString(Paths.get(getClass().getResource("local.crt").toURI()), Charset.forName("utf-8")); - String keyString = Files.readString(Paths.get(getClass().getResource("local.key").toURI()), Charset.forName("utf-8")); - X509Certificate x509Certificate = Pems.readX509Certificate(certString); + var keyString = Files.readString(Paths.get(getClass().getResource("local.key").toURI()), Charset.forName("utf-8")); + var x509Certificate = Pems.readX509Certificate(certString); - byte[] enc = pkiEncryptionManager.encryptData(plainText.getBytes(), x509Certificate); + byte[] enc = pkiEncryptionManager.encrypt(plainText.getBytes(), x509Certificate); System.out.printf("Cleartext: [%s]\n Encrypted: [%s]\n", plainText, new String(enc)); Files.write(Paths.get(outputEncryptedFile.getAbsolutePath()), enc); - PrivateKey privateKey = Pems.readPKCS8PrivateKey(keyString); + var privateKey = Pems.readPKCS8PrivateKey(keyString); long millis = System.currentTimeMillis(); - pkiEncryptionManager.decryptCms(privateKey, enc, outputDencryptedFile.getAbsolutePath()+millis); + pkiEncryptionManager.decryptToFile(privateKey, enc, outputDencryptedFile.getAbsolutePath() + millis); + + byte[] decrypted = pkiEncryptionManager.decrypt(privateKey, enc); + + assert Arrays.equals(plainText.getBytes(), decrypted); + } + + @Test + public void pkiSign() throws Exception { + var pkiEncryptionManager = PkiEncryptionManager.INSTANCE; + + var plainText = "this is a sample text"; + var certString = Files.readString(Paths.get(getClass().getResource("local.crt").toURI()), Charset.forName("utf-8")); + + var keyString = Files.readString(Paths.get(getClass().getResource("local.key").toURI()), Charset.forName("utf-8")); + var x509Certificate = Pems.readX509Certificate(certString); + + var privateKey = Pems.readPKCS8PrivateKey(keyString); + + byte[] signatureClearText = pkiEncryptionManager.sign(x509Certificate, privateKey, plainText.getBytes()); + + System.out.printf("signatureClearText: [%s]\n", new String(signatureClearText)); } }