Imported GNU Classpath 0.92

2006-08-14  Mark Wielaard  <mark@klomp.org>

       Imported GNU Classpath 0.92
       * HACKING: Add more importing hints. Update automake version
       requirement.

       * configure.ac (gconf-peer): New enable AC argument.
       Add --disable-gconf-peer and --enable-default-preferences-peer
       to classpath configure when gconf is disabled.
       * scripts/makemake.tcl: Set gnu/java/util/prefs/gconf and
       gnu/java/awt/dnd/peer/gtk to bc. Classify
       gnu/java/security/Configuration.java as generated source file.

       * gnu/java/lang/management/VMGarbageCollectorMXBeanImpl.java,
       gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java,
       gnu/java/lang/management/VMClassLoadingMXBeanImpl.java,
       gnu/java/lang/management/VMRuntimeMXBeanImpl.java,
       gnu/java/lang/management/VMMemoryManagerMXBeanImpl.java,
       gnu/java/lang/management/VMThreadMXBeanImpl.java,
       gnu/java/lang/management/VMMemoryMXBeanImpl.java,
       gnu/java/lang/management/VMCompilationMXBeanImpl.java: New VM stub
       classes.
       * java/lang/management/VMManagementFactory.java: Likewise.
       * java/net/VMURLConnection.java: Likewise.
       * gnu/java/nio/VMChannel.java: Likewise.

       * java/lang/Thread.java (getState): Add stub implementation.
       * java/lang/Class.java (isEnum): Likewise.
       * java/lang/Class.h (isEnum): Likewise.

       * gnu/awt/xlib/XToolkit.java (getClasspathTextLayoutPeer): Removed.

       * javax/naming/spi/NamingManager.java: New override for StackWalker
       functionality.

       * configure, sources.am, Makefile.in, gcj/Makefile.in,
       include/Makefile.in, testsuite/Makefile.in: Regenerated.

From-SVN: r116139
This commit is contained in:
Mark Wielaard
2006-08-14 23:12:35 +00:00
parent abab460491
commit ac1ed908de
1294 changed files with 99479 additions and 35933 deletions
@@ -49,15 +49,11 @@ import java.util.Map;
import java.util.Random;
/**
* <p>A base abstract class to facilitate implementations of concrete
* Signatures.</p>
* A base abstract class to facilitate implementations of concrete Signatures.
*/
public abstract class BaseSignature implements ISignature
public abstract class BaseSignature
implements ISignature
{
// Constants and variables
// -------------------------------------------------------------------------
/** The canonical name of this signature scheme. */
protected String schemeName;
@@ -79,9 +75,6 @@ public abstract class BaseSignature implements ISignature
/** Our default source of randomness. */
private PRNG prng = null;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* Trivial constructor.
*
@@ -101,14 +94,6 @@ public abstract class BaseSignature implements ISignature
this.md = md;
}
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// gnu.crypto.sig.ISignature interface implementation ----------------------
public String name()
{
return schemeName + "-" + md.name();
@@ -117,51 +102,41 @@ public abstract class BaseSignature implements ISignature
public void setupVerify(Map attributes) throws IllegalArgumentException
{
setup(attributes);
// do we have a public key?
PublicKey key = (PublicKey) attributes.get(VERIFIER_KEY);
if (key != null)
{
setupForVerification(key);
}
setupForVerification(key);
}
public void setupSign(Map attributes) throws IllegalArgumentException
{
setup(attributes);
// do we have a private key?
PrivateKey key = (PrivateKey) attributes.get(SIGNER_KEY);
if (key != null)
{
setupForSigning(key);
}
setupForSigning(key);
}
public void update(byte b)
{
if (md == null)
{
throw new IllegalStateException();
}
throw new IllegalStateException();
md.update(b);
}
public void update(byte[] b, int off, int len)
{
if (md == null)
{
throw new IllegalStateException();
}
throw new IllegalStateException();
md.update(b, off, len);
}
public Object sign()
{
if (md == null || privateKey == null)
{
throw new IllegalStateException();
}
throw new IllegalStateException();
return generateSignature();
}
@@ -169,15 +144,11 @@ public abstract class BaseSignature implements ISignature
public boolean verify(Object sig)
{
if (md == null || publicKey == null)
{
throw new IllegalStateException();
}
throw new IllegalStateException();
return verifySignature(sig);
}
// abstract methods to be implemented by concrete subclasses ---------------
public abstract Object clone();
protected abstract void setupForVerification(PublicKey key)
@@ -191,8 +162,6 @@ public abstract class BaseSignature implements ISignature
protected abstract boolean verifySignature(Object signature)
throws IllegalStateException;
// Other instance methods --------------------------------------------------
/** Initialises the internal fields of this instance. */
protected void init()
{
@@ -204,33 +173,27 @@ public abstract class BaseSignature implements ISignature
}
/**
* <p>Fills the designated byte array with random data.</p>
*
* Fills the designated byte array with random data.
*
* @param buffer the byte array to fill with random data.
*/
protected void nextRandomBytes(byte[] buffer)
{
if (rnd != null)
{
rnd.nextBytes(buffer);
}
rnd.nextBytes(buffer);
else if (irnd != null)
{
try
{
irnd.nextBytes(buffer, 0, buffer.length);
}
catch (IllegalStateException x)
{
throw new RuntimeException("nextRandomBytes(): "
+ String.valueOf(x));
}
catch (LimitReachedException x)
{
throw new RuntimeException("nextRandomBytes(): "
+ String.valueOf(x));
}
}
try
{
irnd.nextBytes(buffer, 0, buffer.length);
}
catch (IllegalStateException x)
{
throw new RuntimeException("nextRandomBytes(): " + x);
}
catch (LimitReachedException x)
{
throw new RuntimeException("nextRandomBytes(): " + x);
}
else
getDefaultPRNG().nextBytes(buffer);
}
@@ -238,17 +201,12 @@ public abstract class BaseSignature implements ISignature
private void setup(Map attributes)
{
init();
// do we have a Random or SecureRandom, or should we use our own?
Object obj = attributes.get(SOURCE_OF_RANDOMNESS);
if (obj instanceof Random)
{
rnd = (Random) obj;
}
rnd = (Random) obj;
else if (obj instanceof IRandom)
{
irnd = (IRandom) obj;
}
irnd = (IRandom) obj;
}
private PRNG getDefaultPRNG()
@@ -41,28 +41,24 @@ package gnu.java.security.sig;
import java.util.Map;
/**
* <p>The visible methods of every signature-with-appendix scheme.</p>
*
* <p>The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
* The visible methods of every signature-with-appendix scheme.
* <p>
* The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
* "Digital signature schemes which require the message as input to the
* verification algorithm are called <i>digital signature schemes with
* appendix</i>. ... They rely on cryptographic hash functions rather than
* customised redundancy functions, and are less prone to existential forgery
* attacks."</p>
*
* <p>References:</p>
* verification algorithm are called <i>digital signature schemes with appendix</i>.
* ... They rely on cryptographic hash functions rather than customised
* redundancy functions, and are less prone to existential forgery attacks."
* <p>
* References:
* <ol>
* <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.2.2 Digital signature schemes with appendix.</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.2.2 Digital signature schemes with appendix.</li>
* </ol>
*/
public interface ISignature extends Cloneable
public interface ISignature
extends Cloneable
{
// Constants
// -------------------------------------------------------------------------
/** Property name of the verifier's public key. */
public static final String VERIFIER_KEY = "gnu.crypto.sig.public.key";
@@ -71,96 +67,93 @@ public interface ISignature extends Cloneable
/**
* Property name of an optional {@link java.security.SecureRandom},
* {@link java.util.Random}, or {@link gnu.crypto.prng.IRandom} instance to
* use. The default is to use a classloader singleton from
* {@link gnu.crypto.util.PRNG}.
* {@link java.util.Random}, or {@link gnu.java.security.prng.IRandom}
* instance to use. The default is to use a classloader singleton from
* {@link gnu.java.security.util.PRNG}.
*/
public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.sig.prng";
// Methods
// -------------------------------------------------------------------------
/**
* <p>Returns the canonical name of this signature scheme.</p>
*
* Returns the canonical name of this signature scheme.
*
* @return the canonical name of this instance.
*/
String name();
/**
* <p>Initialises this instance for signature verification.</p>
*
* Initialises this instance for signature verification.
*
* @param attributes the attributes to use for setting up this instance.
* @throws IllegalArgumentException if the designated public key is not
* appropriate for this signature scheme.
* appropriate for this signature scheme.
* @see #SOURCE_OF_RANDOMNESS
* @see #VERIFIER_KEY
*/
void setupVerify(Map attributes) throws IllegalArgumentException;
/**
* <p>Initialises this instance for signature generation.</p>
*
* Initialises this instance for signature generation.
*
* @param attributes the attributes to use for setting up this instance.
* @throws IllegalArgumentException if the designated private key is not
* appropriate for this signature scheme.
* appropriate for this signature scheme.
* @see #SOURCE_OF_RANDOMNESS
* @see #SIGNER_KEY
*/
void setupSign(Map attributes) throws IllegalArgumentException;
/**
* <p>Digests one byte of a message for signing or verification purposes.</p>
*
* Digests one byte of a message for signing or verification purposes.
*
* @param b the message byte to digest.
* @throws IllegalStateException if this instance was not setup for
* signature generation/verification.
* @throws IllegalStateException if this instance was not setup for signature
* generation/verification.
*/
void update(byte b) throws IllegalStateException;
/**
* <p>Digests a sequence of bytes from a message for signing or verification
* purposes.</p>
*
* Digests a sequence of bytes from a message for signing or verification
* purposes.
*
* @param buffer the byte sequence to consider.
* @param offset the byte poisition in <code>buffer</code> of the first byte
* to consider.
* @param length the number of bytes in <code>buffer</code> starting from the
* byte at index <code>offset</code> to digest.
* @throws IllegalStateException if this instance was not setup for
* signature generation/verification.
* to consider.
* @param length the number of bytes in <code>buffer</code> starting from
* the byte at index <code>offset</code> to digest.
* @throws IllegalStateException if this instance was not setup for signature
* generation/verification.
*/
void update(byte[] buffer, int offset, int length)
throws IllegalStateException;
/**
* <p>Terminates a signature generation phase by digesting and processing the
* context of the underlying message digest algorithm instance.</p>
*
* Terminates a signature generation phase by digesting and processing the
* context of the underlying message digest algorithm instance.
*
* @return a {@link Object} representing the native output of the signature
* scheme implementation.
* @throws IllegalStateException if this instance was not setup for
* signature generation.
* scheme implementation.
* @throws IllegalStateException if this instance was not setup for signature
* generation.
*/
Object sign() throws IllegalStateException;
/**
* <p>Terminates a signature verification phase by digesting and processing
* the context of the underlying message digest algorithm instance.</p>
*
* Terminates a signature verification phase by digesting and processing the
* context of the underlying message digest algorithm instance.
*
* @param signature a native signature object previously generated by an
* invocation of the <code>sign()</code> method.
* invocation of the <code>sign()</code> method.
* @return <code>true</code> iff the outpout of the verification phase
* confirms that the designated signature object has been generated using the
* corresponding public key of the recepient.
* @throws IllegalStateException if this instance was not setup for
* signature verification.
* confirms that the designated signature object has been generated
* using the corresponding public key of the recepient.
* @throws IllegalStateException if this instance was not setup for signature
* verification.
*/
boolean verify(Object signature) throws IllegalStateException;
/**
* <p>Returns a clone copy of this instance.</p>
*
* Returns a clone copy of this instance.
*
* @return a clone copy of this instance.
*/
Object clone();
@@ -41,23 +41,16 @@ package gnu.java.security.sig;
import gnu.java.security.Registry;
/**
* <p>The visible methods of an object that knows how to encode and decode
* The visible methods of an object that knows how to encode and decode
* cryptographic signatures. Codecs are useful for (a) externalising signature
* output data for storage and on-the-wire transmission, as well as (b) re-
* creating their internal Java representation from external sources.</p>
* creating their internal Java representation from external sources.
*/
public interface ISignatureCodec
{
// Constants
// -------------------------------------------------------------------------
/** Constant identifying the <i>Raw</i> encoding format. */
int RAW_FORMAT = Registry.RAW_ENCODING_ID;
// Method(s)
// -------------------------------------------------------------------------
int getFormatID();
byte[] encodeSignature(Object signature);
@@ -53,38 +53,28 @@ public class SignatureFactory
{
private static Set names;
// Constructor(s)
// -------------------------------------------------------------------------
/** Trivial constructor to enforce Singleton pattern. */
private SignatureFactory()
{
super();
}
// Class methods
// -------------------------------------------------------------------------
/**
* Returns an instance of a signature-with-appendix scheme given its name.
*
*
* @param ssa the case-insensitive signature-with-appendix scheme name.
* @return an instance of the scheme, or <code>null</code> if none found.
*/
public static final ISignature getInstance(String ssa)
{
if (ssa == null)
{
return null;
}
return null;
ssa = ssa.trim();
ssa = ssa.toLowerCase();
ISignature result = null;
if (ssa.equalsIgnoreCase(Registry.DSA_SIG) || ssa.equals(Registry.DSS_SIG))
{
result = new DSSSignature();
}
result = new DSSSignature();
else if (ssa.startsWith(Registry.RSA_SIG_PREFIX))
result = RSASignatureFactory.getInstance(ssa);
@@ -92,9 +82,9 @@ public class SignatureFactory
}
/**
* Returns a {@link Set} of signature-with-appendix scheme names supported
* by this <i>Factory</i>.
*
* Returns a {@link Set} of signature-with-appendix scheme names supported by
* this <i>Factory</i>.
*
* @return a {@link Set} of signature-with-appendix scheme names (Strings).
*/
public static synchronized final Set getNames()
@@ -104,10 +94,8 @@ public class SignatureFactory
HashSet hs = new HashSet();
hs.add(Registry.DSS_SIG);
hs.addAll(RSASignatureFactory.getNames());
names = Collections.unmodifiableSet(hs);
}
return names;
}
}
@@ -55,72 +55,65 @@ import java.util.Map;
import java.util.Random;
/**
* <p>The DSS (Digital Signature Standard) algorithm makes use of the following
* parameters:</p>
*
* The DSS (Digital Signature Standard) algorithm makes use of the following
* parameters:
* <ol>
* <li>p: A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup>
* </code> for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a
* multiple of <code>64</code>.</li>
* <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
* <li>p: A prime modulus, where
* <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup> </code> for <code>512 &lt;= L
* &lt;= 1024</code> and <code>L</code> a multiple of <code>64</code>.</li>
* <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
* &lt; q &lt; 2<sup>160</sup></code>.</li>
* <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
* <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
* that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
* <code>q mod p</code>).</li>
* <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
* <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
* <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
* that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
* <code>q mod p</code>).</li>
* <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
* &lt; q</code>.</li>
* <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
* <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
* <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
* <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
* &lt; q</code>.</li>
* </ol>
*
* <p>The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
* <p>
* The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
* public and can be common to a group of users. A user's private and public
* keys are <code>x</code> and <code>y</code>, respectively. They are normally
* fixed for a period of time. Parameters <code>x</code> and <code>k</code> are
* used for signature generation only, and must be kept secret. Parameter
* <code>k</code> must be regenerated for each signature.</p>
*
* <p>The signature of a message <code>M</code> is the pair of numbers <code>r</code>
* and <code>s</code> computed according to the equations below:</p>
*
* keys are <code>x</code> and <code>y</code>, respectively. They are
* normally fixed for a period of time. Parameters <code>x</code> and
* <code>k</code> are used for signature generation only, and must be kept
* secret. Parameter <code>k</code> must be regenerated for each signature.
* <p>
* The signature of a message <code>M</code> is the pair of numbers
* <code>r</code> and <code>s</code> computed according to the equations below:
* <ul>
* <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
* <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
* <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
* <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
* </ul>
*
* <p>In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
* <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 1
* </code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
* is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 180.
* For use in computing <code>s</code>, this string must be converted to an
* integer.</p>
*
* <p>As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
* </code>. If either <code>r == 0</code> or <code>s == 0</code>, a new value
* of <code>k</code> should be generated and the signature should be
* recalculated (it is extremely unlikely that <code>r == 0</code> or <code>s ==
* 0</code> if signatures are generated properly).</p>
*
* <p>The signature is transmitted along with the message to the verifier.</p>
*
* <p>References:</p>
* <p>
* In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
* <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q =
* 1</code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
* is a 160-bit string output by the Secure Hash Algorithm specified in FIPS
* 180. For use in computing <code>s</code>, this string must be converted to
* an integer.
* <p>
* As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
* </code>.
* If either <code>r == 0</code> or <code>s == 0</code>, a new value of
* <code>k</code> should be generated and the signature should be recalculated
* (it is extremely unlikely that <code>r == 0</code> or <code>s == 0</code> if
* signatures are generated properly).
* <p>
* The signature is transmitted along with the message to the verifier.
* <p>
* References:
* <ol>
* <li><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.</li>
* <li><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.</li>
* </ol>
*/
public class DSSSignature extends BaseSignature
public class DSSSignature
extends BaseSignature
{
// Constants and variables
// -------------------------------------------------------------------------
// Constructor(s)
// -------------------------------------------------------------------------
/** Trivial 0-arguments constructor. */
public DSSSignature()
{
@@ -137,16 +130,12 @@ public class DSSSignature extends BaseSignature
this.md = (IMessageDigest) that.md.clone();
}
// Class methods
// -------------------------------------------------------------------------
public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
{
final DSSSignature sig = new DSSSignature();
final Map attributes = new HashMap();
attributes.put(ISignature.SIGNER_KEY, k);
sig.setupSign(attributes);
return sig.computeRS(h);
}
@@ -157,11 +146,9 @@ public class DSSSignature extends BaseSignature
final Map attributes = new HashMap();
attributes.put(ISignature.SIGNER_KEY, k);
if (rnd != null)
{
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
}
sig.setupSign(attributes);
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
sig.setupSign(attributes);
return sig.computeRS(h);
}
@@ -172,11 +159,9 @@ public class DSSSignature extends BaseSignature
final Map attributes = new HashMap();
attributes.put(ISignature.SIGNER_KEY, k);
if (irnd != null)
{
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
}
sig.setupSign(attributes);
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
sig.setupSign(attributes);
return sig.computeRS(h);
}
@@ -187,13 +172,9 @@ public class DSSSignature extends BaseSignature
final Map attributes = new HashMap();
attributes.put(ISignature.VERIFIER_KEY, k);
sig.setupVerify(attributes);
return sig.checkRS(rs, h);
}
// Implementation of abstract methods in superclass
// -------------------------------------------------------------------------
public Object clone()
{
return new DSSSignature(this);
@@ -202,81 +183,37 @@ public class DSSSignature extends BaseSignature
protected void setupForVerification(PublicKey k)
throws IllegalArgumentException
{
if (!(k instanceof DSAPublicKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof DSAPublicKey))
throw new IllegalArgumentException();
this.publicKey = k;
}
protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
{
if (!(k instanceof DSAPrivateKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof DSAPrivateKey))
throw new IllegalArgumentException();
this.privateKey = k;
}
protected Object generateSignature() throws IllegalStateException
{
// BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
// BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
// BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
// BigInteger x = ((DSAPrivateKey) privateKey).getX();
// BigInteger m = new BigInteger(1, md.digest());
// BigInteger k, r, s;
//
// byte[] kb = new byte[20]; // we'll use 159 bits only
// while (true) {
// this.nextRandomBytes(kb);
// k = new BigInteger(1, kb);
// k.clearBit(159);
// r = g.modPow(k, p).mod(q);
// if (r.equals(BigInteger.ZERO)) {
// continue;
// }
// s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
// if (s.equals(BigInteger.ZERO)) {
// continue;
// }
// break;
// }
final BigInteger[] rs = computeRS(md.digest());
// return encodeSignature(r, s);
return encodeSignature(rs[0], rs[1]);
}
protected boolean verifySignature(Object sig) throws IllegalStateException
{
final BigInteger[] rs = decodeSignature(sig);
// BigInteger r = rs[0];
// BigInteger s = rs[1];
//
// BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
// BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
// BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
// BigInteger y = ((DSAPublicKey) publicKey).getY();
// BigInteger w = s.modInverse(q);
//
// byte bytes[] = md.digest();
// BigInteger u1 = w.multiply(new BigInteger(1, bytes)).mod(q);
// BigInteger u2 = r.multiply(w).mod(q);
//
// BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
// return v.equals(r);
return checkRS(rs, md.digest());
}
// Other instance methods
// -------------------------------------------------------------------------
/**
* Returns the output of a signature generation phase.<p>
*
* Returns the output of a signature generation phase.
*
* @return an object encapsulating the DSS signature pair <code>r</code> and
* <code>s</code>.
* <code>s</code>.
*/
private Object encodeSignature(BigInteger r, BigInteger s)
{
@@ -284,9 +221,9 @@ public class DSSSignature extends BaseSignature
}
/**
* Returns the output of a previously generated signature object as a pair
* of {@link java.math.BigInteger}.<p>
*
* Returns the output of a previously generated signature object as a pair of
* {@link java.math.BigInteger}.
*
* @return the DSS signature pair <code>r</code> and <code>s</code>.
*/
private BigInteger[] decodeSignature(Object signature)
@@ -302,7 +239,6 @@ public class DSSSignature extends BaseSignature
final BigInteger x = ((DSAPrivateKey) privateKey).getX();
final BigInteger m = new BigInteger(1, digestBytes);
BigInteger k, r, s;
final byte[] kb = new byte[20]; // we'll use 159 bits only
while (true)
{
@@ -311,17 +247,14 @@ public class DSSSignature extends BaseSignature
k.clearBit(159);
r = g.modPow(k, p).mod(q);
if (r.equals(BigInteger.ZERO))
{
continue;
}
continue;
s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
if (s.equals(BigInteger.ZERO))
{
continue;
}
continue;
break;
}
return new BigInteger[] { r, s };
}
@@ -329,16 +262,13 @@ public class DSSSignature extends BaseSignature
{
final BigInteger r = rs[0];
final BigInteger s = rs[1];
final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
final BigInteger y = ((DSAPublicKey) publicKey).getY();
final BigInteger w = s.modInverse(q);
final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
final BigInteger u2 = r.multiply(w).mod(q);
final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
return v.equals(r);
}
@@ -45,61 +45,46 @@ import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
/**
* <p>An object that implements the {@link ISignatureCodec} operations for the
* <i>Raw</i> format to use with DSS signatures.</p>
* An object that implements the {@link ISignatureCodec} operations for the
* <i>Raw</i> format to use with DSS signatures.
*/
public class DSSSignatureRawCodec implements ISignatureCodec
public class DSSSignatureRawCodec
implements ISignatureCodec
{
// Constants and variables
// -------------------------------------------------------------------------
// Constructor(s)
// -------------------------------------------------------------------------
// implicit 0-arguments constructor
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// gnu.crypto.sig.ISignatureCodec interface implementation -----------------
public int getFormatID()
{
return RAW_FORMAT;
}
/**
* <p>Returns the encoded form of the designated DSS (Digital Signature
* Standard) signature object according to the <i>Raw</i> format supported by
* this library.</p>
*
* <p>The <i>Raw</i> format for a DSA signature, in this implementation, is a
* byte sequence consisting of the following:</p>
*
* Returns the encoded form of the designated DSS (Digital Signature Standard)
* signature object according to the <i>Raw</i> format supported by this
* library.
* <p>
* The <i>Raw</i> format for a DSA signature, in this implementation, is a
* byte sequence consisting of the following:
* <ol>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the DSS parameter
* <code>r</code> in internet order,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,</li>
* <li>4-byte count of following bytes representing the DSS parameter
* <code>s</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.</li>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the DSS parameter
* <code>r</code> in internet order,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,
* </li>
* <li>4-byte count of following bytes representing the DSS parameter
* <code>s</code>,</li>
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
* the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.
* </li>
* </ol>
*
*
* @param signature the signature to encode, consisting of the two DSS
* parameters <code>r</code> and <code>s</code> as a {@link java.math.BigInteger}
* array.
* parameters <code>r</code> and <code>s</code> as a
* {@link BigInteger} array.
* @return the <i>Raw</i> format encoding of the designated signature.
* @exception IllegalArgumentException if the designated signature is not a
* DSS (Digital Signature Standard) one.
* DSS (Digital Signature Standard) one.
*/
public byte[] encodeSignature(Object signature)
{
@@ -112,38 +97,32 @@ public class DSSSignatureRawCodec implements ISignatureCodec
}
catch (Exception x)
{
throw new IllegalArgumentException("key");
throw new IllegalArgumentException("signature");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// magic
baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[0]);
baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[1]);
baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[2]);
baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[3]);
// version
baos.write(0x01);
// r
byte[] buffer = r.toByteArray();
int length = buffer.length;
baos.write(length >>> 24);
baos.write( length >>> 24);
baos.write((length >>> 16) & 0xFF);
baos.write((length >>> 8) & 0xFF);
baos.write(length & 0xFF);
baos.write(buffer, 0, length);
// s
buffer = s.toByteArray();
length = buffer.length;
baos.write(length >>> 24);
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();
}
@@ -154,36 +133,32 @@ public class DSSSignatureRawCodec implements ISignatureCodec
|| k[1] != Registry.MAGIC_RAW_DSS_SIGNATURE[1]
|| k[2] != Registry.MAGIC_RAW_DSS_SIGNATURE[2]
|| k[3] != Registry.MAGIC_RAW_DSS_SIGNATURE[3])
{
throw new IllegalArgumentException("magic");
}
throw new IllegalArgumentException("magic");
// version
if (k[4] != 0x01)
{
throw new IllegalArgumentException("version");
}
throw new IllegalArgumentException("version");
int i = 5;
int l;
byte[] buffer;
// r
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
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 r = new BigInteger(1, buffer);
// s
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
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 s = new BigInteger(1, buffer);
return new BigInteger[] { r, s };
}
}
@@ -47,25 +47,21 @@ import java.security.interfaces.RSAKey;
import java.util.Random;
/**
* <p>An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.</p>
*
* <p>EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
* byte count of an RSA public shared modulus.</p>
*
* <p>References:</p>
* An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.
* <p>
* EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
* byte count of an RSA public shared modulus.
* <p>
* References:
* <ol>
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
* </ol>
*/
public class EME_PKCS1_V1_5
{
// Constants and variables
// -------------------------------------------------------------------------
private int k;
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -73,9 +69,6 @@ public class EME_PKCS1_V1_5
/** Our default source of randomness. */
private PRNG prng = PRNG.getInstance();
// Constructor(s)
// -------------------------------------------------------------------------
private EME_PKCS1_V1_5(final int k)
{
super();
@@ -83,15 +76,11 @@ public class EME_PKCS1_V1_5
this.k = k;
}
// Class methods
// -------------------------------------------------------------------------
public static final EME_PKCS1_V1_5 getInstance(final int k)
{
if (k < 0)
{
throw new IllegalArgumentException("k must be a positive integer");
}
throw new IllegalArgumentException("k must be a positive integer");
return new EME_PKCS1_V1_5(k);
}
@@ -102,34 +91,29 @@ public class EME_PKCS1_V1_5
return EME_PKCS1_V1_5.getInstance(k);
}
// Instance methods
// -------------------------------------------------------------------------
/**
* <p>Generates an octet string <code>PS</code> of length <code>k - mLen -
* 3</code> consisting of pseudo-randomly generated nonzero octets. The
* length of <code>PS</code> will be at least eight octets.</p>
*
* <p>The method then concatenates <code>PS</code>, the message <code>M</code>,
* Generates an octet string <code>PS</code> of length <code>k - mLen -
* 3</code> consisting of pseudo-randomly generated nonzero octets. The length
* of <code>PS</code> will be at least eight octets.
* <p>
* The method then concatenates <code>PS</code>, the message <code>M</code>,
* and other padding to form an encoded message <code>EM</code> of length
* <code>k</code> octets as:</p>
*
* <code>k</code> octets as:
* <pre>
* EM = 0x00 || 0x02 || PS || 0x00 || M.
* EM = 0x00 || 0x02 || PS || 0x00 || M.
* </pre>
*
* <p>This method uses a default PRNG to obtain the padding bytes.</p>
*
* <p>
* This method uses a default PRNG to obtain the padding bytes.
*
* @param M the message to encode.
* @return the encoded message <code>EM</code>.
*/
public byte[] encode(final byte[] M)
{
// a. Generate an octet string PS of length k - mLen - 3 consisting
// of pseudo-randomly generated nonzero octets. The length of PS
// will be at least eight octets.
// of pseudo-randomly generated nonzero octets. The length of PS
// will be at least eight octets.
final byte[] PS = new byte[k - M.length - 3];
// FIXME. This should be configurable, somehow.
prng.nextBytes(PS);
int i = 0;
@@ -139,17 +123,17 @@ public class EME_PKCS1_V1_5
PS[i] = 1;
}
// b. Concatenate PS, the message M, and other padding to form an
// encoded message EM of length k octets as
// encoded message EM of length k octets as
//
// EM = 0x00 || 0x02 || PS || 0x00 || M.
// EM = 0x00 || 0x02 || PS || 0x00 || M.
return assembleEM(PS, M);
}
/**
* <p>Similar to {@link #encode(byte[])} method, except that the source of
* Similar to {@link #encode(byte[])} method, except that the source of
* randomness to use for obtaining the padding bytes (an instance of
* {@link IRandom}) is given as a parameter.</p>
*
* {@link IRandom}) is given as a parameter.
*
* @param M the message to encode.
* @param irnd the {@link IRandom} instance to use as a source of randomness.
* @return the encoded message <code>EM</code>.
@@ -183,14 +167,13 @@ public class EME_PKCS1_V1_5
{
throw new RuntimeException("encode(): " + String.valueOf(x));
}
return assembleEM(PS, M);
}
/**
* <p>Similar to the {@link #encode(byte[], IRandom)} method, except that
* the source of randmoness is an instance of {@link Random}.
*
* Similar to the {@link #encode(byte[], IRandom)} method, except that the
* source of randmoness is an instance of {@link Random}.
*
* @param M the message to encode.
* @param rnd the {@link Random} instance to use as a source of randomness.
* @return the encoded message <code>EM</code>.
@@ -213,33 +196,31 @@ public class EME_PKCS1_V1_5
}
break;
}
return assembleEM(PS, M);
}
/**
* <p>Separate the encoded message <code>EM</code> into an octet string
* Separate the encoded message <code>EM</code> into an octet string
* <code>PS</code> consisting of nonzero octets and a message <code>M</code>
* as:</p>
*
* as:
* <pre>
* EM = 0x00 || 0x02 || PS || 0x00 || M.
* EM = 0x00 || 0x02 || PS || 0x00 || M.
* </pre>
*
* <p>If the first octet of <code>EM</code> does not have hexadecimal value
* <code>0x00</code>, if the second octet of <code>EM</code> does not have
* hexadecimal value <code>0x02</code>, if there is no octet with hexadecimal
* value <code>0x00</code> to separate <code>PS</code> from <code>M</code>,
* or if the length of <code>PS</code> is less than <code>8</code> octets,
* output "decryption error" and stop.</p>
* <p>
* If the first octet of <code>EM</code> does not have hexadecimal value
* <code>0x00</code>, if the second octet of <code>EM</code> does not
* have hexadecimal value <code>0x02</code>, if there is no octet with
* hexadecimal value <code>0x00</code> to separate <code>PS</code> from
* <code>M</code>, or if the length of <code>PS</code> is less than
* <code>8</code> octets, output "decryption error" and stop.
*
* @param EM the designated encoded message.
* @return the decoded message <code>M</code> framed in the designated
* <code>EM</code> value.
* <code>EM</code> value.
* @throws IllegalArgumentException if the length of the designated entity
* <code>EM</code> is different than <code>k</code> (the length in bytes of
* the public shared modulus), or if any of the conditions described above
* is detected.
* <code>EM</code> is different than <code>k</code> (the length
* in bytes of the public shared modulus), or if any of the
* conditions described above is detected.
*/
public byte[] decode(final byte[] EM)
{
@@ -252,46 +233,34 @@ public class EME_PKCS1_V1_5
// the second octet of EM does not have hexadecimal value 0x02, if
// there is no octet with hexadecimal value 0x00 to separate PS from
// M, or if the length of PS is less than 8 octets, output
// "decryption error" and stop. (See the note below.)
// "decryption error" and stop. (See the note below.)
final int emLen = EM.length;
if (emLen != k)
{
throw new IllegalArgumentException("decryption error");
}
throw new IllegalArgumentException("decryption error");
if (EM[0] != 0x00)
{
throw new IllegalArgumentException("decryption error");
}
throw new IllegalArgumentException("decryption error");
if (EM[1] != 0x02)
{
throw new IllegalArgumentException("decryption error");
}
throw new IllegalArgumentException("decryption error");
int i = 2;
for (; i < emLen; i++)
{
if (EM[i] == 0x00)
{
break;
}
break;
}
if (i >= emLen || i < 11)
{
throw new IllegalArgumentException("decryption error");
}
throw new IllegalArgumentException("decryption error");
i++;
final byte[] result = new byte[emLen - i];
System.arraycopy(EM, i, result, 0, result.length);
return result;
}
// helper methods ----------------------------------------------------------
private byte[] assembleEM(final byte[] PS, final byte[] M)
{
// b. Concatenate PS, the message M, and other padding to form an
// encoded message EM of length k octets as
// encoded message EM of length k octets as
//
// EM = 0x00 || 0x02 || PS || 0x00 || M.
// EM = 0x00 || 0x02 || PS || 0x00 || M.
baos.reset();
baos.write(0x00);
baos.write(0x02);
@@ -300,7 +269,6 @@ public class EME_PKCS1_V1_5
baos.write(M, 0, M.length);
final byte[] result = baos.toByteArray();
baos.reset();
return result;
}
}
@@ -45,12 +45,12 @@ import gnu.java.security.hash.IMessageDigest;
import java.io.ByteArrayOutputStream;
/**
* <p>An implementation of the EMSA-PKCS1-V1.5 encoding scheme.</p>
*
* <p>EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
* hLen which denotes the length in octets of the hash function output.</p>
*
* <p>References:</p>
* An implementation of the EMSA-PKCS1-V1.5 encoding scheme.
* <p>
* EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
* hLen which denotes the length in octets of the hash function output.
* <p>
* References:
* <ol>
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
@@ -58,12 +58,9 @@ import java.io.ByteArrayOutputStream;
* Jakob Jonsson and Burt Kaliski.</li>
* </ol>
*/
public class EMSA_PKCS1_V1_5 implements Cloneable
public class EMSA_PKCS1_V1_5
implements Cloneable
{
// Constants and variables
// -------------------------------------------------------------------------
/* Notes.
1. For the six hash functions mentioned in Appendix B.1, the DER encoding
T of the DigestInfo value is equal to the following:
@@ -75,67 +72,46 @@ public class EMSA_PKCS1_V1_5 implements Cloneable
SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H
*/
private static final byte[] MD2_PREFIX = { (byte) 0x30, (byte) 0x20,
(byte) 0x30, (byte) 0x0c,
(byte) 0x06, (byte) 0x08,
(byte) 0x2a, (byte) 0x86,
(byte) 0x48, (byte) 0x86,
(byte) 0xf7, (byte) 0x0d,
(byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00,
(byte) 0x04, (byte) 0x10 };
private static final byte[] MD2_PREFIX = {
(byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
(byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
(byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x02, (byte) 0x05,
(byte) 0x00, (byte) 0x04, (byte) 0x10
};
private static final byte[] MD5_PREFIX = { (byte) 0x30, (byte) 0x20,
(byte) 0x30, (byte) 0x0c,
(byte) 0x06, (byte) 0x08,
(byte) 0x2a, (byte) 0x86,
(byte) 0x48, (byte) 0x86,
(byte) 0xf7, (byte) 0x0d,
(byte) 0x02, (byte) 0x05,
(byte) 0x05, (byte) 0x00,
(byte) 0x04, (byte) 0x10 };
private static final byte[] MD5_PREFIX = {
(byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
(byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
(byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x05, (byte) 0x05,
(byte) 0x00, (byte) 0x04, (byte) 0x10
};
private static final byte[] SHA160_PREFIX = { (byte) 0x30, (byte) 0x21,
(byte) 0x30, (byte) 0x09,
(byte) 0x06, (byte) 0x05,
(byte) 0x2b, (byte) 0x0e,
(byte) 0x03, (byte) 0x02,
(byte) 0x1a, (byte) 0x05,
(byte) 0x00, (byte) 0x04,
(byte) 0x14 };
private static final byte[] SHA160_PREFIX = {
(byte) 0x30, (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06,
(byte) 0x05, (byte) 0x2b, (byte) 0x0e, (byte) 0x03, (byte) 0x02,
(byte) 0x1a, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14
};
private static final byte[] SHA256_PREFIX = { (byte) 0x30, (byte) 0x31,
(byte) 0x30, (byte) 0x0d,
(byte) 0x06, (byte) 0x09,
(byte) 0x60, (byte) 0x86,
(byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03,
(byte) 0x04, (byte) 0x02,
(byte) 0x01, (byte) 0x05,
(byte) 0x00, (byte) 0x04,
(byte) 0x20 };
private static final byte[] SHA256_PREFIX = {
(byte) 0x30, (byte) 0x31, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
(byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x01,
(byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x20
};
private static final byte[] SHA384_PREFIX = { (byte) 0x30, (byte) 0x41,
(byte) 0x30, (byte) 0x0d,
(byte) 0x06, (byte) 0x09,
(byte) 0x60, (byte) 0x86,
(byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03,
(byte) 0x04, (byte) 0x02,
(byte) 0x02, (byte) 0x05,
(byte) 0x00, (byte) 0x04,
(byte) 0x30 };
private static final byte[] SHA384_PREFIX = {
(byte) 0x30, (byte) 0x41, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
(byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x30
};
private static final byte[] SHA512_PREFIX = { (byte) 0x30, (byte) 0x51,
(byte) 0x30, (byte) 0x0d,
(byte) 0x06, (byte) 0x09,
(byte) 0x60, (byte) 0x86,
(byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03,
(byte) 0x04, (byte) 0x02,
(byte) 0x03, (byte) 0x05,
(byte) 0x00, (byte) 0x04,
(byte) 0x40 };
private static final byte[] SHA512_PREFIX = {
(byte) 0x30, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
(byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
(byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x03,
(byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x40
};
/** The underlying hash function to use with this instance. */
private IMessageDigest hash;
@@ -146,11 +122,8 @@ public class EMSA_PKCS1_V1_5 implements Cloneable
/** The DER part of DigestInfo not containing the hash value itself. */
private byte[] prefix;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* <p>Trivial private constructor to enforce use through Factory method.</p>
* Trivial private constructor to enforce use through Factory method.
*
* @param hash the message digest instance to use with this scheme instance.
*/
@@ -162,41 +135,24 @@ public class EMSA_PKCS1_V1_5 implements Cloneable
hLen = hash.hashSize();
final String name = hash.name();
if (name.equals(Registry.MD2_HASH))
{
prefix = MD2_PREFIX;
}
prefix = MD2_PREFIX;
else if (name.equals(Registry.MD5_HASH))
{
prefix = MD5_PREFIX;
}
prefix = MD5_PREFIX;
else if (name.equals(Registry.SHA160_HASH))
{
prefix = SHA160_PREFIX;
}
prefix = SHA160_PREFIX;
else if (name.equals(Registry.SHA256_HASH))
{
prefix = SHA256_PREFIX;
}
prefix = SHA256_PREFIX;
else if (name.equals(Registry.SHA384_HASH))
{
prefix = SHA384_PREFIX;
}
prefix = SHA384_PREFIX;
else if (name.equals(Registry.SHA512_HASH))
{
prefix = SHA512_PREFIX;
}
prefix = SHA512_PREFIX;
else
{
throw new UnsupportedOperationException(); // should not happen
}
throw new UnsupportedOperationException(); // should not happen
}
// Class methods
// -------------------------------------------------------------------------
/**
* <p>Returns an instance of this object given a designated name of a hash
* function.</p>
* Returns an instance of this object given a designated name of a hash
* function.
*
* @param mdName the canonical name of a hash function.
* @return an instance of this object configured for use with the designated
@@ -208,32 +164,26 @@ public class EMSA_PKCS1_V1_5 implements Cloneable
{
final IMessageDigest hash = HashFactory.getInstance(mdName);
final String name = hash.name();
if (!(name.equals(Registry.MD2_HASH) || name.equals(Registry.MD5_HASH)
if (! (name.equals(Registry.MD2_HASH)
|| name.equals(Registry.MD5_HASH)
|| name.equals(Registry.SHA160_HASH)
|| name.equals(Registry.SHA256_HASH)
|| name.equals(Registry.SHA384_HASH) || name.equals(Registry.SHA512_HASH)))
{
throw new UnsupportedOperationException("hash with no OID: " + name);
}
|| name.equals(Registry.SHA384_HASH)
|| name.equals(Registry.SHA512_HASH)))
throw new UnsupportedOperationException("hash with no OID: " + name);
return new EMSA_PKCS1_V1_5(hash);
}
// Instance methods
// -------------------------------------------------------------------------
// Cloneable interface implementation --------------------------------------
public Object clone()
{
return getInstance(hash.name());
}
// own methods -------------------------------------------------------------
/**
* <p>Frames the hash of a message, along with an ID of the hash function in
* Frames the hash of a message, along with an ID of the hash function in
* a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as
* described in RFC-3447 (see class documentation).</p>
* described in RFC-3447 (see class documentation).
*
* @param mHash the byte sequence resulting from applying the message digest
* algorithm Hash to the message <i>M</i>.
@@ -270,17 +220,13 @@ public class EMSA_PKCS1_V1_5 implements Cloneable
// 3. If emLen < tLen + 11, output "intended encoded message length too
// short" and stop.
if (emLen < tLen + 11)
{
throw new IllegalArgumentException("emLen too short");
}
throw new IllegalArgumentException("emLen too short");
// 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
// with hexadecimal value 0xff. The length of PS will be at least 8
// octets.
final byte[] PS = new byte[emLen - tLen - 3];
for (int i = 0; i < PS.length; i++)
{
PS[i] = (byte) 0xFF;
}
PS[i] = (byte) 0xFF;
// 5. Concatenate PS, the DER encoding T, and other padding to form the
// encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T.
baos.reset();
@@ -38,57 +38,42 @@ exception statement from your version. */
package gnu.java.security.sig.rsa;
import gnu.java.security.Configuration;
import gnu.java.security.hash.HashFactory;
import gnu.java.security.hash.IMessageDigest;
import gnu.java.security.util.Util;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.logging.Logger;
/**
* <p>An implementation of the EMSA-PSS encoding/decoding scheme.</p>
*
* <p>EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts
* on octet strings and not on bit strings. In particular, the bit lengths of
* the hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4
* outputs an integer of a desired bit length rather than an octet string.</p>
*
* <p>EMSA-PSS is parameterized by the choice of hash function Hash and mask
* An implementation of the EMSA-PSS encoding/decoding scheme.
* <p>
* EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts on
* octet strings and not on bit strings. In particular, the bit lengths of the
* hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4 outputs
* an integer of a desired bit length rather than an octet string.
* <p>
* EMSA-PSS is parameterized by the choice of hash function Hash and mask
* generation function MGF. In this submission, MGF is based on a Hash
* definition that coincides with the corresponding definitions in IEEE Std
* 1363-2000, PKCS #1 v2.0, and the draft ANSI X9.44. In PKCS #1 v2.0 and the
* draft ANSI X9.44, the recommended hash function is SHA-1, while IEEE Std
* 1363-2000 recommends SHA-1 and RIPEMD-160.</p>
*
* <p>References:</p>
* 1363-2000 recommends SHA-1 and RIPEMD-160.
* <p>
* References:
* <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>
* <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>
*/
public class EMSA_PSS implements Cloneable
public class EMSA_PSS
implements Cloneable
{
// Debugging methods and variables
// -------------------------------------------------------------------------
private static final String NAME = "emsa-pss";
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
// -------------------------------------------------------------------------
private static final Logger log = Logger.getLogger(EMSA_PSS.class.getName());
/** The underlying hash function to use with this instance. */
private IMessageDigest hash;
@@ -96,12 +81,9 @@ public class EMSA_PSS implements Cloneable
/** The output size of the hash function in octets. */
private int hLen;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* <p>Trivial private constructor to enforce use through Factory method.</p>
*
* Trivial private constructor to enforce use through Factory method.
*
* @param hash the message digest instance to use with this scheme instance.
*/
private EMSA_PSS(IMessageDigest hash)
@@ -112,16 +94,13 @@ public class EMSA_PSS implements Cloneable
hLen = hash.hashSize();
}
// Class methods
// -------------------------------------------------------------------------
/**
* <p>Returns an instance of this object given a designated name of a hash
* function.</p>
*
* Returns an instance of this object given a designated name of a hash
* function.
*
* @param mdName the canonical name of a hash function.
* @return an instance of this object configured for use with the designated
* options.
* options.
*/
public static EMSA_PSS getInstance(String mdName)
{
@@ -129,51 +108,38 @@ public class EMSA_PSS implements Cloneable
return new EMSA_PSS(hash);
}
// Instance methods
// -------------------------------------------------------------------------
// Cloneable interface implementation --------------------------------------
public Object clone()
{
return getInstance(hash.name());
}
// own methods -------------------------------------------------------------
/**
* <p>The encoding operation EMSA-PSS-Encode computes the hash of a message
* The encoding operation EMSA-PSS-Encode computes the hash of a message
* <code>M</code> using a hash function and maps the result to an encoded
* message <code>EM</code> of a specified length using a mask generation
* function.</p>
*
* function.
*
* @param mHash the byte sequence resulting from applying the message digest
* algorithm Hash to the message <i>M</i>.
* algorithm Hash to the message <i>M</i>.
* @param emBits the maximal bit length of the integer OS2IP(EM), at least
* <code>8.hLen + 8.sLen + 9</code>.
* <code>8.hLen + 8.sLen + 9</code>.
* @param salt the salt to use when encoding the output.
* @return the encoded message <code>EM</code>, an octet string of length
* <code>emLen = CEILING(emBits / 8)</code>.
* <code>emLen = CEILING(emBits / 8)</code>.
* @exception IllegalArgumentException if an exception occurs.
*
*/
public byte[] encode(byte[] mHash, int emBits, byte[] salt)
{
int sLen = salt.length;
// 1. If the length of M is greater than the input limitation for the hash
// function (2**61 - 1 octets for SHA-1) then output "message too long"
// and stop.
// 2. Let mHash = Hash(M), an octet string of length hLen.
if (hLen != mHash.length)
{
throw new IllegalArgumentException("wrong hash");
}
throw new IllegalArgumentException("wrong hash");
// 3. If emBits < 8.hLen + 8.sLen + 9, output 'encoding error' and stop.
if (emBits < (8 * hLen + 8 * sLen + 9))
{
throw new IllegalArgumentException("encoding error");
}
throw new IllegalArgumentException("encoding error");
int emLen = (emBits + 7) / 8;
// 4. Generate a random octet string salt of length sLen; if sLen = 0,
// then salt is the empty string.
@@ -187,9 +153,8 @@ public class EMSA_PSS implements Cloneable
synchronized (hash)
{
for (i = 0; i < 8; i++)
{
hash.update((byte) 0x00);
}
hash.update((byte) 0x00);
hash.update(mHash, 0, hLen);
hash.update(salt, 0, sLen);
H = hash.digest();
@@ -202,16 +167,14 @@ public class EMSA_PSS implements Cloneable
System.arraycopy(salt, 0, DB, emLen - sLen - hLen - 1, sLen);
// 9. Let dbMask = MGF(H, emLen - hLen - 1).
byte[] dbMask = MGF(H, emLen - hLen - 1);
if (DEBUG && debuglevel > 8)
if (Configuration.DEBUG)
{
debug("dbMask (encode): " + Util.toString(dbMask));
debug("DB (encode): " + Util.toString(DB));
log.fine("dbMask (encode): " + Util.toString(dbMask));
log.fine("DB (encode): " + Util.toString(DB));
}
// 10. Let maskedDB = DB XOR dbMask.
for (i = 0; i < DB.length; i++)
{
DB[i] = (byte) (DB[i] ^ dbMask[i]);
}
DB[i] = (byte)(DB[i] ^ dbMask[i]);
// 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
// maskedDB to zero.
DB[0] &= (0xFF >>> (8 * emLen - emBits));
@@ -226,14 +189,14 @@ public class EMSA_PSS implements Cloneable
}
/**
* <p>The decoding operation EMSA-PSS-Decode recovers the message hash from
* an encoded message <code>EM</code> and compares it to the hash of
* <code>M</code>.</p>
*
* The decoding operation EMSA-PSS-Decode recovers the message hash from an
* encoded message <code>EM</code> and compares it to the hash of
* <code>M</code>.
*
* @param mHash the byte sequence resulting from applying the message digest
* algorithm Hash to the message <i>M</i>.
* algorithm Hash to the message <i>M</i>.
* @param EM the <i>encoded message</i>, an octet string of length
* <code>emLen = CEILING(emBits/8).
* <code>emLen = CEILING(emBits/8).
* @param emBits the maximal bit length of the integer OS2IP(EM), at least
* <code>8.hLen + 8.sLen + 9</code>.
* @param sLen the length, in octets, of the expected salt.
@@ -244,60 +207,50 @@ public class EMSA_PSS implements Cloneable
*/
public boolean decode(byte[] mHash, byte[] EM, int emBits, int sLen)
{
if (DEBUG && debuglevel > 8)
if (Configuration.DEBUG)
{
debug("mHash: " + Util.toString(mHash));
debug("EM: " + Util.toString(EM));
debug("emBits: " + String.valueOf(emBits));
debug("sLen: " + String.valueOf(sLen));
log.fine("mHash: " + Util.toString(mHash));
log.fine("EM: " + Util.toString(EM));
log.fine("emBits: " + String.valueOf(emBits));
log.fine("sLen: " + String.valueOf(sLen));
}
if (sLen < 0)
{
throw new IllegalArgumentException("sLen");
}
throw new IllegalArgumentException("sLen");
// 1. If the length of M is greater than the input limitation for the hash
// function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
// stop.
// function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
// stop.
// 2. Let mHash = Hash(M), an octet string of length hLen.
if (hLen != mHash.length)
{
if (DEBUG && debuglevel > 8)
{
debug("hLen != mHash.length; hLen: " + String.valueOf(hLen));
}
if (Configuration.DEBUG)
log.fine("hLen != mHash.length; hLen: " + String.valueOf(hLen));
throw new IllegalArgumentException("wrong hash");
}
// 3. If emBits < 8.hLen + 8.sLen + 9, output 'decoding error' and stop.
if (emBits < (8 * hLen + 8 * sLen + 9))
{
if (DEBUG && debuglevel > 8)
{
debug("emBits < (8hLen + 8sLen + 9); sLen: " + String.valueOf(sLen));
}
if (Configuration.DEBUG)
log.fine("emBits < (8hLen + 8sLen + 9); sLen: "
+ String.valueOf(sLen));
throw new IllegalArgumentException("decoding error");
}
int emLen = (emBits + 7) / 8;
// 4. If the rightmost octet of EM does not have hexadecimal value bc,
// output 'inconsistent' and stop.
// output 'inconsistent' and stop.
if ((EM[EM.length - 1] & 0xFF) != 0xBC)
{
if (DEBUG && debuglevel > 8)
{
debug("EM does not end with 0xBC");
}
if (Configuration.DEBUG)
log.fine("EM does not end with 0xBC");
return false;
}
// 5. Let maskedDB be the leftmost emLen ? hLen ? 1 octets of EM, and let
// H be the next hLen octets.
// H be the next hLen octets.
// 6. If the leftmost 8.emLen ? emBits bits of the leftmost octet in
// maskedDB are not all equal to zero, output 'inconsistent' and stop.
// maskedDB are not all equal to zero, output 'inconsistent' and stop.
if ((EM[0] & (0xFF << (8 - (8 * emLen - emBits)))) != 0)
{
if (DEBUG && debuglevel > 8)
{
debug("Leftmost 8emLen - emBits bits of EM are not 0s");
}
if (Configuration.DEBUG)
log.fine("Leftmost 8emLen - emBits bits of EM are not 0s");
return false;
}
byte[] DB = new byte[emLen - hLen - 1];
@@ -309,56 +262,48 @@ public class EMSA_PSS implements Cloneable
// 8. Let DB = maskedDB XOR dbMask.
int i;
for (i = 0; i < DB.length; i++)
{
DB[i] = (byte) (DB[i] ^ dbMask[i]);
}
DB[i] = (byte)(DB[i] ^ dbMask[i]);
// 9. Set the leftmost 8.emLen ? emBits bits of DB to zero.
DB[0] &= (0xFF >>> (8 * emLen - emBits));
if (DEBUG && debuglevel > 8)
if (Configuration.DEBUG)
{
debug("dbMask (decode): " + Util.toString(dbMask));
debug("DB (decode): " + Util.toString(DB));
log.fine("dbMask (decode): " + Util.toString(dbMask));
log.fine("DB (decode): " + Util.toString(DB));
}
// 10. If the emLen -hLen -sLen -2 leftmost octets of DB are not zero or
// if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
// output 'inconsistent' and stop.
// if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
// output 'inconsistent' and stop.
// IMPORTANT (rsn): this is an error in the specs, the index of the 0x01
// byte should be emLen -hLen -sLen -2 and not -1! authors have been
// advised
// byte should be emLen -hLen -sLen -2 and not -1! authors have been advised
for (i = 0; i < (emLen - hLen - sLen - 2); i++)
{
if (DB[i] != 0)
{
if (DEBUG && debuglevel > 8)
{
debug("DB[" + String.valueOf(i) + "] != 0x00");
}
if (Configuration.DEBUG)
log.fine("DB[" + String.valueOf(i) + "] != 0x00");
return false;
}
}
if (DB[i] != 0x01)
{ // i == emLen -hLen -sLen -2
if (DEBUG && debuglevel > 8)
{
debug("DB's byte at position (emLen -hLen -sLen -2); i.e. "
+ String.valueOf(i) + " is not 0x01");
}
if (Configuration.DEBUG)
log.fine("DB's byte at position (emLen -hLen -sLen -2); i.e. "
+ String.valueOf(i) + " is not 0x01");
return false;
}
// 11. Let salt be the last sLen octets of DB.
byte[] salt = new byte[sLen];
System.arraycopy(DB, DB.length - sLen, salt, 0, sLen);
// 12. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
// M0 is an octet string of length 8 + hLen + sLen with eight initial
// zero octets.
// M0 is an octet string of length 8 + hLen + sLen with eight initial
// zero octets.
// 13. Let H0 = Hash(M0), an octet string of length hLen.
byte[] H0;
synchronized (hash)
{
for (i = 0; i < 8; i++)
{
hash.update((byte) 0x00);
}
hash.update((byte) 0x00);
hash.update(mHash, 0, hLen);
hash.update(salt, 0, sLen);
H0 = hash.digest();
@@ -367,34 +312,30 @@ public class EMSA_PSS implements Cloneable
return Arrays.equals(H, H0);
}
// helper methods ----------------------------------------------------------
/**
* <p>A mask generation function takes an octet string of variable length
* and a desired output length as input, and outputs an octet string of the
* desired length. There may be restrictions on the length of the input and
* output octet strings, but such bounds are generally very large. Mask
* generation functions are deterministic; the octet string output is
* completely determined by the input octet string. The output of a mask
* generation function should be pseudorandom, that is, it should be
* infeasible to predict, given one part of the output but not the input,
* another part of the output. The provable security of RSA-PSS relies on
* the random nature of the output of the mask generation function, which in
* turn relies on the random nature of the underlying hash function.</p>
*
* A mask generation function takes an octet string of variable length and a
* desired output length as input, and outputs an octet string of the desired
* length. There may be restrictions on the length of the input and output
* octet strings, but such bounds are generally very large. Mask generation
* functions are deterministic; the octet string output is completely
* determined by the input octet string. The output of a mask generation
* function should be pseudorandom, that is, it should be infeasible to
* predict, given one part of the output but not the input, another part of
* the output. The provable security of RSA-PSS relies on the random nature of
* the output of the mask generation function, which in turn relies on the
* random nature of the underlying hash function.
*
* @param Z a seed.
* @param l the desired output length in octets.
* @return the mask.
* @exception IllegalArgumentException if the desired output length is too
* long.
* long.
*/
private byte[] MGF(byte[] Z, int l)
{
// 1. If l > (2**32).hLen, output 'mask too long' and stop.
if (l < 1 || (l & 0xFFFFFFFFL) > ((hLen & 0xFFFFFFFFL) << 32L))
{
throw new IllegalArgumentException("mask too long");
}
throw new IllegalArgumentException("mask too long");
// 2. Let T be the empty octet string.
byte[] result = new byte[l];
// 3. For i = 0 to CEILING(l/hLen) ? 1, do
@@ -409,14 +350,14 @@ public class EMSA_PSS implements Cloneable
int length;
for (int i = 0; i < limit; i++)
{
// 3.1 Convert i to an octet string C of length 4 with the primitive
// I2OSP: C = I2OSP(i, 4).
// 3.2 Concatenate the hash of the seed Z and C to the octet string T:
// T = T || Hash(Z || C)
// 3.1 Convert i to an octet string C of length 4 with the primitive
// I2OSP: C = I2OSP(i, 4).
// 3.2 Concatenate the hash of the seed Z and C to the octet string T:
// T = T || Hash(Z || C)
hashZC = (IMessageDigest) hashZ.clone();
hashZC.update((byte) (i >>> 24));
hashZC.update((byte) (i >>> 16));
hashZC.update((byte) (i >>> 8));
hashZC.update((byte)(i >>> 24));
hashZC.update((byte)(i >>> 16));
hashZC.update((byte)(i >>> 8));
hashZC.update((byte) i);
t = hashZC.digest();
length = l - sofar;
@@ -49,31 +49,26 @@ import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
/**
* <p>Utility methods related to the RSA algorithm.</p>
*
* <p>References:</p>
* Utility methods related to the RSA algorithm.
* <p>
* References:
* <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>
*
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
*
* <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
* Remote timing attacks are practical</a><br>
* D. Boneh and D. Brumley.</li>
* <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>
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
* <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
* Remote timing attacks are practical</a><br>
* D. Boneh and D. Brumley.</li>
* </ol>
*/
public class RSA
{
// Constants and variables
// -------------------------------------------------------------------------
private static final BigInteger ZERO = BigInteger.ZERO;
private static final BigInteger ONE = BigInteger.ONE;
@@ -81,37 +76,28 @@ public class RSA
/** Our default source of randomness. */
private static final PRNG prng = PRNG.getInstance();
// Constructor(s)
// -------------------------------------------------------------------------
/** Trivial private constructor to enforce Singleton pattern. */
private RSA()
{
super();
}
// Class methods
// -------------------------------------------------------------------------
// Signature and verification methods --------------------------------------
/**
* <p>An implementation of the <b>RSASP</b> method: Assuming that the
* designated RSA private key is a valid one, this method computes a
* <i>signature representative</i> for a designated <i>message
* representative</i> signed by the holder of the designated RSA private
* key.<p>
*
* An implementation of the <b>RSASP</b> method: Assuming that the designated
* RSA private key is a valid one, this method computes a <i>signature
* representative</i> for a designated <i>message representative</i> signed
* by the holder of the designated RSA private key.
*
* @param K the RSA private key.
* @param m the <i>message representative</i>: an integer between
* <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
* <i>modulus</i>.
* <code>0</code> and <code>n - 1</code>, where <code>n</code>
* is the RSA <i>modulus</i>.
* @return the <i>signature representative</i>, an integer between
* <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
* <i>modulus</i>.
* <code>0</code> and <code>n - 1</code>, where <code>n</code>
* is the RSA <i>modulus</i>.
* @throws ClassCastException if <code>K</code> is not an RSA one.
* @throws IllegalArgumentException if <code>m</code> (the <i>message
* representative</i>) is out of range.
* representative</i>) is out of range.
*/
public static final BigInteger sign(final PrivateKey K, final BigInteger m)
{
@@ -121,27 +107,27 @@ public class RSA
}
catch (IllegalArgumentException x)
{
throw new IllegalArgumentException(
"message representative out of range");
throw new IllegalArgumentException("message representative out of range");
}
}
/**
* <p>An implementation of the <b>RSAVP</b> method: Assuming that the
* designated RSA public key is a valid one, this method computes a
* <i>message representative</i> for the designated <i>signature
* representative</i> generated by an RSA private key, for a message
* intended for the holder of the designated RSA public key.</p>
*
* An implementation of the <b>RSAVP</b> method: Assuming that the designated
* RSA public key is a valid one, this method computes a <i>message
* representative</i> for the designated <i>signature representative</i>
* generated by an RSA private key, for a message intended for the holder of
* the designated RSA public key.
*
* @param K the RSA public key.
* @param s the <i>signature representative</i>, an integer between
* <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
* <i>modulus</i>.
* <code>0</code> and <code>n - 1</code>, where <code>n</code>
* is the RSA <i>modulus</i>.
* @return a <i>message representative</i>: an integer between <code>0</code>
* and <code>n - 1</code>, where <code>n</code> is the RSA <i>modulus</i>.
* and <code>n - 1</code>, where <code>n</code> is the RSA
* <i>modulus</i>.
* @throws ClassCastException if <code>K</code> is not an RSA one.
* @throws IllegalArgumentException if <code>s</code> (the <i>signature
* representative</i>) is out of range.
* representative</i>) is out of range.
*/
public static final BigInteger verify(final PublicKey K, final BigInteger s)
{
@@ -151,25 +137,24 @@ public class RSA
}
catch (IllegalArgumentException x)
{
throw new IllegalArgumentException(
"signature representative out of range");
throw new IllegalArgumentException("signature representative out of range");
}
}
// Encryption and decryption methods ---------------------------------------
/**
* <p>An implementation of the <code>RSAEP</code> algorithm.</p>
*
* An implementation of the <code>RSAEP</code> algorithm.
*
* @param K the recipient's RSA public key.
* @param m the message representative as an MPI.
* @return the resulting MPI --an MPI between <code>0</code> and
* <code>n - 1</code> (<code>n</code> being the public shared modulus)-- that
* will eventually be padded with an appropriate framing/padding scheme.
* <code>n - 1</code> (<code>n</code> being the public shared
* modulus)-- that will eventually be padded with an appropriate
* framing/padding scheme.
* @throws ClassCastException if <code>K</code> is not an RSA one.
* @throws IllegalArgumentException if <code>m</code>, the message
* representative is not between <code>0</code> and <code>n - 1</code>
* (<code>n</code> being the public shared modulus).
* representative is not between <code>0</code> and
* <code>n - 1</code> (<code>n</code> being the public shared
* modulus).
*/
public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
{
@@ -179,22 +164,23 @@ public class RSA
}
catch (IllegalArgumentException x)
{
throw new IllegalArgumentException(
"message representative out of range");
throw new IllegalArgumentException("message representative out of range");
}
}
/**
* <p>An implementation of the <code>RSADP</code> algorithm.</p>
*
* An implementation of the <code>RSADP</code> algorithm.
*
* @param K the recipient's RSA private key.
* @param c the ciphertext representative as an MPI.
* @return the message representative, an MPI between <code>0</code> and
* <code>n - 1</code> (<code>n</code> being the shared public modulus).
* <code>n - 1</code> (<code>n</code> being the shared public
* modulus).
* @throws ClassCastException if <code>K</code> is not an RSA one.
* @throws IllegalArgumentException if <code>c</code>, the ciphertext
* representative is not between <code>0</code> and <code>n - 1</code>
* (<code>n</code> being the shared public modulus).
* representative is not between <code>0</code> and
* <code>n - 1</code> (<code>n</code> being the shared public
* modulus).
*/
public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
{
@@ -204,22 +190,19 @@ public class RSA
}
catch (IllegalArgumentException x)
{
throw new IllegalArgumentException(
"ciphertext representative out of range");
throw new IllegalArgumentException("ciphertext representative out of range");
}
}
// Conversion methods ------------------------------------------------------
/**
* <p>Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
* octet sequence of length <code>k</code>.</p>
*
* Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
* octet sequence of length <code>k</code>.
*
* @param s the multi-precision integer to convert.
* @param k the length of the output.
* @return the result of the transform.
* @exception IllegalArgumentException if the length in octets of meaningful
* bytes of <code>s</code> is greater than <code>k</code>.
* bytes of <code>s</code> is greater than <code>k</code>.
*/
public static final byte[] I2OSP(final BigInteger s, final int k)
{
@@ -236,9 +219,7 @@ public class RSA
for (int i = 0; i < limit; i++)
{
if (result[i] != 0x00)
{
throw new IllegalArgumentException("integer too large");
}
throw new IllegalArgumentException("integer too large");
}
final byte[] newResult = new byte[k];
System.arraycopy(result, limit, newResult, 0, k);
@@ -247,17 +228,13 @@ public class RSA
return result;
}
// helper methods ----------------------------------------------------------
private static final BigInteger RSAEP(final RSAPublicKey K, final BigInteger m)
{
// 1. If the representative m is not between 0 and n - 1, output
// "representative out of range" and stop.
// "representative out of range" and stop.
final BigInteger n = K.getModulus();
if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
{
throw new IllegalArgumentException();
}
throw new IllegalArgumentException();
// 2. Let c = m^e mod n.
final BigInteger e = K.getPublicExponent();
final BigInteger result = m.modPow(e, n);
@@ -268,16 +245,13 @@ public class RSA
private static final BigInteger RSADP(final RSAPrivateKey K, BigInteger c)
{
// 1. If the representative c is not between 0 and n - 1, output
// "representative out of range" and stop.
// "representative out of range" and stop.
final BigInteger n = K.getModulus();
if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
{
throw new IllegalArgumentException();
}
throw new IllegalArgumentException();
// 2. The representative m is computed as follows.
BigInteger result;
if (!(K instanceof RSAPrivateCrtKey))
if (! (K instanceof RSAPrivateCrtKey))
{
// a. If the first form (n, d) of K is used, let m = c^d mod n.
final BigInteger d = K.getPrivateExponent();
@@ -303,38 +277,32 @@ public class RSA
final BigInteger x = r.modPow(e, n).multiply(c).mod(n);
c = x;
}
// b. If the second form (p, q, dP, dQ, qInv) and (r_i, d_i, t_i)
// of K is used, proceed as follows:
// of K is used, proceed as follows:
final BigInteger p = ((RSAPrivateCrtKey) K).getPrimeP();
final BigInteger q = ((RSAPrivateCrtKey) K).getPrimeQ();
final BigInteger dP = ((RSAPrivateCrtKey) K).getPrimeExponentP();
final BigInteger dQ = ((RSAPrivateCrtKey) K).getPrimeExponentQ();
final BigInteger qInv = ((RSAPrivateCrtKey) K).getCrtCoefficient();
// i. Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
// i. Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
final BigInteger m_1 = c.modPow(dP, p);
final BigInteger m_2 = c.modPow(dQ, q);
// ii. If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
// iii. Let h = (m_1 - m_2) * qInv mod p.
// ii. If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
// iii. Let h = (m_1 - m_2) * qInv mod p.
final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
// iv. Let m = m_2 + q * h.
// iv. Let m = m_2 + q * h.
result = m_2.add(q.multiply(h));
if (rsaBlinding)
{ // post-decryption
result = result.multiply(r.modInverse(n)).mod(n);
}
if (rsaBlinding) // post-decryption
result = result.multiply(r.modInverse(n)).mod(n);
}
// 3. Output m
return result;
}
/**
* <p>Returns a random MPI with a random bit-length of the form <code>8b</code>,
* where <code>b</code> is in the range <code>[32..64]</code>.</p>
*
* Returns a random MPI with a random bit-length of the form <code>8b</code>,
* where <code>b</code> is in the range <code>[32..64]</code>.
*
* @return a random MPI whose length in bytes is between 32 and 64 inclusive.
*/
private static final BigInteger newR(final BigInteger N)
@@ -51,35 +51,29 @@ import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
/**
* <p>The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
* The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
* appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding
* method.</p>
*
* <p>References:</p>
* method.
* <p>
* References:
* <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>
*
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
* <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>
* <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
* Standards (PKCS) #1:</a><br>
* RSA Cryptography Specifications Version 2.1.<br>
* Jakob Jonsson and Burt Kaliski.</li>
* </ol>
*/
public class RSAPKCS1V1_5Signature extends BaseSignature
public class RSAPKCS1V1_5Signature
extends BaseSignature
{
// Constants and variables
// -------------------------------------------------------------------------
/** The underlying EMSA-PKCS1-v1.5 instance for this object. */
private EMSA_PKCS1_V1_5 pkcs1;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* Default 0-arguments constructor. Uses SHA-1 as the default hash.
*/
@@ -89,9 +83,9 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
}
/**
* <p>Constructs an instance of this object using the designated message
* digest algorithm as its underlying hash function.</p>
*
* Constructs an instance of this object using the designated message digest
* algorithm as its underlying hash function.
*
* @param mdName the canonical name of the underlying hash function.
*/
public RSAPKCS1V1_5Signature(final String mdName)
@@ -117,14 +111,6 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone();
}
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// Implementation of abstract methods in superclass ------------------------
public Object clone()
{
return new RSAPKCS1V1_5Signature(this);
@@ -133,49 +119,46 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
protected void setupForVerification(final PublicKey k)
throws IllegalArgumentException
{
if (!(k instanceof RSAPublicKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof RSAPublicKey))
throw new IllegalArgumentException();
publicKey = k;
}
protected void setupForSigning(final PrivateKey k)
throws IllegalArgumentException
{
if (!(k instanceof RSAPrivateKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof RSAPrivateKey))
throw new IllegalArgumentException();
privateKey = k;
}
protected Object generateSignature() throws IllegalStateException
{
// 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
// operation (Section 9.2) to the message M to produce an encoded
// message EM of length k octets:
// operation (Section 9.2) to the message M to produce an encoded
// message EM of length k octets:
//
// EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
// EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
//
// If the encoding operation outputs "message too long," output
// "message too long" and stop. If the encoding operation outputs
// "intended encoded message length too short," output "RSA modulus
// too short" and stop.
// If the encoding operation outputs "message too long," output
// "message too long" and stop. If the encoding operation outputs
// "intended encoded message length too short," output "RSA modulus
// too short" and stop.
final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
final int k = (modBits + 7) / 8;
final byte[] EM = pkcs1.encode(md.digest(), k);
// 2. RSA signature:
// a. Convert the encoded message EM to an integer message epresentative
// m (see Section 4.2): m = OS2IP (EM).
// a. Convert the encoded message EM to an integer message epresentative
// m (see Section 4.2): m = OS2IP (EM).
final BigInteger m = new BigInteger(1, EM);
// b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
// private key K and the message representative m to produce an
// integer signature representative s: s = RSASP1 (K, m).
// b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
// private key K and the message representative m to produce an
// integer signature representative s: s = RSASP1 (K, m).
final BigInteger s = RSA.sign(privateKey, m);
// c. Convert the signature representative s to a signature S of length
// k octets (see Section 4.1): S = I2OSP (s, k).
// c. Convert the signature representative s to a signature S of length
// k octets (see Section 4.1): S = I2OSP (s, k).
// 3. Output the signature S.
return RSA.I2OSP(s, k);
}
@@ -184,28 +167,24 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
throws IllegalStateException
{
if (publicKey == null)
{
throw new IllegalStateException();
}
throw new IllegalStateException();
final byte[] S = (byte[]) sig;
// 1. Length checking: If the length of the signature S is not k octets,
// output "invalid signature" and stop.
// output "invalid signature" and stop.
final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
final int k = (modBits + 7) / 8;
if (S.length != k)
{
return false;
}
return false;
// 2. RSA verification:
// a. Convert the signature S to an integer signature representative
// s (see Section 4.2): s = OS2IP (S).
// a. Convert the signature S to an integer signature representative
// s (see Section 4.2): s = OS2IP (S).
final BigInteger s = new BigInteger(1, S);
// b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
// RSA public key (n, e) and the signature representative s to
// produce an integer message representative m:
// m = RSAVP1 ((n, e), s).
// If RSAVP1 outputs "signature representative out of range,"
// output "invalid signature" and stop.
// b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
// RSA public key (n, e) and the signature representative s to
// produce an integer message representative m:
// m = RSAVP1 ((n, e), s).
// If RSAVP1 outputs "signature representative out of range,"
// output "invalid signature" and stop.
final BigInteger m;
try
{
@@ -215,10 +194,10 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
{
return false;
}
// c. Convert the message representative m to an encoded message EM
// of length k octets (see Section 4.1): EM = I2OSP (m, k).
// If I2OSP outputs "integer too large," output "invalid signature"
// and stop.
// c. Convert the message representative m to an encoded message EM
// of length k octets (see Section 4.1): EM = I2OSP (m, k).
// If I2OSP outputs "integer too large," output "invalid signature"
// and stop.
final byte[] EM;
try
{
@@ -229,17 +208,17 @@ public class RSAPKCS1V1_5Signature extends BaseSignature
return false;
}
// 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
// operation (Section 9.2) to the message M to produce a second
// encoded message EM' of length k octets:
// EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
// If the encoding operation outputs "message too long," output
// "message too long" and stop. If the encoding operation outputs
// "intended encoded message length too short," output "RSA modulus
// too short" and stop.
// operation (Section 9.2) to the message M to produce a second
// encoded message EM' of length k octets:
// EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
// If the encoding operation outputs "message too long," output
// "message too long" and stop. If the encoding operation outputs
// "intended encoded message length too short," output "RSA modulus
// too short" and stop.
final byte[] EMp = pkcs1.encode(md.digest(), k);
// 4. Compare the encoded message EM and the second encoded message EM'.
// If they are the same, output "valid signature"; otherwise, output
// "invalid signature."
// If they are the same, output "valid signature"; otherwise, output
// "invalid signature."
return Arrays.equals(EM, EMp);
}
}
@@ -38,60 +38,44 @@ exception statement from your version. */
package gnu.java.security.sig.rsa;
import gnu.java.security.Configuration;
import gnu.java.security.Registry;
import gnu.java.security.hash.HashFactory;
import gnu.java.security.hash.IMessageDigest;
import gnu.java.security.sig.BaseSignature;
import gnu.java.security.util.Util;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.logging.Logger;
/**
* <p>The RSA-PSS signature scheme is a public-key encryption scheme combining
* the RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding
* method.</p>
*
* <p>The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
* The RSA-PSS signature scheme is a public-key encryption scheme combining the
* RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding method.
* <p>
* The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
* while the inventors of the PSS encoding method are Mihir Bellare and Phillip
* Rogaway. During efforts to adopt RSA-PSS into the P1363a standards effort,
* certain adaptations to the original version of RSA-PSS were made by Mihir
* Bellare and Phillip Rogaway and also by Burt Kaliski (the editor of IEEE
* P1363a) to facilitate implementation and integration into existing protocols.</p>
*
* <p>References:</pr>
* P1363a) to facilitate implementation and integration into existing protocols.
* <p>
* References:
* <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>
* <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>
*/
public class RSAPSSSignature extends BaseSignature
public class RSAPSSSignature
extends BaseSignature
{
// Debugging methods and variables
// -------------------------------------------------------------------------
private static final String NAME = "rsa-pss";
private static final boolean DEBUG = false;
private static final int debuglevel = 1;
private static final PrintWriter err = new PrintWriter(System.out, true);
private static void debug(String s)
{
err.println(">>> " + NAME + ": " + s);
}
// Constants and variables
// -------------------------------------------------------------------------
private static final Logger log = Logger.getLogger(RSAPSSSignature.class.getName());
/** The underlying EMSA-PSS instance for this object. */
private EMSA_PSS pss;
@@ -99,9 +83,6 @@ public class RSAPSSSignature extends BaseSignature
/** The desired length in octets of the EMSA-PSS salt. */
private int sLen;
// Constructor(s)
// -------------------------------------------------------------------------
/**
* Default 0-arguments constructor. Uses SHA-1 as the default hash and a
* 0-octet <i>salt</i>.
@@ -112,10 +93,9 @@ public class RSAPSSSignature extends BaseSignature
}
/**
* <p>Constructs an instance of this object using the designated message
* digest algorithm as its underlying hash function, and having 0-octet
* <i>salt</i>.</p>
*
* Constructs an instance of this object using the designated message digest
* algorithm as its underlying hash function, and having 0-octet <i>salt</i>.
*
* @param mdName the canonical name of the underlying hash function.
*/
public RSAPSSSignature(String mdName)
@@ -124,12 +104,12 @@ public class RSAPSSSignature extends BaseSignature
}
/**
* <p>Constructs an instance of this object using the designated message
* digest algorithm as its underlying hash function.</p>
*
* Constructs an instance of this object using the designated message digest
* algorithm as its underlying hash function.
*
* @param mdName the canonical name of the underlying hash function.
* @param sLen the desired length in octets of the salt to use for encoding /
* decoding signatures.
* decoding signatures.
*/
public RSAPSSSignature(String mdName, int sLen)
{
@@ -155,14 +135,6 @@ public class RSAPSSSignature extends BaseSignature
this.pss = (EMSA_PSS) that.pss.clone();
}
// Class methods
// -------------------------------------------------------------------------
// Instance methods
// -------------------------------------------------------------------------
// Implementation of abstract methods in superclass ------------------------
public Object clone()
{
return new RSAPSSSignature(this);
@@ -171,79 +143,71 @@ public class RSAPSSSignature extends BaseSignature
protected void setupForVerification(PublicKey k)
throws IllegalArgumentException
{
if (!(k instanceof RSAPublicKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof RSAPublicKey))
throw new IllegalArgumentException();
publicKey = (RSAPublicKey) k;
}
protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
{
if (!(k instanceof RSAPrivateKey))
{
throw new IllegalArgumentException();
}
if (! (k instanceof RSAPrivateKey))
throw new IllegalArgumentException();
privateKey = (RSAPrivateKey) k;
}
protected Object generateSignature() throws IllegalStateException
{
// 1. Apply the EMSA-PSS encoding operation to the message M to produce an
// encoded message EM of length CEILING((modBits ? 1)/8) octets such
// that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
// EM = EMSA-PSS-Encode(M,modBits ? 1).
// Note that the octet length of EM will be one less than k if
// modBits ? 1 is divisible by 8. If the encoding operation outputs
// 'message too long' or 'encoding error,' then output 'message too
// long' or 'encoding error' and stop.
// encoded message EM of length CEILING((modBits ? 1)/8) octets such
// that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
// EM = EMSA-PSS-Encode(M,modBits ? 1).
// Note that the octet length of EM will be one less than k if
// modBits ? 1 is divisible by 8. If the encoding operation outputs
// 'message too long' or 'encoding error,' then output 'message too
// long' or 'encoding error' and stop.
int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
byte[] salt = new byte[sLen];
this.nextRandomBytes(salt);
byte[] EM = pss.encode(md.digest(), modBits - 1, salt);
if (DEBUG && debuglevel > 8)
{
debug("EM (sign): " + Util.toString(EM));
}
if (Configuration.DEBUG)
log.fine("EM (sign): " + Util.toString(EM));
// 2. Convert the encoded message EM to an integer message representative
// m (see Section 1.2.2): m = OS2IP(EM).
// m (see Section 1.2.2): m = OS2IP(EM).
BigInteger m = new BigInteger(1, EM);
// 3. Apply the RSASP signature primitive to the public key K and the
// message representative m to produce an integer signature
// representative s: s = RSASP(K,m).
// message representative m to produce an integer signature
// representative s: s = RSASP(K,m).
BigInteger s = RSA.sign(privateKey, m);
// 4. Convert the signature representative s to a signature S of length k
// octets (see Section 1.2.1): S = I2OSP(s, k).
// octets (see Section 1.2.1): S = I2OSP(s, k).
// 5. Output the signature S.
int k = (modBits + 7) / 8;
// return encodeSignature(s, k);
// return encodeSignature(s, k);
return RSA.I2OSP(s, k);
}
protected boolean verifySignature(Object sig) throws IllegalStateException
{
if (publicKey == null)
{
throw new IllegalStateException();
}
// byte[] S = decodeSignature(sig);
throw new IllegalStateException();
// byte[] S = decodeSignature(sig);
byte[] S = (byte[]) sig;
// 1. If the length of the signature S is not k octets, output 'signature
// invalid' and stop.
// invalid' and stop.
int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
int k = (modBits + 7) / 8;
if (S.length != k)
{
return false;
}
return false;
// 2. Convert the signature S to an integer signature representative s:
// s = OS2IP(S).
// s = OS2IP(S).
BigInteger s = new BigInteger(1, S);
// 3. Apply the RSAVP verification primitive to the public key (n, e) and
// the signature representative s to produce an integer message
// representative m: m = RSAVP((n, e), s).
// If RSAVP outputs 'signature representative out of range,' then
// output 'signature invalid' and stop.
// the signature representative s to produce an integer message
// representative m: m = RSAVP((n, e), s).
// If RSAVP outputs 'signature representative out of range,' then
// output 'signature invalid' and stop.
BigInteger m = null;
try
{
@@ -254,22 +218,18 @@ public class RSAPSSSignature extends BaseSignature
return false;
}
// 4. Convert the message representative m to an encoded message EM of
// length emLen = CEILING((modBits - 1)/8) octets, where modBits is
// equal to the bit length of the modulus: EM = I2OSP(m, emLen).
// Note that emLen will be one less than k if modBits - 1 is divisible
// by 8. If I2OSP outputs 'integer too large,' then output 'signature
// invalid' and stop.
// length emLen = CEILING((modBits - 1)/8) octets, where modBits is
// equal to the bit length of the modulus: EM = I2OSP(m, emLen).
// Note that emLen will be one less than k if modBits - 1 is divisible
// by 8. If I2OSP outputs 'integer too large,' then output 'signature
// invalid' and stop.
int emBits = modBits - 1;
int emLen = (emBits + 7) / 8;
byte[] EM = m.toByteArray();
if (DEBUG && debuglevel > 8)
{
debug("EM (verify): " + Util.toString(EM));
}
if (Configuration.DEBUG)
log.fine("EM (verify): " + Util.toString(EM));
if (EM.length > emLen)
{
return false;
}
return false;
else if (EM.length < emLen)
{
byte[] newEM = new byte[emLen];
@@ -277,9 +237,9 @@ public class RSAPSSSignature extends BaseSignature
EM = newEM;
}
// 5. Apply the EMSA-PSS decoding operation to the message M and the
// encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
// Result = 'consistent,' output 'signature verified.' Otherwise,
// output 'signature invalid.'
// encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
// Result = 'consistent,' output 'signature verified.' Otherwise,
// output 'signature invalid.'
byte[] mHash = md.digest();
boolean result = false;
try
@@ -292,55 +252,4 @@ public class RSAPSSSignature extends BaseSignature
}
return result;
}
// Other instance methods --------------------------------------------------
/**
* Converts the <i>signature representative</i> <code>s</code> to a signature
* <code>S</code> of length <code>k</code> octets; i.e.
* <code>S = I2OSP(s, k)</code>, where <code>k = CEILING(modBits/8)</code>.
*
* @param s the <i>signature representative</i>.
* @param k the length of the output.
* @return the signature as an octet sequence.
* @exception IllegalArgumentException if the length in octets of meaningful
* bytes of <code>s</code> is greater than <code>k</code>, implying that
* <code>s</code> is not less than the RSA <i>modulus</i>.
*/
// private Object encodeSignature(BigInteger s, int k) {
// if (DEBUG && debuglevel > 8) {
// debug("s.bitLength(): "+String.valueOf(s.bitLength()));
// debug("k: "+String.valueOf(k));
// }
// byte[] result = s.toByteArray();
// if (DEBUG && debuglevel > 8) {
// debug("s: "+Util.toString(result));
// debug("s (bytes): "+String.valueOf(result.length));
// }
// if (result.length < k) {
// byte[] newResult = new byte[k];
// System.arraycopy(result, 0, newResult, k-result.length, result.length);
// result = newResult;
// } else if (result.length > k) { // leftmost extra bytes should all be 0
// int limit = result.length - k;
// for (int i = 0; i < limit; i++) {
// if (result[i] != 0x00) {
// throw new IllegalArgumentException("integer too large");
// }
// }
// byte[] newResult = new byte[k];
// System.arraycopy(result, limit, newResult, 0, k);
// result = newResult;
// }
// return result;
// }
/**
* Returns the output of a previously generated signature object as an octet
* sequence.<p>
*
* @return the octet sequence <code>S</code>.
*/
// private byte[] decodeSignature(Object signature) {
// return (byte[]) signature;
// }
}
@@ -44,53 +44,41 @@ import gnu.java.security.sig.ISignatureCodec;
import java.io.ByteArrayOutputStream;
/**
* <p>An object that implements the {@link gnu.crypto.sig.ISignatureCodec}
* operations for the <i>Raw</i> format to use with RSA-PSS signatures.</p>
* An object that implements the {@link ISignatureCodec} operations for the
* <i>Raw</i> format to use with RSA-PSS signatures.
*/
public class RSAPSSSignatureRawCodec implements ISignatureCodec
public class RSAPSSSignatureRawCodec
implements ISignatureCodec
{
// Constants and variables
// -------------------------------------------------------------------------
// Constructor(s)
// -------------------------------------------------------------------------
// implicit 0-arguments constructor
// Class methods
// -------------------------------------------------------------------------
// gnu.crypto.keys.IKeyPairCodec interface implementation
// -------------------------------------------------------------------------
public int getFormatID()
{
return RAW_FORMAT;
}
/**
* <p>Returns the encoded form of the designated RSA-PSS signature object
* according to the <i>Raw</i> format supported by this library.</p>
*
* <p>The <i>Raw</i> format for an RSA-PSS signature, in this implementation,
* is a byte sequence consisting of the following:</p>
*
* Returns the encoded form of the designated RSA-PSS signature object
* according to the <i>Raw</i> format supported by this library.
* <p>
* The <i>Raw</i> format for an RSA-PSS signature, in this implementation, is
* a byte sequence consisting of the following:
* <ol>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},<li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the RSA-PSS signature
* bytes in internet order,</li>
* <li>the RSA-PSS signature bytes in internet order.</li>
* <li>4-byte magic consisting of the value of the literal
* {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},
* <li>
* <li>1-byte version consisting of the constant: 0x01,</li>
* <li>4-byte count of following bytes representing the RSA-PSS signature
* bytes in internet order,</li>
* <li>the RSA-PSS signature bytes in internet order.</li>
* </ol>
*
*
* @param signature the signature to encode, consisting of the output of the
* <code>sign()</code> method of a {@link RSAPSSSignature} instance --a byte
* array.
* <code>sign()</code> method of a {@link RSAPSSSignature} instance
* --a byte array.
* @return the <i>Raw</i> format encoding of the designated signature.
* @exception IllegalArgumentException if the designated signature is not an
* RSA-PSS one.
* RSA-PSS one.
*/
public byte[] encodeSignature(Object signature)
{
@@ -101,28 +89,23 @@ public class RSAPSSSignatureRawCodec implements ISignatureCodec
}
catch (Exception x)
{
throw new IllegalArgumentException("key");
throw new IllegalArgumentException("signature");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// magic
baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]);
baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]);
baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]);
baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3]);
// version
baos.write(0x01);
// signature bytes
int length = buffer.length;
baos.write(length >>> 24);
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();
}
@@ -133,25 +116,19 @@ public class RSAPSSSignatureRawCodec implements ISignatureCodec
|| k[1] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]
|| k[2] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]
|| k[3] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3])
{
throw new IllegalArgumentException("magic");
}
throw new IllegalArgumentException("magic");
// version
if (k[4] != 0x01)
{
throw new IllegalArgumentException("version");
}
throw new IllegalArgumentException("version");
int i = 5;
int l;
// signature bytes
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
l = k[i++] << 24
| (k[i++] & 0xFF) << 16
| (k[i++] & 0xFF) << 8
| (k[i++] & 0xFF);
byte[] result = new byte[l];
System.arraycopy(k, i, result, 0, l);
return result;
}
}