org.bouncycastle.pqc.crypto.ntru.NTRUSampling Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.pqc.crypto.ntru;
import org.bouncycastle.pqc.math.ntru.HPSPolynomial;
import org.bouncycastle.pqc.math.ntru.HRSSPolynomial;
import org.bouncycastle.pqc.math.ntru.Polynomial;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHPSParameterSet;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHRSSParameterSet;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUParameterSet;
import org.bouncycastle.util.Arrays;
/**
* NTRU sampling.
*
* @see NTRU specification section 1.10
*/
class NTRUSampling
{
private final NTRUParameterSet params;
/**
* Constructor
*
* @param params an NTRU parameter set
*/
public NTRUSampling(NTRUParameterSet params)
{
this.params = params;
}
/**
* @param uniformBytes random byte array
* @return a pair of polynomial {@code f} and {@code g}
* @see NTRU specification section 1.10.1
*/
public PolynomialPair sampleFg(byte[] uniformBytes)
{
// assert uniformBytes.length == this.params.sampleFgBytes();
if (this.params instanceof NTRUHRSSParameterSet)
{
HRSSPolynomial f = this.sampleIidPlus(Arrays.copyOfRange(uniformBytes, 0, this.params.sampleIidBytes()));
// len(uniformBytes) = sampleIidBytes * 2
HRSSPolynomial g = this.sampleIidPlus(Arrays.copyOfRange(uniformBytes, this.params.sampleIidBytes(), uniformBytes.length));
return new PolynomialPair(f, g);
}
else if (this.params instanceof NTRUHPSParameterSet)
{
HPSPolynomial f = (HPSPolynomial)this.sampleIid(Arrays.copyOfRange(uniformBytes, 0, this.params.sampleIidBytes()));
// len(uniformBytes) = sampleIidBytes + sampleFixedTypeBytes
HPSPolynomial g = this.sampleFixedType(Arrays.copyOfRange(uniformBytes, this.params.sampleIidBytes(), uniformBytes.length));
return new PolynomialPair(f, g);
}
else
{
throw new IllegalArgumentException("Invalid polynomial type");
}
}
/**
* @param uniformBytes random byte array
* @return a pair of polynomial {@code r} and {@code m}
* @see NTRU specification section 1.10.2
*/
public PolynomialPair sampleRm(byte[] uniformBytes)
{
// assert uniformBytes.length == this.params.sampleRmBytes();
if (this.params instanceof NTRUHRSSParameterSet)
{
HRSSPolynomial r = (HRSSPolynomial)this.sampleIid(Arrays.copyOfRange(uniformBytes, 0, this.params.sampleIidBytes()));
HRSSPolynomial m = (HRSSPolynomial)this.sampleIid(Arrays.copyOfRange(uniformBytes, this.params.sampleIidBytes(), uniformBytes.length));
return new PolynomialPair(r, m);
}
else if (this.params instanceof NTRUHPSParameterSet)
{
HPSPolynomial r = (HPSPolynomial)this.sampleIid(Arrays.copyOfRange(uniformBytes, 0, this.params.sampleIidBytes()));
HPSPolynomial m = this.sampleFixedType(Arrays.copyOfRange(uniformBytes, this.params.sampleIidBytes(), uniformBytes.length));
return new PolynomialPair(r, m);
}
else
{
throw new IllegalArgumentException("Invalid polynomial type");
}
}
/**
* @param uniformBytes random byte array
* @return a ternary polynomial
* @see NTRU specification section 1.10.3
*/
public Polynomial sampleIid(byte[] uniformBytes)
{
// assert uniformBytes.length == this.params.sampleIidBytes();
Polynomial r = this.params.createPolynomial();
for (int i = 0; i < this.params.n() - 1; i++)
{
r.coeffs[i] = (short)mod3(uniformBytes[i] & 0xff);
}
r.coeffs[this.params.n() - 1] = 0;
return r;
}
/**
* @param uniformBytes random byte array
* @return a ternary polynomial with exactly q/16 − 1 coefficients equal to 1 and q/16 − 1 coefficient equal to −1
* @see NTRU specification section 1.10.5
*/
public HPSPolynomial sampleFixedType(byte[] uniformBytes)
{
// assert uniformBytes.length == this.params.sampleFixedTypeBytes();
int n = this.params.n();
int weight = ((NTRUHPSParameterSet)this.params).weight();
HPSPolynomial r = new HPSPolynomial((NTRUHPSParameterSet)this.params);
int[] s = new int[n - 1];
int i;
for (i = 0; i < (n - 1) / 4; i++)
{
s[4 * i + 0] = ((uniformBytes[15 * i + 0] & 0xff) << 2) + ((uniformBytes[15 * i + 1] & 0xff) << 10) + ((uniformBytes[15 * i + 2] & 0xff) << 18) + ((uniformBytes[15 * i + 3] & 0xff) << 26);
s[4 * i + 1] = (((uniformBytes[15 + i * 3] & 0xff) & 0xc0) >> 4) + ((uniformBytes[15 * i + 4] & 0xff) << 4) + ((uniformBytes[15 * i + 5] & 0xff) << 12) + ((uniformBytes[15 * i + 6] & 0xff) << 20) + ((uniformBytes[15 * i + 7] & 0xff) << 28);
s[4 * i + 2] = (((uniformBytes[15 + i * 7] & 0xff) & 0xf0) >> 2) + ((uniformBytes[15 * i + 8] & 0xff) << 6) + ((uniformBytes[15 * i + 9] & 0xff) << 14) + ((uniformBytes[15 * i + 10] & 0xff) << 22) + ((uniformBytes[15 * i + 11] & 0xff) << 30);
s[4 * i + 3] = ((uniformBytes[15 * i + 11] & 0xff) & 0xfc) + ((uniformBytes[15 * i + 12] & 0xff) << 8) + ((uniformBytes[15 * i + 13] & 0xff) << 16) + ((uniformBytes[15 * i + 14] & 0xff) << 24);
}
// (N-1) = 2 mod 4
if (n - 1 > ((n - 1) / 4) * 4)
{
i = (n - 1) / 4;
s[4 * i + 0] = ((uniformBytes[15 * i + 0] & 0xff) << 2) + ((uniformBytes[15 * i + 1] & 0xff) << 10) + ((uniformBytes[15 * i + 2] & 0xff) << 18) + ((uniformBytes[15 * i + 3] & 0xff) << 26);
s[4 * i + 1] = (((uniformBytes[15 + i * 3] & 0xff) & 0xc0) >> 4) + ((uniformBytes[15 * i + 4] & 0xff) << 4) + ((uniformBytes[15 * i + 5] & 0xff) << 12) + ((uniformBytes[15 * i + 6] & 0xff) << 20) + ((uniformBytes[15 * i + 7] & 0xff) << 28);
}
for (i = 0; i < weight / 2; i++)
{
s[i] |= 1;
}
for (i = weight / 2; i < weight; i++)
{
s[i] |= 2;
}
java.util.Arrays.sort(s);
for (i = 0; i < n - 1; i++)
{
r.coeffs[i] = (short)(s[i] & 3);
}
r.coeffs[n - 1] = 0;
return r;
}
/**
* @param uniformBytes random byte array
* @return a ternary polynomial that satisfies the non-negative correlation property
* @see NTRU specification section 1.10.4
*/
public HRSSPolynomial sampleIidPlus(byte[] uniformBytes)
{
// assert uniformBytes.length == this.params.sampleIidBytes();
int n = this.params.n();
int i;
short s = 0;
HRSSPolynomial r = (HRSSPolynomial)sampleIid(uniformBytes);
/* Map {0,1,2} -> {0, 1, 2^16 - 1} */
for (i = 0; i < n - 1; i++)
{
r.coeffs[i] = (short)(r.coeffs[i] | (-(r.coeffs[i] >>> 1)));
}
/* s = . (r[n-1] = 0) */
for (i = 0; i < n - 1; i++)
{
s += (short)(r.coeffs[i + 1] * r.coeffs[i]);
}
/* Extract sign of s (sign(0) = 1) */
s = (short)(1 | (-((s & 0xffff) >>> 15)));
for (i = 0; i < n - 1; i += 2)
{
r.coeffs[i] = (short)(s * r.coeffs[i]);
}
/* Map {0,1,2^16-1} -> {0, 1, 2} */
for (i = 0; i < n - 1; i++)
{
r.coeffs[i] = (short)(3 & ((r.coeffs[i] & 0xffff) ^ ((r.coeffs[i] & 0xffff) >>> 15)));
}
return r;
}
private static int mod3(int a)
{
return a % 3;
}
}