@@ -22,17 +22,16 @@ class HQCEngine
2222 private final int fft ;
2323 private final int mulParam ;
2424 private final int N_BYTE ;
25- private final int K_BYTE ;
2625 private final int N1N2_BYTE_64 ;
2726 private final int N1N2_BYTE ;
2827 private final int [] generatorPoly ;
29- private final int N_MU ;
28+ private final int nMu ;
3029 private final int pkSize ;
3130 private final GF2PolynomialCalculator gf ;
3231 private final int rejectionThreshold ;
3332 private final int cipherTextBytes ;
3433
35- HQCEngine (int n , int n1 , int n2 , int k , int g , int delta , int w , int wr , int fft , int nmu , int pkSize ,
34+ HQCEngine (int n , int n1 , int n2 , int k , int g , int delta , int w , int wr , int fft , int nMu , int pkSize ,
3635 int [] generatorPoly )
3736 {
3837 this .n = n ;
@@ -44,11 +43,10 @@ class HQCEngine
4443 this .generatorPoly = generatorPoly ;
4544 this .g = g ;
4645 this .fft = fft ;
47- this .N_MU = nmu ;
46+ this .nMu = nMu ;
4847 this .pkSize = pkSize ;
4948 this .mulParam = n2 >> 7 ;
5049 this .N_BYTE = Utils .getByteSizeFromBitSize (n );
51- this .K_BYTE = k ;
5250 this .N1N2_BYTE_64 = Utils .getByte64SizeFromBitSize (n1 * n2 );
5351 this .N1N2_BYTE = Utils .getByteSizeFromBitSize (n1 * n2 );
5452 this .gf = new GF2PolynomialCalculator (n );
@@ -77,10 +75,10 @@ void genKeyPair(byte[] pk, byte[] sk, SecureRandom secureRandom)
7775
7876 secureRandom .nextBytes (seedKem );
7977 Shake256RandomGenerator ctxKem = new Shake256RandomGenerator (seedKem , (byte )1 );
80- System .arraycopy (seedKem , 0 , sk , pkSize + SEED_BYTES + K_BYTE , SEED_BYTES );
78+ System .arraycopy (seedKem , 0 , sk , pkSize + SEED_BYTES + k , SEED_BYTES );
8179
8280 ctxKem .nextBytes (seedKem );
83- ctxKem .nextBytes (sk , pkSize + SEED_BYTES , K_BYTE );
81+ ctxKem .nextBytes (sk , pkSize + SEED_BYTES , k );
8482
8583 hashHI (keypairSeed , 512 , seedKem , seedKem .length , (byte )2 );
8684 ctxKem .init (keypairSeed , 0 , SEED_BYTES , (byte )1 );
@@ -96,9 +94,9 @@ void genKeyPair(byte[] pk, byte[] sk, SecureRandom secureRandom)
9694 System .arraycopy (keypairSeed , 0 , sk , pkSize , SEED_BYTES );
9795 System .arraycopy (pk , 0 , sk , 0 , pkSize );
9896 Arrays .clear (keypairSeed );
99- Arrays .clear (xLongBytes );
100- Arrays .clear (yLongBytes );
101- Arrays .clear (h );
97+ gf .clear (xLongBytes );
98+ gf .clear (yLongBytes );
99+ gf .clear (h );
102100 }
103101
104102 /**
@@ -112,7 +110,7 @@ void genKeyPair(byte[] pk, byte[] sk, SecureRandom secureRandom)
112110 void encaps (byte [] u , byte [] v , byte [] kTheta , byte [] pk , byte [] salt , SecureRandom secureRandom )
113111 {
114112 // 1. Randomly generate m
115- byte [] m = new byte [K_BYTE ];
113+ byte [] m = new byte [k ];
116114 byte [] hashEkKem = new byte [SEED_BYTES ];
117115 long [] u64 = gf .create ();
118116 long [] v64 = new long [N1N2_BYTE_64 ];
@@ -125,7 +123,7 @@ void encaps(byte[] u, byte[] v, byte[] kTheta, byte[] pk, byte[] salt, SecureRan
125123 pkeEncrypt (u64 , v64 , pk , m , kTheta , SEED_BYTES );
126124 Utils .fromLongArrayToByteArray (u , 0 , u .length , u64 );
127125 Utils .fromLongArrayToByteArray (v , 0 , v .length , v64 );
128- Arrays .clear (u64 );
126+ gf .clear (u64 );
129127 Arrays .clear (v64 );
130128 Arrays .clear (m );
131129 Arrays .clear (hashEkKem );
@@ -173,19 +171,19 @@ int decaps(byte[] ss, byte[] ct, byte[] sk)
173171 System .arraycopy (kThetaPrime , 0 , ss , 0 , 32 );
174172 Arrays .fill (cKemPrimeV64 , 0L );
175173 pkeEncrypt (cKemPrimeU64 , cKemPrimeV64 , sk , mPrime , kThetaPrime , 32 );
176- hashGJ (kBar , 256 , hashEkKem , sk , pkSize + SEED_BYTES , K_BYTE , ct , 0 , ct .length , (byte )3 );
174+ hashGJ (kBar , 256 , hashEkKem , sk , pkSize + SEED_BYTES , k , ct , 0 , ct .length , (byte )3 );
177175
178176 int result = (int )(gf .equalTo (u64 , cKemPrimeU64 ) & gf .equalTo (v64 , cKemPrimeV64 ));
179177
180- for (int i = 0 ; i < K_BYTE ; i ++)
178+ for (int i = 0 ; i < k ; i ++)
181179 {
182180 ss [i ] = (byte )(((ss [i ] & result ) ^ (kBar [i ] & ~result )) & 0xff );
183181 }
184182
185- Arrays .clear (u64 );
186- Arrays .clear (v64 );
187- Arrays .clear (cKemPrimeU64 );
188- Arrays .clear (cKemPrimeV64 );
183+ gf .clear (u64 );
184+ gf .clear (v64 );
185+ gf .clear (cKemPrimeU64 );
186+ gf .clear (cKemPrimeV64 );
189187 Arrays .clear (hashEkKem );
190188 Arrays .clear (kThetaPrime );
191189 Arrays .clear (mPrime );
@@ -218,17 +216,16 @@ private void pkeEncrypt(long[] u, long[] v, byte[] ekPke, byte[] m, byte[] theta
218216
219217 vectSampleFixedWeights2 (randomGenerator , tmp , wr );// tmp is r1
220218 gf .addTo (tmp , u );
221- Arrays .clear (e );
222- Arrays .clear (tmp );
219+ gf .clear (e );
220+ gf .clear (tmp );
223221 Arrays .clear (res );
224222 }
225223
226224 private int barrettReduce (int x )
227225 {
228- long q = ((long ) x * N_MU ) >>> 32 ;
229- int r = x - (int ) (q * n );
230- r -= (-(((r - n ) >>> 31 ) ^ 1 )) & n ;
231- return r ;
226+ int q = (int )(((long )x * nMu ) >>> 32 );
227+ int r = x - n - q * n ;
228+ return r + ((r >> 31 ) & n );
232229 }
233230
234231 private void generateRandomSupport (int [] support , int weight , Shake256RandomGenerator random )
@@ -250,9 +247,9 @@ private void generateRandomSupport(int[] support, int weight, Shake256RandomGene
250247 {
251248 continue ;
252249 }
250+
253251 candidate = barrettReduce (candidate );
254252 boolean duplicate = false ;
255-
256253 for (int k = 0 ; k < count ; k ++)
257254 {
258255 if (support [k ] == candidate )
@@ -261,11 +258,12 @@ private void generateRandomSupport(int[] support, int weight, Shake256RandomGene
261258 break ;
262259 }
263260 }
264-
265- if (!duplicate )
261+ if (duplicate )
266262 {
267- support [ count ++] = candidate ;
263+ continue ;
268264 }
265+
266+ support [count ++] = candidate ;
269267 }
270268 }
271269
@@ -284,69 +282,68 @@ private void writeSupportToVector(long[] v, int[] support, int weight)
284282 for (int j = 0 ; j < weight ; j ++)
285283 {
286284 int tmp = i - indexTab [j ];
287- val |= ( bitTab [j ] & -( 1 ^ (( tmp | -tmp ) >>> 31 )) );
285+ val |= bitTab [j ] & ~(( tmp | -tmp ) >> 31 );
288286 }
289287 v [i ] = val ;
290288 }
291289 }
292290
293- public void vectSampleFixedWeight1 (long [] output , Shake256RandomGenerator random , int weight )
291+ private void vectSampleFixedWeight1 (long [] output , Shake256RandomGenerator random , int weight )
294292 {
295293 int [] support = new int [wr ];
296294 generateRandomSupport (support , weight , random );
297295 writeSupportToVector (output , support , weight );
298296 }
299297
300- private static void hashHI (byte [] output , int bitLength , byte [] in , int inLen , byte domain )
301- {
302- SHA3Digest digest = new SHA3Digest (bitLength );
303- digest .update (in , 0 , inLen );
304- digest .update (domain );
305- digest .doFinal (output , 0 );
306- }
307-
308- private void hashGJ (byte [] output , int bitLength , byte [] hashEkKem , byte [] mOrSigma , int mOrSigmaOff ,
309- int mOrSigmaLen , byte [] saltOrCt , int saltOrCtOff , int saltOrCtOffLen , byte domain )
310- {
311- SHA3Digest digest = new SHA3Digest (bitLength );
312- digest .update (hashEkKem , 0 , hashEkKem .length );
313- digest .update (mOrSigma , mOrSigmaOff , mOrSigmaLen );
314- digest .update (saltOrCt , saltOrCtOff , saltOrCtOffLen );
315- digest .update (domain );
316- digest .doFinal (output , 0 );
317- }
318-
319298 private void vectSampleFixedWeights2 (Shake256RandomGenerator generator , long [] v , int weight )
320299 {
321- int [] support = new int [wr ];
322300 byte [] rand = new byte [wr << 2 ];
323301 generator .xofGetBytes (rand , rand .length );
302+
303+ int [] support = new int [wr ];
324304 Pack .littleEndianToInt (rand , 0 , support );
325- for (int i = 0 ; i < weight ; ++i )
326- {
327- support [i ] = i + (int ) (((support [i ] & 0xFFFFFFFFL ) * (n - i )) >> 32 );
328- }
329305
330- for (int i = weight - 1 ; i -- > 0 ;)
306+ int i = weight ;
307+ while (--i >= 0 )
331308 {
332- int found = 0 ;
309+ int support_i = i + (int )(((support [i ] & 0xFFFFFFFFL ) * (n - i )) >> 32 );
310+ int notFound = -1 ;
333311 for (int j = i + 1 ; j < weight ; ++j )
334312 {
335- found |= compareU32 ( support [ j ] , support [i ]);
313+ notFound &= cdiff ( support_i , support [j ]);
336314 }
337- found = -found ;
338- support [i ] = (found & i ) ^ (~found & support [i ]);
315+ support [i ] = (~notFound & i ) ^ (notFound & support_i );
339316 }
317+
340318 writeSupportToVector (v , support , weight );
341319 }
342320
343- private static int compareU32 ( int v1 , int v2 )
321+ private void vectTruncate ( long [] v )
344322 {
345- return 1 ^ ((( v1 - v2 ) | ( v2 - v1 )) >>> 31 );
323+ Arrays . fill ( v , N1N2_BYTE_64 , ( n + 63 ) >> 6 , 0L );
346324 }
347325
348- private void vectTruncate ( long [] v )
326+ private static int cdiff ( int v1 , int v2 )
349327 {
350- Arrays .fill (v , N1N2_BYTE_64 , (n + 63 ) >> 6 , 0L );
328+ return ((v1 - v2 ) | (v2 - v1 )) >> 31 ;
329+ }
330+
331+ private static void hashGJ (byte [] output , int bitLength , byte [] hashEkKem , byte [] mOrSigma , int mOrSigmaOff ,
332+ int mOrSigmaLen , byte [] saltOrCt , int saltOrCtOff , int saltOrCtOffLen , byte domain )
333+ {
334+ SHA3Digest digest = new SHA3Digest (bitLength );
335+ digest .update (hashEkKem , 0 , hashEkKem .length );
336+ digest .update (mOrSigma , mOrSigmaOff , mOrSigmaLen );
337+ digest .update (saltOrCt , saltOrCtOff , saltOrCtOffLen );
338+ digest .update (domain );
339+ digest .doFinal (output , 0 );
340+ }
341+
342+ private static void hashHI (byte [] output , int bitLength , byte [] in , int inLen , byte domain )
343+ {
344+ SHA3Digest digest = new SHA3Digest (bitLength );
345+ digest .update (in , 0 , inLen );
346+ digest .update (domain );
347+ digest .doFinal (output , 0 );
351348 }
352349}
0 commit comments