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:
@@ -0,0 +1,132 @@
|
||||
/* IKeyPairCodec.java --
|
||||
Copyright 2001, 2002, 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;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* <p>The visible methods of an object that knows how to encode and decode
|
||||
* cryptographic asymmetric keypairs. Codecs are useful for (a) externalising
|
||||
* public and private keys for storage and on-the-wire transmission, as well as
|
||||
* (b) re-creating their internal Java representation from external sources.</p>
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
public interface IKeyPairCodec
|
||||
{
|
||||
// Constants
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Constant identifying the <i>Raw</i> encoding format. */
|
||||
int RAW_FORMAT = Registry.RAW_ENCODING_ID;
|
||||
|
||||
/** Constant identifying the <i>X.509</i> encoding format. */
|
||||
int X509_FORMAT = Registry.X509_ENCODING_ID;
|
||||
|
||||
/** Constant identifying the <i>PKCS#8</i> encoding format. */
|
||||
int PKCS8_FORMAT = Registry.PKCS8_ENCODING_ID;
|
||||
|
||||
/**
|
||||
* Constant identifying the <i>ASN.1</i> encoding format: a combined encoding
|
||||
* of <i>X.509</i> for public keys, and <i>PKCS#8</i> for private ones.
|
||||
*/
|
||||
int ASN1_FORMAT = Registry.ASN1_ENCODING_ID;
|
||||
|
||||
// Method(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns the unique identifier (within this library) of the format used
|
||||
* to externalise public and private keys.</p>
|
||||
*
|
||||
* @return the identifier of the format, the object supports.
|
||||
*/
|
||||
int getFormatID();
|
||||
|
||||
/**
|
||||
* <p>Encodes an instance of a public key for storage or transmission purposes.</p>
|
||||
*
|
||||
* @param key the non-null key to encode.
|
||||
* @return a byte sequence representing the encoding of the designated key
|
||||
* according to the format supported by this codec.
|
||||
* @exception IllegalArgumentException if the designated key is not supported
|
||||
* by this codec.
|
||||
*/
|
||||
byte[] encodePublicKey(PublicKey key);
|
||||
|
||||
/**
|
||||
* <p>Encodes an instance of a private key for storage or transmission purposes.</p>
|
||||
*
|
||||
* @param key the non-null key to encode.
|
||||
* @return a byte sequence representing the encoding of the designated key
|
||||
* according to the format supported by this codec.
|
||||
* @exception IllegalArgumentException if the designated key is not supported
|
||||
* by this codec.
|
||||
*/
|
||||
byte[] encodePrivateKey(PrivateKey key);
|
||||
|
||||
/**
|
||||
* <p>Decodes an instance of an external public key into its native Java
|
||||
* representation.</p>
|
||||
*
|
||||
* @param input the source of the externalised key to decode.
|
||||
* @return a concrete instance of a public key, reconstructed from the
|
||||
* designated input.
|
||||
* @exception IllegalArgumentException if the designated input does not
|
||||
* contain a known representation of a public key for the format supported by
|
||||
* the concrete codec.
|
||||
*/
|
||||
PublicKey decodePublicKey(byte[] input);
|
||||
|
||||
/**
|
||||
* <p>Decodes an instance of an external private key into its native Java
|
||||
* representation.</p>
|
||||
*
|
||||
* @param input the source of the externalised key to decode.
|
||||
* @return a concrete instance of a private key, reconstructed from the
|
||||
* designated input.
|
||||
* @exception IllegalArgumentException if the designated input does not
|
||||
* contain a known representation of a private key for the format supported
|
||||
* by the concrete codec.
|
||||
*/
|
||||
PrivateKey decodePrivateKey(byte[] input);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* IKeyPairGenerator.java --
|
||||
Copyright 2001, 2002, 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;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The visible methods of every asymmetric keypair generator.<p>
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public interface IKeyPairGenerator
|
||||
{
|
||||
|
||||
// Constants
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the canonical name of this keypair generator.<p>
|
||||
*
|
||||
* @return the canonical name of this instance.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* [Re]-initialises this instance for use with a given set of attributes.<p>
|
||||
*
|
||||
* @param attributes a map of name/value pairs to use for setting up the
|
||||
* instance.
|
||||
* @exception IllegalArgumentException if at least one of the mandatory
|
||||
* attributes is missing or an invalid value was specified.
|
||||
*/
|
||||
void setup(Map attributes);
|
||||
|
||||
/**
|
||||
* Generates a new keypair based on the attributes used to configure the
|
||||
* instance.
|
||||
*
|
||||
* @return a new keypair.
|
||||
*/
|
||||
KeyPair generate();
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
/* KeyPairCodecFactory.java --
|
||||
Copyright 2001, 2002, 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;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.dss.DSSKeyPairPKCS8Codec;
|
||||
import gnu.java.security.key.dss.DSSKeyPairRawCodec;
|
||||
import gnu.java.security.key.dss.DSSKeyPairX509Codec;
|
||||
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 gnu.java.security.key.rsa.RSAKeyPairPKCS8Codec;
|
||||
import gnu.java.security.key.rsa.RSAKeyPairRawCodec;
|
||||
import gnu.java.security.key.rsa.RSAKeyPairX509Codec;
|
||||
import gnu.java.security.util.FormatUtil;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.security.Key;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A <i>Factory</i> class to instantiate key encoder/decoder instances.
|
||||
*/
|
||||
public class KeyPairCodecFactory
|
||||
{
|
||||
private static Set names;
|
||||
|
||||
/** Trivial constructor to enforce Singleton pattern. */
|
||||
private KeyPairCodecFactory()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate codec given a composed key-pair generator algorithm
|
||||
* and an encoding format. A composed name is formed by the concatenation of
|
||||
* the canonical key-pair algorithm name, the forward slash character
|
||||
* <code>/</code> and the canonical name of the encoding format.
|
||||
* <p>
|
||||
* <b>IMPORTANT</b>: For backward compatibility, when the encoding format
|
||||
* name is missing, the Raw encoding format is assumed. When this is the case
|
||||
* the trailing forward slash is discarded from the name.
|
||||
*
|
||||
* @param name the case-insensitive key codec name.
|
||||
* @return an instance of the keypair codec, or <code>null</code> if none
|
||||
* found.
|
||||
*/
|
||||
public static IKeyPairCodec getInstance(String name)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
name = name.trim();
|
||||
if (name.length() == 0)
|
||||
return null;
|
||||
|
||||
if (name.startsWith("/"))
|
||||
return null;
|
||||
|
||||
if (name.endsWith("/"))
|
||||
return getInstance(name.substring(0, name.length() - 1),
|
||||
Registry.RAW_ENCODING_ID);
|
||||
|
||||
int i = name.indexOf("/");
|
||||
if (i == -1)
|
||||
return getInstance(name, Registry.RAW_ENCODING_ID);
|
||||
|
||||
String kpgName = name.substring(0, i);
|
||||
String formatName = name.substring(i + 1);
|
||||
return getInstance(kpgName, formatName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a keypair codec given the canonical name of the
|
||||
* key-pair algorithm, and the name of the encoding format to use when
|
||||
* externalizing the keys.
|
||||
*
|
||||
* @param name the case-insensitive key-pair algorithm name.
|
||||
* @param format the name of the encoding format to use when externalizing the
|
||||
* keys generated by the key-pair algorithm.
|
||||
* @return an instance of the key-pair codec, or <code>null</code> if none
|
||||
* found.
|
||||
*/
|
||||
public static IKeyPairCodec getInstance(String name, String format)
|
||||
{
|
||||
int formatID = FormatUtil.getFormatID(format);
|
||||
if (formatID == 0)
|
||||
return null;
|
||||
|
||||
return getInstance(name, formatID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a keypair codec given the canonical name of the
|
||||
* key-pair algorithm, and the identifier of the format to use when
|
||||
* externalizing the keys.
|
||||
*
|
||||
* @param name the case-insensitive key-pair algorithm name.
|
||||
* @param formatID the identifier of the format to use when externalizing the
|
||||
* keys generated by the key-pair algorithm.
|
||||
* @return an instance of the key-pair codec, or <code>null</code> if none
|
||||
* found.
|
||||
*/
|
||||
public static IKeyPairCodec getInstance(String name, int formatID)
|
||||
{
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
name = name.trim();
|
||||
switch (formatID)
|
||||
{
|
||||
case Registry.RAW_ENCODING_ID:
|
||||
return getRawCodec(name);
|
||||
case Registry.X509_ENCODING_ID:
|
||||
return getX509Codec(name);
|
||||
case Registry.PKCS8_ENCODING_ID:
|
||||
return getPKCS8Codec(name);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a keypair codec given a key.
|
||||
*
|
||||
* @param key the key to encode.
|
||||
* @return an instance of the keypair codec, or <code>null</code> if none
|
||||
* found.
|
||||
*/
|
||||
public static IKeyPairCodec getInstance(Key key)
|
||||
{
|
||||
if (key == null)
|
||||
return null;
|
||||
|
||||
String format = key.getFormat();
|
||||
int formatID = FormatUtil.getFormatID(format);
|
||||
if (formatID == 0)
|
||||
return null;
|
||||
|
||||
switch (formatID)
|
||||
{
|
||||
case Registry.RAW_ENCODING_ID:
|
||||
return getRawCodec(key);
|
||||
case Registry.X509_ENCODING_ID:
|
||||
return getX509Codec(key);
|
||||
case Registry.PKCS8_ENCODING_ID:
|
||||
return getPKCS8Codec(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of supported key-pair codec names.
|
||||
*
|
||||
* @return a {@link Set} of the names of supported key-pair codec (Strings).
|
||||
*/
|
||||
public static synchronized final Set getNames()
|
||||
{
|
||||
if (names == null)
|
||||
{
|
||||
HashSet hs = new HashSet();
|
||||
hs.add(Registry.DSS_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
|
||||
hs.add(Registry.DSS_KPG + "/" + Registry.X509_ENCODING_SORT_NAME);
|
||||
hs.add(Registry.DSS_KPG + "/" + Registry.PKCS8_ENCODING_SHORT_NAME);
|
||||
hs.add(Registry.RSA_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
|
||||
hs.add(Registry.RSA_KPG + "/" + Registry.X509_ENCODING_SORT_NAME);
|
||||
hs.add(Registry.RSA_KPG + "/" + Registry.PKCS8_ENCODING_SHORT_NAME);
|
||||
hs.add(Registry.DH_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
|
||||
hs.add(Registry.SRP_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
|
||||
|
||||
names = Collections.unmodifiableSet(hs);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
private static IKeyPairCodec makeInstance (String clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class c = Class.forName (clazz);
|
||||
Constructor ctor = c.getConstructor (new Class[0]);
|
||||
return (IKeyPairCodec) ctor.newInstance (new Object[0]);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
IllegalArgumentException iae =
|
||||
new IllegalArgumentException ("strong crypto key codec not available: "
|
||||
+ clazz);
|
||||
iae.initCause (x);
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matches (Object o, String clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class c = Class.forName (clazz);
|
||||
return c.isAssignableFrom (o.getClass ());
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
// Can't match.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the trimmed name of a key-pair algorithm.
|
||||
* @return a Raw format codec for the designated key-pair algorithm, or
|
||||
* <code>null</code> if none exists.
|
||||
*/
|
||||
private static IKeyPairCodec getRawCodec(String name)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if (name.equalsIgnoreCase(Registry.DSA_KPG)
|
||||
|| name.equals(Registry.DSS_KPG))
|
||||
result = new DSSKeyPairRawCodec();
|
||||
else if (name.equalsIgnoreCase(Registry.RSA_KPG))
|
||||
result = new RSAKeyPairRawCodec();
|
||||
else if (name.equalsIgnoreCase(Registry.DH_KPG))
|
||||
result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
|
||||
else if (name.equalsIgnoreCase(Registry.SRP_KPG))
|
||||
result = makeInstance("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the trimmed name of a key-pair algorithm.
|
||||
* @return a X.509 format codec for the designated key-pair algorithm, or
|
||||
* <code>null</code> if none exists.
|
||||
*/
|
||||
private static IKeyPairCodec getX509Codec(String name)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if (name.equalsIgnoreCase(Registry.DSA_KPG)
|
||||
|| name.equals(Registry.DSS_KPG))
|
||||
result = new DSSKeyPairX509Codec();
|
||||
else if (name.equalsIgnoreCase(Registry.RSA_KPG))
|
||||
result = new RSAKeyPairX509Codec();
|
||||
else if (name.equalsIgnoreCase(Registry.DH_KPG))
|
||||
result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairX509Codec");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the trimmed name of a key-pair algorithm.
|
||||
* @return a PKCS#8 format codec for the designated key-pair algorithm, or
|
||||
* <code>null</code> if none exists.
|
||||
*/
|
||||
private static IKeyPairCodec getPKCS8Codec(String name)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if (name.equalsIgnoreCase(Registry.DSA_KPG)
|
||||
|| name.equals(Registry.DSS_KPG))
|
||||
result = new DSSKeyPairPKCS8Codec();
|
||||
else if (name.equalsIgnoreCase(Registry.RSA_KPG))
|
||||
result = new RSAKeyPairPKCS8Codec();
|
||||
else if (name.equalsIgnoreCase(Registry.DH_KPG))
|
||||
result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairPKCS8Codec");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a {@link Key} for which we want to return a Raw codec.
|
||||
* @return the Raw codec corresponding to the key, or <code>null</code> if
|
||||
* none exists for this key.
|
||||
*/
|
||||
private static IKeyPairCodec getRawCodec(Key key)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if ((key instanceof DSSPublicKey) || (key instanceof DSSPrivateKey))
|
||||
result = new DSSKeyPairRawCodec();
|
||||
else if ((key instanceof GnuRSAPublicKey)
|
||||
|| (key instanceof GnuRSAPrivateKey))
|
||||
result = new RSAKeyPairRawCodec();
|
||||
else if (matches(key, "gnu.javax.crypto.key.dh.GnuDHPublicKey")
|
||||
|| matches(key, "gnu.javax.crypto.key.dh.GnuDHPrivateKey"))
|
||||
result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
|
||||
else if (matches(key, "gnu.javax.crypto.key.srp6.SRPPublicKey")
|
||||
|| matches(key, "gnu.javax.crypto.key.srp6.SRPPrivateKey"))
|
||||
result = makeInstance("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a {@link Key} for which we want to return an X.509 codec.
|
||||
* @return the X.509 codec corresponding to the key, or <code>null</code> if
|
||||
* none exists for this key.
|
||||
*/
|
||||
private static IKeyPairCodec getX509Codec(Key key)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if (key instanceof DSSPublicKey)
|
||||
result = new DSSKeyPairX509Codec();
|
||||
else if (key instanceof GnuRSAPublicKey)
|
||||
result = new RSAKeyPairX509Codec();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a {@link Key} for which we want to return a PKCS#8 codec.
|
||||
* @return the PKCS#8 codec corresponding to the key, or <code>null</code> if
|
||||
* none exists for this key.
|
||||
*/
|
||||
private static IKeyPairCodec getPKCS8Codec(Key key)
|
||||
{
|
||||
IKeyPairCodec result = null;
|
||||
if (key instanceof DSSPrivateKey)
|
||||
result = new DSSKeyPairPKCS8Codec();
|
||||
else if (key instanceof GnuRSAPrivateKey)
|
||||
result = new RSAKeyPairPKCS8Codec();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/* KeyPairGeneratorFactory.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;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.dss.DSSKeyPairGenerator;
|
||||
import gnu.java.security.key.rsa.RSAKeyPairGenerator;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>A Factory to instantiate asymmetric keypair generators.</p>
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public class KeyPairGeneratorFactory
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Trivial constructor to enforce Singleton pattern. */
|
||||
private KeyPairGeneratorFactory()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns an instance of a keypair generator given its name.</p>
|
||||
*
|
||||
* @param name the case-insensitive key generator name.
|
||||
* @return an instance of the keypair generator, or <code>null</code> if none
|
||||
* found.
|
||||
*/
|
||||
public static IKeyPairGenerator getInstance(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
name = name.trim();
|
||||
IKeyPairGenerator result = null;
|
||||
if (name.equalsIgnoreCase(Registry.DSA_KPG)
|
||||
|| name.equals(Registry.DSS_KPG))
|
||||
{
|
||||
result = new DSSKeyPairGenerator();
|
||||
}
|
||||
else if (name.equalsIgnoreCase(Registry.RSA_KPG))
|
||||
{
|
||||
result = new RSAKeyPairGenerator();
|
||||
}
|
||||
else if (name.equalsIgnoreCase(Registry.DH_KPG))
|
||||
{
|
||||
result = makeInstance ("gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator");
|
||||
}
|
||||
else if (name.equalsIgnoreCase(Registry.SRP_KPG))
|
||||
{
|
||||
result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairGenerator");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a {@link Set} of keypair generator names supported by this
|
||||
* <i>Factory</i>. Those keypair generators may be used in conjunction with
|
||||
* the digital signature schemes with appendix supported by this library.</p>
|
||||
*
|
||||
* @return a {@link Set} of keypair generator names (Strings).
|
||||
*/
|
||||
public static final Set getNames()
|
||||
{
|
||||
HashSet hs = new HashSet();
|
||||
hs.add(Registry.DSS_KPG);
|
||||
hs.add(Registry.RSA_KPG);
|
||||
hs.add(Registry.DH_KPG);
|
||||
hs.add(Registry.SRP_KPG);
|
||||
|
||||
return Collections.unmodifiableSet(hs);
|
||||
}
|
||||
|
||||
private static IKeyPairGenerator makeInstance (String clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class c = Class.forName (clazz);
|
||||
Constructor ctor = c.getConstructor (new Class[0]);
|
||||
return (IKeyPairGenerator) ctor.newInstance (new Object[0]);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
IllegalArgumentException iae =
|
||||
new IllegalArgumentException ("strong crypto key pair generator not available: "
|
||||
+ clazz);
|
||||
iae.initCause (x);
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
}
|
||||
@@ -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> < p < 2<sup>L</sup></code>
|
||||
* for <code>512 <= L <= 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> < q
|
||||
* < 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 < h < 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 < x <
|
||||
* 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> < q < 2<sup>160</sup></code></li>
|
||||
* <li><code>2<sup>L-1</sup> < p < 2<sup>L</sup></code> for a
|
||||
* specified <code>L</code>, where <code>L = 512 + 64j</code> for some
|
||||
* <code>0 <= j <= 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> < q
|
||||
* < 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> < X < 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/* GnuRSAKey.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.rsa;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.IKeyPairCodec;
|
||||
import gnu.java.security.util.FormatUtil;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.Key;
|
||||
import java.security.interfaces.RSAKey;
|
||||
|
||||
/**
|
||||
* <p>A base asbtract class for both public and private RSA keys.</p>
|
||||
*
|
||||
* @version $Revision: 1.3 $
|
||||
*/
|
||||
public abstract class GnuRSAKey implements Key, RSAKey
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** The public modulus of an RSA key pair. */
|
||||
private final BigInteger n;
|
||||
|
||||
/** 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)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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(int defaultFormat, BigInteger n, BigInteger e)
|
||||
{
|
||||
super();
|
||||
|
||||
this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
|
||||
: defaultFormat;
|
||||
this.n = n;
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// java.security.interfaces.RSAKey interface implementation ----------------
|
||||
|
||||
public BigInteger getModulus()
|
||||
{
|
||||
return getN();
|
||||
}
|
||||
|
||||
// java.security.Key interface implementation ------------------------------
|
||||
|
||||
public String getAlgorithm()
|
||||
{
|
||||
return Registry.RSA_KPG;
|
||||
}
|
||||
|
||||
/** @deprecated see getEncoded(int). */
|
||||
public byte[] getEncoded()
|
||||
{
|
||||
return getEncoded(IKeyPairCodec.RAW_FORMAT);
|
||||
}
|
||||
|
||||
public String getFormat()
|
||||
{
|
||||
return FormatUtil.getEncodingShortName(defaultFormat);
|
||||
}
|
||||
|
||||
// Other instance methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns the modulus <code>n</code>.</p>
|
||||
*
|
||||
* @return the modulus <code>n</code>.
|
||||
*/
|
||||
public BigInteger getN()
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the public exponent <code>e</code>.</p>
|
||||
*
|
||||
* @return the public exponent <code>e</code>.
|
||||
*/
|
||||
public BigInteger getPublicExponent()
|
||||
{
|
||||
return getE();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Same as {@link #getPublicExponent()}.</p>
|
||||
*
|
||||
* @return the public exponent <code>e</code>.
|
||||
*/
|
||||
public BigInteger getE()
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns <code>true</code> if the designated object is an instance of
|
||||
* {@link RSAKey} and has the same RSA parameter values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null RSA 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(final Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof RSAKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final RSAKey that = (RSAKey) obj;
|
||||
return n.equals(that.getModulus());
|
||||
}
|
||||
|
||||
// abstract methods to be implemented by subclasses ------------------------
|
||||
|
||||
public abstract byte[] getEncoded(int format);
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/* GnuRSAPrivateKey.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.rsa;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.IKeyPairCodec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.interfaces.RSAPrivateCrtKey;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
|
||||
/**
|
||||
* <p>An object that embodies an RSA private key.</p>
|
||||
*
|
||||
* <p>References:</p>
|
||||
* <ol>
|
||||
* <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
|
||||
* RSA-PSS Signature Scheme with Appendix, part B.</a><br>
|
||||
* Primitive specification and supporting documentation.<br>
|
||||
* Jakob Jonsson and Burt Kaliski.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @version $Revision: 1.3 $
|
||||
*/
|
||||
public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
|
||||
RSAPrivateCrtKey
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** The first prime divisor of the modulus. */
|
||||
private final BigInteger p;
|
||||
|
||||
/** The second prime divisor of the modulus. */
|
||||
private final BigInteger q;
|
||||
|
||||
/** The public exponent of an RSA key. */
|
||||
// private final BigInteger e;
|
||||
/** The private exponent of an RSA private key. */
|
||||
private final BigInteger d;
|
||||
|
||||
/** The first factor's exponent. */
|
||||
private final BigInteger dP;
|
||||
|
||||
/** The second factor's exponent. */
|
||||
private final BigInteger dQ;
|
||||
|
||||
/** The CRT (Chinese Remainder Theorem) coefficient. */
|
||||
private final BigInteger qInv;
|
||||
|
||||
// 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 modulus first prime divisor.
|
||||
* @param q the modulus second prime divisor.
|
||||
* @param e the public exponent.
|
||||
* @param d the private exponent.
|
||||
*/
|
||||
public GnuRSAPrivateKey(BigInteger p, BigInteger q, BigInteger e,
|
||||
BigInteger d)
|
||||
{
|
||||
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>.
|
||||
*/
|
||||
public 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;
|
||||
// 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),
|
||||
this.dP = dP;
|
||||
this.dQ = dQ;
|
||||
// the CRT coefficient qInv is a positive integer less than p satisfying
|
||||
// q * qInv = 1 (mod p).
|
||||
this.qInv = qInv;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class method that takes the output of the <code>encodePrivateKey()</code>
|
||||
* method of an RSA keypair codec object (an instance implementing
|
||||
* {@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.
|
||||
* @throws IllegalArgumentException if the byte sequence does not represent a
|
||||
* valid encoding of an instance of this object.
|
||||
*/
|
||||
public static GnuRSAPrivateKey valueOf(final byte[] k)
|
||||
{
|
||||
// try RAW codec
|
||||
if (k[0] == Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0])
|
||||
try
|
||||
{
|
||||
return (GnuRSAPrivateKey) new RSAKeyPairRawCodec().decodePrivateKey(k);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
// try PKCS#8 codec
|
||||
return (GnuRSAPrivateKey) new RSAKeyPairPKCS8Codec().decodePrivateKey(k);
|
||||
}
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public BigInteger getPrimeP()
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
public BigInteger getPrimeQ()
|
||||
{
|
||||
return q;
|
||||
}
|
||||
|
||||
public BigInteger getPrimeExponentP()
|
||||
{
|
||||
return dP;
|
||||
}
|
||||
|
||||
public BigInteger getPrimeExponentQ()
|
||||
{
|
||||
return dQ;
|
||||
}
|
||||
|
||||
public BigInteger getCrtCoefficient()
|
||||
{
|
||||
return qInv;
|
||||
}
|
||||
|
||||
// java.security.interfaces.RSAPrivateKey interface implementation ---------
|
||||
|
||||
public BigInteger getPrivateExponent()
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
// Other instance methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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 RSAKeyPairRawCodec
|
||||
* @see RSAKeyPairPKCS8Codec
|
||||
*/
|
||||
public byte[] getEncoded(int format)
|
||||
{
|
||||
final byte[] result;
|
||||
switch (format)
|
||||
{
|
||||
case IKeyPairCodec.RAW_FORMAT:
|
||||
result = new RSAKeyPairRawCodec().encodePrivateKey(this);
|
||||
break;
|
||||
case IKeyPairCodec.PKCS8_FORMAT:
|
||||
result = new RSAKeyPairPKCS8Codec().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
|
||||
* this class and has the same RSA parameter values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null RSA 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(final Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof RSAPrivateKey)
|
||||
{
|
||||
final RSAPrivateKey that = (RSAPrivateKey) obj;
|
||||
return super.equals(that) && d.equals(that.getPrivateExponent());
|
||||
}
|
||||
if (obj instanceof RSAPrivateCrtKey)
|
||||
{
|
||||
final RSAPrivateCrtKey that = (RSAPrivateCrtKey) obj;
|
||||
return super.equals(that) && p.equals(that.getPrimeP())
|
||||
&& q.equals(that.getPrimeQ())
|
||||
&& dP.equals(that.getPrimeExponentP())
|
||||
&& dQ.equals(that.getPrimeExponentQ())
|
||||
&& qInv.equals(that.getCrtCoefficient());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/* GnuRSAPublicKey.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.rsa;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.IKeyPairCodec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
|
||||
/**
|
||||
* <p>An object that encapsulates an RSA public key.</p>
|
||||
*
|
||||
* <p>References:</p>
|
||||
* <ol>
|
||||
* <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
|
||||
* RSA-PSS Signature Scheme with Appendix, part B.</a><br>
|
||||
* Primitive specification and supporting documentation.<br>
|
||||
* Jakob Jonsson and Burt Kaliski.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
|
||||
RSAPublicKey
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class method that takes the output of the <code>encodePublicKey()</code>
|
||||
* method of an RSA keypair codec object (an instance implementing
|
||||
* {@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.
|
||||
* @throws IllegalArgumentException if the byte sequence does not represent a
|
||||
* valid encoding of an instance of this object.
|
||||
*/
|
||||
public static GnuRSAPublicKey valueOf(final byte[] k)
|
||||
{
|
||||
// try RAW codec
|
||||
if (k[0] == Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0])
|
||||
try
|
||||
{
|
||||
return (GnuRSAPublicKey) new RSAKeyPairRawCodec().decodePublicKey(k);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
// try X.509 codec
|
||||
return (GnuRSAPublicKey) new RSAKeyPairX509Codec().decodePublicKey(k);
|
||||
}
|
||||
|
||||
// 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.
|
||||
* @throws IllegalArgumentException if the format is not supported.
|
||||
* @see RSAKeyPairRawCodec
|
||||
*/
|
||||
public byte[] getEncoded(final int format)
|
||||
{
|
||||
final byte[] result;
|
||||
switch (format)
|
||||
{
|
||||
case IKeyPairCodec.RAW_FORMAT:
|
||||
result = new RSAKeyPairRawCodec().encodePublicKey(this);
|
||||
break;
|
||||
case IKeyPairCodec.X509_FORMAT:
|
||||
result = new RSAKeyPairX509Codec().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
|
||||
* this class and has the same RSA parameter values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null RSA 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(final Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof RSAPublicKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final RSAPublicKey that = (RSAPublicKey) obj;
|
||||
return super.equals(that)
|
||||
&& getPublicExponent().equals(that.getPublicExponent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/* RSAKeyPairGenerator.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.rsa;
|
||||
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.key.IKeyPairGenerator;
|
||||
import gnu.java.security.util.PRNG;
|
||||
import gnu.java.security.util.Prime2;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.RSAKeyGenParameterSpec;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>A key-pair generator for asymetric keys to use in conjunction with the RSA
|
||||
* scheme.</p>
|
||||
*
|
||||
* <p>Reference:</p>
|
||||
* <ol>
|
||||
* <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
|
||||
* RSA-PSS Signature Scheme with Appendix</a>, part B. Primitive
|
||||
* specification and supporting documentation. Jakob Jonsson and Burt Kaliski.
|
||||
* </li>
|
||||
* <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
|
||||
* Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
|
||||
* Vanstone. Section 11.3 RSA and related signature schemes.</li>
|
||||
* </ol>
|
||||
*/
|
||||
public class RSAKeyPairGenerator implements IKeyPairGenerator
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** The BigInteger constant 1. */
|
||||
private static final BigInteger ONE = BigInteger.ONE;
|
||||
|
||||
/** The BigInteger constant 2. */
|
||||
private static final BigInteger TWO = BigInteger.valueOf(2L);
|
||||
|
||||
/** Property name of the length (Integer) of the modulus of an RSA key. */
|
||||
public static final String MODULUS_LENGTH = "gnu.crypto.rsa.L";
|
||||
|
||||
/**
|
||||
* 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.rsa.prng";
|
||||
|
||||
/**
|
||||
* Property name of an optional {@link RSAKeyGenParameterSpec} instance to
|
||||
* use for this generator's <code>n</code>, and <code>e</code> values. The
|
||||
* default is to generate <code>n</code> and use a fixed value for
|
||||
* <code>e</.code> (Fermat's F4 number).
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* This implementation uses, by default, Fermat's F4 number as the public
|
||||
* exponent.
|
||||
*/
|
||||
private BigInteger e = BigInteger.valueOf(65537L);
|
||||
|
||||
/** The optional {@link SecureRandom} instance to use. */
|
||||
private SecureRandom rnd = null;
|
||||
|
||||
/** 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
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
|
||||
|
||||
public String name()
|
||||
{
|
||||
return Registry.RSA_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 less than 1024.
|
||||
*/
|
||||
public void setup(Map attributes)
|
||||
{
|
||||
// do we have a SecureRandom, or should we use our own?
|
||||
rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
|
||||
|
||||
// are we given a set of RSA params or we shall use our own?
|
||||
RSAKeyGenParameterSpec params = (RSAKeyGenParameterSpec) attributes.get(RSA_PARAMETERS);
|
||||
|
||||
// find out the modulus length
|
||||
if (params != null)
|
||||
{
|
||||
L = params.getKeysize();
|
||||
e = params.getPublicExponent();
|
||||
}
|
||||
else
|
||||
{
|
||||
Integer l = (Integer) attributes.get(MODULUS_LENGTH);
|
||||
L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
|
||||
}
|
||||
|
||||
if (L < 1024)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The algorithm used here is described in <i>nessie-pss-B.pdf</i>
|
||||
* document which is part of the RSA-PSS submission to NESSIE.</p>
|
||||
*
|
||||
* @return an RSA keypair.
|
||||
*/
|
||||
public KeyPair generate()
|
||||
{
|
||||
BigInteger p, q, n, d;
|
||||
|
||||
// 1. Generate a prime p in the interval [2**(M-1), 2**M - 1], where
|
||||
// M = CEILING(L/2), and such that GCD(p, e) = 1
|
||||
int M = (L + 1) / 2;
|
||||
BigInteger lower = TWO.pow(M - 1);
|
||||
BigInteger upper = TWO.pow(M).subtract(ONE);
|
||||
byte[] kb = new byte[(M + 7) / 8]; // enough bytes to frame M bits
|
||||
step1: while (true)
|
||||
{
|
||||
nextRandomBytes(kb);
|
||||
p = new BigInteger(1, kb).setBit(0);
|
||||
if (p.compareTo(lower) >= 0 && p.compareTo(upper) <= 0
|
||||
&& Prime2.isProbablePrime(p) && p.gcd(e).equals(ONE))
|
||||
{
|
||||
break step1;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Generate a prime q such that the product of p and q is an L-bit
|
||||
// number, and such that GCD(q, e) = 1
|
||||
step2: while (true)
|
||||
{
|
||||
nextRandomBytes(kb);
|
||||
q = new BigInteger(1, kb).setBit(0);
|
||||
n = p.multiply(q);
|
||||
if (n.bitLength() == L && Prime2.isProbablePrime(q)
|
||||
&& q.gcd(e).equals(ONE))
|
||||
{
|
||||
break step2;
|
||||
}
|
||||
|
||||
// TODO: test for p != q
|
||||
}
|
||||
|
||||
// TODO: ensure p < q
|
||||
|
||||
// 3. Put n = pq. The public key is (n, e).
|
||||
// 4. Compute the parameters necessary for the private key K (see
|
||||
// Section 2.2).
|
||||
BigInteger phi = p.subtract(ONE).multiply(q.subtract(ONE));
|
||||
d = e.modInverse(phi);
|
||||
|
||||
// 5. Output the public key and the private key.
|
||||
PublicKey pubK = new GnuRSAPublicKey(preferredFormat, n, e);
|
||||
PrivateKey secK = new GnuRSAPrivateKey(preferredFormat, p, q, e, d);
|
||||
|
||||
return new KeyPair(pubK, secK);
|
||||
}
|
||||
|
||||
// helper methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <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,284 @@
|
||||
/* 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;
|
||||
import gnu.java.security.util.DerUtil;
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
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 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 InvalidParameterException("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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 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();
|
||||
DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
|
||||
|
||||
DERValue derVersion = der.read();
|
||||
DerUtil.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();
|
||||
DerUtil.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();
|
||||
DerUtil.checkIsConstructed(derRSAPrivateKey, "Wrong RSAPrivateKey field");
|
||||
|
||||
val = der.read();
|
||||
DerUtil.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();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong modulus field");
|
||||
n = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong publicExponent field");
|
||||
e = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong privateExponent field");
|
||||
d = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong prime1 field");
|
||||
p = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong prime2 field");
|
||||
q = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong exponent1 field");
|
||||
dP = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong exponent2 field");
|
||||
dQ = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/* RSAKeyPairRawCodec.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.rsa;
|
||||
|
||||
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} interface for the
|
||||
* <i>Raw</i> format to use with RSA keypairs.</p>
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public class RSAKeyPairRawCodec implements IKeyPairCodec
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// implicit 0-arguments constructor
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// gnu.crypto.key.IKeyPairCodec interface implementation -------------------
|
||||
|
||||
public int getFormatID()
|
||||
{
|
||||
return RAW_FORMAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of the designated RSA public key according to
|
||||
* the <i>Raw</i> format supported by this library.</p>
|
||||
*
|
||||
* <p>The <i>Raw</i> format for an RSA 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_RSA_PUBLIC_KEY},<li>
|
||||
* <li>1-byte version consisting of the constant: 0x01,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>n</code> (the modulus) in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>n</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>e</code> (the public exponent) in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>e</code>.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param key the key to encode.
|
||||
* @return the <i>Raw</i> format encoding of the designated key.
|
||||
* @exception IllegalArgumentException if the designated key is not an RSA
|
||||
* one.
|
||||
*/
|
||||
public byte[] encodePublicKey(PublicKey key)
|
||||
{
|
||||
if (!(key instanceof GnuRSAPublicKey))
|
||||
{
|
||||
throw new IllegalArgumentException("key");
|
||||
}
|
||||
|
||||
GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
// magic
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3]);
|
||||
|
||||
// version
|
||||
baos.write(0x01);
|
||||
|
||||
// n
|
||||
byte[] buffer = rsaKey.getModulus().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);
|
||||
|
||||
// e
|
||||
buffer = rsaKey.getPublicExponent().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_RSA_PUBLIC_KEY[0]
|
||||
|| k[1] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]
|
||||
|| k[2] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]
|
||||
|| k[3] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3])
|
||||
{
|
||||
throw new IllegalArgumentException("magic");
|
||||
}
|
||||
|
||||
// version
|
||||
if (k[4] != 0x01)
|
||||
{
|
||||
throw new IllegalArgumentException("version");
|
||||
}
|
||||
int i = 5;
|
||||
|
||||
int l;
|
||||
byte[] buffer;
|
||||
|
||||
// n
|
||||
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 n = new BigInteger(1, buffer);
|
||||
|
||||
// e
|
||||
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 e = new BigInteger(1, buffer);
|
||||
|
||||
return new GnuRSAPublicKey(n, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of the designated RSA private key according to
|
||||
* the <i>Raw</i> format supported by this library.</p>
|
||||
*
|
||||
* <p>The <i>Raw</i> format for an RSA 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_RSA_PRIVATE_KEY},<li>
|
||||
* <li>1-byte version consisting of the constant: 0x01,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>p</code> (the first prime factor of the modulus) in internet
|
||||
* order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>p</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>q</code> (the second prime factor of the modulus) in internet
|
||||
* order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>q</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>e</code> (the public exponent) in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>e</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the RSA parameter
|
||||
* <code>d</code> (the private exponent) in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the RSA parameter <code>d</code>,</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param key the key to encode.
|
||||
* @return the <i>Raw</i> format encoding of the designated key.
|
||||
*/
|
||||
public byte[] encodePrivateKey(PrivateKey key)
|
||||
{
|
||||
if (!(key instanceof GnuRSAPrivateKey))
|
||||
{
|
||||
throw new IllegalArgumentException("key");
|
||||
}
|
||||
|
||||
GnuRSAPrivateKey rsaKey = (GnuRSAPrivateKey) key;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
// magic
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]);
|
||||
baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3]);
|
||||
|
||||
// version
|
||||
baos.write(0x01);
|
||||
|
||||
// p
|
||||
byte[] buffer = rsaKey.getPrimeP().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 = rsaKey.getPrimeQ().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);
|
||||
|
||||
// e
|
||||
buffer = rsaKey.getPublicExponent().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);
|
||||
|
||||
// d
|
||||
buffer = rsaKey.getPrivateExponent().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_RSA_PRIVATE_KEY[0]
|
||||
|| k[1] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]
|
||||
|| k[2] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]
|
||||
|| k[3] != Registry.MAGIC_RAW_RSA_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);
|
||||
|
||||
// e
|
||||
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 e = new BigInteger(1, buffer);
|
||||
|
||||
// d
|
||||
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 d = new BigInteger(1, buffer);
|
||||
|
||||
return new GnuRSAPrivateKey(p, q, e, d);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/* 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 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;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* 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 Logger log = Logger.getLogger(RSAKeyPairX509Codec.class.getName());
|
||||
private static final OID RSA_ALG_OID = new OID(Registry.RSA_OID_STRING);
|
||||
|
||||
// implicit 0-arguments constructor
|
||||
|
||||
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>
|
||||
* As indicated in RFC-2459: "The parameters field shall have ASN.1 type NULL
|
||||
* for this algorithm identifier.".
|
||||
* <p>
|
||||
* The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
|
||||
* DER-encoded form of the RSA public key defined as:
|
||||
*
|
||||
* <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)
|
||||
{
|
||||
log.entering(this.getClass().getName(), "encodePublicKey()", 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;
|
||||
}
|
||||
|
||||
log.exiting(this.getClass().getName(), "encodePublicKey()", result);
|
||||
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 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)
|
||||
{
|
||||
log.entering(this.getClass().getName(), "decodePublicKey()", 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();
|
||||
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(RSA_ALG_OID))
|
||||
throw new InvalidParameterException("Unexpected OID: " + algOID);
|
||||
|
||||
// rfc-2459 states that this field is OPTIONAL but NULL if/when present
|
||||
DERValue val = der.read();
|
||||
if (val.getTag() == DER.NULL)
|
||||
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();
|
||||
DerUtil.checkIsConstructed(derAlgorithmID, "Wrong subjectPublicKey field");
|
||||
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong modulus field");
|
||||
n = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong publicExponent field");
|
||||
e = (BigInteger) val.getValue();
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
InvalidParameterException y = new InvalidParameterException();
|
||||
y.initCause(x);
|
||||
throw y;
|
||||
}
|
||||
|
||||
PublicKey result = new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
|
||||
log.exiting(this.getClass().getName(), "decodePublicKey()", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParameterException ALWAYS.
|
||||
*/
|
||||
public PrivateKey decodePrivateKey(byte[] input)
|
||||
{
|
||||
throw new InvalidParameterException("Wrong format for private keys");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user