11package org .bouncycastle .crypto .kems ;
22
33import java .math .BigInteger ;
4- import java .security .SecureRandom ;
54
6- import org .bouncycastle .crypto .Digest ;
75import org .bouncycastle .crypto .EncapsulatedSecretExtractor ;
8- import org .bouncycastle .crypto .digests .SHA256Digest ;
96import org .bouncycastle .crypto .params .SAKKEPrivateKeyParameters ;
107import org .bouncycastle .crypto .params .SAKKEPublicKeyParameters ;
118import org .bouncycastle .math .ec .ECCurve ;
1512import org .bouncycastle .util .BigIntegers ;
1613import org .bouncycastle .util .encoders .Hex ;
1714
18- import static org .bouncycastle .crypto .kems .SAKKEKEMSGenerator .pairing ;
1915
2016public class SAKKEKEMExtractor
2117 implements EncapsulatedSecretExtractor
@@ -51,31 +47,26 @@ public byte[] extractSecret(byte[] encapsulation)
5147 ECPoint R_bS = curve .decodePoint (Arrays .copyOfRange (encapsulation , 0 , 257 ));
5248 BigInteger H = new BigInteger (Arrays .copyOfRange (encapsulation , 257 , 274 ));
5349
54- //ECCurveWithTatePairing pairing = new ECCurveWithTatePairing(q, BigInteger.ONE, BigInteger.ZERO, p);
55- //BigInteger w = pairing.TatePairing(R_bS, K_bS).toBigInteger();
5650 // Step 2: Compute w = <R_bS, K_bS> using pairing
57- // BigInteger w = computeTLPairing(new BigInteger[] {R_bS.getXCoord().toBigInteger(), R_bS.getYCoord().toBigInteger()},
58- // new BigInteger[] {K_bS.getXCoord().toBigInteger(), K_bS.getYCoord().toBigInteger()}, this.p, this.q);
5951 BigInteger w = computePairing (R_bS , K_bS , p , q );
6052 System .out .println (new String (Hex .encode (w .toByteArray ())));
6153 //BigInteger w = tatePairing(R_bS.getXCoord().toBigInteger(), R_bS.getYCoord().toBigInteger(), K_bS.getXCoord().toBigInteger(), K_bS.getYCoord().toBigInteger(), q, p);
6254 // Step 3: Compute SSV = H XOR HashToIntegerRange(w, 2^n)
63- BigInteger ssv = computeSSV (H , w );
55+ BigInteger twoToN = BigInteger .ONE .shiftLeft (n );
56+ BigInteger mask = SAKKEUtils .hashToIntegerRange (w .toByteArray (), twoToN );
57+ BigInteger ssv = H .xor (mask );
6458
6559 // Step 4: Compute r = HashToIntegerRange(SSV || b)
6660 BigInteger b = privateKey .getB ();
6761 BigInteger r = SAKKEUtils .hashToIntegerRange (Arrays .concatenate (ssv .toByteArray (), b .toByteArray ()), q );
68- //
69- // // Step 5: Validate R_bS
62+
63+ // Step 5: Validate R_bS
7064 ECPoint bP = P .multiply (b ).normalize ();
7165 ECPoint Test = bP .add (Z_S ).multiply (r ).normalize ();
72- if (!R_bS .equals (Test ))
66+ if (!R_bS .equals (Test ))
7367 {
7468 throw new IllegalStateException ("Validation of R_bS failed" );
7569 }
76- // if (!validateR_bS(r, privateKey.getPrivatePoint(), R_bS)) {
77- // throw new IllegalStateException("Validation of R_bS failed");
78- // }
7970
8071 return BigIntegers .asUnsignedByteArray (n / 8 , ssv );
8172 }
@@ -92,109 +83,75 @@ public int getEncapsulationLength()
9283 }
9384
9485
95- private BigInteger computeSSV (BigInteger H , BigInteger w )
96- {
97- BigInteger twoToN = BigInteger .ONE .shiftLeft (n );
98- BigInteger mask = SAKKEUtils .hashToIntegerRange (w .toByteArray (), twoToN );
99- return H .xor (mask );
100- }
101-
10286 public static BigInteger computePairing (ECPoint R , ECPoint Q , BigInteger p , BigInteger q )
10387 {
104- BigInteger c = p .add (BigInteger .ONE ).divide (q ); // Compute c = (p+1)/q
105- BigInteger [] v = new BigInteger []{BigInteger .ONE , BigInteger .ZERO }; // v = (1,0) in F_p^2
106- //BigInteger v = BigInteger.ONE;
88+ // v = (1,0) in F_p^2
89+ BigInteger [] v = new BigInteger []{BigInteger .ONE , BigInteger .ZERO };
10790 ECPoint C = R ;
10891
10992 BigInteger qMinusOne = q .subtract (BigInteger .ONE );
11093 int numBits = qMinusOne .bitLength ();
94+ BigInteger Qx = Q .getAffineXCoord ().toBigInteger ();
95+ BigInteger Qy = Q .getAffineYCoord ().toBigInteger ();
96+ BigInteger Rx = R .getAffineXCoord ().toBigInteger ();
97+ BigInteger Ry = R .getAffineYCoord ().toBigInteger ();
98+ BigInteger l , Cx , Cy ;
99+ final BigInteger three = BigInteger .valueOf (3 );
100+ final BigInteger two = BigInteger .valueOf (2 );
111101
112102 // Miller loop
113103 for (int i = numBits - 2 ; i >= 0 ; i --)
114104 {
115- v = fp2SquareAndAccumulate (v , C , Q , p );
105+ Cx = C .getAffineXCoord ().toBigInteger ();
106+ Cy = C .getAffineYCoord ().toBigInteger ();
107+
108+ // Compute l = (3 * (Cx^2 - 1)) / (2 * Cy) mod p
109+ l = three .multiply (Cx .multiply (Cx ).subtract (BigInteger .ONE ))
110+ .multiply (Cy .multiply (two ).modInverse (p )).mod (p );
111+
112+ // Compute v = v^2 * ( l*( Q_x + C_x ) + ( i*Q_y - C_y ) )
113+ v = fp2PointSquare (v [0 ], v [1 ], p );
114+ v = fp2Multiply (v [0 ], v [1 ], l .multiply (Qx .add (Cx )).subtract (Cy ), Qy , p );
116115
117116 C = C .twice ().normalize (); // C = [2]C
118117
119118 if (qMinusOne .testBit (i ))
120119 {
121- v = fp2MultiplyAndAccumulate (v , C , R , Q , p );
120+ Cx = C .getAffineXCoord ().toBigInteger ();
121+ Cy = C .getAffineYCoord ().toBigInteger ();
122+
123+ // Compute l = (Cy - Ry) / (Cx - Rx) mod p
124+ l = Cy .subtract (Ry ).multiply (Cx .subtract (Rx ).modInverse (p )).mod (p );
125+
126+ // Compute v = v * ( l*( Q_x + C_x ) + ( i*Q_y - C_y ) )
127+ v = fp2Multiply (v [0 ], v [1 ], l .multiply (Qx .add (Cx )).subtract (Cy ), Qy , p );
128+
122129 C = C .add (R ).normalize ();
123130 }
124131 }
125132
126133 // Final exponentiation: t = v^c
127- return fp2FinalExponentiation (v , p , c );
128- }
129-
130- private static BigInteger [] fp2SquareAndAccumulate (BigInteger [] v , ECPoint C , ECPoint Q , BigInteger p )
131- {
132- BigInteger Cx = C .getAffineXCoord ().toBigInteger ();
133- BigInteger Cy = C .getAffineYCoord ().toBigInteger ();
134- BigInteger Qx = Q .getAffineXCoord ().toBigInteger ();
135- BigInteger Qy = Q .getAffineYCoord ().toBigInteger ();
136-
137- // Compute l = (3 * (Cx^2 - 1)) / (2 * Cy) mod p
138- BigInteger l = BigInteger .valueOf (3 ).multiply (Cx .multiply (Cx ).subtract (BigInteger .ONE ))
139- .multiply (Cy .multiply (BigInteger .valueOf (2 )).modInverse (p )).mod (p );
140-
141- // Compute v = v^2 * ( l*( Q_x + C_x ) + ( i*Q_y - C_y ) )
142- v = fp2Multiply (v [0 ], v [1 ], v [0 ], v [1 ], p );
143- // v[0] = v[0].multiply(v[0]);
144- // v[1] = v[1].multiply(v[1]);
145- return accumulateLine (v [0 ], v [1 ], Cx , Cy , Qx , Qy , l , p );
146- // BigInteger t_x1_bn = Cx.multiply(Cx).subtract(BigInteger.ONE).multiply(BigInteger.valueOf(3)).multiply(Qx.add(Cx)).mod(p)
147- // .subtract(Cy.multiply(Cy).multiply(BigInteger.valueOf(2))).mod(p);
148- // BigInteger t_x2_bn = Cy.multiply(Qy).multiply(BigInteger.valueOf(2)).mod(p);
149- // v = fp2Multiply(v[0], v[1], v[0], v[1], p);
150- // return fp2Multiply(v[0], v[1], t_x1_bn, t_x2_bn, p);
151- }
152-
153- private static BigInteger [] accumulateLine (BigInteger v0 , BigInteger v1 , BigInteger Cx , BigInteger Cy , BigInteger Qx , BigInteger Qy , BigInteger l , BigInteger p )
154- {
155- return fp2Multiply (v0 , v1 , l .multiply (Qx .add (Cx )).subtract (Cy ), Qy , p );
156- }
157-
158- private static BigInteger [] fp2MultiplyAndAccumulate (BigInteger [] v , ECPoint C , ECPoint R , ECPoint Q , BigInteger p )
159- {
160- BigInteger Cx = C .getAffineXCoord ().toBigInteger ();
161- BigInteger Cy = C .getAffineYCoord ().toBigInteger ();
162- BigInteger Rx = R .getAffineXCoord ().toBigInteger ();
163- BigInteger Ry = R .getAffineYCoord ().toBigInteger ();
164- BigInteger Qx = Q .getAffineXCoord ().toBigInteger ();
165- BigInteger Qy = Q .getAffineYCoord ().toBigInteger ();
166-
167- // Compute l = (Cy - Ry) / (Cx - Rx) mod p
168- BigInteger l = Cy .subtract (Ry )
169- .multiply (Cx .subtract (Rx ).modInverse (p ))
170- .mod (p );
171-
172- // Compute v = v * ( l*( Q_x + C_x ) + ( i*Q_y - C_y ) )
173- return accumulateLine (v [0 ], v [1 ], Cx , Cy , Qx , Qy , l , p );
174- // BigInteger t_x1_bn = Qx.add(Rx).multiply(Cy).subtract(Qx.add(Cx).multiply(Ry)).mod(p);
175- // BigInteger t_x2_bn = Cx.subtract(Rx).multiply(Qy).mod(p);
176- // return fp2Multiply(v[0], v[1], t_x1_bn, t_x2_bn, p);
177-
134+ v = fp2PointSquare (v [0 ], v [1 ], p );
135+ v = fp2PointSquare (v [0 ], v [1 ], p );
136+ return v [1 ].multiply (v [0 ].modInverse (p )).mod (p );
178137 }
179138
180-
181139 static BigInteger [] fp2Multiply (BigInteger x_real , BigInteger x_imag , BigInteger y_real , BigInteger y_imag , BigInteger p )
182140 {
183- // Multiply v = (a + i*b) * scalar
184141 return new BigInteger []{
185142 x_real .multiply (y_real ).subtract (x_imag .multiply (y_imag )).mod (p ),
186143 x_real .multiply (y_imag ).add (x_imag .multiply (y_real )).mod (p )
187144 };
188145 }
189146
190- private static BigInteger fp2FinalExponentiation (BigInteger [] v , BigInteger p , BigInteger c )
147+ static BigInteger [] fp2PointSquare (BigInteger currentX , BigInteger currentY , BigInteger p )
191148 {
192- // Compute representative in F_p: return b/a ( mod p)
193- // BigInteger v0 = v[0].modPow(c, p);
194- // BigInteger v1 = v[1].modPow(c, p);
195- // return v1.multiply(v0.modInverse(p)).mod(p);
196- v = fp2Multiply ( v [ 0 ], v [ 1 ], v [ 0 ], v [ 1 ], p );
197- v = fp2Multiply ( v [ 0 ], v [ 1 ], v [ 0 ], v [ 1 ], p );
198- return v [ 1 ]. multiply ( v [ 0 ]. modInverse ( p )). mod ( p ) ;
149+ BigInteger xPlusY = currentX . add ( currentY ). mod ( p );
150+ BigInteger xMinusY = currentX . subtract ( currentY ). mod ( p );
151+ BigInteger newX = xPlusY . multiply ( xMinusY ). mod ( p );
152+
153+ // Compute newY = 2xy mod p
154+ BigInteger newY = currentX . multiply ( currentY ). multiply ( BigInteger . valueOf ( 2 )). mod ( p );
155+ return new BigInteger []{ newX , newY } ;
199156 }
200157}
0 commit comments