From a6c3f74503b29a636bd4efaa85b30c17e418e748 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:34:49 -0500 Subject: [PATCH 1/9] Upped the version used for the gem to jruby-1.7.10 --- .rbenv-version | 2 +- .ruby-gemset | 1 + .ruby-version | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .ruby-gemset create mode 100644 .ruby-version diff --git a/.rbenv-version b/.rbenv-version index 467ee9a..e9bb632 100644 --- a/.rbenv-version +++ b/.rbenv-version @@ -1 +1 @@ -jruby-1.7.2 +jruby-1.7.10 diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 0000000..e97c8b2 --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +jruby-pgp diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..e9bb632 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +jruby-1.7.10 From f98f15cae255599210d00b64fba63a9563662db9 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:35:55 -0500 Subject: [PATCH 2/9] Added a detached signature for testing --- spec/support/fixtures/signed_file_signature.asc | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 spec/support/fixtures/signed_file_signature.asc diff --git a/spec/support/fixtures/signed_file_signature.asc b/spec/support/fixtures/signed_file_signature.asc new file mode 100644 index 0000000..c673288 --- /dev/null +++ b/spec/support/fixtures/signed_file_signature.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- +Version: BCPG v1.47 + +iQEcBAABAgAGBQJTVqdcAAoJEJU54ioziO4kvQkIAJTP7BqbPxPnvXl8W8FBPx3Z +aTFS6edoL6XJpFbDj0FmUIn2fplE478/4NcSVXwZsvfM9dzwKglhxIGrJCFoh4by +Bb89T00hFnU7HyqSZ5mLaKCjwRW5C0xGQhP2eG4PfdHIR0hGFwiyop1K7fyJYQK/ +6UU0qCnbqu6FfqTwJS4TcbwDOfWayp5IYQky0zxqRc03E7I3jkEo5omJrAqpd9kW +YOfa3JkjaAkKtDhP5p/Nr0qUIzzm8Zgp4vQqcTBMiZOUPQNKDgnrOS4dpKSAyaV0 +R4hMDhiGLsKdzoMuPmGn53TFxIBlGwef+ih/Aoiu52D9Q1MLK5NIBLxo1swWz4I= +=W4tR +-----END PGP SIGNATURE----- From a5ad1a31c0c3d306c99169884ebddd58ea454936 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:36:34 -0500 Subject: [PATCH 3/9] Added specs for detached signer/verifier --- spec/lib/pgp/signer_spec.rb | 9 +++++++-- spec/lib/pgp/verifier_spec.rb | 27 ++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/spec/lib/pgp/signer_spec.rb b/spec/lib/pgp/signer_spec.rb index 0176aeb..931b5f0 100644 --- a/spec/lib/pgp/signer_spec.rb +++ b/spec/lib/pgp/signer_spec.rb @@ -12,6 +12,7 @@ end let(:unsigned_file) { Fixtures_Path.join('signed_file.txt') } + let(:unencrypted_file) { Fixtures_Path.join('unencrypted_file.txt') } let(:unsigned_data) { File.read(unsigned_file)} let(:signed_file) { Fixtures_Path.join('signed_file.txt.asc') } let(:verifier) do @@ -21,11 +22,16 @@ end describe '#sign' do - it "signs" do verifier.verify(signer.sign(unsigned_data)).should == unsigned_data end + end + describe '#sign_detached' do + it "signs" do + signature = signer.sign_detached(unencrypted_file) + verifier.verify_detached(unencrypted_file, signature).should == true + end end describe "encrypting and signing" do @@ -40,5 +46,4 @@ verifier.verify(decryptor.decrypt(encryptor.encrypt(signer.sign("something fabulous")))).should == "something fabulous" end end - end diff --git a/spec/lib/pgp/verifier_spec.rb b/spec/lib/pgp/verifier_spec.rb index fe6fbf1..1db3857 100644 --- a/spec/lib/pgp/verifier_spec.rb +++ b/spec/lib/pgp/verifier_spec.rb @@ -6,28 +6,49 @@ let(:verifier) { PGP::Verifier.new } let(:unsigned_file) { Fixtures_Path.join('signed_file.txt') } let(:signed_file) { Fixtures_Path.join('signed_file.txt.asc') } + let(:file_signature) { Fixtures_Path.join('signed_file_signature.asc') } describe '#verify' do before do verifier.add_keys_from_file(public_key_path) end - context 'When the Public Key is from a file' do + context 'When the public key is from a file' do it "verifies" do verifier.verify(File.read(signed_file)).should == File.read(unsigned_file) end end - context 'When the public key cannot verify a signature' do let(:public_key_path) { Fixtures_Path.join('wrong_public_key_for_signature.asc').to_s } it "should raise an exception" do expect { verifier.verify(File.read(signed_file)) - }.to raise_exception(org.sgonyea.pgp.VerificationFailedException, /Signature could not be verified/) + }.to raise_exception(org.sgonyea.pgp.VerificationFailedException, /key.*could not be found/) end end end + describe '#verify_detached' do + before do + verifier.add_keys_from_file(public_key_path) + end + + context 'When the public key is from a file' do + it "verifies" do + verifier.verify_detached(unsigned_file, File.read(file_signature)).should == true + end + end + + context 'When the public key cannot verify a signature' do + let(:public_key_path) { Fixtures_Path.join('wrong_public_key_for_signature.asc').to_s } + + it "should raise an exception" do + expect { + verifier.verify_detached(unsigned_file, File.read(file_signature)) + }.to raise_exception(org.sgonyea.pgp.VerificationFailedException, /ID.*could not be found/) + end + end + end end From 0776468287c9a0cc6b199c8a9ce40f2a9a93356f Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:37:03 -0500 Subject: [PATCH 4/9] Added the new API and bumped the version to 0.3.1 --- lib/pgp/signer.rb | 7 ++++++- lib/pgp/verifier.rb | 7 ++++++- lib/pgp/version.rb | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/pgp/signer.rb b/lib/pgp/signer.rb index 5574b29..5036a46 100644 --- a/lib/pgp/signer.rb +++ b/lib/pgp/signer.rb @@ -15,6 +15,11 @@ def sign(data) String.from_java_bytes(signed_data) end + def sign_detached(filename) + # Ruby bug JRUBY-6389 + sign_data_detached(filename.to_s) + end + def sign_file(file_path) sign File.read(file_path) end @@ -36,4 +41,4 @@ def keyring_from_stream(stream) end end -end \ No newline at end of file +end diff --git a/lib/pgp/verifier.rb b/lib/pgp/verifier.rb index e856ffb..a216bf1 100644 --- a/lib/pgp/verifier.rb +++ b/lib/pgp/verifier.rb @@ -16,6 +16,11 @@ def verify(signed_data) String.from_java_bytes(verified_data) end + def verify_detached(filename, signature) + # Ruby bug JRUBY-6389 + verify_detached_signature(filename.to_s, signature.to_s) + end + def decrypt_file(file_path) decrypt File.read(file_path) end @@ -35,4 +40,4 @@ def keyring_from_stream(stream) end end -end \ No newline at end of file +end diff --git a/lib/pgp/version.rb b/lib/pgp/version.rb index f90a8f7..5780d8c 100644 --- a/lib/pgp/version.rb +++ b/lib/pgp/version.rb @@ -1,3 +1,3 @@ module PGP - VERSION = '0.3.0' + VERSION = '0.3.1' end From 08cc6bc207964cd789ed67a442f05a13b0aa65e1 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:40:23 -0500 Subject: [PATCH 5/9] Added the new detached signer and verifier to Java code and cleaned up the older code a bit --- ext/org/sgonyea/pgp/Signer.java | 188 +++++++++++++++++------------- ext/org/sgonyea/pgp/Verifier.java | 161 +++++++++++++++---------- 2 files changed, 208 insertions(+), 141 deletions(-) diff --git a/ext/org/sgonyea/pgp/Signer.java b/ext/org/sgonyea/pgp/Signer.java index 0177a85..3001545 100644 --- a/ext/org/sgonyea/pgp/Signer.java +++ b/ext/org/sgonyea/pgp/Signer.java @@ -10,124 +10,150 @@ package org.sgonyea.pgp; -import java.io.ByteArrayInputStream; +import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.Security; -import java.util.Date; import java.util.Iterator; -import org.bouncycastle.bcpg.BCPGOutputStream; import org.bouncycastle.bcpg.ArmoredOutputStream; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openpgp.*; +import org.bouncycastle.bcpg.BCPGOutputStream; +import org.bouncycastle.openpgp.PGPCompressedData; +import org.bouncycastle.openpgp.PGPCompressedDataGenerator; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; -import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; public class Signer { + private String passphrase; + private PGPSecretKeyRingCollection _privateKeys; + + public Signer() { + } + + public Signer(PGPSecretKeyRingCollection privateKeys) { + setPrivateKeys(privateKeys); + } + + /** + * Accessor and Attribute Helper Methods + **/ + public PGPSecretKeyRingCollection getPrivateKeys() { + return _privateKeys; + } + + public void setPrivateKeys(PGPSecretKeyRingCollection privateKeys) { + _privateKeys = privateKeys; + } + + public void setPassphrase(String passphrase) { + this.passphrase = passphrase; + } + + private PGPSecretKey findSecretKey() throws PGPException, NoSuchProviderException { + @SuppressWarnings("rawtypes") + Iterator keyRingIter = _privateKeys.getKeyRings(); + while (keyRingIter.hasNext()) { + PGPSecretKeyRing keyRing = (PGPSecretKeyRing) keyRingIter.next(); + + @SuppressWarnings("rawtypes") + Iterator keyIter = keyRing.getSecretKeys(); + while (keyIter.hasNext()) { + PGPSecretKey key = (PGPSecretKey) keyIter.next(); - private PGPSecretKeyRingCollection _privateKeys; + if (key.isSigningKey()) { + return key; + } + } + } - private String passphrase; + throw new IllegalArgumentException("Can't find signing key in key ring."); + } - public Signer() { } - public Signer(PGPSecretKeyRingCollection privateKeys) { - setPrivateKeys(privateKeys); - } + public byte[] signData(byte[] inputData) throws Exception { + ByteArrayOutputStream signatureByteArrayOutputStream = new ByteArrayOutputStream(); + ArmoredOutputStream armoredSignatureOutputStream = new ArmoredOutputStream(signatureByteArrayOutputStream); - /** - * Accessor and Attribute Helper Methods - **/ - public PGPSecretKeyRingCollection getPrivateKeys() { - return _privateKeys; - } + PGPSecretKey pgpSigningKey = findSecretKey(); + PGPPrivateKey pgpPrivateKey = pgpSigningKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder() + .setProvider("BC").build(passphrase.toCharArray())); + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder( + pgpSigningKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC")); - public void setPrivateKeys(PGPSecretKeyRingCollection privateKeys) { - _privateKeys = privateKeys; - } + signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivateKey); - public void setPassphrase(String passphrase) { - this.passphrase = passphrase; - } + @SuppressWarnings("rawtypes") + Iterator iter = pgpSigningKey.getPublicKey().getUserIDs(); + if (iter.hasNext()) { + PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator(); - private PGPSecretKey findSecretKey() - throws PGPException, NoSuchProviderException { - Iterator keyRingIter = _privateKeys.getKeyRings(); - while (keyRingIter.hasNext()) - { - PGPSecretKeyRing keyRing = (PGPSecretKeyRing)keyRingIter.next(); + subpacketGenerator.setSignerUserID(false, (String) iter.next()); + signatureGenerator.setHashedSubpackets(subpacketGenerator.generate()); + } - Iterator keyIter = keyRing.getSecretKeys(); - while (keyIter.hasNext()) - { - PGPSecretKey key = (PGPSecretKey)keyIter.next(); + PGPCompressedDataGenerator compressor = new PGPCompressedDataGenerator(PGPCompressedData.ZLIB); - if (key.isSigningKey()) - { - return key; - } - } - } + BCPGOutputStream pgpOutputStream = new BCPGOutputStream(compressor.open(armoredSignatureOutputStream)); - throw new IllegalArgumentException("Can't find signing key in key ring."); - } + signatureGenerator.generateOnePassVersion(false).encode(pgpOutputStream); - public byte[] signData(byte[] clearData) - throws Exception { - String fileName = "something.txt"; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ArmoredOutputStream out = new ArmoredOutputStream(bos); + PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator(); + OutputStream literalDataGeneratorOutputStream = literalDataGenerator.open(pgpOutputStream, + PGPLiteralData.BINARY, PGPLiteralDataGenerator.CONSOLE, inputData.length, PGPLiteralDataGenerator.NOW); - PGPSecretKey pgpSec = findSecretKey(); - PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(passphrase.toCharArray())); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC")); + literalDataGeneratorOutputStream.write(inputData); + signatureGenerator.update(inputData); - sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey); + literalDataGenerator.close(); - Iterator it = pgpSec.getPublicKey().getUserIDs(); - if (it.hasNext()) - { - PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + signatureGenerator.generate().encode(pgpOutputStream); - spGen.setSignerUserID(false, (String)it.next()); - sGen.setHashedSubpackets(spGen.generate()); - } + compressor.close(); - PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator( - PGPCompressedData.ZLIB); + armoredSignatureOutputStream.close(); - BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out)); + return signatureByteArrayOutputStream.toByteArray(); + } - sGen.generateOnePassVersion(false).encode(bOut); + public String signDataDetached(String inputFileName) throws Exception { + ByteArrayOutputStream signatureByteArrayOutputStream = new ByteArrayOutputStream(); + ArmoredOutputStream armoredSignatureOutputStream = new ArmoredOutputStream(signatureByteArrayOutputStream); - File file = new File(fileName); - PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator(); - OutputStream lOut = lGen.open(bOut, - PGPLiteralData.BINARY, PGPLiteralDataGenerator.CONSOLE, - clearData.length, PGPLiteralDataGenerator.NOW); - int ch; + PGPSecretKey pgpSigningKey = findSecretKey(); + PGPPrivateKey pgpPrivateKey = pgpSigningKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder() + .setProvider("BC").build(passphrase.toCharArray())); + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder( + pgpSigningKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC")); - lOut.write(clearData); - sGen.update(clearData); + signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivateKey); - lGen.close(); + BCPGOutputStream pgpOutputStream = new BCPGOutputStream(armoredSignatureOutputStream); - sGen.generate().encode(bOut); + InputStream inputFileInputStream = new BufferedInputStream(new FileInputStream(inputFileName)); - cGen.close(); + int ch; + while ((ch = inputFileInputStream.read()) >= 0) { + signatureGenerator.update((byte) ch); + } - out.close(); + signatureGenerator.generate().encode(pgpOutputStream); - return bos.toByteArray(); - } + inputFileInputStream.close(); + armoredSignatureOutputStream.close(); + return new String(signatureByteArrayOutputStream.toByteArray()); + } } diff --git a/ext/org/sgonyea/pgp/Verifier.java b/ext/org/sgonyea/pgp/Verifier.java index 3c12801..3825bd2 100644 --- a/ext/org/sgonyea/pgp/Verifier.java +++ b/ext/org/sgonyea/pgp/Verifier.java @@ -10,95 +10,136 @@ package org.sgonyea.pgp; -import org.sgonyea.pgp.VerificationFailedException; - +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.Security; -import java.util.Date; -import java.util.Iterator; - -import org.bouncycastle.bcpg.ArmoredOutputStream; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openpgp.*; - -import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import java.security.GeneralSecurityException; + +import org.bouncycastle.openpgp.PGPCompressedData; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPOnePassSignature; +import org.bouncycastle.openpgp.PGPOnePassSignatureList; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureList; +import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; -import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; public class Verifier { + private PGPPublicKeyRingCollection _publicKeys; + + public Verifier() { + } + + /** + * Accessor and Attribute Helper Methods + **/ + public PGPPublicKeyRingCollection getPublicKeys() { + return _publicKeys; + } + + public void setPublicKeys(PGPPublicKeyRingCollection keys) { + _publicKeys = keys; + } + + public byte[] verifyStream(InputStream inputStream) throws Exception, VerificationFailedException { + InputStream pgpInputStream = PGPUtil.getDecoderStream(inputStream); + + PGPObjectFactory pgpFactory = new PGPObjectFactory(pgpInputStream); + PGPCompressedData pgpCompressedData = (PGPCompressedData) pgpFactory.nextObject(); + pgpFactory = new PGPObjectFactory(pgpCompressedData.getDataStream()); + PGPOnePassSignatureList pgpSignatureList = (PGPOnePassSignatureList) pgpFactory.nextObject(); + PGPOnePassSignature pgpOnePassSignature = pgpSignatureList.get(0); + + PGPLiteralData pgpLiteralData = (PGPLiteralData) pgpFactory.nextObject(); + + PGPPublicKey signingKey = _publicKeys.getPublicKey(pgpOnePassSignature.getKeyID()); + + if (signingKey == null) { + throw new VerificationFailedException("Error: Public key with signature's ID could not be found."); + } - private PGPPublicKeyRingCollection _publicKeys; + pgpOnePassSignature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), signingKey); - public Verifier() { } - /** - * Accessor and Attribute Helper Methods - **/ - public PGPPublicKeyRingCollection getPublicKeys() { - return _publicKeys; - } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - public void setPublicKeys(PGPPublicKeyRingCollection keys) { - _publicKeys = keys; - } + InputStream inputFileInputStream = pgpLiteralData.getInputStream(); + int ch; + while ((ch = inputFileInputStream.read()) >= 0) { + pgpOnePassSignature.update((byte) ch); + outputStream.write(ch); + } + outputStream.close(); - public byte[] verifyStream(InputStream inStream) - throws Exception, VerificationFailedException - { - InputStream in = PGPUtil.getDecoderStream(inStream); + PGPSignatureList pgpSignature = (PGPSignatureList) pgpFactory.nextObject(); - PGPObjectFactory pgpFact = new PGPObjectFactory(in); + if (!pgpOnePassSignature.verify(pgpSignature.get(0))) { + throw new VerificationFailedException("Error: Signature could not be verified."); + } - PGPCompressedData c1 = (PGPCompressedData)pgpFact.nextObject(); + byte[] returnBytes = outputStream.toByteArray(); + outputStream.close(); - pgpFact = new PGPObjectFactory(c1.getDataStream()); + return returnBytes; + } - PGPOnePassSignatureList p1 = (PGPOnePassSignatureList)pgpFact.nextObject(); + public boolean verifyDetachedSignature(String fileName, String signature) throws GeneralSecurityException, + IOException, PGPException, VerificationFailedException { + InputStream signatureInputStream = new BufferedInputStream(new ByteArrayInputStream(signature.getBytes())); - PGPOnePassSignature ops = p1.get(0); + boolean isVerified = verifyDetachedSignature(fileName, signatureInputStream); - PGPLiteralData p2 = (PGPLiteralData)pgpFact.nextObject(); + signatureInputStream.close(); - InputStream dIn = p2.getInputStream(); - int ch; + return isVerified; + } - PGPPublicKey key = _publicKeys.getPublicKey(ops.getKeyID()); - ByteArrayOutputStream out = new ByteArrayOutputStream(); + private boolean verifyDetachedSignature(String fileName, InputStream signature) throws GeneralSecurityException, + IOException, PGPException, VerificationFailedException { + signature = PGPUtil.getDecoderStream(signature); - if(key == null) { - throw new VerificationFailedException("Error: Signature could not be verified."); - } + PGPObjectFactory pgpFactory = new PGPObjectFactory(signature); + PGPSignatureList pgpSignatureList; - ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), key); + Object pgpObject = pgpFactory.nextObject(); + if (pgpObject instanceof PGPCompressedData) { + PGPCompressedData compressedData = (PGPCompressedData) pgpObject; - while ((ch = dIn.read()) >= 0) - { - ops.update((byte)ch); - out.write(ch); - } + pgpFactory = new PGPObjectFactory(compressedData.getDataStream()); - out.close(); + pgpSignatureList = (PGPSignatureList) pgpFactory.nextObject(); + } else { + pgpSignatureList = (PGPSignatureList) pgpObject; + } - PGPSignatureList p3 = (PGPSignatureList)pgpFact.nextObject(); + PGPSignature pgpSignature = pgpSignatureList.get(0); + PGPPublicKey pgpPublicKey = _publicKeys.getPublicKey(pgpSignature.getKeyID()); - if (!ops.verify(p3.get(0))) { - throw new VerificationFailedException("Error: Signature could not be verified."); - } + InputStream inputFileInputStream = new BufferedInputStream(new FileInputStream(fileName)); + if (pgpPublicKey == null) { + inputFileInputStream.close(); + throw new VerificationFailedException("Error: Public key with signature's ID could not be found."); + } - byte[] returnBytes = out.toByteArray(); - out.close(); + pgpSignature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), pgpPublicKey); - return returnBytes; + int ch; + while ((ch = inputFileInputStream.read()) >= 0) { + pgpSignature.update((byte) ch); + } + inputFileInputStream.close(); - } + if (!pgpSignature.verify()) { + throw new VerificationFailedException("Error: Signature could not be verified."); + } + return true; + } } From 92247509ac406438c15a1139554ba08630320b33 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:57:58 -0500 Subject: [PATCH 6/9] Don't ignore the jar --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c2debe9..f2b7f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ test/version_tmp tmp # Skip our compiled jruby-pgp.jar -lib/pgp/jruby-pgp.jar +# lib/pgp/jruby-pgp.jar From 459965ac232578cb281b8c7111191bf483e4ef87 Mon Sep 17 00:00:00 2001 From: Srdjan Grubor Date: Tue, 22 Apr 2014 12:58:13 -0500 Subject: [PATCH 7/9] Add the jar --- lib/pgp/jruby-pgp.jar | Bin 0 -> 24708 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/pgp/jruby-pgp.jar diff --git a/lib/pgp/jruby-pgp.jar b/lib/pgp/jruby-pgp.jar new file mode 100644 index 0000000000000000000000000000000000000000..c60d93da205e96b8ee63aa73fa97b18e94c26738 GIT binary patch literal 24708 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 )hMFZ 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 Date: Tue, 22 Apr 2014 13:58:57 -0500 Subject: [PATCH 8/9] Swapped the order of arguments for detached verifier to match GPG --- lib/pgp/jruby-pgp.jar | Bin 24708 -> 24709 bytes lib/pgp/verifier.rb | 4 ++-- spec/lib/pgp/signer_spec.rb | 2 +- spec/lib/pgp/verifier_spec.rb | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pgp/jruby-pgp.jar b/lib/pgp/jruby-pgp.jar index c60d93da205e96b8ee63aa73fa97b18e94c26738..9b5ec6c60e13e72370a29d8f58ec98874bd14d64 100644 GIT binary patch delta 3784 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 delta 3785 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 Date: Tue, 22 Apr 2014 14:27:28 -0500 Subject: [PATCH 9/9] Made sure that we cloase all streams --- ext/org/sgonyea/pgp/Signer.java | 8 +++++++- lib/pgp/jruby-pgp.jar | Bin 24709 -> 24770 bytes 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/org/sgonyea/pgp/Signer.java b/ext/org/sgonyea/pgp/Signer.java index 3001545..de227cb 100644 --- a/ext/org/sgonyea/pgp/Signer.java +++ b/ext/org/sgonyea/pgp/Signer.java @@ -154,6 +154,12 @@ public String signDataDetached(String inputFileName) throws Exception { armoredSignatureOutputStream.close(); - return new String(signatureByteArrayOutputStream.toByteArray()); + String signatureString = new String(signatureByteArrayOutputStream.toByteArray()); + + signatureByteArrayOutputStream.close(); + + pgpOutputStream.close(); + + return signatureString; } } diff --git a/lib/pgp/jruby-pgp.jar b/lib/pgp/jruby-pgp.jar index 9b5ec6c60e13e72370a29d8f58ec98874bd14d64..1de14261ee8c0fbac3dfc6ebedccab3b20819595 100644 GIT binary patch delta 4497 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 U$5WFaR4S9KU=RiuTmS$701stf?EnA(