/* RSA.java --
   Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.

This file is a part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version.  */


package gnu.java.security.sig.rsa;

import gnu.java.security.Properties;
import gnu.java.security.util.PRNG;

import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

/**
 * 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>
 * </ol>
 */
public class RSA
{
  private static final BigInteger ZERO = BigInteger.ZERO;

  private static final BigInteger ONE = BigInteger.ONE;

  /** Our default source of randomness. */
  private static final PRNG prng = PRNG.getInstance();

  /** Trivial private constructor to enforce Singleton pattern. */
  private RSA()
  {
    super();
  }

  /**
   * 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>.
   * @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>.
   * @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.
   */
  public static final BigInteger sign(final PrivateKey K, final BigInteger m)
  {
    try
      {
        return RSADP((RSAPrivateKey) K, m);
      }
    catch (IllegalArgumentException x)
      {
        throw new IllegalArgumentException("message representative out of range");
      }
  }

  /**
   * 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>.
   * @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>.
   * @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.
   */
  public static final BigInteger verify(final PublicKey K, final BigInteger s)
  {
    try
      {
        return RSAEP((RSAPublicKey) K, s);
      }
    catch (IllegalArgumentException x)
      {
        throw new IllegalArgumentException("signature representative out of range");
      }
  }

  /**
   * 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.
   * @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).
   */
  public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
  {
    try
      {
        return RSAEP((RSAPublicKey) K, m);
      }
    catch (IllegalArgumentException x)
      {
        throw new IllegalArgumentException("message representative out of range");
      }
  }

  /**
   * 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).
   * @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).
   */
  public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
  {
    try
      {
        return RSADP((RSAPrivateKey) K, c);
      }
    catch (IllegalArgumentException x)
      {
        throw new IllegalArgumentException("ciphertext representative out of range");
      }
  }

  /**
   * 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>.
   */
  public static final byte[] I2OSP(final BigInteger s, final int k)
  {
    byte[] result = s.toByteArray();
    if (result.length < k)
      {
        final 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
        final int limit = result.length - k;
        for (int i = 0; i < limit; i++)
          {
            if (result[i] != 0x00)
              throw new IllegalArgumentException("integer too large");
          }
        final byte[] newResult = new byte[k];
        System.arraycopy(result, limit, newResult, 0, k);
        result = newResult;
      }
    return result;
  }

  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.
    final BigInteger n = K.getModulus();
    if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
      throw new IllegalArgumentException();
    // 2. Let c = m^e mod n.
    final BigInteger e = K.getPublicExponent();
    final BigInteger result = m.modPow(e, n);
    // 3. Output c.
    return result;
  }

  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.
    final BigInteger n = K.getModulus();
    if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
      throw new IllegalArgumentException();
    // 2. The representative m is computed as follows.
    BigInteger result;
    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();
        result = c.modPow(d, n);
      }
    else
      {
        // from [3] p.13 --see class docs:
        // The RSA blinding operation calculates x = (r^e) * g mod n before
        // decryption, where r is random, e is the RSA encryption exponent, and
        // g is the ciphertext to be decrypted. x is then decrypted as normal,
        // followed by division by r, i.e. (x^e) / r mod n. Since r is random,
        // x is random and timing the decryption should not reveal information
        // about the key. Note that r should be a new random number for every
        // decryption.
        final boolean rsaBlinding = Properties.doRSABlinding();
        BigInteger r = null;
        BigInteger e = null;
        if (rsaBlinding)
          { // pre-decryption
            r = newR(n);
            e = ((RSAPrivateCrtKey) K).getPublicExponent();
            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:
        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.
        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.
        final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
        // 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);
      }
    // 3. Output m
    return result;
  }

  /**
   * 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)
  {
    final int upper = (N.bitLength() + 7) / 8;
    final int lower = upper / 2;
    final byte[] bl = new byte[1];
    int b;
    do
      {
        prng.nextBytes(bl);
        b = bl[0] & 0xFF;
      }
    while (b < lower || b > upper);
    final byte[] buffer = new byte[b]; // 256-bit MPI
    prng.nextBytes(buffer);
    return new BigInteger(1, buffer);
  }
}
