package org.spongycastle.crypto.params; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.spongycastle.math.ntru.polynomial.DenseTernaryPolynomial; import org.spongycastle.math.ntru.polynomial.IntegerPolynomial; import org.spongycastle.math.ntru.polynomial.Polynomial; import org.spongycastle.math.ntru.polynomial.ProductFormPolynomial; import org.spongycastle.math.ntru.polynomial.SparseTernaryPolynomial; /** * A NtruEncrypt private key is essentially a polynomial named <code>f</code> * which takes different forms depending on whether product-form polynomials are used, * and on <code>fastP</code><br/> * The inverse of <code>f</code> modulo <code>p</code> is precomputed on initialization. */ public class NTRUEncryptionPrivateKeyParameters extends NTRUEncryptionKeyParameters { public Polynomial t; public IntegerPolynomial fp; public IntegerPolynomial h; /** * Constructs a new private key from a polynomial * * @param h the public polynomial for the key. * @param t the polynomial which determines the key: if <code>fastFp=true</code>, <code>f=1+3t</code>; otherwise, <code>f=t</code> * @param fp the inverse of <code>f</code> * @param params the NtruEncrypt parameters to use */ public NTRUEncryptionPrivateKeyParameters(IntegerPolynomial h, Polynomial t, IntegerPolynomial fp, NTRUEncryptionParameters params) { super(true, params); this.h = h; this.t = t; this.fp = fp; } /** * Converts a byte array to a polynomial <code>f</code> and constructs a new private key * * @param b an encoded polynomial * @param params the NtruEncrypt parameters to use * @see #getEncoded() */ public NTRUEncryptionPrivateKeyParameters(byte[] b, NTRUEncryptionParameters params) throws IOException { this(new ByteArrayInputStream(b), params); } /** * Reads a polynomial <code>f</code> from an input stream and constructs a new private key * * @param is an input stream * @param params the NtruEncrypt parameters to use * @see #writeTo(OutputStream) */ public NTRUEncryptionPrivateKeyParameters(InputStream is, NTRUEncryptionParameters params) throws IOException { super(true, params); if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT) { int N = params.N; int df1 = params.df1; int df2 = params.df2; int df3Ones = params.df3; int df3NegOnes = params.fastFp ? params.df3 : params.df3 - 1; h = IntegerPolynomial.fromBinary(is, params.N, params.q); t = ProductFormPolynomial.fromBinary(is, N, df1, df2, df3Ones, df3NegOnes); } else { h = IntegerPolynomial.fromBinary(is, params.N, params.q); IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, params.N); t = params.sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt); } init(); } /** * Initializes <code>fp</code> from t. */ private void init() { if (params.fastFp) { fp = new IntegerPolynomial(params.N); fp.coeffs[0] = 1; } else { fp = t.toIntegerPolynomial().invertF3(); } } /** * Converts the key to a byte array * * @return the encoded key * @see #NTRUEncryptionPrivateKeyParameters(byte[], NTRUEncryptionParameters) */ public byte[] getEncoded() { byte[] hBytes = h.toBinary(params.q); byte[] tBytes; if (t instanceof ProductFormPolynomial) { tBytes = ((ProductFormPolynomial)t).toBinary(); } else { tBytes = t.toIntegerPolynomial().toBinary3Tight(); } byte[] res = new byte[hBytes.length + tBytes.length]; System.arraycopy(hBytes, 0, res, 0, hBytes.length); System.arraycopy(tBytes, 0, res, hBytes.length, tBytes.length); return res; } /** * Writes the key to an output stream * * @param os an output stream * @throws IOException * @see #NTRUEncryptionPrivateKeyParameters(InputStream, NTRUEncryptionParameters) */ public void writeTo(OutputStream os) throws IOException { os.write(getEncoded()); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((params == null) ? 0 : params.hashCode()); result = prime * result + ((t == null) ? 0 : t.hashCode()); result = prime * result + ((h == null) ? 0 : h.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof NTRUEncryptionPrivateKeyParameters)) { return false; } NTRUEncryptionPrivateKeyParameters other = (NTRUEncryptionPrivateKeyParameters)obj; if (params == null) { if (other.params != null) { return false; } } else if (!params.equals(other.params)) { return false; } if (t == null) { if (other.t != null) { return false; } } else if (!t.equals(other.t)) { return false; } if (!h.equals(other.h)) { return false; } return true; } }