Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.pqc.crypto.ntru;
  
  
 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;
 import  org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
Encrypts, decrypts data and generates key pairs.
The parameter p is hardcoded to 3.
 
 public class NTRUEngine
     implements AsymmetricBlockCipher
 {
     private boolean forEncryption;
     private NTRUEncryptionParameters params;
     private SecureRandom random;

    
Constructs a new instance with a set of encryption parameters.
 
     public NTRUEngine()
     {
     }
 
     public void init(boolean forEncryptionCipherParameters parameters)
     {
         this. = forEncryption;
         if (forEncryption)
         {
             if (parameters instanceof ParametersWithRandom)
             {
                 ParametersWithRandom p = (ParametersWithRandom)parameters;
 
                 this. = p.getRandom();
                 this. = (NTRUEncryptionPublicKeyParameters)p.getParameters();
             }
             else
             {
                 this. = new SecureRandom();
                 this. = (NTRUEncryptionPublicKeyParameters)parameters;
             }
 
             this. = .getParameters();
         }
         else
         {
             this. = (NTRUEncryptionPrivateKeyParameters)parameters;
             this. = .getParameters();
         }
     }
 
     public int getInputBlockSize()
     {
         return .;
     }
 
     public int getOutputBlockSize()
     {
         return ((. * log2(.)) + 7) / 8;
     }
 
     public byte[] processBlock(byte[] inint inOffint len)
         throws InvalidCipherTextException
     {
         byte[] tmp = new byte[len];
 
         System.arraycopy(ininOfftmp, 0, len);
 
         if ()
         {
             return encrypt(tmp);
         }
         else
         {
             return decrypt(tmp);
         }
     }

    
Encrypts a message.
See P1363.1 section 9.2.2.

Parameters:
m The message to encrypt
pubKey the public key to encrypt the message with
Returns:
the encrypted message
    private byte[] encrypt(byte[] mNTRUEncryptionPublicKeyParameters pubKey)
    {
        IntegerPolynomial pub = pubKey.h;
        int N = .;
        int q = .;
        int maxLenBytes = .;
        int db = .;
        int bufferLenBits = .;
        int dm0 = .;
        int pkLen = .;
        int minCallsMask = .;
        boolean hashSeed = .;
        byte[] oid = .;
        int l = m.length;
        if (maxLenBytes > 255)
        {
            throw new IllegalArgumentException("llen values bigger than 1 are not supported");
        }
        if (l > maxLenBytes)
        {
            throw new DataLengthException("Message too long: " + l + ">" + maxLenBytes);
        }
        while (true)
        {
            // M = b|octL|m|p0
            byte[] b = new byte[db / 8];
            .nextBytes(b);
            byte[] p0 = new byte[maxLenBytes + 1 - l];
            byte[] M = new byte[bufferLenBits / 8];
            System.arraycopy(b, 0, M, 0, b.length);
            M[b.length] = (byte)l;
            System.arraycopy(m, 0, Mb.length + 1, m.length);
            System.arraycopy(p0, 0, Mb.length + 1 + m.lengthp0.length);
            IntegerPolynomial mTrin = IntegerPolynomial.fromBinary3Sves(MN);
            // sData = OID|m|b|hTrunc
            byte[] bh = pub.toBinary(q);
            byte[] hTrunc = copyOf(bhpkLen / 8);
            byte[] sData = buildSData(oidmlbhTrunc);
            Polynomial r = generateBlindingPoly(sDataM);
            IntegerPolynomial R = r.mult(pubq);
            IntegerPolynomial R4 = (IntegerPolynomial)R.clone();
            R4.modPositive(4);
            byte[] oR4 = R4.toBinary(4);
            IntegerPolynomial mask = MGF(oR4NminCallsMaskhashSeed);
            mTrin.add(mask);
            mTrin.mod3();
            if (mTrin.count(-1) < dm0)
            {
                continue;
            }
            if (mTrin.count(0) < dm0)
            {
                continue;
            }
            if (mTrin.count(1) < dm0)
            {
                continue;
            }
            R.add(mTrinq);
            R.ensurePositive(q);
            return R.toBinary(q);
        }
    }
    private byte[] buildSData(byte[] oidbyte[] mint lbyte[] bbyte[] hTrunc)
    {
        byte[] sData = new byte[oid.length + l + b.length + hTrunc.length];
        System.arraycopy(oid, 0, sData, 0, oid.length);
        System.arraycopy(m, 0, sDataoid.lengthm.length);
        System.arraycopy(b, 0, sDataoid.length + m.lengthb.length);
        System.arraycopy(hTrunc, 0, sDataoid.length + m.length + b.lengthhTrunc.length);
        return sData;
    }
    protected IntegerPolynomial encrypt(IntegerPolynomial m, TernaryPolynomial r, IntegerPolynomial pubKey)
    {
        IntegerPolynomial e = r.mult(pubKey.);
        e.add(m.);
        e.ensurePositive(.);
        return e;
    }

    
Deterministically generates a blinding polynomial from a seed and a message representative.

Parameters:
seed
M message representative
Returns:
a blinding polynomial
    private Polynomial generateBlindingPoly(byte[] seedbyte[] M)
    {
        IndexGenerator ig = new IndexGenerator(seed);
        {
            SparseTernaryPolynomial r1 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig.));
            SparseTernaryPolynomial r2 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig.));
            SparseTernaryPolynomial r3 = new SparseTernaryPolynomial(generateBlindingCoeffs(ig.));
            return new ProductFormPolynomial(r1r2r3);
        }
        else
        {
            int dr = .;
            boolean sparse = .;
            int[] r = generateBlindingCoeffs(igdr);
            if (sparse)
            {
                return new SparseTernaryPolynomial(r);
            }
            else
            {
                return new DenseTernaryPolynomial(r);
            }
        }
    }

    
Generates an int array containing dr elements equal to 1 and dr elements equal to -1 using an index generator.

Parameters:
ig an index generator
dr number of ones / negative ones
Returns:
an array containing numbers between -1 and 1
    private int[] generateBlindingCoeffs(IndexGenerator igint dr)
    {
        int N = .;
        int[] r = new int[N];
        for (int coeff = -1; coeff <= 1; coeff += 2)
        {
            int t = 0;
            while (t < dr)
            {
                int i = ig.nextIndex();
                if (r[i] == 0)
                {
                    r[i] = coeff;
                    t++;
                }
            }
        }
        return r;
    }

    
An implementation of MGF-TP-1 from P1363.1 section 8.4.1.1.

Parameters:
seed
N
minCallsR
hashSeed whether to hash the seed
Returns:
    private IntegerPolynomial MGF(byte[] seedint Nint minCallsRboolean hashSeed)
    {
        Digest hashAlg = .;
        int hashLen = hashAlg.getDigestSize();
        byte[] buf = new byte[minCallsR * hashLen];
        byte[] Z = hashSeed ? calcHash(hashAlgseed) : seed;
        int counter = 0;
        while (counter < minCallsR)
        {
            hashAlg.update(Z, 0, Z.length);
            putInt(hashAlgcounter);
            byte[] hash = calcHash(hashAlg);
            System.arraycopy(hash, 0, bufcounter * hashLenhashLen);
            counter++;
        }
        IntegerPolynomial i = new IntegerPolynomial(N);
        while (true)
        {
            int cur = 0;
            for (int index = 0; index != buf.lengthindex++)
            {
                int O = (int)buf[index] & 0xFF;
                if (O >= 243)   // 243 = 3^5
                {
                    continue;
                }
                for (int terIdx = 0; terIdx < 4; terIdx++)
                {
                    int rem3 = O % 3;
                    i.coeffs[cur] = rem3 - 1;
                    cur++;
                    if (cur == N)
                    {
                        return i;
                    }
                    O = (O - rem3) / 3;
                }
                i.coeffs[cur] = O - 1;
                cur++;
                if (cur == N)
                {
                    return i;
                }
            }
            if (cur >= N)
            {
                return i;
            }
            hashAlg.update(Z, 0, Z.length);
            putInt(hashAlgcounter);
            byte[] hash = calcHash(hashAlg);
            buf = hash;
            counter++;
        }
    }
    private void putInt(Digest hashAlgint counter)
    {
        hashAlg.update((byte)(counter >> 24));
        hashAlg.update((byte)(counter >> 16));
        hashAlg.update((byte)(counter >> 8));
        hashAlg.update((byte)counter);
    }
    private byte[] calcHash(Digest hashAlg)
    {
        byte[] tmp = new byte[hashAlg.getDigestSize()];
        hashAlg.doFinal(tmp, 0);
        return tmp;
    }
    private byte[] calcHash(Digest hashAlgbyte[] input)
    {
        byte[] tmp = new byte[hashAlg.getDigestSize()];
        hashAlg.update(input, 0, input.length);
        hashAlg.doFinal(tmp, 0);
        return tmp;
    }
    
Decrypts a message.
See P1363.1 section 9.2.3.

Parameters:
data The message to decrypt
privKey the corresponding private key
Returns:
the decrypted message
Throws:
InvalidCipherTextException if the encrypted data is invalid, or maxLenBytes is greater than 255
    private byte[] decrypt(byte[] dataNTRUEncryptionPrivateKeyParameters privKey)
        throws InvalidCipherTextException
    {
        Polynomial priv_t = privKey.t;
        IntegerPolynomial priv_fp = privKey.fp;
        IntegerPolynomial pub = privKey.h;
        int N = .;
        int q = .;
        int db = .;
        int maxMsgLenBytes = .;
        int dm0 = .;
        int pkLen = .;
        int minCallsMask = .;
        boolean hashSeed = .;
        byte[] oid = .;
        if (maxMsgLenBytes > 255)
        {
            throw new DataLengthException("maxMsgLenBytes values bigger than 255 are not supported");
        }
        int bLen = db / 8;
        IntegerPolynomial e = IntegerPolynomial.fromBinary(dataNq);
        IntegerPolynomial ci = decrypt(epriv_tpriv_fp);
        if (ci.count(-1) < dm0)
        {
            throw new InvalidCipherTextException("Less than dm0 coefficients equal -1");
        }
        if (ci.count(0) < dm0)
        {
            throw new InvalidCipherTextException("Less than dm0 coefficients equal 0");
        }
        if (ci.count(1) < dm0)
        {
            throw new InvalidCipherTextException("Less than dm0 coefficients equal 1");
        }
        IntegerPolynomial cR = (IntegerPolynomial)e.clone();
        cR.sub(ci);
        cR.modPositive(q);
        IntegerPolynomial cR4 = (IntegerPolynomial)cR.clone();
        cR4.modPositive(4);
        byte[] coR4 = cR4.toBinary(4);
        IntegerPolynomial mask = MGF(coR4NminCallsMaskhashSeed);
        IntegerPolynomial cMTrin = ci;
        cMTrin.sub(mask);
        cMTrin.mod3();
        byte[] cM = cMTrin.toBinary3Sves();
        byte[] cb = new byte[bLen];
        System.arraycopy(cM, 0, cb, 0, bLen);
        int cl = cM[bLen] & 0xFF;   // llen=1, so read one byte
        if (cl > maxMsgLenBytes)
        {
            throw new InvalidCipherTextException("Message too long: " + cl + ">" + maxMsgLenBytes);
        }
        byte[] cm = new byte[cl];
        System.arraycopy(cMbLen + 1, cm, 0, cl);
        byte[] p0 = new byte[cM.length - (bLen + 1 + cl)];
        System.arraycopy(cMbLen + 1 + clp0, 0, p0.length);
        if (!Arrays.constantTimeAreEqual(p0new byte[p0.length]))
        {
           throw new InvalidCipherTextException("The message is not followed by zeroes");
        }
        // sData = OID|m|b|hTrunc
        byte[] bh = pub.toBinary(q);
        byte[] hTrunc = copyOf(bhpkLen / 8);
        byte[] sData = buildSData(oidcmclcbhTrunc);
        Polynomial cr = generateBlindingPoly(sDatacm);
        IntegerPolynomial cRPrime = cr.mult(pub);
        cRPrime.modPositive(q);
        if (!cRPrime.equals(cR))
        {
            throw new InvalidCipherTextException("Invalid message encoding");
        }
        return cm;
    }

    

Parameters:
e
priv_t a polynomial such that if fastFp=true, f=1+3*priv_t; otherwise, f=priv_t
priv_fp
Returns:
    protected IntegerPolynomial decrypt(IntegerPolynomial e, Polynomial priv_t, IntegerPolynomial priv_fp)
    {
        IntegerPolynomial a;
        if (.)
        {
            a = priv_t.mult(e.);
            a.mult(3);
            a.add(e);
        }
        else
        {
            a = priv_t.mult(e.);
        }
        a.center0(.);
        a.mod3();
        IntegerPolynomial c = . ? a : new DenseTernaryPolynomial(a).mult(priv_fp, 3);
        c.center0(3);
        return c;
    }
    private byte[] copyOf(byte[] srcint len)
    {
        byte[] tmp = new byte[len];
        System.arraycopy(src, 0, tmp, 0, len < src.length ? len : src.length);
        return tmp;
    }
    private int log2(int value)
    {
        if (value == 2048)
        {
            return 11;
        }
        throw new IllegalStateException("log2 not fully implemented");
    }
New to GrepCode? Check out our FAQ X