Temporarily include bndlib 1.47 for testing purposes (not yet on central)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1185095 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java
new file mode 100644
index 0000000..630597f
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Crypto.java
@@ -0,0 +1,67 @@
+package aQute.libg.cryptography;
+
+import java.math.*;
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+import java.util.regex.*;
+
+public class Crypto {
+	static final Pattern	RSA_PRIVATE	= Pattern
+												.compile("\\s*RSA.Private\\((\\p{xDigit})+:(\\p{xDigit})+\\)\\s*");
+	static final Pattern	RSA_PUBLIC	= Pattern
+												.compile("\\s*RSA.Public\\((\\p{xDigit})+:(\\p{xDigit})+\\)\\s*");
+
+	/**
+	 * 
+	 * @param <T>
+	 * @param spec
+	 * @return
+	 * @throws Exception
+	 */
+	@SuppressWarnings("unchecked") public static <T> T fromString(String spec, Class<T> c) throws Exception {
+		if ( PrivateKey.class.isAssignableFrom(c)) {
+			Matcher m = RSA_PRIVATE.matcher(spec); 
+			if ( m.matches()) {
+				return (T) RSA.createPrivate(  
+						new BigInteger(m.group(1)), new BigInteger(m.group(2)));
+			}
+			throw new IllegalArgumentException("No such private key " + spec );
+		}
+		
+		if ( PublicKey.class.isAssignableFrom(c)) {
+			Matcher m = RSA_PUBLIC.matcher(spec); 
+			if ( m.matches()) {
+				return (T) RSA.create( new RSAPublicKeySpec( 
+						new BigInteger(m.group(1)), new BigInteger(m.group(2))));
+			}
+			throw new IllegalArgumentException("No such public key " + spec );			
+		}
+		return null;
+	}
+
+	public static String toString( Object key ) {
+		if ( key instanceof RSAPrivateKey ) {
+			RSAPrivateKey pk = (RSAPrivateKey) key;
+			return "RSA.Private(" + pk.getModulus() + ":" + pk.getPrivateExponent() + ")";
+		}
+		if ( key instanceof RSAPublicKey ) {
+			RSAPublicKey pk = (RSAPublicKey) key;
+			return "RSA.Private(" + pk.getModulus() + ":" + pk.getPublicExponent() + ")";
+		}
+		return null;
+	}
+
+
+	public static <T extends Digest> Signer<T> signer(PrivateKey key, Digester<T> digester) throws NoSuchAlgorithmException {
+		Signature s = Signature.getInstance(key.getAlgorithm() + "with" + digester.getAlgorithm());
+		return new Signer<T>(s,digester);
+	}
+
+	public static Verifier verifier(PublicKey key, Digest digest) throws NoSuchAlgorithmException {
+		Signature s = Signature.getInstance(key.getAlgorithm() + "with" + digest.getAlgorithm());
+		return new Verifier(s,digest);
+	}
+
+	
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Digest.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Digest.java
new file mode 100644
index 0000000..f70caa0
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Digest.java
@@ -0,0 +1,25 @@
+package aQute.libg.cryptography;
+
+import aQute.lib.hex.*;
+
+public abstract class Digest {
+	final byte[]	digest;
+
+	protected Digest(byte[] checksum, int width) {
+		this.digest = checksum;
+		if (digest.length != width)
+			throw new IllegalArgumentException("Invalid width for digest: " + digest.length
+					+ " expected " + width);
+	}
+
+
+	public byte[] digest() {
+		return digest;
+	}
+
+	@Override public String toString() {
+		return String.format("%s(d=%s)", getAlgorithm(), Hex.toHexString(digest));
+	}
+
+	public abstract String getAlgorithm();
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Digester.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Digester.java
new file mode 100644
index 0000000..50b9659
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Digester.java
@@ -0,0 +1,35 @@
+package aQute.libg.cryptography;
+
+import java.io.*;
+import java.security.*;
+
+import aQute.lib.io.*;
+
+public abstract class Digester<T extends Digest> extends OutputStream {
+	protected MessageDigest	md;
+	
+	public Digester(MessageDigest instance){
+		md = instance;
+	}
+	@Override
+	public void write( byte[] buffer, int offset, int length) throws IOException{
+		md.update(buffer,offset,length);
+	}
+	@Override
+	public void write( int b) throws IOException{
+		md.update((byte) b);
+	}
+	
+	public MessageDigest getMessageDigest() throws Exception {
+		return md;
+	}
+	
+	public T from(InputStream in) throws Exception {
+		IO.copy(in,this);
+		return digest();
+	}
+		
+	public abstract T digest() throws Exception;
+	public abstract T digest( byte [] bytes) throws Exception;
+	public abstract String getAlgorithm();
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Key.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Key.java
new file mode 100644
index 0000000..160ec05
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Key.java
@@ -0,0 +1,8 @@
+package aQute.libg.cryptography;
+
+
+public abstract class Key implements java.security.Key {
+	private static final long	serialVersionUID	= 1L;
+
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/MD5.java b/bundleplugin/src/main/java/aQute/libg/cryptography/MD5.java
new file mode 100644
index 0000000..3fd7158
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/MD5.java
@@ -0,0 +1,33 @@
+package aQute.libg.cryptography;
+
+import java.security.*;
+
+
+
+public class MD5 extends Digest {
+	public final static String ALGORITHM = "MD5";
+	
+	public static Digester<MD5> getDigester() throws Exception {
+		return new Digester<MD5>(MessageDigest.getInstance(ALGORITHM)) {
+			
+			@Override public MD5 digest() throws Exception {
+				return new MD5(md.digest());
+			}
+
+			@Override public MD5 digest(byte[] bytes) {
+				return new MD5(bytes);
+			}
+			@Override public String getAlgorithm() {
+				return ALGORITHM;
+			}
+		};
+	}
+	
+	
+	public MD5(byte[] digest) {
+		super(digest,16);
+	}
+
+	@Override public String getAlgorithm() { return ALGORITHM; }
+
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/RSA.java b/bundleplugin/src/main/java/aQute/libg/cryptography/RSA.java
new file mode 100644
index 0000000..61bafb5
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/RSA.java
@@ -0,0 +1,43 @@
+package aQute.libg.cryptography;
+
+import java.math.*;
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import aQute.libg.tuple.*;
+
+public class RSA {
+	final static String		ALGORITHM	= "RSA";
+
+	final static KeyFactory	factory		= getKeyFactory();
+
+	static private KeyFactory getKeyFactory() {
+		try {
+			return KeyFactory.getInstance(ALGORITHM);
+		} catch (Exception e) {
+			// built in
+		}
+		return null;
+	}
+
+	public static RSAPrivateKey create(RSAPrivateKeySpec keyspec) throws InvalidKeySpecException {
+		return (RSAPrivateKey) factory.generatePrivate(keyspec);
+	}
+	public static RSAPublicKey create(RSAPublicKeySpec keyspec) throws InvalidKeySpecException {
+		return (RSAPublicKey) factory.generatePrivate(keyspec);
+	}
+	
+	public static RSAPublicKey createPublic(BigInteger m, BigInteger e) throws InvalidKeySpecException {
+		return create( new RSAPublicKeySpec(m,e));
+	}
+	public static RSAPrivateKey createPrivate(BigInteger m, BigInteger e) throws InvalidKeySpecException {
+		return create( new RSAPrivateKeySpec(m,e));
+	}
+	
+	public static Pair<RSAPrivateKey, RSAPublicKey> generate() throws NoSuchAlgorithmException {
+		KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
+		KeyPair keypair = kpg.generateKeyPair();
+		return new Pair<RSAPrivateKey,RSAPublicKey>( (RSAPrivateKey) keypair.getPrivate(), (RSAPublicKey) keypair.getPublic());
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/SHA1.java b/bundleplugin/src/main/java/aQute/libg/cryptography/SHA1.java
new file mode 100644
index 0000000..22e725b
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/SHA1.java
@@ -0,0 +1,33 @@
+package aQute.libg.cryptography;
+
+import java.security.*;
+
+
+
+public class SHA1 extends Digest {
+	public final static String ALGORITHM = "SHA1";
+	
+	public static Digester<SHA1> getDigester() throws NoSuchAlgorithmException {
+		MessageDigest md = MessageDigest.getInstance(ALGORITHM);
+		return new Digester<SHA1>(md) {
+			@Override public SHA1 digest() throws Exception {
+				return new SHA1(md.digest());
+			}
+
+			@Override public SHA1 digest(byte[] bytes) {
+				return new SHA1(bytes);
+			}
+			@Override public String getAlgorithm() {
+				return ALGORITHM;
+			}
+		};
+	}
+	
+	public SHA1(byte[] b) {
+		super(b, 20);
+	}
+
+
+	@Override public String getAlgorithm() { return ALGORITHM; }
+
+}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Signer.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Signer.java
new file mode 100644
index 0000000..a068677
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Signer.java
@@ -0,0 +1,35 @@
+package aQute.libg.cryptography;
+
+import java.io.*;
+import java.security.*;
+
+public class Signer<D extends Digest> extends OutputStream {
+	Signature	signature;
+	Digester<D> digester;
+	
+	Signer(Signature s, Digester<D> digester) {
+		this.signature = s;
+		this.digester  = digester;
+	}
+
+	@Override public void write(byte[] buffer, int offset, int length) throws IOException {
+		try {
+			signature.update(buffer, offset, length);
+		} catch (SignatureException e) {
+			throw new IOException(e);
+		}
+	}
+
+	@Override public void write(int b) throws IOException {
+		try {
+			signature.update((byte) b);
+		} catch (SignatureException e) {
+			throw new IOException(e);
+		}
+	}
+	
+
+	public D signature() throws Exception {
+		return digester.digest(signature().digest());
+	}
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/Verifier.java b/bundleplugin/src/main/java/aQute/libg/cryptography/Verifier.java
new file mode 100644
index 0000000..90d6993
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/Verifier.java
@@ -0,0 +1,38 @@
+package aQute.libg.cryptography;
+
+import java.io.*;
+import java.security.*;
+
+
+public class Verifier extends OutputStream {
+	final Signature signature;
+	final Digest d;
+	
+	Verifier(Signature s, Digest d) {
+		this.signature = s;
+		this.d = d;
+	}
+	
+	@Override
+	public void write( byte[] buffer, int offset, int length) throws IOException {
+		try {
+			signature.update(buffer, offset, length);
+		} catch (SignatureException e) {
+			throw new IOException(e);
+		}
+	}
+
+	@Override
+	public void write( int b) throws IOException {
+		try {
+			signature.update((byte) b);
+		} catch (SignatureException e) {
+			throw new IOException(e);
+		}
+	}
+
+	public boolean verify() throws Exception {
+		return signature.verify(d.digest());
+	}
+	
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/cryptography/packageinfo b/bundleplugin/src/main/java/aQute/libg/cryptography/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/cryptography/packageinfo
@@ -0,0 +1 @@
+version 1.0