/*********************************************************************************
* 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 totalcross.crypto.*;
import totalcross.crypto.cipher.Key;
import totalcross.io.ByteArrayStream;
/**
* This class provides the functionality of a signature algorithm for signing and verifying.
*/
public abstract class Signature
{
Object signatureRef;
Object keyRef;
protected int operation = -1;
protected Key key;
private ByteArrayStream input = new ByteArrayStream(128);
private byte[] oneByte = new byte[1];
/**
* Constant used to initialize this signature algorithm to sign.
*/
public static final int OPERATION_SIGN = 0;
/**
* Constant used to initialize this signature algorithm to verify.
*/
public static final int OPERATION_VERIFY = 1;
/**
* Returns the name of the algorithm.
*
* @return The name of the algorithm used.
*/
public final String toString()
{
return getAlgorithm();
}
/**
* Initializes this message signature algorithm to sign or verify. Calling this method will also reset the input data buffer.
*
* @param operation The operation mode of this signature algorithm (<code>OPERATION_SIGN</code> or <code>OPERATION_VERIFY</code>).
* @param key The key.
*
* @throws CryptoException If one or more initialization parameters are invalid or the signature algorithm fails to initialize with the given
* parameters.
*/
public final void reset(int operation, Key key) throws CryptoException
{
if (operation < OPERATION_SIGN || operation > OPERATION_VERIFY)
throw new CryptoException("Invalid or unsupported signature operation: " + operation);
if (key == null || !isKeySupported(key, operation))
throw new CryptoException("Invalid or unsupported signature key: " + key);
this.operation = operation;
this.key = key;
input.reset();
doReset();
}
/**
* Updates the input data that will be processed by this signature algorithm. The data will be accumulated in an input buffer to be processed when
* {@link #sign()} or {@link #verify(byte[])} is finally called.
*
* @param data The input data.
*/
public final void update(int data)
{
oneByte[0] = (byte)(data & 0xFF);
input.writeBytes(oneByte, 0, 1);
}
/**
* Updates the input data that will be processed by this signature algorithm. The data will be accumulated in an input buffer to be processed when
* {@link #sign()} or {@link #verify(byte[])} is finally called.
*
* @param data The input data.
*/
public final void update(byte[] data)
{
input.writeBytes(data, 0, data.length);
}
/**
* Updates the input data that will be processed by this signature algorithm. The data will be accumulated in an input buffer to be processed when
* {@link #sign()} or {@link #verify(byte[])} is finally called.
*
* @param data The input data.
* @param start The offset in <code>data</code> where the data starts.
* @param count The input length.
*/
public final void update(byte[] data, int start, int count)
{
input.writeBytes(data, start, count);
}
/**
* Finalizes the sign operation by processing all the accumulated input data and returning
* the result in a new buffer.
*
* @return The signature in a new buffer.
*/
public byte[] sign() throws CryptoException
{
if (operation != OPERATION_SIGN)
throw new CryptoException("Signature is not in sign mode");
return doSign(input.toByteArray());
}
/**
* Finalizes the verify operation by processing all the accumulated input data and returning
* the signature comparison result.
*
* @return the signature comparison result.
*/
public boolean verify(byte[] signature) throws CryptoException
{
if (operation != OPERATION_VERIFY)
throw new CryptoException("Signature is not in verify mode");
return doVerify(input.toByteArray(), signature);
}
/**
* Returns the name of the signature algorithm.
*
* @return The name of the signature algorithm used.
*/
public abstract String getAlgorithm();
protected abstract boolean isKeySupported(Key key, int operation);
protected abstract void doReset() throws NoSuchAlgorithmException, CryptoException;
protected abstract byte[] doSign(byte[] data) throws CryptoException;
protected abstract boolean doVerify(byte[] data, byte[] expected) throws CryptoException;
}