summaryrefslogtreecommitdiff
path: root/gnu/java
diff options
context:
space:
mode:
authorRaif S. Naffah <raif@swiftdsl.com.au>2006-02-09 11:52:48 +0000
committerRaif S. Naffah <raif@swiftdsl.com.au>2006-02-09 11:52:48 +0000
commit9460f315752210eeb2a38061e30cf2b9a9009ddf (patch)
tree2267381d705885e38eb1952934d0969de311be4b /gnu/java
parentd8993f8af9c2de977890ab8d5a2724f081b8485d (diff)
downloadclasspath-9460f315752210eeb2a38061e30cf2b9a9009ddf.tar.gz
2006-02-09 Raif S. Naffah <raif@swiftdsl.com.au>
* gnu/java/security/key/rsa/RSAKeyPairX509Codec.java: New file. * gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java: Likewise. * gnu/java/security/key/rsa/RSAKeyPairGenerator.java (PREFERRED_ENCODING_FORMAT): New constant. (DEFAULT_ENCODING_FORMAT): Likewise. (preferredFormat): New field. (setup): Add support for preferred encoding format. (generate): Call key constructors with explicit format identifier. * gnu/java/security/key/rsa/GnuRSAPublicKey.java (GnuRSAPublicKey(2)): Call constructor with 3 arguments.. (GnuRSAPublicKey(3)): New constructor. (valueOf): Added support for ASN.1 format. (getEncoded): Likewise. * gnu/java/security/key/rsa/GnuRSAPrivateKey.java (GnuRSAPrivateKey(4)): Call constructor with 5 arguments. (GnuRSAPrivateKey(5)): New constructor. (GnuRSAPrivateKey(9)): New constructor. (valueOf): Added support for ASN.1 format. (getEncoded): Likewise. * gnu/java/security/key/rsa/GnuRSAKey.java (defaultFormat): New field. (GnuRSAKey): Modified constructor. (getFormat): Return preferred format identifier. * gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java (decodePrivateKey): Fixed documentation. Check Version field. * gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java (initialize(int,SecureRandom)): Set ASN.1 as the preferred encoding format. (initialize(AlgorithmParameterSpec,SecureRandom)): Likewise. * gnu/java/security/jce/sig/EncodedKeyFactory.java (engineGeneratePublic): Added support for RSA. (engineGeneratePrivate): Likewise.
Diffstat (limited to 'gnu/java')
-rw-r--r--gnu/java/security/jce/sig/EncodedKeyFactory.java20
-rw-r--r--gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java6
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java8
-rw-r--r--gnu/java/security/key/rsa/GnuRSAKey.java22
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPrivateKey.java136
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPublicKey.java84
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairGenerator.java22
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java289
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairX509Codec.java237
9 files changed, 726 insertions, 98 deletions
diff --git a/gnu/java/security/jce/sig/EncodedKeyFactory.java b/gnu/java/security/jce/sig/EncodedKeyFactory.java
index 5b99607e3..7075b3541 100644
--- a/gnu/java/security/jce/sig/EncodedKeyFactory.java
+++ b/gnu/java/security/jce/sig/EncodedKeyFactory.java
@@ -41,6 +41,8 @@ package gnu.java.security.jce.sig;
import gnu.java.security.Registry;
import gnu.java.security.key.dss.DSSPrivateKey;
import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
@@ -79,7 +81,14 @@ public class EncodedKeyFactory
{
}
- // FIXME: try RSA
+ // try RSA
+ try
+ {
+ return GnuRSAPublicKey.valueOf(input);
+ }
+ catch (InvalidParameterException ignored)
+ {
+ }
// FIXME: try DH
@@ -103,7 +112,14 @@ public class EncodedKeyFactory
{
}
- // FIXME: try RSA
+ // try RSA
+ try
+ {
+ return GnuRSAPrivateKey.valueOf(input);
+ }
+ catch (InvalidParameterException ignored)
+ {
+ }
// FIXME: try DH
diff --git a/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java b/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
index 54783eacf..24dc7c501 100644
--- a/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
+++ b/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
@@ -1,4 +1,4 @@
-/* RSAKeyPairGeneratorSpi.java --
+/* RSAKeyPairGeneratorSpi.java -- JCE RSA KeyPairGenerator Adapter
Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -84,6 +84,8 @@ public class RSAKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
}
+ attributes.put(RSAKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
adaptee.setup(attributes);
}
@@ -106,6 +108,8 @@ public class RSAKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
}
+ attributes.put(RSAKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
adaptee.setup(attributes);
}
}
diff --git a/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java b/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java
index bdbd31b4b..8918804c6 100644
--- a/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java
+++ b/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java
@@ -177,7 +177,7 @@ public class DSSKeyPairPKCS8Codec
/**
* @param input the byte array to unmarshall into a valid DSS
- * {@link PublicKey} instance. MUST NOT be null.
+ * {@link PrivateKey} instance. MUST NOT be null.
* @return a new instance of a {@link DSSPrivateKey} decoded from the
* <i>PrivateKeyInfo</i> material fed as <code>input</code>.
* @throw InvalidParameterException if an exception occurs during the
@@ -188,7 +188,7 @@ public class DSSKeyPairPKCS8Codec
if (input == null)
throw new InvalidParameterException("Input bytes MUST NOT be null");
- BigInteger p, q, g, x;
+ BigInteger version, p, q, g, x;
DERReader der = new DERReader(input);
try
{
@@ -199,6 +199,10 @@ public class DSSKeyPairPKCS8Codec
if (! (derVersion.getValue() instanceof BigInteger))
throw new InvalidParameterException("Wrong Version field");
+ version = (BigInteger) derVersion.getValue();
+ if (version.compareTo(BigInteger.ZERO) != 0)
+ throw new InvalidParameterException("Unexpected Version: " + version);
+
DERValue derAlgoritmID = der.read();
checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
diff --git a/gnu/java/security/key/rsa/GnuRSAKey.java b/gnu/java/security/key/rsa/GnuRSAKey.java
index a92ef50a5..953ad54a0 100644
--- a/gnu/java/security/key/rsa/GnuRSAKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAKey.java
@@ -40,6 +40,7 @@ package gnu.java.security.key.rsa;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
import java.math.BigInteger;
import java.security.Key;
@@ -48,7 +49,7 @@ import java.security.interfaces.RSAKey;
/**
* <p>A base asbtract class for both public and private RSA keys.</p>
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
*/
public abstract class GnuRSAKey implements Key, RSAKey
{
@@ -62,20 +63,29 @@ public abstract class GnuRSAKey implements Key, RSAKey
/** The public exponent of an RSA key pair. */
private final BigInteger e;
+ /**
+ * Identifier of the default encoding format to use when externalizing the
+ * key material.
+ */
+ protected final int defaultFormat;
+
// Constructor(s)
// -------------------------------------------------------------------------
/**
- * <p>Trivial protected constructor.</p>
- *
+ * Trivial protected constructor.
+ *
+ * @param defaultFormat the identifier of the encoding format to use by
+ * default when externalizing the key.
* @param n the public modulus <code>n</code>.
* @param e the public exponent <code>e</code>.
*/
- // protected GnuRSAKey(BigInteger n) {
- protected GnuRSAKey(final BigInteger n, final BigInteger e)
+ protected GnuRSAKey(int defaultFormat, BigInteger n, BigInteger e)
{
super();
+ this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
+ : defaultFormat;
this.n = n;
this.e = e;
}
@@ -108,7 +118,7 @@ public abstract class GnuRSAKey implements Key, RSAKey
public String getFormat()
{
- return null;
+ return KeyPairCodecFactory.getEncodingShortName(defaultFormat);
}
// Other instance methods --------------------------------------------------
diff --git a/gnu/java/security/key/rsa/GnuRSAPrivateKey.java b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
index 851ea271b..48d7e7df7 100644
--- a/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
@@ -57,7 +57,7 @@ import java.security.interfaces.RSAPrivateKey;
* Jakob Jonsson and Burt Kaliski.</li>
* </ol>
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
*/
public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
RSAPrivateCrtKey
@@ -90,80 +90,119 @@ public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
// -------------------------------------------------------------------------
/**
- * <p>Trivial constructor.</p>
+ * Convenience constructor. Calls the constructor with 5 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
*
* @param p the modulus first prime divisor.
* @param q the modulus second prime divisor.
* @param e the public exponent.
* @param d the private exponent.
*/
- public GnuRSAPrivateKey(final BigInteger p, final BigInteger q,
- final BigInteger e, final BigInteger d)
+ public GnuRSAPrivateKey(BigInteger p, BigInteger q, BigInteger e,
+ BigInteger d)
{
- // super(p.multiply(q));
- super(p.multiply(q), e);
+ this(Registry.RAW_ENCODING_ID, p, q, e, d);
+ }
+ /**
+ * Constructs a new instance of a <code>GnuRSAPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ */
+ public GnuRSAPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger e, BigInteger d)
+ {
+ this(preferredFormat, p.multiply(q), e, d, p, q,
+ e.modInverse(p.subtract(BigInteger.ONE)),
+ e.modInverse(q.subtract(BigInteger.ONE)),
+ q.modInverse(p));
+ }
+
+ /**
+ * Constructs a new instance of a <code>GnuRSAPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param n the public modulus, which is also the product of <code>p</code>
+ * and <code>q</code>.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param dP the first prime's exponen. A positive integer less than
+ * <code>p</code> and <code>q</code>, satisfying <code>e * dP = 1 (mod p-1)
+ * </code>.
+ * @param dQ the second prime's exponent. A positive integer less than
+ * <code>p</code> and <code>q</code>, satisfying <code>e * dQ = 1 (mod p-1)
+ * </code>.
+ * @param qInv the Chinese Remainder Theorem coefiicient. A positive integer
+ * less than <code>p</code>, satisfying <code>q * qInv = 1 (mod p)</code>.
+ */
+ GnuRSAPrivateKey(int preferredFormat, BigInteger n, BigInteger e,
+ BigInteger d, BigInteger p, BigInteger q, BigInteger dP,
+ BigInteger dQ, BigInteger qInv)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
+ : preferredFormat,
+ n, e);
+
+ this.d = d;
this.p = p;
this.q = q;
- // this.e = e;
- this.d = d;
-
// the exponents dP and dQ are positive integers less than p and q
// respectively satisfying
// e * dP = 1 (mod p-1);
// e * dQ = 1 (mod q-1),
- dP = e.modInverse(p.subtract(BigInteger.ONE));
- dQ = e.modInverse(q.subtract(BigInteger.ONE));
- // and the CRT coefficient qInv is a positive integer less than p
- // satisfying
+ this.dP = dP;
+ this.dQ = dQ;
+ // the CRT coefficient qInv is a positive integer less than p satisfying
// q * qInv = 1 (mod p).
- qInv = q.modInverse(p);
+ this.qInv = qInv;
}
// Class methods
// -------------------------------------------------------------------------
/**
- * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * A class method that takes the output of the <code>encodePrivateKey()</code>
* method of an RSA keypair codec object (an instance implementing
- * {@link gnu.crypto.key.IKeyPairCodec} for RSA keys, and re-constructs an
- * instance of this object.</p>
- *
+ * {@link IKeyPairCodec} for RSA keys, and re-constructs an instance of this
+ * object.
+ *
* @param k the contents of a previously encoded instance of this object.
* @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
- * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * <code>k</code>, to represent a valid encoding of an instance
+ * of this object.
* @throws IllegalArgumentException if the byte sequence does not represent a
- * valid encoding of an instance of this object.
+ * valid encoding of an instance of this object.
*/
public static GnuRSAPrivateKey valueOf(final byte[] k)
{
- // check magic...
- // we should parse here enough bytes to know which codec to use, and
- // direct the byte array to the appropriate codec. since we only have one
- // codec, we could have immediately tried it; nevertheless since testing
- // one byte is cheaper than instatiating a codec that will fail we test
- // the first byte before we carry on.
+ // try RAW codec
if (k[0] == Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0])
- {
- // it's likely to be in raw format. get a raw codec and hand it over
- final IKeyPairCodec codec = new RSAKeyPairRawCodec();
- return (GnuRSAPrivateKey) codec.decodePrivateKey(k);
- }
- else
- {
- throw new IllegalArgumentException("magic");
- }
+ try
+ {
+ return (GnuRSAPrivateKey) new RSAKeyPairRawCodec().decodePrivateKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try PKCS#8 codec
+ return (GnuRSAPrivateKey) new RSAKeyPairPKCS8Codec().decodePrivateKey(k);
}
// Instance methods
// -------------------------------------------------------------------------
- // java.security.interfaces.RSAPrivateCrtKey interface implementation ------
-
- // public BigInteger getPublicExponent() {
- // return e;
- // }
-
public BigInteger getPrimeP()
{
return p;
@@ -199,16 +238,17 @@ public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
// Other instance methods --------------------------------------------------
/**
- * <p>Returns the encoded form of this private key according to the
- * designated format.</p>
+ * Returns the encoded form of this private key according to the
+ * designated format.
*
* @param format the desired format identifier of the resulting encoding.
* @return the byte sequence encoding this key according to the designated
* format.
* @throws IllegalArgumentException if the format is not supported.
- * @see gnu.crypto.key.rsa.RSAKeyPairRawCodec
+ * @see RSAKeyPairRawCodec
+ * @see RSAKeyPairPKCS8Codec
*/
- public byte[] getEncoded(final int format)
+ public byte[] getEncoded(int format)
{
final byte[] result;
switch (format)
@@ -216,8 +256,12 @@ public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
case IKeyPairCodec.RAW_FORMAT:
result = new RSAKeyPairRawCodec().encodePrivateKey(this);
break;
+ case IKeyPairCodec.PKCS8_FORMAT:
+ result = new RSAKeyPairPKCS8Codec().encodePrivateKey(this);
+ break;
default:
- throw new IllegalArgumentException("format");
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
}
return result;
}
diff --git a/gnu/java/security/key/rsa/GnuRSAPublicKey.java b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
index 0e5cdb4cf..f49027ca6 100644
--- a/gnu/java/security/key/rsa/GnuRSAPublicKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
@@ -56,7 +56,7 @@ import java.security.interfaces.RSAPublicKey;
* Jakob Jonsson and Burt Kaliski.</li>
* </ol>
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.2 $
*/
public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
RSAPublicKey
@@ -65,70 +65,73 @@ public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
// Constants and variables
// -------------------------------------------------------------------------
- /** The public exponent of an RSA public key. */
- // private final BigInteger e;
// Constructor(s)
// -------------------------------------------------------------------------
+
/**
- * <p>Trivial constructor.</p>
+ * Conveience constructor. Calls the constructor with 3 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
*
* @param n the modulus.
* @param e the public exponent.
*/
public GnuRSAPublicKey(final BigInteger n, final BigInteger e)
{
- // super(n);
- super(n, e);
- //
- // this.e = e;
+ this(Registry.RAW_ENCODING_ID, n, e);
+ }
+
+ /**
+ * Constructs a new instance of <code>GnuRSAPublicKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the identifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param n the modulus.
+ * @param e the public exponent.
+ */
+ public GnuRSAPublicKey(int preferredFormat, BigInteger n, BigInteger e)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
+ : preferredFormat,
+ n, e);
}
// Class methods
// -------------------------------------------------------------------------
/**
- * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * A class method that takes the output of the <code>encodePublicKey()</code>
* method of an RSA keypair codec object (an instance implementing
- * {@link gnu.crypto.key.IKeyPairCodec} for RSA keys, and re-constructs an
- * instance of this object.</p>
- *
+ * {@link IKeyPairCodec} for RSA keys, and re-constructs an instance of this
+ * object.
+ *
* @param k the contents of a previously encoded instance of this object.
* @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
- * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * <code>k</code>, to represent a valid encoding of an instance
+ * of this object.
* @throws IllegalArgumentException if the byte sequence does not represent a
- * valid encoding of an instance of this object.
+ * valid encoding of an instance of this object.
*/
public static GnuRSAPublicKey valueOf(final byte[] k)
{
- // check magic...
- // we should parse here enough bytes to know which codec to use, and
- // direct the byte array to the appropriate codec. since we only have one
- // codec, we could have immediately tried it; nevertheless since testing
- // one byte is cheaper than instatiating a codec that will fail we test
- // the first byte before we carry on.
+ // try RAW codec
if (k[0] == Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0])
- {
- // it's likely to be in raw format. get a raw codec and hand it over
- final IKeyPairCodec codec = new RSAKeyPairRawCodec();
- return (GnuRSAPublicKey) codec.decodePublicKey(k);
- }
- else
- {
- throw new IllegalArgumentException("magic");
- }
+ try
+ {
+ return (GnuRSAPublicKey) new RSAKeyPairRawCodec().decodePublicKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try X.509 codec
+ return (GnuRSAPublicKey) new RSAKeyPairX509Codec().decodePublicKey(k);
}
// Instance methods
// -------------------------------------------------------------------------
- // java.security.interfaces.RSAPublicKey interface implementation ----------
-
- // public BigInteger getPublicExponent() {
- // return e;
- // }
-
- // Other instance methods --------------------------------------------------
-
/**
* <p>Returns the encoded form of this public key according to the designated
* format.</p>
@@ -147,8 +150,12 @@ public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
case IKeyPairCodec.RAW_FORMAT:
result = new RSAKeyPairRawCodec().encodePublicKey(this);
break;
+ case IKeyPairCodec.X509_FORMAT:
+ result = new RSAKeyPairX509Codec().encodePublicKey(this);
+ break;
default:
- throw new IllegalArgumentException("format");
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
}
return result;
}
@@ -172,7 +179,6 @@ public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
return false;
}
final RSAPublicKey that = (RSAPublicKey) obj;
- // return super.equals(that) && e.equals(that.getPublicExponent());
return super.equals(that)
&& getPublicExponent().equals(that.getPublicExponent());
}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairGenerator.java b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
index 360036723..9c7338f66 100644
--- a/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
+++ b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
@@ -95,9 +95,19 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
*/
public static final String RSA_PARAMETERS = "gnu.crypto.rsa.params";
+ /**
+ * Property name of the preferred encoding format to use when externalizing
+ * generated instance of key-pairs from this generator. The property is taken
+ * to be an {@link Integer} that encapsulates an encoding format identifier.
+ */
+ public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.rsa.encoding";
+
/** Default value for the modulus length. */
private static final int DEFAULT_MODULUS_LENGTH = 1024;
+ /** Default encoding format to use when none was specified. */
+ private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
+
/** The desired bit length of the modulus. */
private int L;
@@ -113,6 +123,9 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
/** Our default source of randomness. */
private PRNG prng = null;
+ /** Preferred encoding format of generated keys. */
+ private int preferredFormat;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -159,6 +172,11 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
{
throw new IllegalArgumentException(MODULUS_LENGTH);
}
+
+ // what is the preferred encoding format
+ Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
+ preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
+ : formatID.intValue();
}
/**
@@ -213,8 +231,8 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
d = e.modInverse(phi);
// 5. Output the public key and the private key.
- PublicKey pubK = new GnuRSAPublicKey(n, e);
- PrivateKey secK = new GnuRSAPrivateKey(p, q, e, d);
+ PublicKey pubK = new GnuRSAPublicKey(preferredFormat, n, e);
+ PrivateKey secK = new GnuRSAPrivateKey(preferredFormat, p, q, e, d);
return new KeyPair(pubK, secK);
}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java b/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
new file mode 100644
index 000000000..56b0ecf95
--- /dev/null
+++ b/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
@@ -0,0 +1,289 @@
+/* RSAKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode PKCS#8 ASN.1 external representation of RSA private keys.
+ */
+public class RSAKeyPairPKCS8Codec
+ implements IKeyPairCodec
+{
+ private static final OID RSA_ALG_OID = new OID(Registry.RSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ private static void checkIsConstructed(DERValue v, String msg)
+ {
+ if (! v.isConstructed())
+ throw new InvalidParameterException(msg);
+ }
+
+ private static void checkIsBigInteger(DERValue v, String msg)
+ {
+ if (! (v.getValue() instanceof BigInteger))
+ throw new InvalidParameterException(msg);
+ }
+
+ public int getFormatID()
+ {
+ return PKCS8_FORMAT;
+ }
+
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ throw new IllegalArgumentException("Wrong format for public keys");
+ }
+
+ /**
+ * Returns the PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of an RSA
+ * private key. The ASN.1 specification is as follows:
+ *
+ * <pre>
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version INTEGER, -- MUST be 0
+ * privateKeyAlgorithm AlgorithmIdentifier,
+ * privateKey OCTET STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ * </pre>
+ *
+ * <p>The <i>privateKey</i> field, which is an OCTET STRING, contains the
+ * DER-encoded form of the RSA private key defined as:</p>
+ *
+ * <pre>
+ * RSAPrivateKey ::= SEQUENCE {
+ * version INTEGER, -- MUST be 0
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * }
+ * </pre>
+ *
+ * @return the DER encoded form of the ASN.1 representation of the
+ * <i>PrivateKeyInfo</i> field for an RSA {@link PrivateKey}..
+ * @throw InvalidParameterException if an error occurs during the marshalling
+ * process.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (! (key instanceof GnuRSAPrivateKey))
+ throw new IllegalArgumentException("Wrong key type");
+
+ GnuRSAPrivateKey pk = (GnuRSAPrivateKey) key;
+ BigInteger n = pk.getN();
+ BigInteger e = pk.getE();
+ BigInteger d = pk.getPrivateExponent();
+ BigInteger p = pk.getPrimeP();
+ BigInteger q = pk.getPrimeQ();
+ BigInteger dP = pk.getPrimeExponentP();
+ BigInteger dQ = pk.getPrimeExponentQ();
+ BigInteger qInv = pk.getCrtCoefficient();
+
+ DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, RSA_ALG_OID);
+
+ ArrayList algorithmID = new ArrayList(1);
+ algorithmID.add(derOID);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derRSAVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+ DERValue derN = new DERValue(DER.INTEGER, n);
+ DERValue derE = new DERValue(DER.INTEGER, e);
+ DERValue derD = new DERValue(DER.INTEGER, d);
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derDP = new DERValue(DER.INTEGER, dP);
+ DERValue derDQ = new DERValue(DER.INTEGER, dQ);
+ DERValue derQInv = new DERValue(DER.INTEGER, qInv);
+
+ ArrayList rsaPrivateKey = new ArrayList();
+ rsaPrivateKey.add(derRSAVersion);
+ rsaPrivateKey.add(derN);
+ rsaPrivateKey.add(derE);
+ rsaPrivateKey.add(derD);
+ rsaPrivateKey.add(derP);
+ rsaPrivateKey.add(derQ);
+ rsaPrivateKey.add(derDP);
+ rsaPrivateKey.add(derDQ);
+ rsaPrivateKey.add(derQInv);
+ DERValue derRSAPrivateKey = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ rsaPrivateKey);
+ byte[] pkBytes = derRSAPrivateKey.getEncoded();
+ DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, pkBytes);
+
+ ArrayList pki = new ArrayList(3);
+ pki.add(derVersion);
+ pki.add(derAlgorithmID);
+ pki.add(derPrivateKey);
+ DERValue derPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, pki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return result;
+ }
+
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ throw new IllegalArgumentException("Wrong format for public keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid RSA
+ * {@link PrivateKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuRSAPrivateKey} decoded from the
+ * <i>PrivateKeyInfo</i> material fed as <code>input</code>.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger version, n, e, d, p, q, dP, dQ, qInv;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derPKI = der.read();
+ checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
+
+ DERValue derVersion = der.read();
+ checkIsBigInteger(derVersion, "Wrong Version field");
+ version = (BigInteger) derVersion.getValue();
+ if (version.compareTo(BigInteger.ZERO) != 0)
+ throw new InvalidParameterException("Unexpected Version: " + version);
+
+ DERValue derAlgoritmID = der.read();
+ checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(RSA_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ DERValue val = der.read();
+ byte[] pkBytes = (byte[]) val.getValue();
+
+ der = new DERReader(pkBytes);
+ DERValue derRSAPrivateKey = der.read();
+ checkIsConstructed(derRSAPrivateKey, "Wrong RSAPrivateKey field");
+
+ val = der.read();
+ checkIsBigInteger(val, "Wrong RSAPrivateKey Version field");
+ version = (BigInteger) val.getValue();
+ if (version.compareTo(BigInteger.ZERO) != 0)
+ throw new InvalidParameterException("Unexpected RSAPrivateKey Version: "
+ + version);
+
+ val = der.read();
+ checkIsBigInteger(val, "Wrong modulus field");
+ n = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong publicExponent field");
+ e = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong privateExponent field");
+ d = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong prime1 field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong prime2 field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong exponent1 field");
+ dP = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong exponent2 field");
+ dQ = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong coefficient field");
+ qInv = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID, n, e, d, p, q,
+ dP, dQ, qInv);
+ }
+}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java b/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java
new file mode 100644
index 000000000..1a153b542
--- /dev/null
+++ b/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java
@@ -0,0 +1,237 @@
+/* RSAKeyPairX509Codec.java -- X.509 Encoding/Decoding handler
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode X.509 ASN.1 external representation of RSA public keys.
+ */
+public class RSAKeyPairX509Codec
+ implements IKeyPairCodec
+{
+ private static final OID RSA_ALG_OID = new OID(Registry.RSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ private static void checkIsConstructed(DERValue v, String msg)
+ {
+ if (! v.isConstructed())
+ throw new InvalidParameterException(msg);
+ }
+
+ private static void checkIsBigInteger(DERValue v, String msg)
+ {
+ if (! (v.getValue() instanceof BigInteger))
+ throw new InvalidParameterException(msg);
+ }
+
+ public int getFormatID()
+ {
+ return X509_FORMAT;
+ }
+
+ /**
+ * Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of an
+ * RSA public key. The ASN.1 specification, as defined in RFC-3280, and
+ * RFC-2459, is as follows:
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ * </pre>
+ *
+ * <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the RSA public key defined as:</p>
+ *
+ * <pre>
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ * </pre>
+ *
+ * @param key the {@link PublicKey} instance to encode. MUST be an instance of
+ * {@link GnuRSAPublicKey}.
+ * @return the ASN.1 representation of the <i>SubjectPublicKeyInfo</i> in an
+ * X.509 certificate.
+ * @throw InvalidParameterException if <code>key</code> is not an instance
+ * of {@link GnuRSAPublicKey} or if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (! (key instanceof GnuRSAPublicKey))
+ throw new InvalidParameterException("key");
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, RSA_ALG_OID);
+
+ GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
+ BigInteger n = rsaKey.getN();
+ BigInteger e = rsaKey.getE();
+
+ DERValue derN = new DERValue(DER.INTEGER, n);
+ DERValue derE = new DERValue(DER.INTEGER, e);
+
+ ArrayList algorithmID = new ArrayList(1);
+ algorithmID.add(derOID);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ ArrayList publicKey = new ArrayList(2);
+ publicKey.add(derN);
+ publicKey.add(derE);
+ DERValue derPublicKey = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ publicKey);
+ byte[] spkBytes = derPublicKey.getEncoded();
+ DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(spkBytes));
+
+ ArrayList spki = new ArrayList(2);
+ spki.add(derAlgorithmID);
+ spki.add(derSPK);
+ DERValue derSPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, spki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derSPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return result;
+ }
+
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ throw new IllegalArgumentException("Wrong format for private keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid RSA
+ * {@link PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuRSAPublicKey} decoded from the
+ * <i>SubjectPublicKeyInfo</i> material in an X.509 certificate.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger n, e;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derSPKI = der.read();
+ checkIsConstructed(derSPKI, "Wrong SubjectPublicKeyInfo field");
+
+ DERValue derAlgorithmID = der.read();
+ checkIsConstructed(derAlgorithmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ if (! (derOID.getValue() instanceof OID))
+ throw new InvalidParameterException("Wrong Algorithm field");
+
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(RSA_ALG_OID))
+ throw new IllegalArgumentException("Unexpected OID: " + algOID);
+
+ DERValue val = der.read();
+ if (! (val.getValue() instanceof BitString))
+ throw new InvalidParameterException("Wrong SubjectPublicKey field");
+
+ byte[] spkBytes = ((BitString) val.getValue()).toByteArray();
+
+ der = new DERReader(spkBytes);
+ val = der.read();
+ checkIsConstructed(derAlgorithmID, "Wrong subjectPublicKey field");
+
+ val = der.read();
+ checkIsBigInteger(val, "Wrong modulus field");
+ n = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong publicExponent field");
+ e = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
+ }
+
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ throw new IllegalArgumentException("Wrong format for private keys");
+ }
+}