package org.bouncycastle.pqc.crypto.ntru; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.DecimalFormat; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA256Digest; import org.bouncycastle.crypto.digests.SHA512Digest; /** * A set of parameters for NtruSign. Several predefined parameter sets are available and new ones can be created as well. */ public class NTRUSigningParameters implements Cloneable { public int N; public int q; public int d, d1, d2, d3, B; double beta; public double betaSq; double normBound; public double normBoundSq; public int signFailTolerance = 100; int bitsF = 6; // max #bits needed to encode one coefficient of the polynomial F public Digest hashAlg; /** * Constructs a parameter set that uses ternary private keys (i.e. <code>polyType=SIMPLE</code>). * * @param N number of polynomial coefficients * @param q modulus * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code> * @param B number of perturbations * @param beta balancing factor for the transpose lattice * @param normBound maximum norm for valid signatures * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method. */ public NTRUSigningParameters(int N, int q, int d, int B, double beta, double normBound, Digest hashAlg) { this.N = N; this.q = q; this.d = d; this.B = B; this.beta = beta; this.normBound = normBound; this.hashAlg = hashAlg; init(); } /** * Constructs a parameter set that uses product-form private keys (i.e. <code>polyType=PRODUCT</code>). * * @param N number of polynomial coefficients * @param q modulus * @param d1 number of -1's in the private polynomials <code>f</code> and <code>g</code> * @param d2 number of -1's in the private polynomials <code>f</code> and <code>g</code> * @param d3 number of -1's in the private polynomials <code>f</code> and <code>g</code> * @param B number of perturbations * @param beta balancing factor for the transpose lattice * @param normBound maximum norm for valid signatures * @param keyNormBound maximum norm for the ploynomials <code>F</code> and <code>G</code> * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method. */ public NTRUSigningParameters(int N, int q, int d1, int d2, int d3, int B, double beta, double normBound, double keyNormBound, Digest hashAlg) { this.N = N; this.q = q; this.d1 = d1; this.d2 = d2; this.d3 = d3; this.B = B; this.beta = beta; this.normBound = normBound; this.hashAlg = hashAlg; init(); } private void init() { betaSq = beta * beta; normBoundSq = normBound * normBound; } /** * Reads a parameter set from an input stream. * * @param is an input stream * @throws IOException */ public NTRUSigningParameters(InputStream is) throws IOException { DataInputStream dis = new DataInputStream(is); N = dis.readInt(); q = dis.readInt(); d = dis.readInt(); d1 = dis.readInt(); d2 = dis.readInt(); d3 = dis.readInt(); B = dis.readInt(); beta = dis.readDouble(); normBound = dis.readDouble(); signFailTolerance = dis.readInt(); bitsF = dis.readInt(); String alg = dis.readUTF(); if ("SHA-512".equals(alg)) { hashAlg = new SHA512Digest(); } else if ("SHA-256".equals(alg)) { hashAlg = new SHA256Digest(); } init(); } /** * Writes the parameter set to an output stream * * @param os an output stream * @throws IOException */ public void writeTo(OutputStream os) throws IOException { DataOutputStream dos = new DataOutputStream(os); dos.writeInt(N); dos.writeInt(q); dos.writeInt(d); dos.writeInt(d1); dos.writeInt(d2); dos.writeInt(d3); dos.writeInt(B); dos.writeDouble(beta); dos.writeDouble(normBound); dos.writeInt(signFailTolerance); dos.writeInt(bitsF); dos.writeUTF(hashAlg.getAlgorithmName()); } public NTRUSigningParameters clone() { return new NTRUSigningParameters(N, q, d, B, beta, normBound, hashAlg); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + B; result = prime * result + N; long temp; temp = Double.doubleToLongBits(beta); result = prime * result + (int)(temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(betaSq); result = prime * result + (int)(temp ^ (temp >>> 32)); result = prime * result + bitsF; result = prime * result + d; result = prime * result + d1; result = prime * result + d2; result = prime * result + d3; result = prime * result + ((hashAlg == null) ? 0 : hashAlg.getAlgorithmName().hashCode()); temp = Double.doubleToLongBits(normBound); result = prime * result + (int)(temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(normBoundSq); result = prime * result + (int)(temp ^ (temp >>> 32)); result = prime * result + q; result = prime * result + signFailTolerance; return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof NTRUSigningParameters)) { return false; } NTRUSigningParameters other = (NTRUSigningParameters)obj; if (B != other.B) { return false; } if (N != other.N) { return false; } if (Double.doubleToLongBits(beta) != Double.doubleToLongBits(other.beta)) { return false; } if (Double.doubleToLongBits(betaSq) != Double.doubleToLongBits(other.betaSq)) { return false; } if (bitsF != other.bitsF) { return false; } if (d != other.d) { return false; } if (d1 != other.d1) { return false; } if (d2 != other.d2) { return false; } if (d3 != other.d3) { return false; } if (hashAlg == null) { if (other.hashAlg != null) { return false; } } else if (!hashAlg.getAlgorithmName().equals(other.hashAlg.getAlgorithmName())) { return false; } if (Double.doubleToLongBits(normBound) != Double.doubleToLongBits(other.normBound)) { return false; } if (Double.doubleToLongBits(normBoundSq) != Double.doubleToLongBits(other.normBoundSq)) { return false; } if (q != other.q) { return false; } if (signFailTolerance != other.signFailTolerance) { return false; } return true; } public String toString() { DecimalFormat format = new DecimalFormat("0.00"); StringBuilder output = new StringBuilder("SignatureParameters(N=" + N + " q=" + q); output.append(" B=" + B + " beta=" + format.format(beta) + " normBound=" + format.format(normBound) + " hashAlg=" + hashAlg + ")"); return output.toString(); } }