private byte[] signHash(byte[] msgHash, SignatureKeyPair kp) { int r = 0; IntegerPolynomial s; IntegerPolynomial i; do { r++; if (r > param.signFailTolerance) { throw new NtruException("Signing failed: too many retries (max=" + param.signFailTolerance + ")"); } i = createMsgRep(msgHash, r); s = sign(i, kp); } while (!verify(i, s, kp.pub.h)); byte[] rawSig = s.ToBinary(param.q); MemoryStream sbuf = new MemoryStream(rawSig.Length + 4); BinaryWriter bwr = new BinaryWriter(sbuf); bwr.Write(rawSig); bwr.Write(r); return(sbuf.ToArray()); }
private IntegerPolynomial sign(IntegerPolynomial i, SignatureKeyPair kp) { int N = param.N; int q = param.q; int perturbationBases = param.B; IntegerPolynomial s = new IntegerPolynomial(N); int iLoop = perturbationBases; while (iLoop >= 1) { IPolynomial f = kp.priv.getBasis(iLoop).f; IPolynomial fPrime = kp.priv.getBasis(iLoop).fPrime; IntegerPolynomial y = f.Multiply(i); y.Divide(q); y = fPrime.Multiply(y); IntegerPolynomial x = fPrime.Multiply(i); x.Divide(q); x = f.Multiply(x); IntegerPolynomial si = y; si.Subtract(x); s.Add(si); IntegerPolynomial hi = kp.priv.getBasis(iLoop).h.Clone(); if (iLoop > 1) { hi.Subtract(kp.priv.getBasis(iLoop - 1).h); } else { hi.Subtract(kp.pub.h); } i = si.Multiply(hi, q); iLoop--; } IPolynomial f2 = kp.priv.getBasis(0).f; IPolynomial fPrime2 = kp.priv.getBasis(0).fPrime; IntegerPolynomial y2 = f2.Multiply(i); y2.Divide(q); y2 = fPrime2.Multiply(y2); IntegerPolynomial x2 = fPrime2.Multiply(i); x2.Divide(q); x2 = f2.Multiply(x2); y2.Subtract(x2); s.Add(y2); s.ModPositive(q); return(s); }
/** * Resets the engine for signing a message. * @param kp * @throws NtruException if the JRE doesn't implement the specified hash algorithm */ public void initSign(SignatureKeyPair kp) { this.signingKeyPair = kp; try { hashAlg = new SHA256();// MessageDigest.getInstance(param.hashAlg); } catch (Exception e) { throw new NtruException(e.Message); } hashAlg.Reset(); }
/** * Signs a message.<br/> * This is a "one stop" method and does not require <code>initSign</code> to be called. Only the message supplied via * the parameter <code>m</code> is signed, regardless of prior calls to {@link #update(byte[])}. * @param m the message to sign * @param kp a key pair (the public key is needed to ensure there are no signing failures) * @return a signature * @throws NtruException if the JRE doesn't implement the specified hash algorithm */ public byte[] sign(byte[] m, SignatureKeyPair kp) { try { // EESS directly passes the message into the MRGM (message representative // generation method). Since that is inefficient for long messages, we work // with the hash of the message. hashAlg = new SHA256(); byte[] msgHash = hashAlg.ComputeHash(m); return(signHash(msgHash, kp)); } catch (Exception e) { throw new NtruException(e.Message); } }
/** * Generates a new signature key pair. Uses up to <code>B+1</code> threads * if multiple processors are available. * @return a key pair */ public SignatureKeyPair generateKeyPair() { int processors = Environment.ProcessorCount; SignaturePrivateKey priv = new SignaturePrivateKey(param); int B = param.B; //if (processors == 1) // generate all B+1 bases in the current thread for (int k = B; k >= 0; k--) { priv.add(generateBoundedBasis()); } /*else { * List<Future<Basis>> bases = new ArrayList<Future<Basis>>(); * * // start up to processors-1 new threads and generate B bases * int numThreads = Math.min(B, processors-1); * if (numThreads > 0) { * ExecutorService executor = Executors.newFixedThreadPool(numThreads); * for (int k=B-1; k>=0; k--) * bases.add(executor.submit(new BasisGenerationTask())); * executor.shutdown(); * } * * // generate the remaining basis in the current thread * Basis basis0 = generateBoundedBasis(); * * // build the private key * for (Future<Basis> basis: bases) * try { * priv.add(basis.get()); * } catch (Exception e) { * throw new NtruException(e); * } * priv.add(basis0); * }*/ int q = param.q; SignaturePublicKey pub = new SignaturePublicKey(priv.getBasis(0).h, q); priv.getBasis(0).h = null; // remove the public polynomial h from the private key SignatureKeyPair kp = new SignatureKeyPair(priv, pub); return(kp); }
/** * Generates a new signature key pair. Runs in a single thread. * @return a key pair */ public SignatureKeyPair generateKeyPairSingleThread() { SignaturePrivateKey priv = new SignaturePrivateKey(param); SignaturePublicKey pub = null; Basis pubBasis = generateBoundedBasis(); pub = new SignaturePublicKey(pubBasis.h, param.q); pubBasis.h = null; // remove the public polynomial h from the private key priv.add(pubBasis); for (int k = param.B; k > 0; k--) { Basis basis = generateBoundedBasis(); priv.add(basis); } SignatureKeyPair kp = new SignatureKeyPair(priv, pub); return(kp); }
//@Override public override bool Equals(object obj) { if (this == obj) { return(true); } if (obj == null) { return(false); } //if (getClass() != obj.getClass()) // return false; SignatureKeyPair other = (SignatureKeyPair)obj; if (priv == null) { if (other.priv != null) { return(false); } } else if (!priv.Equals(other.priv)) { return(false); } if (pub == null) { if (other.pub != null) { return(false); } } else if (!pub.Equals(other.pub)) { return(false); } return(true); }
private void Encode(SignatureParameters param) { NtruSign ntru = new NtruSign(param); SignatureKeyPair kp = ntru.generateKeyPair(); // encode to byte[] and reconstruct byte[] pub = kp.pub.getEncoded(); byte[] priv = kp.priv.getEncoded(); SignatureKeyPair kp2 = new SignatureKeyPair(new SignaturePrivateKey(priv), new SignaturePublicKey(pub)); Assert.Equals(kp.pub, kp2.pub); Assert.Equals(kp.priv, kp2.priv); // encode to OutputStream and reconstruct MemoryStream bos1 = new MemoryStream(); MemoryStream bos2 = new MemoryStream(); kp.priv.writeTo(bos1); kp.pub.writeTo(bos2); MemoryStream bis1 = new MemoryStream(bos1.ToArray()); MemoryStream bis2 = new MemoryStream(bos2.ToArray()); SignatureKeyPair kp3 = new SignatureKeyPair(new SignaturePrivateKey(bis1), new SignaturePublicKey(bis2)); Assert.Equals(kp.pub, kp3.pub); Assert.Equals(kp.priv, kp3.priv); // Assert.assertNull(kp3.priv.getBasis(0).h); ToDo: why? }
private void SignVerify(SignatureParameters param) { NtruSign ntru = new NtruSign(param); SignatureKeyPair kp = ntru.generateKeyPair(); Assert.Equals(param.B + 1, kp.priv.getNumBases()); Random rng = new Random(); byte[] msg = new byte[10 + rng.Next(1000)]; rng.NextBytes(msg); // sign and verify byte[] s = ntru.sign(msg, kp); bool valid = ntru.verify(msg, s, kp.pub); Assert.True(valid); // altering the signature should make it invalid s[rng.Next(param.N)] += 1; valid = ntru.verify(msg, s, kp.pub); Assert.False(valid); // test that a random signature fails rng.NextBytes(s); valid = ntru.verify(msg, s, kp.pub); Assert.False(valid); // encode, decode keypair, test SignaturePrivateKey priv = new SignaturePrivateKey(kp.priv.getEncoded()); SignaturePublicKey pub = new SignaturePublicKey(kp.pub.getEncoded()); kp = new SignatureKeyPair(priv, pub); s = ntru.sign(msg, kp); valid = ntru.verify(msg, s, kp.pub); Assert.True(valid); // altering the signature should make it invalid s[rng.Next(s.Length)] += 1; valid = ntru.verify(msg, s, kp.pub); Assert.False(valid); // sparse/dense param.sparse = !param.sparse; s = ntru.sign(msg, kp); valid = ntru.verify(msg, s, kp.pub); Assert.True(valid); s[rng.Next(s.Length)] += 1; valid = ntru.verify(msg, s, kp.pub); Assert.False(valid); param.sparse = !param.sparse; // decrease NormBound to force multiple signing attempts SignatureParameters params2 = param.Clone(); params2.normBoundSq *= (float)4.0 / 9; // works for APR2011_439_PROD but may need to be increased for different params params2.signFailTolerance = 10000; ntru = new NtruSign(params2); s = ntru.sign(msg, kp); valid = ntru.verify(msg, s, kp.pub); Assert.True(valid); // test KeyGenAlg.FLOAT (default=RESULTANT) params2 = param.Clone(); param.keyGenAlg = KeyGenAlg.FLOAT; ntru = new NtruSign(param); kp = ntru.generateKeyPair(); s = ntru.sign(msg, kp); valid = ntru.verify(msg, s, kp.pub); Assert.True(valid); s[rng.Next(s.Length)] += 1; valid = ntru.verify(msg, s, kp.pub); Assert.False(valid); }
/** * Generates a new signature key pair. Runs in a single thread. * @return a key pair */ public SignatureKeyPair generateKeyPairSingleThread() { SignaturePrivateKey priv = new SignaturePrivateKey(param); SignaturePublicKey pub = null; Basis pubBasis = generateBoundedBasis(); pub = new SignaturePublicKey(pubBasis.h, param.q); pubBasis.h = null; // remove the public polynomial h from the private key priv.add(pubBasis); for (int k = param.B; k > 0; k--) { Basis basis = generateBoundedBasis(); priv.add(basis); } SignatureKeyPair kp = new SignatureKeyPair(priv, pub); return kp; }
/** * Generates a new signature key pair. Uses up to <code>B+1</code> threads * if multiple processors are available. * @return a key pair */ public SignatureKeyPair generateKeyPair() { int processors = Environment.ProcessorCount; SignaturePrivateKey priv = new SignaturePrivateKey(param); int B = param.B; //if (processors == 1) // generate all B+1 bases in the current thread for (int k = B; k >= 0; k--) priv.add(generateBoundedBasis()); /*else { List<Future<Basis>> bases = new ArrayList<Future<Basis>>(); // start up to processors-1 new threads and generate B bases int numThreads = Math.min(B, processors-1); if (numThreads > 0) { ExecutorService executor = Executors.newFixedThreadPool(numThreads); for (int k=B-1; k>=0; k--) bases.add(executor.submit(new BasisGenerationTask())); executor.shutdown(); } // generate the remaining basis in the current thread Basis basis0 = generateBoundedBasis(); // build the private key for (Future<Basis> basis: bases) try { priv.add(basis.get()); } catch (Exception e) { throw new NtruException(e); } priv.add(basis0); }*/ int q = param.q; SignaturePublicKey pub = new SignaturePublicKey(priv.getBasis(0).h, q); priv.getBasis(0).h = null; // remove the public polynomial h from the private key SignatureKeyPair kp = new SignatureKeyPair(priv, pub); return kp; }
private IntegerPolynomial sign(IntegerPolynomial i, SignatureKeyPair kp) { int N = param.N; int q = param.q; int perturbationBases = param.B; IntegerPolynomial s = new IntegerPolynomial(N); int iLoop = perturbationBases; while (iLoop >= 1) { IPolynomial f = kp.priv.getBasis(iLoop).f; IPolynomial fPrime = kp.priv.getBasis(iLoop).fPrime; IntegerPolynomial y = f.Multiply(i); y.Divide(q); y = fPrime.Multiply(y); IntegerPolynomial x = fPrime.Multiply(i); x.Divide(q); x = f.Multiply(x); IntegerPolynomial si = y; si.Subtract(x); s.Add(si); IntegerPolynomial hi = kp.priv.getBasis(iLoop).h.Clone(); if (iLoop > 1) hi.Subtract(kp.priv.getBasis(iLoop - 1).h); else hi.Subtract(kp.pub.h); i = si.Multiply(hi, q); iLoop--; } IPolynomial f2 = kp.priv.getBasis(0).f; IPolynomial fPrime2 = kp.priv.getBasis(0).fPrime; IntegerPolynomial y2 = f2.Multiply(i); y2.Divide(q); y2 = fPrime2.Multiply(y2); IntegerPolynomial x2 = fPrime2.Multiply(i); x2.Divide(q); x2 = f2.Multiply(x2); y2.Subtract(x2); s.Add(y2); s.ModPositive(q); return s; }
private byte[] signHash(byte[] msgHash, SignatureKeyPair kp) { int r = 0; IntegerPolynomial s; IntegerPolynomial i; do { r++; if (r > param.signFailTolerance) throw new NtruException("Signing failed: too many retries (max=" + param.signFailTolerance + ")"); i = createMsgRep(msgHash, r); s = sign(i, kp); } while (!verify(i, s, kp.pub.h)); byte[] rawSig = s.ToBinary(param.q); MemoryStream sbuf = new MemoryStream(rawSig.Length + 4); BinaryWriter bwr = new BinaryWriter(sbuf); bwr.Write(rawSig); bwr.Write(r); return sbuf.ToArray(); }
/** * Signs a message.<br/> * This is a "one stop" method and does not require <code>initSign</code> to be called. Only the message supplied via * the parameter <code>m</code> is signed, regardless of prior calls to {@link #update(byte[])}. * @param m the message to sign * @param kp a key pair (the public key is needed to ensure there are no signing failures) * @return a signature * @throws NtruException if the JRE doesn't implement the specified hash algorithm */ public byte[] sign(byte[] m, SignatureKeyPair kp) { try { // EESS directly passes the message into the MRGM (message representative // generation method). Since that is inefficient for long messages, we work // with the hash of the message. hashAlg = new SHA256(); byte[] msgHash = hashAlg.ComputeHash(m); return signHash(msgHash, kp); } catch (Exception e) { throw new NtruException(e.Message); } }
private void Encode(SignatureParameters param) { NtruSign ntru = new NtruSign(param); SignatureKeyPair kp = ntru.generateKeyPair(); // encode to byte[] and reconstruct byte[] enc = kp.getEncoded(); SignatureKeyPair kp2 = new SignatureKeyPair(enc); Assert.Equals(kp, kp2); // encode to OutputStream and reconstruct MemoryStream bos = new MemoryStream(); kp.writeTo(bos); MemoryStream bis = new MemoryStream(bos.ToArray()); SignatureKeyPair kp3 = new SignatureKeyPair(bis); Assert.Equals(kp, kp3); }