Author: ogusakov
Date: Mon Aug 11 17:08:39 2008
New Revision: 684996
URL: http://svn.apache.org/viewvc?rev=684996&view=rev
Log:
implemented PGP signatures, changed StreamVerifier modus operandi to get
initialized with signature upfront as crypto signature needs that. Changed http
client to follow this new paradigm
Added:
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifier.java
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
Added:
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
URL:
http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties?rev=684996&view=auto
==============================================================================
---
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
(added)
+++
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
Mon Aug 11 17:08:39 2008
@@ -0,0 +1,23 @@
+null.input.stream=input stream should not be null
+bad.key.id=bad hex key id: {0}
+
+no.secret.key=no secret key {0} in the specified keyring
+no.public.key=no public key {0} in the specified keyring
+
+null.private.key=supplied key cannot be null
+
+null.verify.signature=out of sequence call to verify signature: verifier has
not been initialized yet
+
+bad.verify.signature.state=out of sequence call to produce signature: verifier
has not been initialized yet
+
+no.signatures.in.stream=no signatures found in the input streamn
+no.objects.in.stream=no pgp objects found in the input streamn
+
+bad.factory.init.verify=cannot initialize signature verification factory
without trusted ring
+bad.factory.init.verify.empty=trusted ring read in is null, cannot proceed
+bad.factory.init.generate=cannot initialize signature generation factory
without secret key
+
+no.stream.processor=neither signature generator nor signature verifier has
been initialized. Don't know what to do.
+no.trusted.ring=trusted ring seem to be empty. There is no one I can trust, so
signature verification is pointless.
+no.signature.string=there is signature supplied, so signature verification is
pointless.
+
Added:
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
URL:
http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java?rev=684996&view=auto
==============================================================================
---
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
(added)
+++
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
Mon Aug 11 17:08:39 2008
@@ -0,0 +1,173 @@
+package org.apache.maven.mercury.crypto.pgp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.Iterator;
+
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.bcpg.BCPGOutputStream;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPLiteralData;
+import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
+import org.bouncycastle.openpgp.PGPCompressedData;
+import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
+import org.bouncycastle.openpgp.PGPObjectFactory;
+import org.bouncycastle.openpgp.PGPOnePassSignature;
+import org.bouncycastle.openpgp.PGPOnePassSignatureList;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
+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.PGPSignatureList;
+import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.codehaus.plexus.i18n.DefaultLanguage;
+import org.codehaus.plexus.i18n.Language;
+
+/**
+ * PGP helper - collection of utility methods, loosely based on one of the
+ * Bouncy Castle's SignedFileProcessor.java
+ *
+ */
+public class PgpHelper
+{
+ public static final String PROVIDER = "BC";
+ public static final String EXTENSION = "asc";
+
+ private static final Language lang = new DefaultLanguage( PgpHelper.class );
+
//---------------------------------------------------------------------------------
+ static
+ {
+ Security.addProvider( new BouncyCastleProvider() );
+ }
+
//---------------------------------------------------------------------------------
+ /**
+ * load a key ring stream and find the secret key by hex id
+ *
+ * @param in PGP keystore
+ * @param hexId key id
+ * @return
+ * @throws IOException
+ * @throws PGPException
+ */
+ public static PGPSecretKeyRing readKeyRing( InputStream in, String hexId )
+ throws IOException, PGPException
+ {
+ if( in == null )
+ throw new IllegalArgumentException( lang.getMessage( "null.input.stream"
) );
+
+ if( hexId == null || hexId.length() < 16 )
+ throw new IllegalArgumentException( lang.getMessage( "bad.key.id", hexId
) );
+
+ long id = hexToId( hexId );
+
+ in = PGPUtil.getDecoderStream( in );
+
+ PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( in );
+
+ Iterator<PGPSecretKeyRing> ringIt = pgpSec.getKeyRings();
+
+ while( ringIt.hasNext() )
+ {
+ PGPSecretKeyRing keyRing = ringIt.next();
+ PGPSecretKey key = keyRing.getSecretKey( id );
+ if( key != null )
+ return keyRing;
+ }
+
+ throw new IllegalArgumentException( lang.getMessage( "no.secret.key",
hexId ) );
+ }
+
//---------------------------------------------------------------------------------
+ public static long hexToId( String hexId )
+ {
+ return Long.parseLong( hexId, 16 );
+ }
+
//---------------------------------------------------------------------------------
+ public static PGPSignature readSignature( InputStream inS )
+ throws IOException, PGPException
+ {
+ if( inS == null )
+ throw new IllegalArgumentException( "null.input.stream" );
+
+ InputStream in = inS;
+ in = PGPUtil.getDecoderStream( in );
+
+ PGPObjectFactory pgpObjectFactory = new PGPObjectFactory( in );
+ PGPSignatureList sigList = null;
+
+ Object pgpObject = pgpObjectFactory.nextObject();
+
+ if( pgpObject == null )
+ throw new PGPException( lang.getMessage( "no.objects.in.stream" ) );
+
+ if( pgpObject instanceof PGPCompressedData )
+ {
+ PGPCompressedData cd = (PGPCompressedData)pgpObject;
+
+ pgpObjectFactory = new PGPObjectFactory( cd.getDataStream() );
+
+ sigList = (PGPSignatureList)pgpObjectFactory.nextObject();
+ }
+ else
+ {
+ sigList = (PGPSignatureList)pgpObject;
+ }
+
+ if( sigList.size() < 1 )
+ throw new PGPException( lang.getMessage( "no.signatures.in.stream" ) );
+
+ PGPSignature sig = sigList.get(0);
+
+ return sig;
+ }
+
//---------------------------------------------------------------------------------
+ public static String streamToString( InputStream in )
+ throws IOException
+ {
+ if( in == null )
+ return null;
+
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ int b = 0;
+ while( (b = in.read()) != -1 )
+ ba.write( b );
+
+ return ba.toString();
+ }
+
//---------------------------------------------------------------------------------
+ public static String fileToString( String fileName )
+ throws IOException
+ {
+ FileInputStream fis = null;
+ try
+ {
+ fis = new FileInputStream( fileName );
+ return streamToString( fis );
+ }
+ finally
+ {
+ if( fis != null ) try { fis.close(); } catch( Exception any ) {}
+ }
+ }
+
//---------------------------------------------------------------------------------
+
//---------------------------------------------------------------------------------
+}
Added:
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifier.java
URL:
http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifier.java?rev=684996&view=auto
==============================================================================
---
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifier.java
(added)
+++
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifier.java
Mon Aug 11 17:08:39 2008
@@ -0,0 +1,210 @@
+package org.apache.maven.mercury.crypto.pgp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+
+import org.apache.maven.mercury.crypto.api.AbstractStreamVerifier;
+import org.apache.maven.mercury.crypto.api.StreamObserverException;
+import org.apache.maven.mercury.crypto.api.StreamVerifier;
+import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.bcpg.BCPGOutputStream;
+import org.bouncycastle.openpgp.PGPCompressedData;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPObjectFactory;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.PGPSignatureList;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.codehaus.plexus.i18n.DefaultLanguage;
+import org.codehaus.plexus.i18n.Language;
+import org.codehaus.plexus.util.StringInputStream;
+
+/**
+ * lightweight pgp stream encoder, created one per stream
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class PgpStreamVerifier
+extends AbstractStreamVerifier
+implements StreamVerifier
+{
+ public static final String TYPE = "pgp";
+ private static final Language lang = new DefaultLanguage(
PgpStreamVerifier.class );
+
+ private PGPPublicKeyRingCollection trustedPublicKeyRing;
+
+ private PGPSignatureGenerator signatureGenerator;
+
+ private PGPSignature signature;
+
+ private String signatureString;
+
+
//-----------------------------------------------------------------------------------
+ public PgpStreamVerifier( StreamVerifierAttributes attributes )
+ {
+ super( attributes );
+ }
+
//-----------------------------------------------------------------------------------
+ public void init( PGPPublicKeyRingCollection trustedPublicKeyRing )
+ {
+ this.trustedPublicKeyRing = trustedPublicKeyRing;
+ }
+
//-----------------------------------------------------------------------------------
+ public void init( PGPPrivateKey privateKey, int algorithm, int
digestAlgorithm )
+ throws StreamVerifierException
+ {
+ if( privateKey == null )
+ throw new IllegalArgumentException( lang.getMessage( "null.private.key"
));
+
+ try
+ {
+ signatureGenerator = new PGPSignatureGenerator( algorithm
+ , digestAlgorithm
+ , PgpHelper.PROVIDER
+ );
+ signatureGenerator.initSign( PGPSignature.BINARY_DOCUMENT, privateKey );
+
+ signatureString = null;
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException(e);
+ }
+ }
+
+
//-----------------------------------------------------------------------------------
+ public void byteReady( int b )
+ throws StreamObserverException
+ {
+ try
+ {
+ if( signature == null )
+ {
+ if( signatureGenerator == null )
+ throw new StreamVerifierException( lang.getMessage(
"no.stream.processor" ) );
+ signatureGenerator.update( (byte)b );
+ }
+ else
+ signature.update( (byte)b );
+ }
+ catch( SignatureException e )
+ {
+ throw new StreamObserverException(e);
+ }
+ }
+
+
//-----------------------------------------------------------------------------------
+ public void bytesReady( byte[] b, int off, int len )
+ throws StreamObserverException
+ {
+ try
+ {
+ if( signature == null )
+ {
+ if( signatureGenerator == null )
+ throw new StreamVerifierException( lang.getMessage(
"no.stream.processor" ) );
+ signatureGenerator.update( b, off, len );
+ }
+ else
+ signature.update( b, off, len );
+ }
+ catch( SignatureException e )
+ {
+ throw new StreamObserverException(e);
+ }
+ }
+
//-----------------------------------------------------------------------------------
+ public void initSignature( String signatureString )
+ throws StreamVerifierException
+ {
+ try
+ {
+ if( trustedPublicKeyRing == null )
+ throw new StreamVerifierException( lang.getMessage( "no.trusted.ring"
) );
+
+ if( signatureString == null || signatureString.length() < 1 )
+ throw new StreamVerifierException( lang.getMessage(
"no.signature.string" ) );
+
+ signature = PgpHelper.readSignature( new ByteArrayInputStream(
signatureString.getBytes() ) );
+
+ if( signature == null )
+ throw new StreamVerifierException( "no.signatures.in.stream" );
+
+ signature.initVerify( trustedPublicKeyRing.getPublicKey(
signature.getKeyID() ), PgpHelper.PROVIDER );
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException(e);
+ }
+
+ if( signature == null )
+ throw new StreamVerifierException("no.signatures.in.stream");
+
+ }
+
//-----------------------------------------------------------------------------------
+ public boolean verifySignature()
+ throws StreamVerifierException
+ {
+
+ if( signature == null )
+ throw new StreamVerifierException( lang.getMessage(
"null.verify.signature" ));
+
+ try
+ {
+ return signature.verify();
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException( e );
+ }
+ }
+
+
//-----------------------------------------------------------------------------------
+ public String getSignature()
+ throws StreamVerifierException
+ {
+ if( signatureString != null )
+ return signatureString;
+
+ if( signatureGenerator == null )
+ throw new StreamVerifierException("bad.verify.signature.state");
+
+ BCPGOutputStream signaturePgpBytes = null;
+ try
+ {
+ ByteArrayOutputStream signatureBytes = new ByteArrayOutputStream();
+ ArmoredOutputStream aos = new ArmoredOutputStream( signatureBytes );
+ signaturePgpBytes = new BCPGOutputStream( aos );
+ signatureGenerator.generate().encode( signaturePgpBytes );
+ signaturePgpBytes.finish();
+ aos.flush();
+ aos.close();
+ signatureString = signatureBytes.toString();
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException( e );
+ }
+ finally
+ {
+ if( signaturePgpBytes != null ) try { signaturePgpBytes.close(); }
catch( Exception any ) {}
+ }
+
+ signatureGenerator = null;
+
+ return signatureString;
+ }
+
//-----------------------------------------------------------------------------------
+
//-----------------------------------------------------------------------------------
+}
Added:
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
URL:
http://svn.apache.org/viewvc/maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java?rev=684996&view=auto
==============================================================================
---
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
(added)
+++
maven/sandbox/trunk/mercury/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
Mon Aug 11 17:08:39 2008
@@ -0,0 +1,128 @@
+package org.apache.maven.mercury.crypto.pgp;
+
+import java.io.InputStream;
+
+import org.apache.maven.mercury.crypto.api.AbstractStreamVerifierFactory;
+import org.apache.maven.mercury.crypto.api.StreamVerifier;
+import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
+import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.codehaus.plexus.i18n.DefaultLanguage;
+import org.codehaus.plexus.i18n.Language;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class PgpStreamVerifierFactory
+extends AbstractStreamVerifierFactory
+implements StreamVerifierFactory
+{
+
+ public static final String DEFAULT_EXTENSION = PgpHelper.EXTENSION;
+
+ private static final Language lang = new DefaultLanguage(
PgpStreamVerifierFactory.class );
+
+ private PGPPublicKeyRingCollection trustedPublicKeyRing;
+
+ private PGPPrivateKey privateKey;
+
+ private int algorithm = 0;
+
+ private int digestAlgorithm = PGPUtil.SHA1;
+
+
//--------------------------------------------------------------------------------------------
+ public PgpStreamVerifierFactory( StreamVerifierAttributes attributes
+ , InputStream trustedPublicKeyRingStream
+ )
+ throws StreamVerifierException
+ {
+ super( attributes );
+ init( trustedPublicKeyRingStream );
+
+ }
+
//--------------------------------------------------------------------------------------------
+ public PgpStreamVerifierFactory( StreamVerifierAttributes attributes
+ , InputStream secretKeyRingStream
+ , String secretKeyId
+ , String secretKeyPass
+ )
+ throws StreamVerifierException
+ {
+ super( attributes );
+ init( secretKeyRingStream, secretKeyId, secretKeyPass );
+ }
+
//--------------------------------------------------------------------------------------------
+ public void init( InputStream trustedPublicKeyRingStream )
+ throws StreamVerifierException
+ {
+ try
+ {
+ if( trustedPublicKeyRingStream != null )
+ {
+ trustedPublicKeyRing = new
PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(trustedPublicKeyRingStream));
+ if( trustedPublicKeyRing == null )
+ throw new StreamVerifierException( lang.getMessage(
"bad.factory.init.verify.empty" ) );
+ }
+ else
+ throw new StreamVerifierException( lang.getMessage(
"bad.factory.init.verify" ) );
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException(e);
+ }
+ }
+
//--------------------------------------------------------------------------------------------
+ public void init( InputStream secretKeyRingStream
+ , String secretKeyId
+ , String secretKeyPass
+ )
+ throws StreamVerifierException
+ {
+ try
+ {
+ if( secretKeyRingStream != null && secretKeyId != null && secretKeyPass
!= null )
+ {
+ PGPSecretKeyRing secRing = PgpHelper.readKeyRing( secretKeyRingStream,
secretKeyId );
+ PGPSecretKey secKey = secRing.getSecretKey( PgpHelper.hexToId(
secretKeyId ) );
+ privateKey = secKey.extractPrivateKey( secretKeyPass.toCharArray(),
PgpHelper.PROVIDER );
+ algorithm = secKey.getPublicKey().getAlgorithm();
+ }
+ else
+ throw new StreamVerifierException( lang.getMessage(
"bad.factory.init.generate" ) );
+ }
+ catch( Exception e )
+ {
+ throw new StreamVerifierException(e);
+ }
+ }
+
//--------------------------------------------------------------------------------------------
+ public String getDefaultExtension()
+ {
+ return DEFAULT_EXTENSION;
+ }
+
//--------------------------------------------------------------------------------------------
+ public StreamVerifier newInstance()
+ throws StreamVerifierException
+ {
+ PgpStreamVerifier sv = new PgpStreamVerifier( attributes );
+
+ if( privateKey != null )
+ sv.init( privateKey, algorithm, digestAlgorithm );
+
+ if( trustedPublicKeyRing != null )
+ sv.init( trustedPublicKeyRing );
+
+ return sv;
+ }
+
//--------------------------------------------------------------------------------------------
+
//--------------------------------------------------------------------------------------------
+}