diff options
4 files changed, 474 insertions, 0 deletions
diff --git a/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java b/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java index 9bd0e33f..4559fdb9 100644 --- a/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java +++ b/src/test/java/org/bouncycastle/pqc/crypto/test/AllTests.java @@ -38,6 +38,9 @@ public class AllTests suite.addTestSuite(NTRUEncryptionParametersTest.class); suite.addTestSuite(NTRUEncryptTest.class); suite.addTestSuite(NTRUSignatureParametersTest.class); + suite.addTestSuite(NTRUSignatureKeyTest.class); + suite.addTestSuite(NTRUSignerTest.class); + suite.addTestSuite(NTRUSigningParametersTest.class); return suite; } diff --git a/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java new file mode 100644 index 00000000..b9e84fb5 --- /dev/null +++ b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignatureKeyTest.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package org.bouncycastle.pqc.crypto.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import junit.framework.TestCase; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyPairGenerator; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPrivateKeyParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPublicKeyParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigner; + +public class NTRUSignatureKeyTest + extends TestCase +{ + public void testEncode() throws IOException { + for (NTRUSigningKeyGenerationParameters params: new NTRUSigningKeyGenerationParameters[] {NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD}) + testEncode(params); + } + + private void testEncode(NTRUSigningKeyGenerationParameters params) throws IOException { + NTRUSigner ntru = new NTRUSigner(params.getSigningParameters()); + NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator(); + + kGen.init(params); + + AsymmetricCipherKeyPair kp = kGen.generateKeyPair(); + + NTRUSigningPrivateKeyParameters kPriv = (NTRUSigningPrivateKeyParameters)kp.getPrivate(); + NTRUSigningPublicKeyParameters kPub = (NTRUSigningPublicKeyParameters)kp.getPublic(); + + // encode to byte[] and reconstruct + byte[] priv = kPriv.getEncoded(); + byte[] pub = kPub.getEncoded(); + AsymmetricCipherKeyPair kp2 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(pub, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(priv, params)); + assertEquals(kPub, kp2.getPublic()); + assertEquals(kPriv, kp2.getPrivate()); + + // encode to OutputStream and reconstruct + ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); + kPriv.writeTo(bos1); + kPub.writeTo(bos2); + ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray()); + ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray()); + AsymmetricCipherKeyPair kp3 = new AsymmetricCipherKeyPair(new NTRUSigningPublicKeyParameters(bis2, params.getSigningParameters()), new NTRUSigningPrivateKeyParameters(bis1, params)); + assertEquals(kPub, kp3.getPublic()); + assertEquals(kPriv, kp3.getPrivate()); + } +}
\ No newline at end of file diff --git a/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java new file mode 100644 index 00000000..2459cc2b --- /dev/null +++ b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSignerTest.java @@ -0,0 +1,325 @@ +/** + * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package org.bouncycastle.pqc.crypto.test; + + +import java.io.IOException; +import java.util.Random; + +import junit.framework.TestCase; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyPairGenerator; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPrivateKeyParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningPublicKeyParameters; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigner; +import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial; +import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial; +import org.bouncycastle.util.Arrays; + +public class NTRUSignerTest + extends TestCase +{ + public void testCreateBasis() + { + for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()}) + { + testCreateBasis(params); + } + } + + private void testCreateBasis(NTRUSigningKeyGenerationParameters params) + { + NTRUSigningKeyPairGenerator ntru = new NTRUSigningKeyPairGenerator(); + + ntru.init(params); + + NTRUSigningKeyPairGenerator.FGBasis basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis(); + assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N)); + + // test KeyGenAlg.FLOAT (default=RESULTANT) + params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT; + ntru.init(params); + basis = (NTRUSigningKeyPairGenerator.FGBasis)ntru.generateBoundedBasis(); + assertTrue(equalsQ(basis.f, basis.fPrime, basis.F, basis.G, params.q, params.N)); + } + + // verifies that f*G-g*F=q + private boolean equalsQ(Polynomial f, Polynomial g, IntegerPolynomial F, IntegerPolynomial G, int q, int N) + { + IntegerPolynomial x = f.mult(G); + x.sub(g.mult(F)); + boolean equalsQ = true; + for (int i = 1; i < x.coeffs.length; i++) + { + equalsQ &= x.coeffs[i] == 0; + } + equalsQ &= x.coeffs[0] == q; + return equalsQ; + } + + /** + * a test for the one-method-call variants: sign(byte, SignatureKeyPair) and verify(byte[], byte[], SignatureKeyPair) + */ + public void testSignVerify() + throws IOException + { + for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()}) + { + testSignVerify(params); + } + } + + private void testSignVerify(NTRUSigningKeyGenerationParameters params) + throws IOException + { + NTRUSigner ntru = new NTRUSigner(params.getSigningParameters()); + NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator(); + + kGen.init(params); + + AsymmetricCipherKeyPair kp = kGen.generateKeyPair(); + + Random rng = new Random(); + byte[] msg = new byte[10 + rng.nextInt(1000)]; + rng.nextBytes(msg); + + // sign and verify + ntru.init(true, kp.getPrivate()); + + ntru.update(msg, 0, msg.length); + + byte[] s = ntru.generateSignature(); + + ntru.init(false, kp.getPublic()); + + ntru.update(msg, 0, msg.length); + + boolean valid = ntru.verifySignature(s); + + assertTrue(valid); + + // altering the signature should make it invalid + s[rng.nextInt(params.N)] += 1; + ntru.init(false, kp.getPublic()); + + ntru.update(msg, 0, msg.length); + + valid = ntru.verifySignature(s); + assertFalse(valid); + + // test that a random signature fails + rng.nextBytes(s); + + ntru.init(false, kp.getPublic()); + + ntru.update(msg, 0, msg.length); + + valid = ntru.verifySignature(s); + assertFalse(valid); + + // encode, decode keypair, test + NTRUSigningPrivateKeyParameters priv = new NTRUSigningPrivateKeyParameters(((NTRUSigningPrivateKeyParameters)kp.getPrivate()).getEncoded(), params); + NTRUSigningPublicKeyParameters pub = new NTRUSigningPublicKeyParameters(((NTRUSigningPublicKeyParameters)kp.getPublic()).getEncoded(), params.getSigningParameters()); + kp = new AsymmetricCipherKeyPair(pub, priv); + + ntru.init(true, kp.getPrivate()); + ntru.update(msg, 0, msg.length); + + s = ntru.generateSignature(); + + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + + valid = ntru.verifySignature(s); + assertTrue(valid); + + // altering the signature should make it invalid + s[rng.nextInt(s.length)] += 1; + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + assertFalse(valid); + + // sparse/dense + params.sparse = !params.sparse; + + ntru.init(true, kp.getPrivate()); + ntru.update(msg, 0, msg.length); + + s = ntru.generateSignature(); + + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + assertTrue(valid); + + s[rng.nextInt(s.length)] += 1; + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + assertFalse(valid); + params.sparse = !params.sparse; + + // decrease NormBound to force multiple signing attempts + NTRUSigningKeyGenerationParameters params2 = params.clone(); + params2.normBoundSq *= 4.0 / 9; + params2.signFailTolerance = 10000; + ntru = new NTRUSigner(params2.getSigningParameters()); + + ntru.init(true, kp.getPrivate()); + ntru.update(msg, 0, msg.length); + + s = ntru.generateSignature(); + + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + + assertTrue(valid); + + // test KeyGenAlg.FLOAT (default=RESULTANT) + params2 = params.clone(); + params.keyGenAlg = NTRUSigningKeyGenerationParameters.KEY_GEN_ALG_FLOAT; + ntru = new NTRUSigner(params.getSigningParameters()); + + kGen.init(params); + + kp = kGen.generateKeyPair(); + ntru.init(true, kp.getPrivate()); + ntru.update(msg, 0, msg.length); + + s = ntru.generateSignature(); + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + assertTrue(valid); + s[rng.nextInt(s.length)] += 1; + ntru.init(false, kp.getPublic()); + ntru.update(msg, 0, msg.length); + valid = ntru.verifySignature(s); + assertFalse(valid); + } + + /** + * test for the initSign/update/sign and initVerify/update/verify variant + */ + public void testInitUpdateSign() + { + for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()}) + { + testInitUpdateSign(params); + } + } + + private void testInitUpdateSign(NTRUSigningKeyGenerationParameters params) + { + NTRUSigner ntru = new NTRUSigner(params.getSigningParameters()); + NTRUSigningKeyPairGenerator kGen = new NTRUSigningKeyPairGenerator(); + + kGen.init(params); + + AsymmetricCipherKeyPair kp = kGen.generateKeyPair(); + + Random rng = new Random(); + byte[] msg = new byte[10 + rng.nextInt(1000)]; + rng.nextBytes(msg); + + // sign and verify a message in two pieces each + ntru.init(true, kp.getPrivate()); + int splitIdx = rng.nextInt(msg.length); + ntru.update(msg[0]); // first byte + ntru.update(msg, 1, splitIdx - 1); // part 1 of msg + ntru.update(msg, splitIdx, msg.length - splitIdx); + byte[] s = ntru.generateSignature(); // part 2 of msg + ntru.init(false, kp.getPublic()); + splitIdx = rng.nextInt(msg.length); + ntru.update(msg, 0, splitIdx); // part 1 of msg + ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg + boolean valid = ntru.verifySignature(s); + assertTrue(valid); + // verify the same signature with the one-step method + ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic()); + ntru.update(msg, 0, msg.length); // part 1 of msg + valid = ntru.verifySignature(s); + assertTrue(valid); + + // sign using the one-step method and verify using the multi-step method + ntru.init(true, kp.getPrivate()); + ntru.update(msg, 0, msg.length); + s = ntru.generateSignature(); + ntru.init(false, (NTRUSigningPublicKeyParameters)kp.getPublic()); + splitIdx = rng.nextInt(msg.length); + ntru.update(msg, 0, splitIdx); // part 1 of msg + ntru.update(msg, splitIdx, msg.length - splitIdx); // part 2 of msg + valid = ntru.verifySignature(s); + assertTrue(valid); + } + + public void testCreateMsgRep() + { + for (NTRUSigningKeyGenerationParameters params : new NTRUSigningKeyGenerationParameters[]{NTRUSigningKeyGenerationParameters.TEST157.clone(), NTRUSigningKeyGenerationParameters.TEST157_PROD.clone()}) + { + testCreateMsgRep(params); + } + } + + private void testCreateMsgRep(NTRUSigningKeyGenerationParameters params) + { + VisibleNTRUSigner ntru = new VisibleNTRUSigner(params.getSigningParameters()); + byte[] msgHash = "adfsadfsdfs23234234".getBytes(); + + // verify that the message representative is reproducible + IntegerPolynomial i1 = ntru.createMsgRep(msgHash, 1); + IntegerPolynomial i2 = ntru.createMsgRep(msgHash, 1); + assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs)); + i1 = ntru.createMsgRep(msgHash, 5); + i2 = ntru.createMsgRep(msgHash, 5); + assertTrue(Arrays.areEqual(i1.coeffs, i2.coeffs)); + + i1 = ntru.createMsgRep(msgHash, 2); + i2 = ntru.createMsgRep(msgHash, 3); + assertFalse(Arrays.areEqual(i1.coeffs, i2.coeffs)); + } + + private class VisibleNTRUSigner + extends NTRUSigner + { + + /** + * Constructs a new instance with a set of signature parameters. + * + * @param params signature parameters + */ + public VisibleNTRUSigner(NTRUSigningParameters params) + { + super(params); + } + + public IntegerPolynomial createMsgRep(byte[] hash, int i) + { + return super.createMsgRep(hash, i); + } + } +}
\ No newline at end of file diff --git a/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java new file mode 100644 index 00000000..0e611793 --- /dev/null +++ b/src/test/java/org/bouncycastle/pqc/crypto/test/NTRUSigningParametersTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package org.bouncycastle.pqc.crypto.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import junit.framework.TestCase; +import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters; + +public class NTRUSigningParametersTest + extends TestCase +{ + + public void testLoadSave() throws IOException { + for (NTRUSigningKeyGenerationParameters params: new NTRUSigningKeyGenerationParameters[] {NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD}) + testLoadSave(params); + } + + private void testLoadSave(NTRUSigningKeyGenerationParameters params) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + params.writeTo(os); + ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); + assertEquals(params, new NTRUSigningKeyGenerationParameters(is)); + } + + public void testEqualsHashCode() throws IOException { + for (NTRUSigningKeyGenerationParameters params: new NTRUSigningKeyGenerationParameters[] {NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD}) + testEqualsHashCode(params); + } + + private void testEqualsHashCode(NTRUSigningKeyGenerationParameters params) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + params.writeTo(os); + ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); + NTRUSigningKeyGenerationParameters params2 = new NTRUSigningKeyGenerationParameters(is); + + assertEquals(params, params2); + assertEquals(params.hashCode(), params2.hashCode()); + + params.N += 1; + assertFalse(params.equals(params2)); + assertFalse(params.equals(params2)); + assertFalse(params.hashCode() == params2.hashCode()); + } + + public void testClone() { + for (NTRUSigningKeyGenerationParameters params: new NTRUSigningKeyGenerationParameters[] {NTRUSigningKeyGenerationParameters.TEST157, NTRUSigningKeyGenerationParameters.TEST157_PROD}) + assertEquals(params, params.clone()); + } +}
\ No newline at end of file |