// RSAPrivateKeyImpl.java
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

// The source code is jointly developed by W3C and some of its members
// participating in the Digital Signature Initiative.  The authors are:
//    Mark Champine, HP, <champine@apollo.hp.com>
//    Yang-hua Chu, MIT/W3C, <yhchu@w3.org>
//    Vasanthan Dasan, Sun, <vasanthan.dasan@central.sun.com>
//    Peter Lipp, University of Technology, Graz <plipp@iaik.tu-graz.ac.at>
//    Andreas Sterbenz, U. of Technology, Graz <sterbenz@iaik.tu-graz.ac.at>

package w3c.crypto.us.dsig;

import java.math.BigInteger;
import java.security.interfaces.*;
import java.security.*;
import COM.rsa.jsafe.*;
import java.util.*;
import java.io.*;


/**
 * An implementation of the 
 * <CODE>java.security.interfaces.RSAPrivatecKey</CODE>
 * interface. This was written because generating a RSA private key
 * from given parameters using the JDK implementation in the Sun
 * provider is not possible by via the security interfaces (BUG!).
 *
 * @author Mark Champine
 * @see     w3c.crypto.us.dsig.RSAPublicKeyImpl
 * @version 1.0 (last modified 10-February-1998)
 */

public class RSAPrivateKeyImpl implements RSAPrivateKey {

  private BigInteger d; //private exponent
  private BigInteger e;
  private BigInteger n;
  private byte [] encoded_key;
  private JSAFE_PrivateKey privateKey = null;  //JSAFE format

  /**
   * Create a new RSA private key from the given private exponent d, given 
   * public exponent e, and given modulus n.
   */
    public RSAPrivateKeyImpl(BigInteger d, BigInteger e, BigInteger n)
    {
        this.d = d;
        this.e = e;
        this.n = n;
    }

  /**
   * returns the exponent of the RSA key
   */
    public BigInteger getExponent() { return d;}

  /**
   * returns the modulus of the RSA key
   */
    public BigInteger getModulus() { return n;}

  /**
   * returns the String "RSA"
   */
    public String getAlgorithm() { return "RSA"; }

  /**
   * returns the String "ASN1"
   */
    public String getFormat() { return "ASN1";}

  /**
   * returns the encoding.
   */
    public byte[] getEncoded() { return encoded_key;}

  /**
   * returns the encrypted byte arary for the given byte array input.
   * @exception SignatureException if an error occurs during signature
   * generation.
   */
    public byte [] encrypt(byte [] signMe) throws SignatureException {

        byte [] signature = null;
        byte [] priExpo = d.toByteArray();
        byte [] modulus = n.toByteArray();

        //build a privateKey as expected by JSAFE
         byte[][] priKeyData = {
          modulus,
          priExpo
        };

        try {
        privateKey = JSAFE_PrivateKey.getInstance ("RSA");
        privateKey.setKeyData ("RSAPrivateKey",priKeyData);
        } catch (Exception e) {
	  throw new SignatureException("%RSASIGN-F-GENRSA; Exception encountered " +
				  " during RSA key pair generation." +
				  "; " + e.toString());  
        }

        try {
          //Create the JSAFE_Signature instance that actually does the signing.
          // Use "RSA/PKCS1Block01Pad", which doesn't hash before signing
          JSAFE_Signature signer =
            JSAFE_Signature.getInstance( "RSA/PKCS1Block01Pad", "Java" );

          signer.signInit( privateKey, null );
          signer.signUpdate( signMe, 0, signMe.length );
          signature = signer.signFinal();

          //System.out.println("%RSASIGN-I-SIGN; The signature is:");
          //hexDump( signature );

          // There might be sensitive information still in the signer object,
          // so we should call clearSensitiveData() before it goes out of scope.
          signer.clearSensitiveData();
        } catch (Exception e) {
	throw new SignatureException("%RSASIGN-F-VERIFY; Exception encountered " +
				" during RSA signature generation" +
				"; " + e.toString());  
        }

        return signature;
	
    }
}
