/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine 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. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.crypto.signature;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.spec.*;
import totalcross.crypto.*;
import totalcross.crypto.cipher.*;
import totalcross.crypto.digest.*;
/**
* This class implements the PKCS #1 signature algorithm.
*/
public class PKCS1Signature extends Signature
{
private String algorithm;
/**
* Creates a new PKCS1Signature algorithm with the given message digest.
*
* @param digest The message digest.
* @throws CryptoException If the given message digest is not supported.
* @throws NoSuchAlgorithmException If no Provider supports a Signature implementation for the specified algorithm.
*/
public PKCS1Signature(Digest digest) throws NoSuchAlgorithmException, CryptoException
{
if (digest instanceof MD5Digest)
algorithm = "MD5withRSA";
else if (digest instanceof SHA1Digest)
algorithm = "SHA1withRSA";
else if (digest instanceof SHA256Digest)
algorithm = "SHA256withRSA";
else
throw new CryptoException("Invalid or unsupported signature digest: " + digest.getAlgorithm());
try
{
signatureRef = java.security.Signature.getInstance(algorithm);
}
catch (java.security.NoSuchAlgorithmException e)
{
throw new CryptoException(e.getMessage());
}
}
/**
* Returns the name of the algorithm.
*
* @return The name of the algorithm used.
*/
public String getAlgorithm()
{
return algorithm;
}
protected boolean isKeySupported(Key key, int operation)
{
return (operation == OPERATION_SIGN && key instanceof RSAPrivateKey) || (operation == OPERATION_VERIFY && key instanceof RSAPublicKey);
}
protected void doReset() throws NoSuchAlgorithmException, CryptoException
{
try
{
KeyFactory factory = KeyFactory.getInstance("RSA");
if (operation == OPERATION_SIGN)
{
RSAPrivateKey privKey = (RSAPrivateKey)key;
BigInteger d = new BigInteger(privKey.getPrivateExponent());
BigInteger n = new BigInteger(privKey.getModulus());
keyRef = factory.generatePrivate(new RSAPrivateKeySpec(n, d));
}
else
{
RSAPublicKey pubKey = (RSAPublicKey)key;
BigInteger e = new BigInteger(pubKey.getPublicExponent());
BigInteger n = new BigInteger(pubKey.getModulus());
keyRef = factory.generatePublic(new RSAPublicKeySpec(n, e));
}
}
catch (java.security.NoSuchAlgorithmException e)
{
throw new CryptoException(e.getMessage());
}
catch (GeneralSecurityException e)
{
throw new CryptoException(e.getMessage());
}
}
protected byte[] doSign(byte[] data) throws CryptoException
{
try
{
java.security.Signature engine = (java.security.Signature)signatureRef;
engine.initSign((java.security.PrivateKey)keyRef);
engine.update(data);
return engine.sign();
}
catch (GeneralSecurityException e)
{
throw new CryptoException(e.getMessage());
}
}
protected boolean doVerify(byte[] data, byte[] signature) throws CryptoException
{
try
{
java.security.Signature engine = (java.security.Signature)signatureRef;
engine.initVerify((java.security.PublicKey)keyRef);
engine.update(data);
return engine.verify(signature);
}
catch (GeneralSecurityException e)
{
throw new CryptoException(e.getMessage());
}
}
}