blob: 2e64510fcc41e2b8fd83964cea8f378fa26698d4 [file] [log] [blame]
package org.bouncycastle.pqc.crypto.qtesla;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.pqc.crypto.MessageSigner;
/**
* Signer for the qTESLA algorithm (https://qtesla.org/)
*/
public class QTESLASigner
implements MessageSigner
{
/**
* The Public Key of the Identity Whose Signature Will be Generated
*/
private QTESLAPublicKeyParameters publicKey;
/**
* The Private Key of the Identity Whose Signature Will be Generated
*/
private QTESLAPrivateKeyParameters privateKey;
/**
* The Source of Randomness for private key operations
*/
private SecureRandom secureRandom;
public QTESLASigner()
{
}
/**
* Initialise the signer.
*
* @param forSigning true if we are generating a signature, false
* otherwise.
* @param param ParametersWithRandom containing a private key for signature generation, public key otherwise.
*/
public void init(boolean forSigning, CipherParameters param)
{
if (forSigning)
{
if (param instanceof ParametersWithRandom)
{
this.secureRandom = ((ParametersWithRandom)param).getRandom();
privateKey = (QTESLAPrivateKeyParameters)((ParametersWithRandom)param).getParameters();
}
else
{
this.secureRandom = CryptoServicesRegistrar.getSecureRandom();
privateKey = (QTESLAPrivateKeyParameters)param;
}
publicKey = null;
QTESLASecurityCategory.validate(privateKey.getSecurityCategory());
}
else
{
privateKey = null;
publicKey = (QTESLAPublicKeyParameters)param;
QTESLASecurityCategory.validate(publicKey.getSecurityCategory());
}
}
/**
* Generate a signature directly for the passed in message.
*
* @param message the message to be signed.
* @return the signature generated.
*/
public byte[] generateSignature(byte[] message)
{
byte[] sig = new byte[QTESLASecurityCategory.getSignatureSize(privateKey.getSecurityCategory())];
switch (privateKey.getSecurityCategory())
{
case QTESLASecurityCategory.HEURISTIC_I:
QTESLA.signingI(sig, message, 0, message.length, privateKey.getSecret(), secureRandom);
break;
case QTESLASecurityCategory.HEURISTIC_III_SIZE:
QTESLA.signingIIISize(sig, message, 0, message.length, privateKey.getSecret(), secureRandom);
break;
case QTESLASecurityCategory.HEURISTIC_III_SPEED:
QTESLA.signingIIISpeed(sig, message, 0, message.length, privateKey.getSecret(), secureRandom);
break;
case QTESLASecurityCategory.PROVABLY_SECURE_I:
QTESLA.signingIP(sig, message, 0, message.length, privateKey.getSecret(), secureRandom);
break;
case QTESLASecurityCategory.PROVABLY_SECURE_III:
QTESLA.signingIIIP(sig, message, 0, message.length, privateKey.getSecret(), secureRandom);
break;
default:
throw new IllegalArgumentException("unknown security category: " + privateKey.getSecurityCategory());
}
return sig;
}
/**
* Verify the signature against the passed in message.
*
* @param message the message that was supposed to have been signed.
* @param signature the signature of the message
* @return true if the signature passes, false otherwise.
*/
public boolean verifySignature(byte[] message, byte[] signature)
{
int status;
switch (publicKey.getSecurityCategory())
{
case QTESLASecurityCategory.HEURISTIC_I:
status = QTESLA.verifyingI(message, signature, 0, signature.length, publicKey.getPublicData());
break;
case QTESLASecurityCategory.HEURISTIC_III_SIZE:
status = QTESLA.verifyingIIISize(message, signature, 0, signature.length, publicKey.getPublicData());
break;
case QTESLASecurityCategory.HEURISTIC_III_SPEED:
status = QTESLA.verifyingIIISpeed(message, signature, 0, signature.length, publicKey.getPublicData());
break;
case QTESLASecurityCategory.PROVABLY_SECURE_I:
status = QTESLA.verifyingPI(message, signature, 0, signature.length, publicKey.getPublicData());
break;
case QTESLASecurityCategory.PROVABLY_SECURE_III:
status = QTESLA.verifyingPIII(message, signature, 0, signature.length, publicKey.getPublicData());
break;
default:
throw new IllegalArgumentException("unknown security category: " + publicKey.getSecurityCategory());
}
return 0 == status;
}
}