// RSAPublicKeyImpl.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.*;

public class RSAPublicKeyImpl implements RSAPublicKey {

/**
 * An implementation of the 
 * <CODE>java.security.interfaces.RSAPubliccKey</CODE>
 * interface. This was written because generating a RSA publi 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.RSAPrivateKeyImpl
 * @version 1.0 (last modified 10-February-1998)
 */

  private BigInteger e;
  private BigInteger n;
  private byte [] encoded_key;

  /**
   * Create a new RSA publi key from other classes that implements
   * java.security.interface.RSAPublicKey
   */
  public RSAPublicKeyImpl(RSAPublicKey key)
  {
    this(key.getExponent(), key.getModulus());
  }

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

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

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

  /**
   * 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 true if the given input data (signMe) matches the signature,
   * false otherwise.
   * @exception SignatureException if an error occurs during signature
   * verification.
   */
    boolean verify(byte [] signMe, byte [] signature) 
       throws SignatureException {
      
      JSAFE_PublicKey publicKey = null;
      boolean CompareOkay = true;
      
      byte [] modulus = n.toByteArray();
      byte [] pubExpo = e.toByteArray();
      
      byte[][] pubKeyData = {
	modulus,
	pubExpo
      };
      
      try {
        publicKey = JSAFE_PublicKey.getInstance ("RSA");
        publicKey.setKeyData (pubKeyData);
      } catch (Exception e) {
	throw new SignatureException("%RSASIGN-F-GENRSA; Exception encountered " +
				" during publicKey creation from data." +
				"; " + e.toString());  
      }

      try {
	JSAFE_Signature verifier =
	  JSAFE_Signature.getInstance( "RSA/PKCS1Block01Pad", "Java" );
	verifier.verifyInit( publicKey, null);
	verifier.verifyUpdate( signMe, 0, signMe.length );
	CompareOkay = verifier.verifyFinal( signature, 0, signature.length );

	// The verifier may also contain sensitive information, so we should
	// call clearSensitiveData() before it goes out of scope.
	verifier.clearSensitiveData();
      } catch (Exception e) {
	throw new SignatureException("%RSASIGN-F-VERIFY; Exception encountered " +
				" during RSA signature verification" +
				"; " + e.toString());  
      }
      
      publicKey.clearSensitiveData();  //be a good security doo-bee
      
      return CompareOkay;
    }
}
