package net.i2p.crypto.eddsa;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* @author str4d
*
*/
public class EdDSAEngineTest {
static final byte[] TEST_SEED = Utils.hexToBytes("0000000000000000000000000000000000000000000000000000000000000000");
static final byte[] TEST_PK = Utils.hexToBytes("3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29");
static final byte[] TEST_MSG = "This is a secret message".getBytes(Charset.forName("UTF-8"));
static final byte[] TEST_MSG_SIG = Utils.hexToBytes("94825896c7075c31bcb81f06dba2bdcd9dcf16e79288d4b9f87c248215c8468d475f429f3de3b4a2cf67fe17077ae19686020364d6d4fa7a0174bab4a123ba0f");
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testSign() throws Exception {
//Signature sgr = Signature.getInstance("EdDSA", "I2P");
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
for (Ed25519TestVectors.TestTuple testCase : Ed25519TestVectors.testCases) {
EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(testCase.seed, spec);
PrivateKey sKey = new EdDSAPrivateKey(privKey);
sgr.initSign(sKey);
sgr.update(testCase.message);
assertThat("Test case " + testCase.caseNum + " failed",
sgr.sign(), is(equalTo(testCase.sig)));
}
}
@Test
public void testVerify() throws Exception {
//Signature sgr = Signature.getInstance("EdDSA", "I2P");
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
for (Ed25519TestVectors.TestTuple testCase : Ed25519TestVectors.testCases) {
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(testCase.pk, spec);
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
sgr.update(testCase.message);
assertThat("Test case " + testCase.caseNum + " failed",
sgr.verify(testCase.sig), is(true));
}
}
/**
* Checks that a wrong-length signature throws an IAE.
*/
@Test
public void testVerifyWrongSigLength() throws Exception {
//Signature sgr = Signature.getInstance("EdDSA", "I2P");
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK,
EdDSANamedCurveTable.getByName("ed25519-sha-512"));
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
sgr.update(TEST_MSG);
exception.expect(SignatureException.class);
exception.expectMessage("signature length is wrong");
sgr.verify(new byte[] {0});
}
@Test
public void testSignResetsForReuse() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(TEST_SEED, spec);
PrivateKey sKey = new EdDSAPrivateKey(privKey);
sgr.initSign(sKey);
// First usage
sgr.update(new byte[] {0});
sgr.sign();
// Second usage
sgr.update(TEST_MSG);
assertThat("Second sign failed", sgr.sign(), is(equalTo(TEST_MSG_SIG)));
}
@Test
public void testVerifyResetsForReuse() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK,
EdDSANamedCurveTable.getByName("ed25519-sha-512"));
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
// First usage
sgr.update(new byte[] {0});
sgr.verify(TEST_MSG_SIG);
// Second usage
sgr.update(TEST_MSG);
assertThat("Second verify failed", sgr.verify(TEST_MSG_SIG), is(true));
}
@Test
public void testSignOneShotMode() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(TEST_SEED, spec);
PrivateKey sKey = new EdDSAPrivateKey(privKey);
sgr.initSign(sKey);
sgr.setParameter(EdDSAEngine.ONE_SHOT_MODE);
sgr.update(TEST_MSG);
assertThat("One-shot mode sign failed", sgr.sign(), is(equalTo(TEST_MSG_SIG)));
}
@Test
public void testVerifyOneShotMode() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK,
EdDSANamedCurveTable.getByName("ed25519-sha-512"));
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
sgr.setParameter(EdDSAEngine.ONE_SHOT_MODE);
sgr.update(TEST_MSG);
assertThat("One-shot mode verify failed", sgr.verify(TEST_MSG_SIG), is(true));
}
@Test
public void testSignOneShotModeMultipleUpdates() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(TEST_SEED, spec);
PrivateKey sKey = new EdDSAPrivateKey(privKey);
sgr.initSign(sKey);
sgr.setParameter(EdDSAEngine.ONE_SHOT_MODE);
sgr.update(TEST_MSG);
exception.expect(SignatureException.class);
exception.expectMessage("update() already called");
sgr.update(TEST_MSG);
}
@Test
public void testVerifyOneShotModeMultipleUpdates() throws Exception {
Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK,
EdDSANamedCurveTable.getByName("ed25519-sha-512"));
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
sgr.setParameter(EdDSAEngine.ONE_SHOT_MODE);
sgr.update(TEST_MSG);
exception.expect(SignatureException.class);
exception.expectMessage("update() already called");
sgr.update(TEST_MSG);
}
@Test
public void testSignOneShot() throws Exception {
EdDSAEngine sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(TEST_SEED, spec);
PrivateKey sKey = new EdDSAPrivateKey(privKey);
sgr.initSign(sKey);
assertThat("signOneShot() failed", sgr.signOneShot(TEST_MSG), is(equalTo(TEST_MSG_SIG)));
}
@Test
public void testVerifyOneShot() throws Exception {
EdDSAEngine sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK,
EdDSANamedCurveTable.getByName("ed25519-sha-512"));
PublicKey vKey = new EdDSAPublicKey(pubKey);
sgr.initVerify(vKey);
assertThat("verifyOneShot() failed", sgr.verifyOneShot(TEST_MSG, TEST_MSG_SIG), is(true));
}
}