diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java new file mode 100644 index 0000000..451422e --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUSigningPrivateKeyParameters.java @@ -0,0 +1,388 @@ +package org.bouncycastle.pqc.crypto.ntru; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial; +import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial; +import org.bouncycastle.pqc.math.ntru.polynomial.Polynomial; +import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial; +import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial; + +/** + * A NtruSign private key comprises one or more {@link NTRUSigningPrivateKeyParameters.Basis} of three polynomials each, + * except the zeroth basis for which <code>h</code> is undefined. + */ +public class NTRUSigningPrivateKeyParameters + extends AsymmetricKeyParameter +{ + private List<Basis> bases; + private NTRUSigningPublicKeyParameters publicKey; + + /** + * Constructs a new private key from a byte array + * + * @param b an encoded private key + * @param params the NtruSign parameters to use + */ + public NTRUSigningPrivateKeyParameters(byte[] b, NTRUSigningKeyGenerationParameters params) + throws IOException + { + this(new ByteArrayInputStream(b), params); + } + + /** + * Constructs a new private key from an input stream + * + * @param is an input stream + * @param params the NtruSign parameters to use + */ + public NTRUSigningPrivateKeyParameters(InputStream is, NTRUSigningKeyGenerationParameters params) + throws IOException + { + super(true); + bases = new ArrayList<Basis>(); + for (int i = 0; i <= params.B; i++) + // include a public key h[i] in all bases except for the first one + { + add(new Basis(is, params, i != 0)); + } + publicKey = new NTRUSigningPublicKeyParameters(is, params.getSigningParameters()); + } + + public NTRUSigningPrivateKeyParameters(List<Basis> bases, NTRUSigningPublicKeyParameters publicKey) + { + super(true); + this.bases = new ArrayList<Basis>(bases); + this.publicKey = publicKey; + } + + /** + * Adds a basis to the key. + * + * @param b a NtruSign basis + */ + private void add(Basis b) + { + bases.add(b); + } + + /** + * Returns the <code>i</code>-th basis + * + * @param i the index + * @return the basis at index <code>i</code> + */ + public Basis getBasis(int i) + { + return bases.get(i); + } + + public NTRUSigningPublicKeyParameters getPublicKey() + { + return publicKey; + } + + /** + * Converts the key to a byte array + * + * @return the encoded key + */ + public byte[] getEncoded() + throws IOException + { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + for (int i = 0; i < bases.size(); i++) + { + // all bases except for the first one contain a public key + bases.get(i).encode(os, i != 0); + } + + os.write(publicKey.getEncoded()); + + return os.toByteArray(); + } + + /** + * Writes the key to an output stream + * + * @param os an output stream + * @throws IOException + */ + public void writeTo(OutputStream os) + throws IOException + { + os.write(getEncoded()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result; + if (bases==null) return result; + result += bases.hashCode(); + for (Basis basis : bases) + { + result += basis.hashCode(); + } + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + NTRUSigningPrivateKeyParameters other = (NTRUSigningPrivateKeyParameters)obj; + if ((bases == null) != (other.bases == null)) + { + return false; + } + if (bases == null) + { + return true; + } + if (bases.size() != other.bases.size()) + { + return false; + } + for (int i = 0; i < bases.size(); i++) + { + Basis basis1 = bases.get(i); + Basis basis2 = other.bases.get(i); + if (!basis1.f.equals(basis2.f)) + { + return false; + } + if (!basis1.fPrime.equals(basis2.fPrime)) + { + return false; + } + if (i != 0 && !basis1.h.equals(basis2.h)) // don't compare h for the 0th basis + { + return false; + } + if (!basis1.params.equals(basis2.params)) + { + return false; + } + } + return true; + } + + /** + * A NtruSign basis. Contains three polynomials <code>f, f', h</code>. + */ + public static class Basis + { + public Polynomial f; + public Polynomial fPrime; + public IntegerPolynomial h; + NTRUSigningKeyGenerationParameters params; + + /** + * Constructs a new basis from polynomials <code>f, f', h</code>. + * + * @param f + * @param fPrime + * @param h + * @param params NtruSign parameters + */ + protected Basis(Polynomial f, Polynomial fPrime, IntegerPolynomial h, NTRUSigningKeyGenerationParameters params) + { + this.f = f; + this.fPrime = fPrime; + this.h = h; + this.params = params; + } + + /** + * Reads a basis from an input stream and constructs a new basis. + * + * @param is an input stream + * @param params NtruSign parameters + * @param include_h whether to read the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>) + */ + Basis(InputStream is, NTRUSigningKeyGenerationParameters params, boolean include_h) + throws IOException + { + int N = params.N; + int q = params.q; + int d1 = params.d1; + int d2 = params.d2; + int d3 = params.d3; + boolean sparse = params.sparse; + this.params = params; + + if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT) + { + f = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3); + } + else + { + IntegerPolynomial fInt = IntegerPolynomial.fromBinary3Tight(is, N); + f = sparse ? new SparseTernaryPolynomial(fInt) : new DenseTernaryPolynomial(fInt); + } + + if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD) + { + IntegerPolynomial fPrimeInt = IntegerPolynomial.fromBinary(is, N, q); + for (int i = 0; i < fPrimeInt.coeffs.length; i++) + { + fPrimeInt.coeffs[i] -= q / 2; + } + fPrime = fPrimeInt; + } + else if (params.polyType == NTRUParameters.TERNARY_POLYNOMIAL_TYPE_PRODUCT) + { + fPrime = ProductFormPolynomial.fromBinary(is, N, d1, d2, d3 + 1, d3); + } + else + { + fPrime = IntegerPolynomial.fromBinary3Tight(is, N); + } + + if (include_h) + { + h = IntegerPolynomial.fromBinary(is, N, q); + } + } + + /** + * Writes the basis to an output stream + * + * @param os an output stream + * @param include_h whether to write the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>) + * @throws IOException + */ + void encode(OutputStream os, boolean include_h) + throws IOException + { + int q = params.q; + + os.write(getEncoded(f)); + if (params.basisType == NTRUSigningKeyGenerationParameters.BASIS_TYPE_STANDARD) + { + IntegerPolynomial fPrimeInt = fPrime.toIntegerPolynomial(); + for (int i = 0; i < fPrimeInt.coeffs.length; i++) + { + fPrimeInt.coeffs[i] += q / 2; + } + os.write(fPrimeInt.toBinary(q)); + } + else + { + os.write(getEncoded(fPrime)); + } + if (include_h) + { + os.write(h.toBinary(q)); + } + } + + private byte[] getEncoded(Polynomial p) + { + if (p instanceof ProductFormPolynomial) + { + return ((ProductFormPolynomial)p).toBinary(); + } + else + { + return p.toIntegerPolynomial().toBinary3Tight(); + } + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((f == null) ? 0 : f.hashCode()); + result = prime * result + ((fPrime == null) ? 0 : fPrime.hashCode()); + result = prime * result + ((h == null) ? 0 : h.hashCode()); + result = prime * result + ((params == null) ? 0 : params.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof Basis)) + { + return false; + } + Basis other = (Basis)obj; + if (f == null) + { + if (other.f != null) + { + return false; + } + } + else if (!f.equals(other.f)) + { + return false; + } + if (fPrime == null) + { + if (other.fPrime != null) + { + return false; + } + } + else if (!fPrime.equals(other.fPrime)) + { + return false; + } + if (h == null) + { + if (other.h != null) + { + return false; + } + } + else if (!h.equals(other.h)) + { + return false; + } + if (params == null) + { + if (other.params != null) + { + return false; + } + } + else if (!params.equals(other.params)) + { + return false; + } + return true; + } + } +} |