Imported GNU Classpath 0.90

Imported GNU Classpath 0.90
       * scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore.
       * gnu/classpath/jdwp/VMFrame.java (SIZE): New constant.
       * java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5.
       * java/lang/Math.java: New override file.
       * java/lang/Character.java: Merged from Classpath.
       (start, end): Now 'int's.
       (canonicalName): New field.
       (CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants.
       (UnicodeBlock): Added argument.
       (of): New overload.
       (forName): New method.
       Updated unicode blocks.
       (sets): Updated.
       * sources.am: Regenerated.
       * Makefile.in: Likewise.

From-SVN: r111942
This commit is contained in:
Mark Wielaard
2006-03-10 21:46:48 +00:00
parent 27079765d0
commit 8aa540d2f7
1367 changed files with 188789 additions and 22762 deletions
@@ -0,0 +1,182 @@
/* DSSKey.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.Registry;
import gnu.java.security.util.FormatUtil;
import java.math.BigInteger;
import java.security.Key;
import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAParams;
import java.security.spec.DSAParameterSpec;
/**
* <p>A base asbtract class for both public and private DSS (Digital Signature
* Standard) keys. It encapsulates the three DSS numbers: <code>p</code>,
* <code>q</code> and <code>g</code>.</p>
*
* <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
* The format used in this implementation is called <i>Raw</i>, and basically
* consists of the raw byte sequences of algorithm parameters. The exact order
* of the byte sequences and the implementation details are given in each of
* the relevant <code>getEncoded()</code> methods of each of the private and
* public keys.</p>
*
* @version $Revision: 1.4 $
* @see DSSPrivateKey#getEncoded
* @see DSSPublicKey#getEncoded
*/
public abstract class DSSKey implements Key, DSAKey
{
// Constants and variables
// -------------------------------------------------------------------------
/**
* A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code>
* for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a multiple of
* <code>64</code>.
*/
protected final BigInteger p;
/**
* A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> &lt; q
* &lt; 2<sup>160</sup></code>.
*/
protected final BigInteger q;
/**
* <code>g = h<sup>(p-1)</sup>/q mod p</code>, where <code>h</code> is any
* integer with <code>1 &lt; h &lt; p - 1</code> such that <code>h<sup>
* (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order <code>q mod p
* </code>).
*/
protected final BigInteger g;
/**
* Identifier of the default encoding format to use when externalizing the
* key material.
*/
protected final int defaultFormat;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* Trivial protected constructor.
*
* @param defaultFormat the identifier of the encoding format to use by
* default when externalizing the key.
* @param p the DSS parameter <code>p</code>.
* @param q the DSS parameter <code>q</code>.
* @param g the DSS parameter <code>g</code>.
*/
protected DSSKey(int defaultFormat, BigInteger p, BigInteger q, BigInteger g)
{
super();
this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
: defaultFormat;
this.p = p;
this.q = q;
this.g = g;
}
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// java.security.interfaces.DSAKey interface implementation ----------------
public DSAParams getParams()
{
return new DSAParameterSpec(p, q, g);
}
// java.security.Key interface implementation ------------------------------
public String getAlgorithm()
{
return Registry.DSS_KPG;
}
/** @deprecated see getEncoded(int). */
public byte[] getEncoded()
{
return getEncoded(defaultFormat);
}
public String getFormat()
{
return FormatUtil.getEncodingShortName(defaultFormat);
}
// Other instance methods --------------------------------------------------
/**
* <p>Returns <code>true</code> if the designated object is an instance of
* {@link DSAKey} and has the same DSS (Digital Signature Standard) parameter
* values as this one.</p>
*
* @param obj the other non-null DSS key to compare to.
* @return <code>true</code> if the designated object is of the same type and
* value as this one.
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (!(obj instanceof DSAKey))
{
return false;
}
DSAKey that = (DSAKey) obj;
return p.equals(that.getParams().getP())
&& q.equals(that.getParams().getQ())
&& g.equals(that.getParams().getG());
}
// abstract methods to be implemented by subclasses ------------------------
public abstract byte[] getEncoded(int format);
}
@@ -0,0 +1,445 @@
/* DSSKeyPairGenerator.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.Registry;
import gnu.java.security.hash.Sha160;
import gnu.java.security.key.IKeyPairGenerator;
import gnu.java.security.util.PRNG;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.DSAParameterSpec;
import java.util.Map;
/**
* <p>A key-pair generator for asymetric keys to use in conjunction with the DSS
* (Digital Signature Standard).</p>
*
* References:<br>
* <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
* Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
* National Institute of Standards and Technology.
*/
public class DSSKeyPairGenerator implements IKeyPairGenerator
{
// Debugging methods and variables
// -------------------------------------------------------------------------
private static final String NAME = "dss";
private static final boolean DEBUG = false;
private static final int debuglevel = 5;
private static final PrintWriter err = new PrintWriter(System.out, true);
private static void debug(String s)
{
err.println(">>> " + NAME + ": " + s);
}
// Constants and variables
// -------------------------------------------------------------------------
/** The BigInteger constant 2. */
private static final BigInteger TWO = new BigInteger("2");
/** Property name of the length (Integer) of the modulus (p) of a DSS key. */
public static final String MODULUS_LENGTH = "gnu.crypto.dss.L";
/**
* Property name of the Boolean indicating wether or not to use default pre-
* computed values of <code>p</code>, <code>q</code> and <code>g</code> for
* a given modulus length. The ultimate behaviour of this generator with
* regard to using pre-computed parameter sets will depend on the value of
* this property and of the following one {@link #STRICT_DEFAULTS}:
*
* <ol>
* <li>If this property is {@link Boolean#FALSE} then this generator
* will accept being setup for generating parameters for any modulus length
* provided the modulus length is between <code>512</code> and
* <code>1024</code>, and is of the form <code>512 + 64 * n</code>. In
* addition, a new paramter set will always be generated; i.e. no pre-
* computed values are used.</li>
*
* <li>If this property is {@link Boolean#TRUE} and the value of
* {@link #STRICT_DEFAULTS} is also {@link Boolean#TRUE} then this generator
* will only accept being setup for generating parameters for modulus
* lengths of <code>512</code>, <code>768</code> and <code>1024</code>. Any
* other value, of the modulus length, even if between <code>512</code> and
* <code>1024</code>, and of the form <code>512 + 64 * n</code>, will cause
* an {@link IllegalArgumentException} to be thrown. When those modulus
* length (<code>512</code>, <code>768</code>, and <code>1024</code>) are
* specified, the paramter set is always the same.</li>
*
* <li>Finally, if this property is {@link Boolean#TRUE} and the value of
* {@link #STRICT_DEFAULTS} is {@link Boolean#FALSE} then this generator
* will behave as in point 1 above, except that it will use pre-computed
* values when possible; i.e. the modulus length is one of <code>512</code>,
* <code>768</code>, or <code>1024</code>.</li>
* </ol>
*
* The default value of this property is {@link Boolean#TRUE}.
*/
public static final String USE_DEFAULTS = "gnu.crypto.dss.use.defaults";
/**
* Property name of the Boolean indicating wether or not to generate new
* parameters, even if the modulus length <i>L</i> is not one of the pre-
* computed defaults (value {@link Boolean#FALSE}), or throw an exception
* (value {@link Boolean#TRUE}) -- the exception in this case is an
* {@link IllegalArgumentException}. The default value for this property is
* {@link Boolean#FALSE}. The ultimate behaviour of this generator will
* depend on the values of this and {@link #USE_DEFAULTS} properties -- see
* {@link #USE_DEFAULTS} for more information.
*/
public static final String STRICT_DEFAULTS = "gnu.crypto.dss.strict.defaults";
/**
* Property name of an optional {@link SecureRandom} instance to use. The
* default is to use a classloader singleton from {@link PRNG}.
*/
public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dss.prng";
/**
* Property name of an optional {@link DSAParameterSpec} instance to use for
* this generator's <code>p</code>, <code>q</code>, and <code>g</code> values.
* The default is to generate these values or use pre-computed ones,
* depending on the value of the <code>USE_DEFAULTS</code> attribute.
*/
public static final String DSS_PARAMETERS = "gnu.crypto.dss.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.dss.encoding";
/** Default value for the modulus length. */
public 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;
/** Initial SHS context. */
private static final int[] T_SHS = new int[] { 0x67452301, 0xEFCDAB89,
0x98BADCFE, 0x10325476,
0xC3D2E1F0 };
// from jdk1.3.1/docs/guide/security/CryptoSpec.html#AppB
public static final DSAParameterSpec KEY_PARAMS_512 = new DSAParameterSpec(
new BigInteger(
"fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae"
+ "01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17",
16),
new BigInteger(
"962eddcc369cba8ebb260ee6b6a126d9346e38c5",
16),
new BigInteger(
"678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e"
+ "35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4",
16));
public static final DSAParameterSpec KEY_PARAMS_768 = new DSAParameterSpec(
new BigInteger(
"e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d8901419"
+ "22d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d77"
+ "7d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf",
16),
new BigInteger(
"9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511",
16),
new BigInteger(
"30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4"
+ "dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d8"
+ "3c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252",
16));
public static final DSAParameterSpec KEY_PARAMS_1024 = new DSAParameterSpec(
new BigInteger(
"fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669"
+ "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7"
+ "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb"
+ "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7",
16),
new BigInteger(
"9760508f15230bccb292b982a2eb840bf0581cf5",
16),
new BigInteger(
"f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267"
+ "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1"
+ "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b"
+ "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a",
16));
private static final BigInteger TWO_POW_160 = TWO.pow(160);
/** The length of the modulus of DSS keys generated by this instance. */
private int L;
/** The optional {@link SecureRandom} instance to use. */
private SecureRandom rnd = null;
private BigInteger seed;
private BigInteger counter;
private BigInteger p;
private BigInteger q;
private BigInteger e;
private BigInteger g;
private BigInteger XKEY;
/** Our default source of randomness. */
private PRNG prng = null;
/** Preferred encoding format of generated keys. */
private int preferredFormat;
// Constructor(s)
// -------------------------------------------------------------------------
// implicit 0-arguments constructor
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
public String name()
{
return Registry.DSS_KPG;
}
/**
* <p>Configures this instance.</p>
*
* @param attributes the map of name/value pairs to use.
* @exception IllegalArgumentException if the designated MODULUS_LENGTH
* value is not greater than 512, less than 1024 and not of the form
* <code>512 + 64j</code>.
*/
public void setup(Map attributes)
{
// find out the modulus length
Integer l = (Integer) attributes.get(MODULUS_LENGTH);
L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
if ((L % 64) != 0 || L < 512 || L > 1024)
throw new IllegalArgumentException(MODULUS_LENGTH);
// should we use the default pre-computed params?
Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
if (useDefaults == null)
{
useDefaults = Boolean.TRUE;
}
Boolean strictDefaults = (Boolean) attributes.get(STRICT_DEFAULTS);
if (strictDefaults == null)
strictDefaults = Boolean.FALSE;
// are we given a set of DSA params or we shall use/generate our own?
DSAParameterSpec params = (DSAParameterSpec) attributes.get(DSS_PARAMETERS);
if (params != null)
{
p = params.getP();
q = params.getQ();
g = params.getG();
}
else if (useDefaults.equals(Boolean.TRUE))
{
switch (L)
{
case 512:
p = KEY_PARAMS_512.getP();
q = KEY_PARAMS_512.getQ();
g = KEY_PARAMS_512.getG();
break;
case 768:
p = KEY_PARAMS_768.getP();
q = KEY_PARAMS_768.getQ();
g = KEY_PARAMS_768.getG();
break;
case 1024:
p = KEY_PARAMS_1024.getP();
q = KEY_PARAMS_1024.getQ();
g = KEY_PARAMS_1024.getG();
break;
default:
if (strictDefaults.equals(Boolean.TRUE))
throw new IllegalArgumentException(
"Does not provide default parameters for " + L
+ "-bit modulus length");
else
{
p = null;
q = null;
g = null;
}
}
}
else
{
p = null;
q = null;
g = null;
}
// do we have a SecureRandom, or should we use our own?
rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
// what is the preferred encoding format
Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
preferredFormat = formatID == null
? DEFAULT_ENCODING_FORMAT
: formatID.intValue();
// set the seed-key
byte[] kb = new byte[20]; // we need 160 bits of randomness
nextRandomBytes(kb);
XKEY = new BigInteger(1, kb).setBit(159).setBit(0);
}
public KeyPair generate()
{
if (p == null)
{
BigInteger[] params = new FIPS186(L, rnd).generateParameters();
seed = params[FIPS186.DSA_PARAMS_SEED];
counter = params[FIPS186.DSA_PARAMS_COUNTER];
q = params[FIPS186.DSA_PARAMS_Q];
p = params[FIPS186.DSA_PARAMS_P];
e = params[FIPS186.DSA_PARAMS_E];
g = params[FIPS186.DSA_PARAMS_G];
if (DEBUG && debuglevel > 0)
{
debug("seed: " + seed.toString(16));
debug("counter: " + counter.intValue());
debug("q: " + q.toString(16));
debug("p: " + p.toString(16));
debug("e: " + e.toString(16));
debug("g: " + g.toString(16));
}
}
BigInteger x = nextX();
BigInteger y = g.modPow(x, p);
PublicKey pubK = new DSSPublicKey(preferredFormat, p, q, g, y);
PrivateKey secK = new DSSPrivateKey(preferredFormat, p, q, g, x);
return new KeyPair(pubK, secK);
}
// Other instance methods --------------------------------------------------
/**
* <p>This method applies the following algorithm described in 3.1 of
* FIPS-186:</p>
*
* <ol>
* <li>XSEED = optional user input.</li>
* <li>XVAL = (XKEY + XSEED) mod 2<sup>b</sup>.</li>
* <li>x = G(t, XVAL) mod q.</li>
* <li>XKEY = (1 + XKEY + x) mod 2<sup>b</sup>.</li>
* </ol>
*
* <p>Where <code>b</code> is the length of a secret b-bit seed-key (XKEY).</p>
*
* <p>Note that in this implementation, XSEED, the optional user input, is
* always zero.</p>
*/
private synchronized BigInteger nextX()
{
byte[] xk = XKEY.toByteArray();
byte[] in = new byte[64]; // 512-bit block for SHS
System.arraycopy(xk, 0, in, 0, xk.length);
int[] H = Sha160.G(T_SHS[0], T_SHS[1], T_SHS[2], T_SHS[3], T_SHS[4], in, 0);
byte[] h = new byte[20];
for (int i = 0, j = 0; i < 5; i++)
{
h[j++] = (byte) (H[i] >>> 24);
h[j++] = (byte) (H[i] >>> 16);
h[j++] = (byte) (H[i] >>> 8);
h[j++] = (byte) H[i];
}
BigInteger result = new BigInteger(1, h).mod(q);
XKEY = XKEY.add(result).add(BigInteger.ONE).mod(TWO_POW_160);
return result;
}
/**
* <p>Fills the designated byte array with random data.</p>
*
* @param buffer the byte array to fill with random data.
*/
private void nextRandomBytes(byte[] buffer)
{
if (rnd != null)
{
rnd.nextBytes(buffer);
}
else
getDefaultPRNG().nextBytes(buffer);
}
private PRNG getDefaultPRNG()
{
if (prng == null)
prng = PRNG.getInstance();
return prng;
}
}
@@ -0,0 +1,235 @@
/* DSSKeyPairPKCS8Codec.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.dss;
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;
import gnu.java.security.util.DerUtil;
import gnu.java.security.util.Util;
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 PKCS#8 ASN.1 external representation of DSS private keys.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class DSSKeyPairPKCS8Codec
implements IKeyPairCodec
{
private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
// implicit 0-arguments constructor
public int getFormatID()
{
return PKCS8_FORMAT;
}
/**
* @throws InvalidParameterException ALWAYS.
*/
public byte[] encodePublicKey(PublicKey key)
{
throw new InvalidParameterException("Wrong format for public keys");
}
/**
* Returns the PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of a DSA
* 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
* }
*
* DssParams ::= SEQUENCE {
* p INTEGER,
* q INTEGER,
* g INTEGER
* }
* </pre>
*
* @return the DER encoded form of the ASN.1 representation of the
* <i>PrivateKeyInfo</i> field in an X.509 certificate.
* @throw InvalidParameterException if an error occurs during the marshalling
* process.
*/
public byte[] encodePrivateKey(PrivateKey key)
{
if (! (key instanceof DSSPrivateKey))
throw new InvalidParameterException("Wrong key type");
DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
DSSPrivateKey pk = (DSSPrivateKey) key;
BigInteger p = pk.getParams().getP();
BigInteger q = pk.getParams().getQ();
BigInteger g = pk.getParams().getG();
BigInteger x = pk.getX();
ArrayList params = new ArrayList(3);
params.add(new DERValue(DER.INTEGER, p));
params.add(new DERValue(DER.INTEGER, q));
params.add(new DERValue(DER.INTEGER, g));
DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
ArrayList algorithmID = new ArrayList(2);
algorithmID.add(derOID);
algorithmID.add(derParams);
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
algorithmID);
DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, Util.trim(x));
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 e)
{
InvalidParameterException y = new InvalidParameterException();
y.initCause(e);
throw y;
}
return result;
}
/**
* @throws InvalidParameterException ALWAYS.
*/
public PublicKey decodePublicKey(byte[] input)
{
throw new InvalidParameterException("Wrong format for public keys");
}
/**
* @param input the byte array to unmarshall into a valid DSS
* {@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
* unmarshalling process.
*/
public PrivateKey decodePrivateKey(byte[] input)
{
if (input == null)
throw new InvalidParameterException("Input bytes MUST NOT be null");
BigInteger version, p, q, g, x;
DERReader der = new DERReader(input);
try
{
DERValue derPKI = der.read();
DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
DERValue derVersion = der.read();
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();
DerUtil.checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
DERValue derOID = der.read();
OID algOID = (OID) derOID.getValue();
if (! algOID.equals(DSA_ALG_OID))
throw new InvalidParameterException("Unexpected OID: " + algOID);
DERValue derParams = der.read();
DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
DERValue val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong P field");
p = (BigInteger) val.getValue();
val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong Q field");
q = (BigInteger) val.getValue();
val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong G field");
g = (BigInteger) val.getValue();
val = der.read();
byte[] xBytes = (byte[]) val.getValue();
x = new BigInteger(1, xBytes);
}
catch (IOException e)
{
InvalidParameterException y = new InvalidParameterException();
y.initCause(e);
throw y;
}
return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
}
}
@@ -0,0 +1,383 @@
/* DSSKeyPairRawCodec.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* <p>An object that implements the {@link IKeyPairCodec} operations for the
* <i>Raw</i> format to use with DSS keypairs.</p>
*
* @version $Revision: 1.1 $
*/
public class DSSKeyPairRawCodec implements IKeyPairCodec
{
// Constants and variables
// -------------------------------------------------------------------------
// Constructor(s)
// -------------------------------------------------------------------------
// implicit 0-arguments constructor
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
public int getFormatID()
{
return RAW_FORMAT;
}
/**
* <p>Returns the encoded form of the designated DSS (Digital Signature
* Standard) public key according to the <i>Raw</i> format supported by
* this library.</p>
*
* <p>The <i>Raw</i> format for a DSA public key, in this implementation, is
* a byte sequence consisting of the following:</p>
* <ol>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_DSS_PUBLIC_KEY},<li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>p</code> in internet order,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>p</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>q</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>q</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>g</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>g</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>y</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>y</code>,</li>
* </ol>
*
* @param key the key to encode.
* @return the <i>Raw</i> format encoding of the designated key.
* @throws IllegalArgumentException if the designated key is not a DSS
* (Digital Signature Standard) one.
* @see Registry#MAGIC_RAW_DSS_PUBLIC_KEY
*/
public byte[] encodePublicKey(PublicKey key)
{
if (!(key instanceof DSSPublicKey))
{
throw new IllegalArgumentException("key");
}
DSSPublicKey dssKey = (DSSPublicKey) key;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// magic
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]);
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]);
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]);
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3]);
// version
baos.write(0x01);
// p
byte[] buffer = dssKey.getParams().getP().toByteArray();
int length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// q
buffer = dssKey.getParams().getQ().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// g
buffer = dssKey.getParams().getG().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// y
buffer = dssKey.getY().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
return baos.toByteArray();
}
public PublicKey decodePublicKey(byte[] k)
{
// magic
if (k[0] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]
|| k[1] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]
|| k[2] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]
|| k[3] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3])
{
throw new IllegalArgumentException("magic");
}
// version
if (k[4] != 0x01)
{
throw new IllegalArgumentException("version");
}
int i = 5;
int l;
byte[] buffer;
// p
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger p = new BigInteger(1, buffer);
// q
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger q = new BigInteger(1, buffer);
// g
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger g = new BigInteger(1, buffer);
// y
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger y = new BigInteger(1, buffer);
return new DSSPublicKey(p, q, g, y);
}
/**
* <p>Returns the encoded form of the designated DSS (Digital Signature
* Standard) private key according to the <i>Raw</i> format supported by
* this library.</p>
*
* <p>The <i>Raw</i> format for a DSA private key, in this implementation, is
* a byte sequence consisting of the following:</p>
* <ol>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_DSS_PRIVATE_KEY},<li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>p</code> in internet order,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>p</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>q</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>q</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>g</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>g</code>,</li>
* <li>4-byte count of following bytes representing the DSA parameter
* <code>x</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSA parameter
* <code>x</code>,</li>
* </ol>
*
* @param key the key to encode.
* @return the <i>Raw</i> format encoding of the designated key.
* @throws IllegalArgumentException if the designated key is not a DSS
* (Digital Signature Standard) one.
*/
public byte[] encodePrivateKey(PrivateKey key)
{
if (!(key instanceof DSSPrivateKey))
{
throw new IllegalArgumentException("key");
}
DSSPrivateKey dssKey = (DSSPrivateKey) key;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// magic
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]);
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]);
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]);
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3]);
// version
baos.write(0x01);
// p
byte[] buffer = dssKey.getParams().getP().toByteArray();
int length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// q
buffer = dssKey.getParams().getQ().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// g
buffer = dssKey.getParams().getG().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// x
buffer = dssKey.getX().toByteArray();
length = buffer.length;
baos.write(length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
return baos.toByteArray();
}
public PrivateKey decodePrivateKey(byte[] k)
{
// magic
if (k[0] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]
|| k[1] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]
|| k[2] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]
|| k[3] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3])
{
throw new IllegalArgumentException("magic");
}
// version
if (k[4] != 0x01)
{
throw new IllegalArgumentException("version");
}
int i = 5;
int l;
byte[] buffer;
// p
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger p = new BigInteger(1, buffer);
// q
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger q = new BigInteger(1, buffer);
// g
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger g = new BigInteger(1, buffer);
// x
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
buffer = new byte[l];
System.arraycopy(k, i, buffer, 0, l);
i += l;
BigInteger x = new BigInteger(1, buffer);
return new DSSPrivateKey(p, q, g, x);
}
}
@@ -0,0 +1,248 @@
/* DSSKeyPairX509Codec.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.dss;
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 gnu.java.security.util.DerUtil;
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 DSS public keys.
*/
public class DSSKeyPairX509Codec
implements IKeyPairCodec
{
private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
// implicit 0-arguments constructor
public int getFormatID()
{
return X509_FORMAT;
}
/**
* Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of a
* DSA 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
* }
*
* DssParams ::= SEQUENCE {
* p INTEGER,
* q INTEGER,
* g INTEGER
* }
* </pre>
*
* <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
* DER-encoded form of the DSA public key as an INTEGER.</p>
*
* <pre>
* DSAPublicKey ::= INTEGER -- public key, Y
* </pre>
*
* @param key the {@link PublicKey} instance to encode. MUST be an instance of
* {@link DSSPublicKey}.
* @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 DSSPublicKey} or if an exception occurs during the
* marshalling process.
*/
public byte[] encodePublicKey(PublicKey key)
{
if (! (key instanceof DSSPublicKey))
throw new InvalidParameterException("key");
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
DSSPublicKey dssKey = (DSSPublicKey) key;
BigInteger p = dssKey.getParams().getP();
BigInteger q = dssKey.getParams().getQ();
BigInteger g = dssKey.getParams().getG();
BigInteger y = dssKey.getY();
DERValue derP = new DERValue(DER.INTEGER, p);
DERValue derQ = new DERValue(DER.INTEGER, q);
DERValue derG = new DERValue(DER.INTEGER, g);
ArrayList params = new ArrayList(3);
params.add(derP);
params.add(derQ);
params.add(derG);
DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
ArrayList algorithmID = new ArrayList(2);
algorithmID.add(derOID);
algorithmID.add(derParams);
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
algorithmID);
DERValue derDSAPublicKey = new DERValue(DER.INTEGER, y);
byte[] yBytes = derDSAPublicKey.getEncoded();
DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(yBytes));
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 e = new InvalidParameterException();
e.initCause(x);
throw e;
}
return result;
}
/**
* @throws InvalidParameterException ALWAYS.
*/
public byte[] encodePrivateKey(PrivateKey key)
{
throw new InvalidParameterException("Wrong format for private keys");
}
/**
* @param input the byte array to unmarshall into a valid DSS
* {@link PublicKey} instance. MUST NOT be null.
* @return a new instance of a {@link DSSPublicKey} 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 p, g, q, y;
DERReader der = new DERReader(input);
try
{
DERValue derSPKI = der.read();
DerUtil.checkIsConstructed(derSPKI, "Wrong SubjectPublicKeyInfo field");
DERValue derAlgorithmID = der.read();
DerUtil.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(DSA_ALG_OID))
throw new InvalidParameterException("Unexpected OID: " + algOID);
DERValue derParams = der.read();
DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
DERValue val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong P field");
p = (BigInteger) val.getValue();
val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong Q field");
q = (BigInteger) val.getValue();
val = der.read();
DerUtil.checkIsBigInteger(val, "Wrong G field");
g = (BigInteger) val.getValue();
val = der.read();
if (! (val.getValue() instanceof BitString))
throw new InvalidParameterException("Wrong SubjectPublicKey field");
byte[] yBytes = ((BitString) val.getValue()).toByteArray();
DERReader dsaPub = new DERReader(yBytes);
val = dsaPub.read();
DerUtil.checkIsBigInteger(val, "Wrong Y field");
y = (BigInteger) val.getValue();
}
catch (IOException x)
{
InvalidParameterException e = new InvalidParameterException();
e.initCause(x);
throw e;
}
return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
}
/**
* @throws InvalidParameterException ALWAYS.
*/
public PrivateKey decodePrivateKey(byte[] input)
{
throw new InvalidParameterException("Wrong format for private keys");
}
}
@@ -0,0 +1,201 @@
/* DSSPrivateKey.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.interfaces.DSAPrivateKey;
/**
* <p>An object that embodies a DSS (Digital Signature Standard) private key.</p>
*
* @version $Revision: 1.2 $
* @see #getEncoded
*/
public class DSSPrivateKey extends DSSKey implements PrivateKey, DSAPrivateKey
{
// Constants and variables
// -------------------------------------------------------------------------
/**
* <p>A randomly or pseudorandomly generated integer with <code>0 &lt; x &lt;
* q</code>.</p>
*/
private final BigInteger x;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* 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 public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
* <sub>p</sub></code>.
* @param x the private key part.
*/
public DSSPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x)
{
this(Registry.RAW_ENCODING_ID, p, q, g, x);
}
/**
* Constructs a new instance of a <code>DSSPrivateKey</code> given the
* designated arguments.
*
* @param preferredFormat the indetifier of the preferred encoding format to
* use when externalizing this key.
* @param p the public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
* <sub>p</sub></code>.
* @param x the private key part.
*/
public DSSPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
BigInteger g, BigInteger x)
{
super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
: preferredFormat,
p, q, g);
this.x = x;
}
// Class methods
// -------------------------------------------------------------------------
/**
* A class method that takes the output of the <code>encodePrivateKey()</code>
* method of a DSS keypair codec object (an instance implementing
* {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
* an instance of this object.
*
* @param k the contents of a previously encoded instance of this object.
* @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
* <code>k</code>, to represent a valid encoding of an
* instance of this object.
* @exception IllegalArgumentException if the byte sequence does not represent
* a valid encoding of an instance of this object.
*/
public static DSSPrivateKey valueOf(byte[] k)
{
// try RAW codec
if (k[0] == Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0])
try
{
return (DSSPrivateKey) new DSSKeyPairRawCodec().decodePrivateKey(k);
}
catch (IllegalArgumentException ignored)
{
}
// try PKCS#8 codec
return (DSSPrivateKey) new DSSKeyPairPKCS8Codec().decodePrivateKey(k);
}
// Instance methods
// -------------------------------------------------------------------------
// java.security.interfaces.DSAPrivateKey interface implementation ---------
public BigInteger getX()
{
return x;
}
// Other instance methods --------------------------------------------------
/**
* <p>Returns the encoded form of this private key according to the
* designated format.</p>
*
* @param format the desired format identifier of the resulting encoding.
* @return the byte sequence encoding this key according to the designated
* format.
* @exception IllegalArgumentException if the format is not supported.
* @see DSSKeyPairRawCodec
*/
public byte[] getEncoded(int format)
{
byte[] result;
switch (format)
{
case IKeyPairCodec.RAW_FORMAT:
result = new DSSKeyPairRawCodec().encodePrivateKey(this);
break;
case IKeyPairCodec.PKCS8_FORMAT:
result = new DSSKeyPairPKCS8Codec().encodePrivateKey(this);
break;
default:
throw new IllegalArgumentException("Unsupported encoding format: "
+ format);
}
return result;
}
/**
* <p>Returns <code>true</code> if the designated object is an instance of
* {@link DSAPrivateKey} and has the same DSS (Digital Signature Standard)
* parameter values as this one.</p>
*
* @param obj the other non-null DSS key to compare to.
* @return <code>true</code> if the designated object is of the same type and
* value as this one.
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (!(obj instanceof DSAPrivateKey))
{
return false;
}
DSAPrivateKey that = (DSAPrivateKey) obj;
return super.equals(that) && x.equals(that.getX());
}
}
@@ -0,0 +1,201 @@
/* DSSPublicKey.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.interfaces.DSAPublicKey;
/**
* <p>An object that embodies a DSS (Digital Signature Standard) public key.</p>
*
* @version $Revision: 1.2 $
* @see #getEncoded
*/
public class DSSPublicKey extends DSSKey implements PublicKey, DSAPublicKey
{
// Constants and variables
// -------------------------------------------------------------------------
/**
* <code>y = g<sup>x</sup> mod p</code> where <code>x</code> is the private
* part of the DSA key.
*/
private final BigInteger y;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* Conveience constructor. Calls the constructor with 5 arguments passing
* {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
* encoding format.
*
* @param p the public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
* <sub>p</sub></code>.
* @param y the public key part.
*/
public DSSPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
{
this(Registry.RAW_ENCODING_ID, p, q, g, y);
}
/**
* Constructs a new instance of <code>DSSPublicKey</code> given the designated
* arguments.
*
* @param preferredFormat the identifier of the preferred encoding format to
* use when externalizing this key.
* @param p the public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
* <sub>p</sub></code>.
* @param y the public key part.
*/
public DSSPublicKey(int preferredFormat, BigInteger p, BigInteger q,
BigInteger g, BigInteger y)
{
super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
: preferredFormat,
p, q, g);
this.y = y;
}
// Class methods
// -------------------------------------------------------------------------
/**
* A class method that takes the output of the <code>encodePublicKey()</code>
* method of a DSS keypair codec object (an instance implementing
* {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
* an instance of this object.
*
* @param k the contents of a previously encoded instance of this object.
* @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
* <code>k</code>, to represent a valid encoding of an
* instance of this object.
* @exception IllegalArgumentException if the byte sequence does not represent
* a valid encoding of an instance of this object.
*/
public static DSSPublicKey valueOf(byte[] k)
{
// try RAW codec
if (k[0] == Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0])
try
{
return (DSSPublicKey) new DSSKeyPairRawCodec().decodePublicKey(k);
}
catch (IllegalArgumentException ignored)
{
}
// try X.509 codec
return (DSSPublicKey) new DSSKeyPairX509Codec().decodePublicKey(k);
}
// Instance methods
// -------------------------------------------------------------------------
// java.security.interfaces.DSAPublicKey interface implementation ----------
public BigInteger getY()
{
return y;
}
// Other instance methods --------------------------------------------------
/**
* <p>Returns the encoded form of this public key according to the designated
* format.</p>
*
* @param format the desired format identifier of the resulting encoding.
* @return the byte sequence encoding this key according to the designated
* format.
* @exception IllegalArgumentException if the format is not supported.
* @see DSSKeyPairRawCodec
*/
public byte[] getEncoded(int format)
{
byte[] result;
switch (format)
{
case IKeyPairCodec.RAW_FORMAT:
result = new DSSKeyPairRawCodec().encodePublicKey(this);
break;
case IKeyPairCodec.X509_FORMAT:
result = new DSSKeyPairX509Codec().encodePublicKey(this);
break;
default:
throw new IllegalArgumentException("Unsupported encoding format: "
+ format);
}
return result;
}
/**
* <p>Returns <code>true</code> if the designated object is an instance of
* {@link DSAPublicKey} and has the same DSS (Digital Signature Standard)
* parameter values as this one.</p>
*
* @param obj the other non-null DSS key to compare to.
* @return <code>true</code> if the designated object is of the same type and
* value as this one.
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (!(obj instanceof DSAPublicKey))
{
return false;
}
DSAPublicKey that = (DSAPublicKey) obj;
return super.equals(that) && y.equals(that.getY());
}
}
@@ -0,0 +1,296 @@
/* FIPS186.java --
Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is a 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 of the License, 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; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, 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.dss;
import gnu.java.security.hash.Sha160;
import gnu.java.security.util.PRNG;
import gnu.java.security.util.Prime2;
import java.math.BigInteger;
import java.security.SecureRandom;
/**
* <p>An implementation of the DSA parameters generation as described in
* FIPS-186.</p>
*
* References:<br>
* <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
* Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
* National Institute of Standards and Technology.
*
* @version $Revision: 1.2 $
*/
public class FIPS186
{
// Constants and variables
// -------------------------------------------------------------------------
public static final int DSA_PARAMS_SEED = 0;
public static final int DSA_PARAMS_COUNTER = 1;
public static final int DSA_PARAMS_Q = 2;
public static final int DSA_PARAMS_P = 3;
public static final int DSA_PARAMS_E = 4;
public static final int DSA_PARAMS_G = 5;
/** The BigInteger constant 2. */
private static final BigInteger TWO = new BigInteger("2");
private static final BigInteger TWO_POW_160 = TWO.pow(160);
/** The SHA instance to use. */
private Sha160 sha = new Sha160();
/** The length of the modulus of DSS keys generated by this instance. */
private int L;
/** The optional {@link SecureRandom} instance to use. */
private SecureRandom rnd = null;
/** Our default source of randomness. */
private PRNG prng = null;
// Constructor(s)
// -------------------------------------------------------------------------
public FIPS186(int L, SecureRandom rnd)
{
super();
this.L = L;
this.rnd = rnd;
}
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
/**
* This method generates the DSS <code>p</code>, <code>q</code>, and
* <code>g</code> parameters only when <code>L</code> (the modulus length)
* is not one of the following: <code>512</code>, <code>768</code> and
* <code>1024</code>. For those values of <code>L</code>, this implementation
* uses pre-computed values of <code>p</code>, <code>q</code>, and
* <code>g</code> given in the document <i>CryptoSpec</i> included in the
* security guide documentation of the standard JDK distribution.<p>
*
* The DSS requires two primes , <code>p</code> and <code>q</code>,
* satisfying the following three conditions:
*
* <ul>
* <li><code>2<sup>159</sup> &lt; q &lt; 2<sup>160</sup></code></li>
* <li><code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code> for a
* specified <code>L</code>, where <code>L = 512 + 64j</code> for some
* <code>0 &lt;= j &lt;= 8</code></li>
* <li>q divides p - 1.</li>
* </ul>
*
* The algorithm used to find these primes is as described in FIPS-186,
* section 2.2: GENERATION OF PRIMES. This prime generation scheme starts by
* using the {@link Sha160} and a user supplied <i>SEED</i>
* to construct a prime, <code>q</code>, in the range 2<sup>159</sup> &lt; q
* &lt; 2<sup>160</sup>. Once this is accomplished, the same <i>SEED</i>
* value is used to construct an <code>X</code> in the range <code>2<sup>L-1
* </sup> &lt; X &lt; 2<sup>L</sup>. The prime, <code>p</code>, is then
* formed by rounding <code>X</code> to a number congruent to <code>1 mod
* 2q</code>. In this implementation we use the same <i>SEED</i> value given
* in FIPS-186, Appendix 5.
*/
public BigInteger[] generateParameters()
{
int counter, offset;
BigInteger SEED, alpha, U, q, OFFSET, SEED_PLUS_OFFSET, W, X, p, c, g;
byte[] a, u;
byte[] kb = new byte[20]; // to hold 160 bits of randomness
// Let L-1 = n*160 + b, where b and n are integers and 0 <= b < 160.
int b = (L - 1) % 160;
int n = (L - 1 - b) / 160;
BigInteger[] V = new BigInteger[n + 1];
algorithm: while (true)
{
step1: while (true)
{
// 1. Choose an arbitrary sequence of at least 160 bits and
// call it SEED.
nextRandomBytes(kb);
SEED = new BigInteger(1, kb).setBit(159).setBit(0);
// Let g be the length of SEED in bits. here always 160
// 2. Compute: U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]
alpha = SEED.add(BigInteger.ONE).mod(TWO_POW_160);
synchronized (sha)
{
a = SEED.toByteArray();
sha.update(a, 0, a.length);
a = sha.digest();
u = alpha.toByteArray();
sha.update(u, 0, u.length);
u = sha.digest();
}
for (int i = 0; i < a.length; i++)
{
a[i] ^= u[i];
}
U = new BigInteger(1, a);
// 3. Form q from U by setting the most significant bit (the
// 2**159 bit) and the least significant bit to 1. In terms of
// boolean operations, q = U OR 2**159 OR 1. Note that
// 2**159 < q < 2**160.
q = U.setBit(159).setBit(0);
// 4. Use a robust primality testing algorithm to test whether
// q is prime(1). A robust primality test is one where the
// probability of a non-prime number passing the test is at
// most 1/2**80.
// 5. If q is not prime, go to step 1.
if (Prime2.isProbablePrime(q))
{
break step1;
}
} // step1
// 6. Let counter = 0 and offset = 2.
counter = 0;
offset = 2;
step7: while (true)
{
OFFSET = BigInteger.valueOf(offset & 0xFFFFFFFFL);
SEED_PLUS_OFFSET = SEED.add(OFFSET);
// 7. For k = 0,...,n let V[k] = SHA[(SEED + offset + k) mod 2**g].
synchronized (sha)
{
for (int k = 0; k <= n; k++)
{
a = SEED_PLUS_OFFSET.add(
BigInteger.valueOf(k & 0xFFFFFFFFL)).mod(
TWO_POW_160).toByteArray();
sha.update(a, 0, a.length);
V[k] = new BigInteger(1, sha.digest());
}
}
// 8. Let W be the integer:
// V[0]+V[1]*2**160+...+V[n-1]*2**((n-1)*160)+(V[n]mod2**b)*2**(n*160)
// and let : X = W + 2**(L-1).
// Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L.
W = V[0];
for (int k = 1; k < n; k++)
{
W = W.add(V[k].multiply(TWO.pow(k * 160)));
}
W = W.add(V[n].mod(TWO.pow(b)).multiply(TWO.pow(n * 160)));
X = W.add(TWO.pow(L - 1));
// 9. Let c = X mod 2q and set p = X - (c - 1).
// Note that p is congruent to 1 mod 2q.
c = X.mod(TWO.multiply(q));
p = X.subtract(c.subtract(BigInteger.ONE));
// 10. If p < 2**(L-1), then go to step 13.
if (p.compareTo(TWO.pow(L - 1)) >= 0)
{
// 11. Perform a robust primality test on p.
// 12. If p passes the test performed in step 11, go to step 15.
if (Prime2.isProbablePrime(p))
{
break algorithm;
}
}
// 13. Let counter = counter + 1 and offset = offset + n + 1.
counter++;
offset += n + 1;
// 14. If counter >= 4096 go to step 1, otherwise go to step 7.
if (counter >= 4096)
{
continue algorithm;
}
} // step7
} // algorithm
// compute g. from FIPS-186, Appendix 4:
// 1. Generate p and q as specified in Appendix 2.
// 2. Let e = (p - 1) / q
BigInteger e = p.subtract(BigInteger.ONE).divide(q);
BigInteger h = TWO;
BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
g = TWO;
// 3. Set h = any integer, where 1 < h < p - 1 and
// h differs from any value previously tried
for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
{
// 4. Set g = h**e mod p
g = h.modPow(e, p);
// 5. If g = 1, go to step 3
if (!g.equals(BigInteger.ONE))
{
break;
}
}
return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
}
// helper methods ----------------------------------------------------------
/**
* Fills the designated byte array with random data.
*
* @param buffer the byte array to fill with random data.
*/
private void nextRandomBytes(byte[] buffer)
{
if (rnd != null)
{
rnd.nextBytes(buffer);
}
else
getDefaultPRNG().nextBytes(buffer);
}
private PRNG getDefaultPRNG()
{
if (prng == null)
prng = PRNG.getInstance();
return prng;
}
}