From 76c3d659ec781d0f57051053aae98d4314d27aa3 Mon Sep 17 00:00:00 2001 From: Georg Schmidt Date: Fri, 3 Nov 2017 12:43:03 +0100 Subject: [PATCH 1/2] 1. fix signature output, 2. improve decrypt speed, 3. tests without requirements, check results and stop times, 4. reformat code --- .../bc/openpgp/tests/TestBCOpenPGP.java | 154 +++-- .../jdamico/bc/openpgp/utils/PgpHelper.java | 652 +++++++++--------- .../bc/openpgp/utils/RSAKeyPairGenerator.java | 55 +- 3 files changed, 445 insertions(+), 416 deletions(-) diff --git a/src/org/jdamico/bc/openpgp/tests/TestBCOpenPGP.java b/src/org/jdamico/bc/openpgp/tests/TestBCOpenPGP.java index f8efd40..db05438 100644 --- a/src/org/jdamico/bc/openpgp/tests/TestBCOpenPGP.java +++ b/src/org/jdamico/bc/openpgp/tests/TestBCOpenPGP.java @@ -1,90 +1,138 @@ package org.jdamico.bc.openpgp.tests; + + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Base64; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.SecureRandom; import java.security.Security; import java.security.SignatureException; - import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPException; import org.jdamico.bc.openpgp.utils.PgpHelper; import org.jdamico.bc.openpgp.utils.RSAKeyPairGenerator; -import org.junit.Test; public class TestBCOpenPGP { - private boolean isArmored = false; - private String id = "damico"; - private String passwd = "******"; - private boolean integrityCheck = true; + private boolean isArmored = true; + private String id = "damico"; + private String passwd = "******"; + private boolean integrityCheck = true; + + + private String pubKeyFile = "test_out/pub.asc"; + private String privKeyFile = "test_out/secret.asc"; + + private String plainTextFile = "test_out/plain-text.txt"; + private String cipherTextFile = "test_out/cypher-text.asc"; + private String decPlainTextFile = "test_out/dec-plain-text.txt"; + private String signatureFile = "test_out/signature.txt"; + + @Before + public void setUp() throws Exception { + if (Files.notExists(Paths.get("test_out"))) { + Files.createDirectory(Paths.get("test_out")); + } + + if (Files.notExists(Paths.get(plainTextFile))) { + byte[] rand = new byte[819200]; + new SecureRandom().nextBytes(rand); + Files.write(Paths.get(plainTextFile), Base64.getEncoder().encode(rand)); + } + } + + @Test + public void genKeyPair() throws InvalidKeyException, NoSuchProviderException, SignatureException, IOException, PGPException, NoSuchAlgorithmException { + + RSAKeyPairGenerator rkpg = new RSAKeyPairGenerator(); + + Security.addProvider(new BouncyCastleProvider()); + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC"); + + kpg.initialize(1024); + + KeyPair kp = kpg.generateKeyPair(); + + FileOutputStream out1 = new FileOutputStream(privKeyFile); + FileOutputStream out2 = new FileOutputStream(pubKeyFile); + + rkpg.exportKeyPair(out1, out2, kp.getPublic(), kp.getPrivate(), id, passwd.toCharArray(), isArmored); + } + @Test + public void encrypt() throws NoSuchProviderException, IOException, PGPException { + long start = System.currentTimeMillis(); - private String pubKeyFile = "/tmp/pub.dat"; - private String privKeyFile = "/tmp/secret.dat"; + FileInputStream pubKeyIs = new FileInputStream(pubKeyFile); + FileOutputStream cipheredFileIs = new FileOutputStream(cipherTextFile); + PgpHelper.getInstance().encryptFile(cipheredFileIs, plainTextFile, PgpHelper.getInstance().readPublicKey(pubKeyIs), isArmored, integrityCheck); + cipheredFileIs.close(); + pubKeyIs.close(); - private String plainTextFile = "/tmp/plain-text.txt"; //create a text file to be encripted, before run the tests - private String cipherTextFile = "/tmp/cypher-text.dat"; - private String decPlainTextFile = "/tmp/dec-plain-text.txt"; - private String signatureFile = "/tmp/signature.txt"; + System.out.println("encrypt() takes " + (int) ((System.currentTimeMillis() - start) / 1000) + " seconds."); - @Test - public void genKeyPair() throws InvalidKeyException, NoSuchProviderException, SignatureException, IOException, PGPException, NoSuchAlgorithmException { + byte[] orgF = Files.readAllBytes(Paths.get(plainTextFile)); + byte[] newF = Files.readAllBytes(Paths.get(cipherTextFile)); - RSAKeyPairGenerator rkpg = new RSAKeyPairGenerator(); + assertNotEquals(Arrays.toString(orgF), Arrays.toString(newF)); + } - Security.addProvider(new BouncyCastleProvider()); + @Test + public void decrypt() throws Exception { + long start = System.currentTimeMillis(); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC"); + FileInputStream cipheredFileIs = new FileInputStream(cipherTextFile); + FileInputStream privKeyIn = new FileInputStream(privKeyFile); + FileOutputStream plainTextFileIs = new FileOutputStream(decPlainTextFile); + PgpHelper.getInstance().decryptFile(cipheredFileIs, plainTextFileIs, privKeyIn, passwd.toCharArray()); + cipheredFileIs.close(); + plainTextFileIs.close(); + privKeyIn.close(); - kpg.initialize(1024); + System.out.println("decrypt() takes " + (int) ((System.currentTimeMillis() - start) / 1000) + " seconds."); - KeyPair kp = kpg.generateKeyPair(); + byte[] orgF = Files.readAllBytes(Paths.get(plainTextFile)); + byte[] newF = Files.readAllBytes(Paths.get(decPlainTextFile)); - FileOutputStream out1 = new FileOutputStream(privKeyFile); - FileOutputStream out2 = new FileOutputStream(pubKeyFile); + assertArrayEquals(orgF, newF); + } - rkpg.exportKeyPair(out1, out2, kp.getPublic(), kp.getPrivate(), id, passwd.toCharArray(), isArmored); + @Test + public void signAndVerify() throws Exception { + long start = System.currentTimeMillis(); + FileInputStream privKeyIn = new FileInputStream(privKeyFile); + FileInputStream pubKeyIs = new FileInputStream(pubKeyFile); + FileInputStream plainTextInput = new FileInputStream(plainTextFile); + FileOutputStream signatureOut = new FileOutputStream(signatureFile); - } + // todo: remove that? + // byte[] bIn = PgpHelper.getInstance().inputStreamToByteArray(plainTextInput); - @Test - public void encrypt() throws NoSuchProviderException, IOException, PGPException{ - FileInputStream pubKeyIs = new FileInputStream(pubKeyFile); - FileOutputStream cipheredFileIs = new FileOutputStream(cipherTextFile); - PgpHelper.getInstance().encryptFile(cipheredFileIs, plainTextFile, PgpHelper.getInstance().readPublicKey(pubKeyIs), isArmored, integrityCheck); - cipheredFileIs.close(); - pubKeyIs.close(); - } + byte[] sig = PgpHelper.getInstance().createSignature(plainTextFile, privKeyIn, signatureOut, passwd.toCharArray(), true); - @Test - public void decrypt() throws Exception{ + boolean res = PgpHelper.getInstance().verifySignature(plainTextFile, sig, pubKeyIs); - FileInputStream cipheredFileIs = new FileInputStream(cipherTextFile); - FileInputStream privKeyIn = new FileInputStream(privKeyFile); - FileOutputStream plainTextFileIs = new FileOutputStream(decPlainTextFile); - PgpHelper.getInstance().decryptFile(cipheredFileIs, plainTextFileIs, privKeyIn, passwd.toCharArray()); - cipheredFileIs.close(); - plainTextFileIs.close(); - privKeyIn.close(); - } + System.out.println("signAndVerify() takes " + (int) ((System.currentTimeMillis() - start) / 1000) + " seconds."); - @Test - public void signAndVerify() throws Exception{ - FileInputStream privKeyIn = new FileInputStream(privKeyFile); - FileInputStream pubKeyIs = new FileInputStream(pubKeyFile); - FileInputStream plainTextInput = new FileInputStream(plainTextFile); - FileOutputStream signatureOut = new FileOutputStream(signatureFile); - - byte[] bIn = PgpHelper.getInstance().inputStreamToByteArray(plainTextInput); - byte[] sig = PgpHelper.getInstance().createSignature(plainTextFile, privKeyIn, signatureOut, passwd.toCharArray(), true); - PgpHelper.getInstance().verifySignature(plainTextFile, sig, pubKeyIs); - } + assertTrue(res); + } -} +} \ No newline at end of file diff --git a/src/org/jdamico/bc/openpgp/utils/PgpHelper.java b/src/org/jdamico/bc/openpgp/utils/PgpHelper.java index 370aef8..cbb0df2 100644 --- a/src/org/jdamico/bc/openpgp/utils/PgpHelper.java +++ b/src/org/jdamico/bc/openpgp/utils/PgpHelper.java @@ -1,5 +1,6 @@ package org.jdamico.bc.openpgp.utils; +import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -53,348 +54,333 @@ * * @author seamans * @author jdamico - * */ public class PgpHelper { - private static PgpHelper INSTANCE = null; - - public static PgpHelper getInstance(){ - - if(INSTANCE == null) INSTANCE = new PgpHelper(); - return INSTANCE; - } - - private PgpHelper(){} - - - public PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException { - in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); - PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); - - // - // we just loop through the collection till we find a key suitable for encryption, in the real - // world you would probably want to be a bit smarter about this. - // - PGPPublicKey key = null; - - // - // iterate through the key rings. - // - Iterator rIt = pgpPub.getKeyRings(); - - while (key == null && rIt.hasNext()) { - PGPPublicKeyRing kRing = rIt.next(); - Iterator kIt = kRing.getPublicKeys(); - while (key == null && kIt.hasNext()) { - PGPPublicKey k = kIt.next(); - - if (k.isEncryptionKey()) { - key = k; - } - } - } - - if (key == null) { - throw new IllegalArgumentException("Can't find encryption key in key ring."); - } - - return key; - } - - /** - * Load a secret key ring collection from keyIn and find the secret key corresponding to - * keyID if it exists. - * - * @param keyIn input stream representing a key ring collection. - * @param keyID keyID we want. - * @param pass passphrase to decrypt secret key with. - * @return - * @throws IOException - * @throws PGPException - * @throws NoSuchProviderException - */ - public PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) - throws IOException, PGPException, NoSuchProviderException - { - PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( - org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn)); - - PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); - - if (pgpSecKey == null) { - return null; - } - - PBESecretKeyDecryptor a = new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(pass); - - return pgpSecKey.extractPrivateKey(a); - } - - /** - * decrypt the passed in message stream - */ - @SuppressWarnings("unchecked") - public void decryptFile(InputStream in, OutputStream out, InputStream keyIn, char[] passwd) - throws Exception - { - Security.addProvider(new BouncyCastleProvider()); - in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); - PGPObjectFactory pgpF = new PGPObjectFactory(in); - PGPEncryptedDataList enc; - Object o = pgpF.nextObject(); - // - // the first object might be a PGP marker packet. - // - if (o instanceof PGPEncryptedDataList) { - enc = (PGPEncryptedDataList) o; - } else { - enc = (PGPEncryptedDataList) pgpF.nextObject(); - } + private static PgpHelper INSTANCE = null; + + public static PgpHelper getInstance() { + + if (INSTANCE == null) INSTANCE = new PgpHelper(); + return INSTANCE; + } + + private PgpHelper() { + } + + + public PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException { + in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); + PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); + + // + // we just loop through the collection till we find a key suitable for encryption, in the real + // world you would probably want to be a bit smarter about this. + // + PGPPublicKey key = null; + + // + // iterate through the key rings. + // + Iterator rIt = pgpPub.getKeyRings(); + + while (key == null && rIt.hasNext()) { + PGPPublicKeyRing kRing = rIt.next(); + Iterator kIt = kRing.getPublicKeys(); + while (key == null && kIt.hasNext()) { + PGPPublicKey k = kIt.next(); + + if (k.isEncryptionKey()) { + key = k; + } + } + } + + if (key == null) { + throw new IllegalArgumentException("Can't find encryption key in key ring."); + } + + return key; + } + + /** + * Load a secret key ring collection from keyIn and find the secret key corresponding to + * keyID if it exists. + * + * @param keyIn input stream representing a key ring collection. + * @param keyID keyID we want. + * @param pass passphrase to decrypt secret key with. + * @return + * @throws IOException + * @throws PGPException + * @throws NoSuchProviderException + */ + public PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) + throws IOException, PGPException, NoSuchProviderException { + PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( + org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn)); + + PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); + + if (pgpSecKey == null) { + return null; + } + + PBESecretKeyDecryptor a = new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(pass); + + return pgpSecKey.extractPrivateKey(a); + } + + /** + * decrypt the passed in message stream + */ + @SuppressWarnings("unchecked") + public void decryptFile(InputStream in, OutputStream out, InputStream keyIn, char[] passwd) + throws Exception { + Security.addProvider(new BouncyCastleProvider()); + in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); + PGPObjectFactory pgpF = new PGPObjectFactory(in); + PGPEncryptedDataList enc; + Object o = pgpF.nextObject(); + // + // the first object might be a PGP marker packet. + // + if (o instanceof PGPEncryptedDataList) { + enc = (PGPEncryptedDataList) o; + } else { + enc = (PGPEncryptedDataList) pgpF.nextObject(); + } + + // + // find the secret key + // + Iterator it = enc.getEncryptedDataObjects(); + PGPPrivateKey sKey = null; + PGPPublicKeyEncryptedData pbe = null; + + while (sKey == null && it.hasNext()) { + pbe = it.next(); + sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd); + } + + if (sKey == null) { + throw new IllegalArgumentException("Secret key for message not found."); + } + + PublicKeyDataDecryptorFactory b = new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").setContentProvider("BC").build(sKey); + + InputStream clear = pbe.getDataStream(b); + + PGPObjectFactory plainFact = new PGPObjectFactory(clear); + + Object message = plainFact.nextObject(); + + if (message instanceof PGPCompressedData) { + PGPCompressedData cData = (PGPCompressedData) message; + PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream()); + + message = pgpFact.nextObject(); + } + + if (message instanceof PGPLiteralData) { + PGPLiteralData ld = (PGPLiteralData) message; + InputStream unc = ld.getInputStream(); + + IOUtils.copy(unc, out); + } else if (message instanceof PGPOnePassSignatureList) { + throw new PGPException("Encrypted message contains a signed message - not literal data."); + } else { + throw new PGPException("Message is not a simple encrypted file - type unknown."); + } + + if (pbe.isIntegrityProtected()) { + if (!pbe.verify()) { + throw new PGPException("Message failed integrity check"); + } + } + } + + public void encryptFile(OutputStream out, String fileName, + PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) + throws IOException, NoSuchProviderException, PGPException { + Security.addProvider(new BouncyCastleProvider()); + + if (armor) { + out = new ArmoredOutputStream(out); + } + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator( + PGPCompressedData.ZIP); + + org.bouncycastle.openpgp.PGPUtil.writeFileToLiteralData(comData.open(bOut), + PGPLiteralData.BINARY, new File(fileName)); + + comData.close(); + + JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"); + + PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c); + + JcePublicKeyKeyEncryptionMethodGenerator d = new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom()); + + cPk.addMethod(d); + + byte[] bytes = bOut.toByteArray(); + + OutputStream cOut = cPk.open(out, bytes.length); + + cOut.write(bytes); + + cOut.close(); + + out.close(); + } + + + public byte[] inputStreamToByteArray(InputStream is) throws IOException { + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[1024]; - // - // find the secret key - // - Iterator it = enc.getEncryptedDataObjects(); - PGPPrivateKey sKey = null; - PGPPublicKeyEncryptedData pbe = null; + while ((nRead = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } - while (sKey == null && it.hasNext()) { - pbe = it.next(); - sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd); - } + buffer.flush(); - if (sKey == null) { - throw new IllegalArgumentException("Secret key for message not found."); - } - - PublicKeyDataDecryptorFactory b = new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").setContentProvider("BC").build(sKey); - - InputStream clear = pbe.getDataStream(b); - - PGPObjectFactory plainFact = new PGPObjectFactory(clear); - - Object message = plainFact.nextObject(); - - if (message instanceof PGPCompressedData) { - PGPCompressedData cData = (PGPCompressedData) message; - PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream()); - - message = pgpFact.nextObject(); - } - - if (message instanceof PGPLiteralData) { - PGPLiteralData ld = (PGPLiteralData) message; - InputStream unc = ld.getInputStream(); - int ch; - while ((ch = unc.read()) >= 0) { - out.write(ch); - } - } else if (message instanceof PGPOnePassSignatureList) { - throw new PGPException("Encrypted message contains a signed message - not literal data."); - } else { - throw new PGPException("Message is not a simple encrypted file - type unknown."); - } - - if (pbe.isIntegrityProtected()) { - if (!pbe.verify()) { - throw new PGPException("Message failed integrity check"); - } - } - } - - public void encryptFile(OutputStream out, String fileName, - PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) - throws IOException, NoSuchProviderException, PGPException - { - Security.addProvider(new BouncyCastleProvider()); - - if (armor) { - out = new ArmoredOutputStream(out); - } - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator( - PGPCompressedData.ZIP); - - org.bouncycastle.openpgp.PGPUtil.writeFileToLiteralData(comData.open(bOut), - PGPLiteralData.BINARY, new File(fileName)); - - comData.close(); - - JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"); - - PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c); - - JcePublicKeyKeyEncryptionMethodGenerator d = new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom()); - - cPk.addMethod(d); - - byte[] bytes = bOut.toByteArray(); - - OutputStream cOut = cPk.open(out, bytes.length); - - cOut.write(bytes); - - cOut.close(); - - out.close(); - } - - - public byte[] inputStreamToByteArray(InputStream is) throws IOException{ - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - int nRead; - byte[] data = new byte[1024]; - - while ((nRead = is.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - buffer.flush(); + return buffer.toByteArray(); + } - return buffer.toByteArray(); - } + /** + * verify the signature in in against the file fileName. + */ + public boolean verifySignature( + String fileName, + byte[] b, + InputStream keyIn) + throws GeneralSecurityException, IOException, PGPException { + //in = PGPUtil.getDecoderStream(in); + + PGPObjectFactory pgpFact = new PGPObjectFactory(b); + PGPSignatureList p3 = null; + + Object o = pgpFact.nextObject(); + if (o instanceof PGPCompressedData) { + PGPCompressedData c1 = (PGPCompressedData) o; + + pgpFact = new PGPObjectFactory(c1.getDataStream()); + + p3 = (PGPSignatureList) pgpFact.nextObject(); + } else { + p3 = (PGPSignatureList) o; + } + + PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn)); + + + InputStream dIn = new BufferedInputStream(new FileInputStream(fileName)); + + PGPSignature sig = p3.get(0); + PGPPublicKey key = pgpPubRingCollection.getPublicKey(sig.getKeyID()); - /** - * verify the signature in in against the file fileName. - */ - public void verifySignature( - String fileName, - byte[] b, - InputStream keyIn) - throws GeneralSecurityException, IOException, PGPException - { - //in = PGPUtil.getDecoderStream(in); - - PGPObjectFactory pgpFact = new PGPObjectFactory(b); - PGPSignatureList p3 = null; - - Object o = pgpFact.nextObject(); - if (o instanceof PGPCompressedData) - { - PGPCompressedData c1 = (PGPCompressedData)o; - - pgpFact = new PGPObjectFactory(c1.getDataStream()); - - p3 = (PGPSignatureList)pgpFact.nextObject(); - } - else - { - p3 = (PGPSignatureList)o; - } - - PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn)); - - - InputStream dIn = new BufferedInputStream(new FileInputStream(fileName)); - - PGPSignature sig = p3.get(0); - PGPPublicKey key = pgpPubRingCollection.getPublicKey(sig.getKeyID()); - - sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(new BouncyCastleProvider()), key); - - int ch; - while ((ch = dIn.read()) >= 0) - { - sig.update((byte)ch); - } - - dIn.close(); - - if (sig.verify()) - { - System.out.println("signature verified."); - } - else - { - System.out.println("signature verification failed."); - } - } - - public PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException - { - PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( - PGPUtil.getDecoderStream(input)); - - // - // we just loop through the collection till we find a key suitable for encryption, in the real - // world you would probably want to be a bit smarter about this. - // - - Iterator keyRingIter = pgpSec.getKeyRings(); - while (keyRingIter.hasNext()) - { - PGPSecretKeyRing keyRing = (PGPSecretKeyRing)keyRingIter.next(); - - Iterator keyIter = keyRing.getSecretKeys(); - while (keyIter.hasNext()) - { - PGPSecretKey key = (PGPSecretKey)keyIter.next(); - - if (key.isSigningKey()) - { - return key; - } - } - } - - throw new IllegalArgumentException("Can't find signing key in key ring."); - } - - public byte[] createSignature( - String fileName, - InputStream keyIn, - OutputStream out, - char[] pass, - boolean armor) - throws GeneralSecurityException, IOException, PGPException - { - - - PGPSecretKey pgpSecKey = readSecretKey(keyIn); - PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(new BouncyCastleProvider()).build(pass)); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSecKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1).setProvider(new BouncyCastleProvider())); - - - sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey); - - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - ArmoredOutputStream aOut = new ArmoredOutputStream(byteOut); - - - BCPGOutputStream bOut = new BCPGOutputStream(byteOut); - - InputStream fIn = new BufferedInputStream(new FileInputStream(fileName)); - - int ch; - while ((ch = fIn.read()) >= 0) - { - sGen.update((byte)ch); - - } - + + int ch; + while ((ch = dIn.read()) >= 0) { + sig.update((byte) ch); + } + + dIn.close(); + + if (sig.verify()) { + System.out.println("signature verified."); + return true; + } else { + System.out.println("signature verification failed."); + return false; + } + } + + public PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException { + PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( + PGPUtil.getDecoderStream(input)); + + // + // we just loop through the collection till we find a key suitable for encryption, in the real + // world you would probably want to be a bit smarter about this. + // + + Iterator keyRingIter = pgpSec.getKeyRings(); + while (keyRingIter.hasNext()) { + PGPSecretKeyRing keyRing = (PGPSecretKeyRing) keyRingIter.next(); + + Iterator keyIter = keyRing.getSecretKeys(); + while (keyIter.hasNext()) { + PGPSecretKey key = (PGPSecretKey) keyIter.next(); + + if (key.isSigningKey()) { + return key; + } + } + } + + throw new IllegalArgumentException("Can't find signing key in key ring."); + } + + public byte[] createSignature( + String fileName, + InputStream keyIn, + OutputStream out, + char[] pass, + boolean armor) + throws GeneralSecurityException, IOException, PGPException { + + + PGPSecretKey pgpSecKey = readSecretKey(keyIn); + PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(new BouncyCastleProvider()).build(pass)); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSecKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1).setProvider(new BouncyCastleProvider())); + + + sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey); + + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + + BCPGOutputStream bOut = new BCPGOutputStream(byteOut); + + InputStream fIn = new BufferedInputStream(new FileInputStream(fileName)); + + int ch; + while ((ch = fIn.read()) >= 0) { + sGen.update((byte) ch); + } + + fIn.close(); + + sGen.generate().encode(bOut); + + if (armor) { + ByteArrayOutputStream byteArmored = new ByteArrayOutputStream(); + ArmoredOutputStream aOut = new ArmoredOutputStream(byteArmored); + aOut.write(byteOut.toByteArray()); + aOut.flush(); aOut.endClearText(); - - fIn.close(); - - sGen.generate().encode(bOut); - - if (armor) - { - aOut.close(); - } - - - - - return byteOut.toByteArray(); - } - -} \ No newline at end of file + aOut.close(); + + out.write(byteArmored.toByteArray()); + } else { + out.write(byteOut.toByteArray()); + } + + out.flush(); + out.close(); + + return byteOut.toByteArray(); + } + +} diff --git a/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java b/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java index 2b656ce..041d472 100644 --- a/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java +++ b/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java @@ -31,51 +31,46 @@ *

* usage: RSAKeyPairGenerator [-a] identity passPhrase *

- * Where identity is the name to be associated with the public key. The keys are placed + * Where identity is the name to be associated with the public key. The keys are placed * in the files pub.[asc|bpg] and secret.[asc|bpg]. */ -public class RSAKeyPairGenerator -{ +public class RSAKeyPairGenerator { public void exportKeyPair( - OutputStream secretOut, - OutputStream publicOut, - PublicKey publicKey, - PrivateKey privateKey, - String identity, - char[] passPhrase, - boolean armor) - throws IOException, InvalidKeyException, NoSuchProviderException, SignatureException, PGPException - { - if (armor) - { + OutputStream secretOut, + OutputStream publicOut, + PublicKey publicKey, + PrivateKey privateKey, + String identity, + char[] passPhrase, + boolean armor) + throws IOException, InvalidKeyException, NoSuchProviderException, SignatureException, PGPException { + if (armor) { secretOut = new ArmoredOutputStream(secretOut); } - - + PGPPublicKey a = (new JcaPGPKeyConverter().getPGPPublicKey(PGPPublicKey.RSA_GENERAL, publicKey, new Date())); - RSAPrivateCrtKey rsK = (RSAPrivateCrtKey)privateKey; + RSAPrivateCrtKey rsK = (RSAPrivateCrtKey) privateKey; RSASecretBCPGKey privPk = new RSASecretBCPGKey(rsK.getPrivateExponent(), rsK.getPrimeP(), rsK.getPrimeQ()); PGPPrivateKey b = new PGPPrivateKey(a.getKeyID(), a.getPublicKeyPacket(), privPk); PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1); - PGPKeyPair keyPair = new PGPKeyPair(a,b); - PGPSecretKey secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, identity, sha1Calc, null, null, new JcaPGPContentSignerBuilder(keyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.CAST5, sha1Calc).setProvider("BC").build(passPhrase)); - + PGPKeyPair keyPair = new PGPKeyPair(a, b); + PGPSecretKey secretKey = new PGPSecretKey(PGPSignature.DEFAULT_CERTIFICATION, keyPair, identity, sha1Calc, null, null, new JcaPGPContentSignerBuilder(keyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.CAST5, sha1Calc).setProvider("BC").build(passPhrase)); + secretKey.encode(secretOut); - + secretOut.close(); - - if (armor) - { + + if (armor) { publicOut = new ArmoredOutputStream(publicOut); } - PGPPublicKey key = secretKey.getPublicKey(); - + PGPPublicKey key = secretKey.getPublicKey(); + key.encode(publicOut); - + publicOut.close(); } - - -} + + +} \ No newline at end of file From 22b415850146a5ceed00f3d078f3c9d7494f4527 Mon Sep 17 00:00:00 2001 From: Georg Schmidt Date: Fri, 18 Oct 2019 01:53:22 +0200 Subject: [PATCH 2/2] fix bc 163 --- .../jdamico/bc/openpgp/utils/PgpHelper.java | 28 +++++++++++-------- .../bc/openpgp/utils/RSAKeyPairGenerator.java | 4 +-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/org/jdamico/bc/openpgp/utils/PgpHelper.java b/src/org/jdamico/bc/openpgp/utils/PgpHelper.java index cbb0df2..f480cda 100644 --- a/src/org/jdamico/bc/openpgp/utils/PgpHelper.java +++ b/src/org/jdamico/bc/openpgp/utils/PgpHelper.java @@ -1,6 +1,6 @@ package org.jdamico.bc.openpgp.utils; -import org.apache.commons.io.IOUtils; +// import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -41,6 +41,7 @@ import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; @@ -71,7 +72,7 @@ private PgpHelper() { public PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException { in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); - PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); + PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in, new BcKeyFingerprintCalculator()); // // we just loop through the collection till we find a key suitable for encryption, in the real @@ -118,7 +119,7 @@ public PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPExcepti public PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException { PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( - org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn)); + org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn), new BcKeyFingerprintCalculator()); PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); @@ -139,7 +140,7 @@ public void decryptFile(InputStream in, OutputStream out, InputStream keyIn, cha throws Exception { Security.addProvider(new BouncyCastleProvider()); in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in); - PGPObjectFactory pgpF = new PGPObjectFactory(in); + PGPObjectFactory pgpF = new PGPObjectFactory(in, new BcKeyFingerprintCalculator()); PGPEncryptedDataList enc; Object o = pgpF.nextObject(); // @@ -171,13 +172,13 @@ public void decryptFile(InputStream in, OutputStream out, InputStream keyIn, cha InputStream clear = pbe.getDataStream(b); - PGPObjectFactory plainFact = new PGPObjectFactory(clear); + PGPObjectFactory plainFact = new PGPObjectFactory(clear, new BcKeyFingerprintCalculator()); Object message = plainFact.nextObject(); if (message instanceof PGPCompressedData) { PGPCompressedData cData = (PGPCompressedData) message; - PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream()); + PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream(), new BcKeyFingerprintCalculator()); message = pgpFact.nextObject(); } @@ -186,7 +187,11 @@ public void decryptFile(InputStream in, OutputStream out, InputStream keyIn, cha PGPLiteralData ld = (PGPLiteralData) message; InputStream unc = ld.getInputStream(); - IOUtils.copy(unc, out); + // java 9+ + unc.transferTo(out); + //IOUtils.copy(unc, out); + //out = inputStreamToByteArray(unc); + } else if (message instanceof PGPOnePassSignatureList) { throw new PGPException("Encrypted message contains a signed message - not literal data."); } else { @@ -266,21 +271,21 @@ public boolean verifySignature( throws GeneralSecurityException, IOException, PGPException { //in = PGPUtil.getDecoderStream(in); - PGPObjectFactory pgpFact = new PGPObjectFactory(b); + PGPObjectFactory pgpFact = new PGPObjectFactory(b, new BcKeyFingerprintCalculator()); PGPSignatureList p3 = null; Object o = pgpFact.nextObject(); if (o instanceof PGPCompressedData) { PGPCompressedData c1 = (PGPCompressedData) o; - pgpFact = new PGPObjectFactory(c1.getDataStream()); + pgpFact = new PGPObjectFactory(c1.getDataStream(), new BcKeyFingerprintCalculator()); p3 = (PGPSignatureList) pgpFact.nextObject(); } else { p3 = (PGPSignatureList) o; } - PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn)); + PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn), new BcKeyFingerprintCalculator()); InputStream dIn = new BufferedInputStream(new FileInputStream(fileName)); @@ -309,7 +314,7 @@ public boolean verifySignature( public PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException { PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( - PGPUtil.getDecoderStream(input)); + PGPUtil.getDecoderStream(input), new BcKeyFingerprintCalculator()); // // we just loop through the collection till we find a key suitable for encryption, in the real @@ -382,5 +387,4 @@ public byte[] createSignature( return byteOut.toByteArray(); } - } diff --git a/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java b/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java index 041d472..f60c693 100644 --- a/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java +++ b/src/org/jdamico/bc/openpgp/utils/RSAKeyPairGenerator.java @@ -71,6 +71,4 @@ public void exportKeyPair( publicOut.close(); } - - -} \ No newline at end of file +}