@@ -4,63 +4,63 @@ package internal | |||
// helper used for Uint128 representation | |||
type Uint128 struct { | |||
H, L uint64 | |||
H, L uint64 | |||
} | |||
// Adds 2 64bit digits in constant time. | |||
// Returns result and carry (1 or 0) | |||
func Addc64(cin, a, b uint64) (ret, cout uint64) { | |||
t := a + cin | |||
ret = b + t | |||
cout = ((a & b) | ((a | b) & (^ret))) >> 63 | |||
return | |||
t := a + cin | |||
ret = b + t | |||
cout = ((a & b) | ((a | b) & (^ret))) >> 63 | |||
return | |||
} | |||
// Substracts 2 64bit digits in constant time. | |||
// Returns result and borrow (1 or 0) | |||
func Subc64(bIn, a, b uint64) (ret, bOut uint64) { | |||
var tmp1 = a - b | |||
// Set bOut if bIn!=0 and tmp1==0 in constant time | |||
bOut = bIn & (1 ^ ((tmp1 | uint64(0-tmp1)) >> 63)) | |||
// Constant time check if x<y | |||
bOut |= (a ^ ((a ^ b) | (uint64(a-b) ^ b))) >> 63 | |||
ret = tmp1 - bIn | |||
return | |||
var tmp1 = a - b | |||
// Set bOut if bIn!=0 and tmp1==0 in constant time | |||
bOut = bIn & (1 ^ ((tmp1 | uint64(0-tmp1)) >> 63)) | |||
// Constant time check if x<y | |||
bOut |= (a ^ ((a ^ b) | (uint64(a-b) ^ b))) >> 63 | |||
ret = tmp1 - bIn | |||
return | |||
} | |||
// Multiplies 2 64bit digits in constant time | |||
func Mul64(a, b uint64) (res Uint128) { | |||
var al, bl, ah, bh, albl, albh, ahbl, ahbh uint64 | |||
var res1, res2, res3 uint64 | |||
var carry, maskL, maskH, temp uint64 | |||
var al, bl, ah, bh, albl, albh, ahbl, ahbh uint64 | |||
var res1, res2, res3 uint64 | |||
var carry, maskL, maskH, temp uint64 | |||
maskL = (^maskL) >> 32 | |||
maskH = ^maskL | |||
maskL = (^maskL) >> 32 | |||
maskH = ^maskL | |||
al = a & maskL | |||
ah = a >> 32 | |||
bl = b & maskL | |||
bh = b >> 32 | |||
al = a & maskL | |||
ah = a >> 32 | |||
bl = b & maskL | |||
bh = b >> 32 | |||
albl = al * bl | |||
albh = al * bh | |||
ahbl = ah * bl | |||
ahbh = ah * bh | |||
res.L = albl & maskL | |||
albl = al * bl | |||
albh = al * bh | |||
ahbl = ah * bl | |||
ahbh = ah * bh | |||
res.L = albl & maskL | |||
res1 = albl >> 32 | |||
res2 = ahbl & maskL | |||
res3 = albh & maskL | |||
temp = res1 + res2 + res3 | |||
carry = temp >> 32 | |||
res.L ^= temp << 32 | |||
res1 = albl >> 32 | |||
res2 = ahbl & maskL | |||
res3 = albh & maskL | |||
temp = res1 + res2 + res3 | |||
carry = temp >> 32 | |||
res.L ^= temp << 32 | |||
res1 = ahbl >> 32 | |||
res2 = albh >> 32 | |||
res3 = ahbh & maskL | |||
temp = res1 + res2 + res3 + carry | |||
res.H = temp & maskL | |||
carry = temp & maskH | |||
res.H ^= (ahbh & maskH) + carry | |||
return | |||
res1 = ahbl >> 32 | |||
res2 = albh >> 32 | |||
res3 = ahbh & maskL | |||
temp = res1 + res2 + res3 + carry | |||
res.H = temp & maskL | |||
carry = temp & maskH | |||
res.H ^= (ahbh & maskH) + carry | |||
return | |||
} |
@@ -1,7 +1,7 @@ | |||
package internal | |||
type CurveOperations struct { | |||
Params *SidhParams | |||
Params *SidhParams | |||
} | |||
// Computes j-invariant for a curve y2=x3+A/Cx+x with A,C in F_(p^2). Result | |||
@@ -10,284 +10,284 @@ type CurveOperations struct { | |||
// of SIDH, buffer size must be at least size of shared secret. | |||
// Implementation corresponds to Algorithm 9 from SIKE. | |||
func (c *CurveOperations) Jinvariant(cparams *ProjectiveCurveParameters, jBytes []byte) { | |||
var j, t0, t1 Fp2Element | |||
op := c.Params.Op | |||
op.Square(&j, &cparams.A) // j = A^2 | |||
op.Square(&t1, &cparams.C) // t1 = C^2 | |||
op.Add(&t0, &t1, &t1) // t0 = t1 + t1 | |||
op.Sub(&t0, &j, &t0) // t0 = j - t0 | |||
op.Sub(&t0, &t0, &t1) // t0 = t0 - t1 | |||
op.Sub(&j, &t0, &t1) // t0 = t0 - t1 | |||
op.Square(&t1, &t1) // t1 = t1^2 | |||
op.Mul(&j, &j, &t1) // j = j * t1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Square(&t1, &t0) // t1 = t0^2 | |||
op.Mul(&t0, &t0, &t1) // t0 = t0 * t1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Inv(&j, &j) // j = 1/j | |||
op.Mul(&j, &t0, &j) // j = t0 * j | |||
c.Fp2ToBytes(jBytes, &j) | |||
var j, t0, t1 Fp2Element | |||
op := c.Params.Op | |||
op.Square(&j, &cparams.A) // j = A^2 | |||
op.Square(&t1, &cparams.C) // t1 = C^2 | |||
op.Add(&t0, &t1, &t1) // t0 = t1 + t1 | |||
op.Sub(&t0, &j, &t0) // t0 = j - t0 | |||
op.Sub(&t0, &t0, &t1) // t0 = t0 - t1 | |||
op.Sub(&j, &t0, &t1) // t0 = t0 - t1 | |||
op.Square(&t1, &t1) // t1 = t1^2 | |||
op.Mul(&j, &j, &t1) // j = j * t1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Square(&t1, &t0) // t1 = t0^2 | |||
op.Mul(&t0, &t0, &t1) // t0 = t0 * t1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Inv(&j, &j) // j = 1/j | |||
op.Mul(&j, &t0, &j) // j = t0 * j | |||
c.Fp2ToBytes(jBytes, &j) | |||
} | |||
// Given affine points x(P), x(Q) and x(Q-P) in a extension field F_{p^2}, function | |||
// recorvers projective coordinate A of a curve. This is Algorithm 10 from SIKE. | |||
func (c *CurveOperations) RecoverCoordinateA(curve *ProjectiveCurveParameters, xp, xq, xr *Fp2Element) { | |||
var t0, t1 Fp2Element | |||
op := c.Params.Op | |||
op.Add(&t1, xp, xq) // t1 = Xp + Xq | |||
op.Mul(&t0, xp, xq) // t0 = Xp * Xq | |||
op.Mul(&curve.A, xr, &t1) // A = X(q-p) * t1 | |||
op.Add(&curve.A, &curve.A, &t0) // A = A + t0 | |||
op.Mul(&t0, &t0, xr) // t0 = t0 * X(q-p) | |||
op.Sub(&curve.A, &curve.A, &c.Params.OneFp2) // A = A - 1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t1, &t1, xr) // t1 = t1 + X(q-p) | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Square(&curve.A, &curve.A) // A = A^2 | |||
op.Inv(&t0, &t0) // t0 = 1/t0 | |||
op.Mul(&curve.A, &curve.A, &t0) // A = A * t0 | |||
op.Sub(&curve.A, &curve.A, &t1) // A = A - t1 | |||
var t0, t1 Fp2Element | |||
op := c.Params.Op | |||
op.Add(&t1, xp, xq) // t1 = Xp + Xq | |||
op.Mul(&t0, xp, xq) // t0 = Xp * Xq | |||
op.Mul(&curve.A, xr, &t1) // A = X(q-p) * t1 | |||
op.Add(&curve.A, &curve.A, &t0) // A = A + t0 | |||
op.Mul(&t0, &t0, xr) // t0 = t0 * X(q-p) | |||
op.Sub(&curve.A, &curve.A, &c.Params.OneFp2) // A = A - 1 | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Add(&t1, &t1, xr) // t1 = t1 + X(q-p) | |||
op.Add(&t0, &t0, &t0) // t0 = t0 + t0 | |||
op.Square(&curve.A, &curve.A) // A = A^2 | |||
op.Inv(&t0, &t0) // t0 = 1/t0 | |||
op.Mul(&curve.A, &curve.A, &t0) // A = A * t0 | |||
op.Sub(&curve.A, &curve.A, &t1) // A = A - t1 | |||
} | |||
// Computes equivalence (A:C) ~ (A+2C : A-2C) | |||
func (c *CurveOperations) CalcCurveParamsEquiv3(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv { | |||
var coef CurveCoefficientsEquiv | |||
var c2 Fp2Element | |||
var op = c.Params.Op | |||
op.Add(&c2, &cparams.C, &cparams.C) | |||
// A24p = A+2*C | |||
op.Add(&coef.A, &cparams.A, &c2) | |||
// A24m = A-2*C | |||
op.Sub(&coef.C, &cparams.A, &c2) | |||
return coef | |||
var coef CurveCoefficientsEquiv | |||
var c2 Fp2Element | |||
var op = c.Params.Op | |||
op.Add(&c2, &cparams.C, &cparams.C) | |||
// A24p = A+2*C | |||
op.Add(&coef.A, &cparams.A, &c2) | |||
// A24m = A-2*C | |||
op.Sub(&coef.C, &cparams.A, &c2) | |||
return coef | |||
} | |||
// Computes equivalence (A:C) ~ (A+2C : 4C) | |||
func (c *CurveOperations) CalcCurveParamsEquiv4(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv { | |||
var coefEq CurveCoefficientsEquiv | |||
var op = c.Params.Op | |||
op.Add(&coefEq.C, &cparams.C, &cparams.C) | |||
// A24p = A+2C | |||
op.Add(&coefEq.A, &cparams.A, &coefEq.C) | |||
// C24 = 4*C | |||
op.Add(&coefEq.C, &coefEq.C, &coefEq.C) | |||
return coefEq | |||
var coefEq CurveCoefficientsEquiv | |||
var op = c.Params.Op | |||
op.Add(&coefEq.C, &cparams.C, &cparams.C) | |||
// A24p = A+2C | |||
op.Add(&coefEq.A, &cparams.A, &coefEq.C) | |||
// C24 = 4*C | |||
op.Add(&coefEq.C, &coefEq.C, &coefEq.C) | |||
return coefEq | |||
} | |||
// Helper function for RightToLeftLadder(). Returns A+2C / 4. | |||
func (c *CurveOperations) CalcAplus2Over4(cparams *ProjectiveCurveParameters) (ret Fp2Element) { | |||
var tmp Fp2Element | |||
var op = c.Params.Op | |||
// 2C | |||
op.Add(&tmp, &cparams.C, &cparams.C) | |||
// A+2C | |||
op.Add(&ret, &cparams.A, &tmp) | |||
// 1/4C | |||
op.Add(&tmp, &tmp, &tmp) | |||
op.Inv(&tmp, &tmp) | |||
// A+2C/4C | |||
op.Mul(&ret, &ret, &tmp) | |||
return | |||
var tmp Fp2Element | |||
var op = c.Params.Op | |||
// 2C | |||
op.Add(&tmp, &cparams.C, &cparams.C) | |||
// A+2C | |||
op.Add(&ret, &cparams.A, &tmp) | |||
// 1/4C | |||
op.Add(&tmp, &tmp, &tmp) | |||
op.Inv(&tmp, &tmp) | |||
// A+2C/4C | |||
op.Mul(&ret, &ret, &tmp) | |||
return | |||
} | |||
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:A-2C). | |||
func (c *CurveOperations) RecoverCurveCoefficients3(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) { | |||
var op = c.Params.Op | |||
op.Add(&cparams.A, &coefEq.A, &coefEq.C) | |||
// cparams.A = 2*(A+2C+A-2C) = 4A | |||
op.Add(&cparams.A, &cparams.A, &cparams.A) | |||
// cparams.C = (A+2C-A+2C) = 4C | |||
op.Sub(&cparams.C, &coefEq.A, &coefEq.C) | |||
return | |||
var op = c.Params.Op | |||
op.Add(&cparams.A, &coefEq.A, &coefEq.C) | |||
// cparams.A = 2*(A+2C+A-2C) = 4A | |||
op.Add(&cparams.A, &cparams.A, &cparams.A) | |||
// cparams.C = (A+2C-A+2C) = 4C | |||
op.Sub(&cparams.C, &coefEq.A, &coefEq.C) | |||
return | |||
} | |||
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:4C). | |||
func (c *CurveOperations) RecoverCurveCoefficients4(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) { | |||
var op = c.Params.Op | |||
// cparams.C = (4C)*1/2=2C | |||
op.Mul(&cparams.C, &coefEq.C, &c.Params.HalfFp2) | |||
// cparams.A = A+2C - 2C = A | |||
op.Sub(&cparams.A, &coefEq.A, &cparams.C) | |||
// cparams.C = 2C * 1/2 = C | |||
op.Mul(&cparams.C, &cparams.C, &c.Params.HalfFp2) | |||
return | |||
var op = c.Params.Op | |||
// cparams.C = (4C)*1/2=2C | |||
op.Mul(&cparams.C, &coefEq.C, &c.Params.HalfFp2) | |||
// cparams.A = A+2C - 2C = A | |||
op.Sub(&cparams.A, &coefEq.A, &cparams.C) | |||
// cparams.C = 2C * 1/2 = C | |||
op.Mul(&cparams.C, &cparams.C, &c.Params.HalfFp2) | |||
return | |||
} | |||
// Combined coordinate doubling and differential addition. Takes projective points | |||
// P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E. | |||
// Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE | |||
func (c *CurveOperations) xDblAdd(P, Q, QmP *ProjectivePoint, a24 *Fp2Element) (dblP, PaQ ProjectivePoint) { | |||
var t0, t1, t2 Fp2Element | |||
var op = c.Params.Op | |||
xQmP, zQmP := &QmP.X, &QmP.Z | |||
xPaQ, zPaQ := &PaQ.X, &PaQ.Z | |||
x2P, z2P := &dblP.X, &dblP.Z | |||
xP, zP := &P.X, &P.Z | |||
xQ, zQ := &Q.X, &Q.Z | |||
op.Add(&t0, xP, zP) // t0 = Xp+Zp | |||
op.Sub(&t1, xP, zP) // t1 = Xp-Zp | |||
op.Square(x2P, &t0) // 2P.X = t0^2 | |||
op.Sub(&t2, xQ, zQ) // t2 = Xq-Zq | |||
op.Add(xPaQ, xQ, zQ) // Xp+q = Xq+Zq | |||
op.Mul(&t0, &t0, &t2) // t0 = t0 * t2 | |||
op.Mul(z2P, &t1, &t1) // 2P.Z = t1 * t1 | |||
op.Mul(&t1, &t1, xPaQ) // t1 = t1 * Xp+q | |||
op.Sub(&t2, x2P, z2P) // t2 = 2P.X - 2P.Z | |||
op.Mul(x2P, x2P, z2P) // 2P.X = 2P.X * 2P.Z | |||
op.Mul(xPaQ, a24, &t2) // Xp+q = A24 * t2 | |||
op.Sub(zPaQ, &t0, &t1) // Zp+q = t0 - t1 | |||
op.Add(z2P, xPaQ, z2P) // 2P.Z = Xp+q + 2P.Z | |||
op.Add(xPaQ, &t0, &t1) // Xp+q = t0 + t1 | |||
op.Mul(z2P, z2P, &t2) // 2P.Z = 2P.Z * t2 | |||
op.Square(zPaQ, zPaQ) // Zp+q = Zp+q ^ 2 | |||
op.Square(xPaQ, xPaQ) // Xp+q = Xp+q ^ 2 | |||
op.Mul(zPaQ, xQmP, zPaQ) // Zp+q = Xq-p * Zp+q | |||
op.Mul(xPaQ, zQmP, xPaQ) // Xp+q = Zq-p * Xp+q | |||
return | |||
var t0, t1, t2 Fp2Element | |||
var op = c.Params.Op | |||
xQmP, zQmP := &QmP.X, &QmP.Z | |||
xPaQ, zPaQ := &PaQ.X, &PaQ.Z | |||
x2P, z2P := &dblP.X, &dblP.Z | |||
xP, zP := &P.X, &P.Z | |||
xQ, zQ := &Q.X, &Q.Z | |||
op.Add(&t0, xP, zP) // t0 = Xp+Zp | |||
op.Sub(&t1, xP, zP) // t1 = Xp-Zp | |||
op.Square(x2P, &t0) // 2P.X = t0^2 | |||
op.Sub(&t2, xQ, zQ) // t2 = Xq-Zq | |||
op.Add(xPaQ, xQ, zQ) // Xp+q = Xq+Zq | |||
op.Mul(&t0, &t0, &t2) // t0 = t0 * t2 | |||
op.Mul(z2P, &t1, &t1) // 2P.Z = t1 * t1 | |||
op.Mul(&t1, &t1, xPaQ) // t1 = t1 * Xp+q | |||
op.Sub(&t2, x2P, z2P) // t2 = 2P.X - 2P.Z | |||
op.Mul(x2P, x2P, z2P) // 2P.X = 2P.X * 2P.Z | |||
op.Mul(xPaQ, a24, &t2) // Xp+q = A24 * t2 | |||
op.Sub(zPaQ, &t0, &t1) // Zp+q = t0 - t1 | |||
op.Add(z2P, xPaQ, z2P) // 2P.Z = Xp+q + 2P.Z | |||
op.Add(xPaQ, &t0, &t1) // Xp+q = t0 + t1 | |||
op.Mul(z2P, z2P, &t2) // 2P.Z = 2P.Z * t2 | |||
op.Square(zPaQ, zPaQ) // Zp+q = Zp+q ^ 2 | |||
op.Square(xPaQ, xPaQ) // Xp+q = Xp+q ^ 2 | |||
op.Mul(zPaQ, xQmP, zPaQ) // Zp+q = Xq-p * Zp+q | |||
op.Mul(xPaQ, zQmP, xPaQ) // Xp+q = Zq-p * Xp+q | |||
return | |||
} | |||
// Given the curve parameters, xP = x(P), computes xP = x([2^k]P) | |||
// Safe to overlap xP, x2P. | |||
func (c *CurveOperations) Pow2k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) { | |||
var t0, t1 Fp2Element | |||
var op = c.Params.Op | |||
x, z := &xP.X, &xP.Z | |||
for i := uint32(0); i < k; i++ { | |||
op.Sub(&t0, x, z) // t0 = Xp - Zp | |||
op.Add(&t1, x, z) // t1 = Xp + Zp | |||
op.Square(&t0, &t0) // t0 = t0 ^ 2 | |||
op.Square(&t1, &t1) // t1 = t1 ^ 2 | |||
op.Mul(z, ¶ms.C, &t0) // Z2p = C24 * t0 | |||
op.Mul(x, z, &t1) // X2p = Z2p * t1 | |||
op.Sub(&t1, &t1, &t0) // t1 = t1 - t0 | |||
op.Mul(&t0, ¶ms.A, &t1) // t0 = A24+ * t1 | |||
op.Add(z, z, &t0) // Z2p = Z2p + t0 | |||
op.Mul(z, z, &t1) // Zp = Z2p * t1 | |||
} | |||
var t0, t1 Fp2Element | |||
var op = c.Params.Op | |||
x, z := &xP.X, &xP.Z | |||
for i := uint32(0); i < k; i++ { | |||
op.Sub(&t0, x, z) // t0 = Xp - Zp | |||
op.Add(&t1, x, z) // t1 = Xp + Zp | |||
op.Square(&t0, &t0) // t0 = t0 ^ 2 | |||
op.Square(&t1, &t1) // t1 = t1 ^ 2 | |||
op.Mul(z, ¶ms.C, &t0) // Z2p = C24 * t0 | |||
op.Mul(x, z, &t1) // X2p = Z2p * t1 | |||
op.Sub(&t1, &t1, &t0) // t1 = t1 - t0 | |||
op.Mul(&t0, ¶ms.A, &t1) // t0 = A24+ * t1 | |||
op.Add(z, z, &t0) // Z2p = Z2p + t0 | |||
op.Mul(z, z, &t1) // Zp = Z2p * t1 | |||
} | |||
} | |||
// Given the curve parameters, xP = x(P), and k >= 0, compute xP = x([3^k]P). | |||
// | |||
// Safe to overlap xP, xR. | |||
func (c *CurveOperations) Pow3k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) { | |||
var t0, t1, t2, t3, t4, t5, t6 Fp2Element | |||
var op = c.Params.Op | |||
x, z := &xP.X, &xP.Z | |||
for i := uint32(0); i < k; i++ { | |||
op.Sub(&t0, x, z) // t0 = Xp - Zp | |||
op.Square(&t2, &t0) // t2 = t0^2 | |||
op.Add(&t1, x, z) // t1 = Xp + Zp | |||
op.Square(&t3, &t1) // t3 = t1^2 | |||
op.Add(&t4, &t1, &t0) // t4 = t1 + t0 | |||
op.Sub(&t0, &t1, &t0) // t0 = t1 - t0 | |||
op.Square(&t1, &t4) // t1 = t4^2 | |||
op.Sub(&t1, &t1, &t3) // t1 = t1 - t3 | |||
op.Sub(&t1, &t1, &t2) // t1 = t1 - t2 | |||
op.Mul(&t5, &t3, ¶ms.A) // t5 = t3 * A24+ | |||
op.Mul(&t3, &t3, &t5) // t3 = t5 * t3 | |||
op.Mul(&t6, &t2, ¶ms.C) // t6 = t2 * A24- | |||
op.Mul(&t2, &t2, &t6) // t2 = t2 * t6 | |||
op.Sub(&t3, &t2, &t3) // t3 = t2 - t3 | |||
op.Sub(&t2, &t5, &t6) // t2 = t5 - t6 | |||
op.Mul(&t1, &t2, &t1) // t1 = t2 * t1 | |||
op.Add(&t2, &t3, &t1) // t2 = t3 + t1 | |||
op.Square(&t2, &t2) // t2 = t2^2 | |||
op.Mul(x, &t2, &t4) // X3p = t2 * t4 | |||
op.Sub(&t1, &t3, &t1) // t1 = t3 - t1 | |||
op.Square(&t1, &t1) // t1 = t1^2 | |||
op.Mul(z, &t1, &t0) // Z3p = t1 * t0 | |||
} | |||
var t0, t1, t2, t3, t4, t5, t6 Fp2Element | |||
var op = c.Params.Op | |||
x, z := &xP.X, &xP.Z | |||
for i := uint32(0); i < k; i++ { | |||
op.Sub(&t0, x, z) // t0 = Xp - Zp | |||
op.Square(&t2, &t0) // t2 = t0^2 | |||
op.Add(&t1, x, z) // t1 = Xp + Zp | |||
op.Square(&t3, &t1) // t3 = t1^2 | |||
op.Add(&t4, &t1, &t0) // t4 = t1 + t0 | |||
op.Sub(&t0, &t1, &t0) // t0 = t1 - t0 | |||
op.Square(&t1, &t4) // t1 = t4^2 | |||
op.Sub(&t1, &t1, &t3) // t1 = t1 - t3 | |||
op.Sub(&t1, &t1, &t2) // t1 = t1 - t2 | |||
op.Mul(&t5, &t3, ¶ms.A) // t5 = t3 * A24+ | |||
op.Mul(&t3, &t3, &t5) // t3 = t5 * t3 | |||
op.Mul(&t6, &t2, ¶ms.C) // t6 = t2 * A24- | |||
op.Mul(&t2, &t2, &t6) // t2 = t2 * t6 | |||
op.Sub(&t3, &t2, &t3) // t3 = t2 - t3 | |||
op.Sub(&t2, &t5, &t6) // t2 = t5 - t6 | |||
op.Mul(&t1, &t2, &t1) // t1 = t2 * t1 | |||
op.Add(&t2, &t3, &t1) // t2 = t3 + t1 | |||
op.Square(&t2, &t2) // t2 = t2^2 | |||
op.Mul(x, &t2, &t4) // X3p = t2 * t4 | |||
op.Sub(&t1, &t3, &t1) // t1 = t3 - t1 | |||
op.Square(&t1, &t1) // t1 = t1^2 | |||
op.Mul(z, &t1, &t0) // Z3p = t1 * t0 | |||
} | |||
} | |||
// Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3). | |||
// | |||
// All xi, yi must be distinct. | |||
func (c *CurveOperations) Fp2Batch3Inv(x1, x2, x3, y1, y2, y3 *Fp2Element) { | |||
var x1x2, t Fp2Element | |||
var op = c.Params.Op | |||
op.Mul(&x1x2, x1, x2) // x1*x2 | |||
op.Mul(&t, &x1x2, x3) // 1/(x1*x2*x3) | |||
op.Inv(&t, &t) | |||
op.Mul(y1, &t, x2) // 1/x1 | |||
op.Mul(y1, y1, x3) | |||
op.Mul(y2, &t, x1) // 1/x2 | |||
op.Mul(y2, y2, x3) | |||
op.Mul(y3, &t, &x1x2) // 1/x3 | |||
var x1x2, t Fp2Element | |||
var op = c.Params.Op | |||
op.Mul(&x1x2, x1, x2) // x1*x2 | |||
op.Mul(&t, &x1x2, x3) // 1/(x1*x2*x3) | |||
op.Inv(&t, &t) | |||
op.Mul(y1, &t, x2) // 1/x1 | |||
op.Mul(y1, y1, x3) | |||
op.Mul(y2, &t, x1) // 1/x2 | |||
op.Mul(y2, y2, x3) | |||
op.Mul(y3, &t, &x1x2) // 1/x3 | |||
} | |||
// ScalarMul3Pt is a right-to-left point multiplication that given the | |||
// x-coordinate of P, Q and P-Q calculates the x-coordinate of R=Q+[scalar]P. | |||
// nbits must be smaller or equal to len(scalar). | |||
func (c *CurveOperations) ScalarMul3Pt(cparams *ProjectiveCurveParameters, P, Q, PmQ *ProjectivePoint, nbits uint, scalar []uint8) ProjectivePoint { | |||
var R0, R2, R1 ProjectivePoint | |||
var op = c.Params.Op | |||
aPlus2Over4 := c.CalcAplus2Over4(cparams) | |||
R1 = *P | |||
R2 = *PmQ | |||
R0 = *Q | |||
// Iterate over the bits of the scalar, bottom to top | |||
prevBit := uint8(0) | |||
for i := uint(0); i < nbits; i++ { | |||
bit := (scalar[i>>3] >> (i & 7) & 1) | |||
swap := prevBit ^ bit | |||
prevBit = bit | |||
op.CondSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, swap) | |||
R0, R2 = c.xDblAdd(&R0, &R2, &R1, &aPlus2Over4) | |||
} | |||
op.CondSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, prevBit) | |||
return R1 | |||
var R0, R2, R1 ProjectivePoint | |||
var op = c.Params.Op | |||
aPlus2Over4 := c.CalcAplus2Over4(cparams) | |||
R1 = *P | |||
R2 = *PmQ | |||
R0 = *Q | |||
// Iterate over the bits of the scalar, bottom to top | |||
prevBit := uint8(0) | |||
for i := uint(0); i < nbits; i++ { | |||
bit := (scalar[i>>3] >> (i & 7) & 1) | |||
swap := prevBit ^ bit | |||
prevBit = bit | |||
op.CondSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, swap) | |||
R0, R2 = c.xDblAdd(&R0, &R2, &R1, &aPlus2Over4) | |||
} | |||
op.CondSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, prevBit) | |||
return R1 | |||
} | |||
// Convert the input to wire format. | |||
// | |||
// The output byte slice must be at least 2*bytelen(p) bytes long. | |||
func (c *CurveOperations) Fp2ToBytes(output []byte, fp2 *Fp2Element) { | |||
if len(output) < 2*c.Params.Bytelen { | |||
panic("output byte slice too short") | |||
} | |||
var a Fp2Element | |||
c.Params.Op.FromMontgomery(fp2,&a) | |||
// convert to bytes in little endian form | |||
for i := 0; i < c.Params.Bytelen; i++ { | |||
// set i = j*8 + k | |||
fp2 := i / 8 | |||
k := uint64(i % 8) | |||
output[i] = byte(a.A[fp2] >> (8 * k)) | |||
output[i+c.Params.Bytelen] = byte(a.B[fp2] >> (8 * k)) | |||
} | |||
if len(output) < 2*c.Params.Bytelen { | |||
panic("output byte slice too short") | |||
} | |||
var a Fp2Element | |||
c.Params.Op.FromMontgomery(fp2, &a) | |||
// convert to bytes in little endian form | |||
for i := 0; i < c.Params.Bytelen; i++ { | |||
// set i = j*8 + k | |||
fp2 := i / 8 | |||
k := uint64(i % 8) | |||
output[i] = byte(a.A[fp2] >> (8 * k)) | |||
output[i+c.Params.Bytelen] = byte(a.B[fp2] >> (8 * k)) | |||
} | |||
} | |||
// Read 2*bytelen(p) bytes into the given ExtensionFieldElement. | |||
// | |||
// It is an error to call this function if the input byte slice is less than 2*bytelen(p) bytes long. | |||
func (c *CurveOperations) Fp2FromBytes(fp2 *Fp2Element, input []byte) { | |||
if len(input) < 2*c.Params.Bytelen { | |||
panic("input byte slice too short") | |||
} | |||
for i:=0; i<c.Params.Bytelen; i++ { | |||
j := i / 8 | |||
k := uint64(i % 8) | |||
fp2.A[j] |= uint64(input[i]) << (8 * k) | |||
fp2.B[j] |= uint64(input[i+c.Params.Bytelen]) << (8 * k) | |||
} | |||
c.Params.Op.ToMontgomery(fp2) | |||
if len(input) < 2*c.Params.Bytelen { | |||
panic("input byte slice too short") | |||
} | |||
for i := 0; i < c.Params.Bytelen; i++ { | |||
j := i / 8 | |||
k := uint64(i % 8) | |||
fp2.A[j] |= uint64(input[i]) << (8 * k) | |||
fp2.B[j] |= uint64(input[i+c.Params.Bytelen]) << (8 * k) | |||
} | |||
c.Params.Op.ToMontgomery(fp2) | |||
} | |||
/* ------------------------------------------------------------------------- | |||
@@ -296,12 +296,12 @@ func (c *CurveOperations) Fp2FromBytes(fp2 *Fp2Element, input []byte) { | |||
// Constructs isogeny3 objects | |||
func Newisogeny3(op FieldOps) Isogeny { | |||
return &isogeny3{Field: op} | |||
return &isogeny3{Field: op} | |||
} | |||
// Constructs isogeny4 objects | |||
func Newisogeny4(op FieldOps) Isogeny { | |||
return &isogeny4{isogeny3: isogeny3{Field: op}} | |||
return &isogeny4{isogeny3: isogeny3{Field: op}} | |||
} | |||
// Given a three-torsion point p = x(PB) on the curve E_(A:C), construct the | |||
@@ -311,32 +311,32 @@ func Newisogeny4(op FieldOps) Isogeny { | |||
// Output: * Curve coordinates (A' + 2C', A' - 2C') corresponding to E_A'/C' = A_E/C/<P3> | |||
// * Isogeny phi with constants in F_p^2 | |||
func (phi *isogeny3) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv { | |||
var t0, t1, t2, t3, t4 Fp2Element | |||
var coefEq CurveCoefficientsEquiv | |||
var K1, K2 = &phi.K1, &phi.K2 | |||
op := phi.Field | |||
op.Sub(K1, &p.X, &p.Z) // K1 = XP3 - ZP3 | |||
op.Square(&t0, K1) // t0 = K1^2 | |||
op.Add(K2, &p.X, &p.Z) // K2 = XP3 + ZP3 | |||
op.Square(&t1, K2) // t1 = K2^2 | |||
op.Add(&t2, &t0, &t1) // t2 = t0 + t1 | |||
op.Add(&t3, K1, K2) // t3 = K1 + K2 | |||
op.Square(&t3, &t3) // t3 = t3^2 | |||
op.Sub(&t3, &t3, &t2) // t3 = t3 - t2 | |||
op.Add(&t2, &t1, &t3) // t2 = t1 + t3 | |||
op.Add(&t3, &t3, &t0) // t3 = t3 + t0 | |||
op.Add(&t4, &t3, &t0) // t4 = t3 + t0 | |||
op.Add(&t4, &t4, &t4) // t4 = t4 + t4 | |||
op.Add(&t4, &t1, &t4) // t4 = t1 + t4 | |||
op.Mul(&coefEq.C, &t2, &t4) // A24m = t2 * t4 | |||
op.Add(&t4, &t1, &t2) // t4 = t1 + t2 | |||
op.Add(&t4, &t4, &t4) // t4 = t4 + t4 | |||
op.Add(&t4, &t0, &t4) // t4 = t0 + t4 | |||
op.Mul(&t4, &t3, &t4) // t4 = t3 * t4 | |||
op.Sub(&t0, &t4, &coefEq.C) // t0 = t4 - A24m | |||
op.Add(&coefEq.A, &coefEq.C, &t0) // A24p = A24m + t0 | |||
return coefEq | |||
var t0, t1, t2, t3, t4 Fp2Element | |||
var coefEq CurveCoefficientsEquiv | |||
var K1, K2 = &phi.K1, &phi.K2 | |||
op := phi.Field | |||
op.Sub(K1, &p.X, &p.Z) // K1 = XP3 - ZP3 | |||
op.Square(&t0, K1) // t0 = K1^2 | |||
op.Add(K2, &p.X, &p.Z) // K2 = XP3 + ZP3 | |||
op.Square(&t1, K2) // t1 = K2^2 | |||
op.Add(&t2, &t0, &t1) // t2 = t0 + t1 | |||
op.Add(&t3, K1, K2) // t3 = K1 + K2 | |||
op.Square(&t3, &t3) // t3 = t3^2 | |||
op.Sub(&t3, &t3, &t2) // t3 = t3 - t2 | |||
op.Add(&t2, &t1, &t3) // t2 = t1 + t3 | |||
op.Add(&t3, &t3, &t0) // t3 = t3 + t0 | |||
op.Add(&t4, &t3, &t0) // t4 = t3 + t0 | |||
op.Add(&t4, &t4, &t4) // t4 = t4 + t4 | |||
op.Add(&t4, &t1, &t4) // t4 = t1 + t4 | |||
op.Mul(&coefEq.C, &t2, &t4) // A24m = t2 * t4 | |||
op.Add(&t4, &t1, &t2) // t4 = t1 + t2 | |||
op.Add(&t4, &t4, &t4) // t4 = t4 + t4 | |||
op.Add(&t4, &t0, &t4) // t4 = t0 + t4 | |||
op.Mul(&t4, &t3, &t4) // t4 = t3 * t4 | |||
op.Sub(&t0, &t4, &coefEq.C) // t0 = t4 - A24m | |||
op.Add(&coefEq.A, &coefEq.C, &t0) // A24p = A24m + t0 | |||
return coefEq | |||
} | |||
// Given a 3-isogeny phi and a point pB = x(PB), compute x(QB), the x-coordinate | |||
@@ -345,23 +345,23 @@ func (phi *isogeny3) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv { | |||
// The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve | |||
// parameters are returned by the GenerateCurve function used to construct phi. | |||
func (phi *isogeny3) EvaluatePoint(p *ProjectivePoint) ProjectivePoint { | |||
var t0, t1, t2 Fp2Element | |||
var q ProjectivePoint | |||
var K1, K2 = &phi.K1, &phi.K2 | |||
var px, pz = &p.X, &p.Z | |||
op := phi.Field | |||
op.Add(&t0, px, pz) // t0 = XQ + ZQ | |||
op.Sub(&t1, px, pz) // t1 = XQ - ZQ | |||
op.Mul(&t0, K1, &t0) // t2 = K1 * t0 | |||
op.Mul(&t1, K2, &t1) // t1 = K2 * t1 | |||
op.Add(&t2, &t0, &t1) // t2 = t0 + t1 | |||
op.Sub(&t0, &t1, &t0) // t0 = t1 - t0 | |||
op.Square(&t2, &t2) // t2 = t2 ^ 2 | |||
op.Square(&t0, &t0) // t0 = t0 ^ 2 | |||
op.Mul(&q.X, px, &t2) // XQ'= XQ * t2 | |||
op.Mul(&q.Z, pz, &t0) // ZQ'= ZQ * t0 | |||
return q | |||
var t0, t1, t2 Fp2Element | |||
var q ProjectivePoint | |||
var K1, K2 = &phi.K1, &phi.K2 | |||
var px, pz = &p.X, &p.Z | |||
op := phi.Field | |||
op.Add(&t0, px, pz) // t0 = XQ + ZQ | |||
op.Sub(&t1, px, pz) // t1 = XQ - ZQ | |||
op.Mul(&t0, K1, &t0) // t2 = K1 * t0 | |||
op.Mul(&t1, K2, &t1) // t1 = K2 * t1 | |||
op.Add(&t2, &t0, &t1) // t2 = t0 + t1 | |||
op.Sub(&t0, &t1, &t0) // t0 = t1 - t0 | |||
op.Square(&t2, &t2) // t2 = t2 ^ 2 | |||
op.Square(&t0, &t0) // t0 = t0 ^ 2 | |||
op.Mul(&q.X, px, &t2) // XQ'= XQ * t2 | |||
op.Mul(&q.Z, pz, &t0) // ZQ'= ZQ * t0 | |||
return q | |||
} | |||
// Given a four-torsion point p = x(PB) on the curve E_(A:C), construct the | |||
@@ -371,21 +371,21 @@ func (phi *isogeny3) EvaluatePoint(p *ProjectivePoint) ProjectivePoint { | |||
// Output: * Curve coordinates (A' + 2C', 4C') corresponding to E_A'/C' = A_E/C/<P4> | |||
// * Isogeny phi with constants in F_p^2 | |||
func (phi *isogeny4) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv { | |||
var coefEq CurveCoefficientsEquiv | |||
var xp4, zp4 = &p.X, &p.Z | |||
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3 | |||
op := phi.Field | |||
op.Sub(K2, xp4, zp4) | |||
op.Add(K3, xp4, zp4) | |||
op.Square(K1, zp4) | |||
op.Add(K1, K1, K1) | |||
op.Square(&coefEq.C, K1) | |||
op.Add(K1, K1, K1) | |||
op.Square(&coefEq.A, xp4) | |||
op.Add(&coefEq.A, &coefEq.A, &coefEq.A) | |||
op.Square(&coefEq.A, &coefEq.A) | |||
return coefEq | |||
var coefEq CurveCoefficientsEquiv | |||
var xp4, zp4 = &p.X, &p.Z | |||
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3 | |||
op := phi.Field | |||
op.Sub(K2, xp4, zp4) | |||
op.Add(K3, xp4, zp4) | |||
op.Square(K1, zp4) | |||
op.Add(K1, K1, K1) | |||
op.Square(&coefEq.C, K1) | |||
op.Add(K1, K1, K1) | |||
op.Square(&coefEq.A, xp4) | |||
op.Add(&coefEq.A, &coefEq.A, &coefEq.A) | |||
op.Square(&coefEq.A, &coefEq.A) | |||
return coefEq | |||
} | |||
// Given a 4-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate | |||
@@ -394,47 +394,47 @@ func (phi *isogeny4) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv { | |||
// Input: Isogeny returned by GenerateCurve and point q=(Qx,Qz) from E0_A/C | |||
// Output: Corresponding point q from E1_A'/C', where E1 is 4-isogenous to E0 | |||
func (phi *isogeny4) EvaluatePoint(p *ProjectivePoint) ProjectivePoint { | |||
var t0, t1 Fp2Element | |||
var q = *p | |||
var xq, zq = &q.X, &q.Z | |||
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3 | |||
op := phi.Field | |||
op.Add(&t0, xq, zq) | |||
op.Sub(&t1, xq, zq) | |||
op.Mul(xq, &t0, K2) | |||
op.Mul(zq, &t1, K3) | |||
op.Mul(&t0, &t0, &t1) | |||
op.Mul(&t0, &t0, K1) | |||
op.Add(&t1, xq, zq) | |||
op.Sub(zq, xq, zq) | |||
op.Square(&t1, &t1) | |||
op.Square(zq, zq) | |||
op.Add(xq, &t0, &t1) | |||
op.Sub(&t0, zq, &t0) | |||
op.Mul(xq, xq, &t1) | |||
op.Mul(zq, zq, &t0) | |||
return q | |||
var t0, t1 Fp2Element | |||
var q = *p | |||
var xq, zq = &q.X, &q.Z | |||
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3 | |||
op := phi.Field | |||
op.Add(&t0, xq, zq) | |||
op.Sub(&t1, xq, zq) | |||
op.Mul(xq, &t0, K2) | |||
op.Mul(zq, &t1, K3) | |||
op.Mul(&t0, &t0, &t1) | |||
op.Mul(&t0, &t0, K1) | |||
op.Add(&t1, xq, zq) | |||
op.Sub(zq, xq, zq) | |||
op.Square(&t1, &t1) | |||
op.Square(zq, zq) | |||
op.Add(xq, &t0, &t1) | |||
op.Sub(&t0, zq, &t0) | |||
op.Mul(xq, xq, &t1) | |||
op.Mul(zq, zq, &t0) | |||
return q | |||
} | |||
/* ------------------------------------------------------------------------- | |||
Utils | |||
-------------------------------------------------------------------------*/ | |||
func (point *ProjectivePoint) ToAffine(c *CurveOperations) *Fp2Element { | |||
var affine_x Fp2Element | |||
c.Params.Op.Inv(&affine_x, &point.Z) | |||
c.Params.Op.Mul(&affine_x, &affine_x, &point.X) | |||
return &affine_x | |||
var affine_x Fp2Element | |||
c.Params.Op.Inv(&affine_x, &point.Z) | |||
c.Params.Op.Mul(&affine_x, &affine_x, &point.X) | |||
return &affine_x | |||
} | |||
// Cleans data in fp | |||
func (fp *Fp2Element) Zeroize() { | |||
// Zeroizing in 2 seperated loops tells compiler to | |||
// use fast runtime.memclr() | |||
for i:=range fp.A { | |||
fp.A[i] = 0 | |||
} | |||
for i:=range fp.B { | |||
fp.B[i] = 0 | |||
} | |||
// Zeroizing in 2 seperated loops tells compiler to | |||
// use fast runtime.memclr() | |||
for i := range fp.A { | |||
fp.A[i] = 0 | |||
} | |||
for i := range fp.B { | |||
fp.B[i] = 0 | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
package internal | |||
const ( | |||
FP_MAX_WORDS = 12 // Currently p751.NumWords | |||
FP_MAX_WORDS = 12 // Currently p751.NumWords | |||
) | |||
// I keep it bool in order to be able to apply logical NOT | |||
@@ -14,58 +14,60 @@ type PrimeFieldId uint | |||
// an element in Montgomery form, or not. Tracking the meaning of the field | |||
// element is left to higher types. | |||
type FpElement [FP_MAX_WORDS]uint64 | |||
// Represents an intermediate product of two elements of the base field F_p. | |||
type FpElementX2 [2 * FP_MAX_WORDS]uint64 | |||
// Represents an element of the extended field Fp^2 = Fp(x+i) | |||
type Fp2Element struct { | |||
A FpElement | |||
B FpElement | |||
A FpElement | |||
B FpElement | |||
} | |||
type DomainParams struct { | |||
// P, Q and R=P-Q base points | |||
Affine_P, Affine_Q, Affine_R Fp2Element | |||
// Size of a compuatation strategy for x-torsion group | |||
IsogenyStrategy []uint32 | |||
// Max size of secret key for x-torsion group | |||
SecretBitLen uint | |||
// Max size of secret key for x-torsion group | |||
SecretByteLen uint | |||
// P, Q and R=P-Q base points | |||
Affine_P, Affine_Q, Affine_R Fp2Element | |||
// Size of a compuatation strategy for x-torsion group | |||
IsogenyStrategy []uint32 | |||
// Max size of secret key for x-torsion group | |||
SecretBitLen uint | |||
// Max size of secret key for x-torsion group | |||
SecretByteLen uint | |||
} | |||
type SidhParams struct { | |||
Id PrimeFieldId | |||
// Bytelen of P | |||
Bytelen int | |||
// The public key size, in bytes. | |||
PublicKeySize int | |||
// The shared secret size, in bytes. | |||
SharedSecretSize uint | |||
// 2- and 3-torsion group parameter definitions | |||
A, B DomainParams | |||
// Precomputed identity element in the Fp2 in Montgomery domain | |||
OneFp2 Fp2Element | |||
// Precomputed 1/2 in the Fp2 in Montgomery domain | |||
HalfFp2 Fp2Element | |||
// Length of SIKE secret message. Must be one of {24,32,40}, | |||
// depending on size of prime field used (see [SIKE], 1.4 and 5.1) | |||
MsgLen uint | |||
// Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1) | |||
KemSize uint | |||
// Access to field arithmetic | |||
Op FieldOps | |||
Id PrimeFieldId | |||
// Bytelen of P | |||
Bytelen int | |||
// The public key size, in bytes. | |||
PublicKeySize int | |||
// The shared secret size, in bytes. | |||
SharedSecretSize uint | |||
// 2- and 3-torsion group parameter definitions | |||
A, B DomainParams | |||
// Precomputed identity element in the Fp2 in Montgomery domain | |||
OneFp2 Fp2Element | |||
// Precomputed 1/2 in the Fp2 in Montgomery domain | |||
HalfFp2 Fp2Element | |||
// Length of SIKE secret message. Must be one of {24,32,40}, | |||
// depending on size of prime field used (see [SIKE], 1.4 and 5.1) | |||
MsgLen uint | |||
// Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1) | |||
KemSize uint | |||
// Access to field arithmetic | |||
Op FieldOps | |||
} | |||
// Interface for working with isogenies. | |||
type Isogeny interface { | |||
// Given a torsion point on a curve computes isogenous curve. | |||
// Returns curve coefficients (A:C), so that E_(A/C) = E_(A/C)/<P>, | |||
// where P is a provided projective point. Sets also isogeny constants | |||
// that are needed for isogeny evaluation. | |||
GenerateCurve(*ProjectivePoint) CurveCoefficientsEquiv | |||
// Evaluates isogeny at caller provided point. Requires isogeny curve constants | |||
// to be earlier computed by GenerateCurve. | |||
EvaluatePoint(*ProjectivePoint) ProjectivePoint | |||
// Given a torsion point on a curve computes isogenous curve. | |||
// Returns curve coefficients (A:C), so that E_(A/C) = E_(A/C)/<P>, | |||
// where P is a provided projective point. Sets also isogeny constants | |||
// that are needed for isogeny evaluation. | |||
GenerateCurve(*ProjectivePoint) CurveCoefficientsEquiv | |||
// Evaluates isogeny at caller provided point. Requires isogeny curve constants | |||
// to be earlier computed by GenerateCurve. | |||
EvaluatePoint(*ProjectivePoint) ProjectivePoint | |||
} | |||
// Stores curve projective parameters equivalent to A/C. Meaning of the | |||
@@ -75,8 +77,8 @@ type Isogeny interface { | |||
// * four then (A:C) ~ (A+2C: 4C) | |||
// See Appendix A of SIKE for more details | |||
type CurveCoefficientsEquiv struct { | |||
A Fp2Element | |||
C Fp2Element | |||
A Fp2Element | |||
C Fp2Element | |||
} | |||
// A point on the projective line P^1(F_{p^2}). | |||
@@ -84,59 +86,59 @@ type CurveCoefficientsEquiv struct { | |||
// This represents a point on the Kummer line of a Montgomery curve. The | |||
// curve is specified by a ProjectiveCurveParameters struct. | |||
type ProjectivePoint struct { | |||
X Fp2Element | |||
Z Fp2Element | |||
X Fp2Element | |||
Z Fp2Element | |||
} | |||
// A point on the projective line P^1(F_{p^2}). | |||
// | |||
// This is used to work projectively with the curve coefficients. | |||
type ProjectiveCurveParameters struct { | |||
A Fp2Element | |||
C Fp2Element | |||
A Fp2Element | |||
C Fp2Element | |||
} | |||
// Stores Isogeny 3 curve constants | |||
type isogeny3 struct { | |||
Field FieldOps | |||
K1 Fp2Element | |||
K2 Fp2Element | |||
Field FieldOps | |||
K1 Fp2Element | |||
K2 Fp2Element | |||
} | |||
// Stores Isogeny 4 curve constants | |||
type isogeny4 struct { | |||
isogeny3 | |||
K3 Fp2Element | |||
isogeny3 | |||
K3 Fp2Element | |||
} | |||
type FieldOps interface { | |||
// Set res = lhs + rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Add(res, lhs, rhs *Fp2Element) | |||
// Set res = lhs - rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Sub(res, lhs, rhs *Fp2Element) | |||
// Set res = lhs * rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Mul(res, lhs, rhs *Fp2Element) | |||
// Set res = x * x | |||
// | |||
// Allowed to overlap res with x. | |||
Square(res, x *Fp2Element) | |||
// Set res = 1/x | |||
// | |||
// Allowed to overlap res with x. | |||
Inv(res, x *Fp2Element) | |||
// If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y). | |||
CondSwap(xPx, xPz, xQx, xQz *Fp2Element, choice uint8) | |||
// Converts Fp2Element to Montgomery domain (x*R mod p) | |||
ToMontgomery(x *Fp2Element) | |||
// Converts 'a' in montgomery domain to element from Fp2Element | |||
// and stores it in 'x' | |||
FromMontgomery(x *Fp2Element, a *Fp2Element) | |||
// Set res = lhs + rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Add(res, lhs, rhs *Fp2Element) | |||
// Set res = lhs - rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Sub(res, lhs, rhs *Fp2Element) | |||
// Set res = lhs * rhs. | |||
// | |||
// Allowed to overlap lhs or rhs with res. | |||
Mul(res, lhs, rhs *Fp2Element) | |||
// Set res = x * x | |||
// | |||
// Allowed to overlap res with x. | |||
Square(res, x *Fp2Element) | |||
// Set res = 1/x | |||
// | |||
// Allowed to overlap res with x. | |||
Inv(res, x *Fp2Element) | |||
// If choice = 1u8, set (x,y) = (y,x). If choice = 0u8, set (x,y) = (x,y). | |||
CondSwap(xPx, xPz, xQx, xQz *Fp2Element, choice uint8) | |||
// Converts Fp2Element to Montgomery domain (x*R mod p) | |||
ToMontgomery(x *Fp2Element) | |||
// Converts 'a' in montgomery domain to element from Fp2Element | |||
// and stores it in 'x' | |||
FromMontgomery(x *Fp2Element, a *Fp2Element) | |||
} |
@@ -9,6 +9,7 @@ package utils | |||
// Signals support for MULX which is in BMI2 | |||
var HasBMI2 bool | |||
// Signals support for MULX and BMI2 | |||
var HasADX bool | |||
@@ -18,17 +19,17 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) | |||
// Returns true in case bit 'n' in 'bits' is set, otherwise false | |||
func bitn(bits uint32, n uint8) bool { | |||
return (bits>>n)&1 == 1 | |||
return (bits>>n)&1 == 1 | |||
} | |||
func init() { | |||
// CPUID returns max possible input that can be requested | |||
max, _, _, _ := cpuid(0,0) | |||
if max < 7 { | |||
return | |||
} | |||
_, ebx, _, _ := cpuid(7,0) | |||
HasBMI2 = bitn(ebx, 19) | |||
HasADX = bitn(ebx, 7) | |||
// CPUID returns max possible input that can be requested | |||
max, _, _, _ := cpuid(0, 0) | |||
if max < 7 { | |||
return | |||
} | |||
_, ebx, _, _ := cpuid(7, 0) | |||
HasBMI2 = bitn(ebx, 19) | |||
HasADX = bitn(ebx, 7) | |||
} |
@@ -3,7 +3,7 @@ | |||
package p751 | |||
import ( | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
cpu "github.com/cloudflare/p751sidh/internal/utils" | |||
"testing" | |||
@@ -3,8 +3,8 @@ | |||
package p751 | |||
import ( | |||
cpu "github.com/cloudflare/p751sidh/internal/utils" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
cpu "github.com/cloudflare/p751sidh/internal/utils" | |||
) | |||
// If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x. | |||
@@ -3,8 +3,8 @@ | |||
package p751 | |||
import ( | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
. "github.com/cloudflare/p751sidh/internal/arith" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
) | |||
// Compute z = x + y (mod p). | |||
@@ -1,10 +1,10 @@ | |||
package p751 | |||
import ( | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"math/big" | |||
"testing" | |||
"testing/quick" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"testing/quick" | |||
) | |||
func TestPrimeFieldElementToBigInt(t *testing.T) { | |||
@@ -149,7 +149,7 @@ func TestFp2ElementBatch3Inv(t *testing.T) { | |||
var y1, y2, y3 Fp2Element | |||
kCurveOps.Fp2Batch3Inv(&x1.ExtElem, &x2.ExtElem, &x3.ExtElem, &y1, &y2, &y3) | |||
return (VartimeEqFp2(&x1Inv,&y1) && VartimeEqFp2(&x2Inv,&y2) && VartimeEqFp2(&x3Inv,&y3)) | |||
return (VartimeEqFp2(&x1Inv, &y1) && VartimeEqFp2(&x2Inv, &y2) && VartimeEqFp2(&x3Inv, &y3)) | |||
} | |||
// This is more expensive; run fewer tests | |||
@@ -199,15 +199,15 @@ var p751R2 = FpElement{ | |||
// 1*R mod p | |||
var P751_OneFp2 = Fp2Element{ | |||
A: FpElement{ | |||
0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2}, | |||
A: FpElement{ | |||
0x249ad, 0x0, 0x0, 0x0, 0x0, 0x8310000000000000, 0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x2d5b24bce5e2}, | |||
} | |||
// 1/2 * R mod p | |||
var P751_HalfFp2 = Fp2Element{ | |||
A: FpElement{ | |||
0x00000000000124D6, 0x0000000000000000, 0x0000000000000000, | |||
0x0000000000000000, 0x0000000000000000, 0xB8E0000000000000, | |||
0x9C8A2434C0AA7287, 0xA206996CA9A378A3, 0x6876280D41A41B52, | |||
0xE903B49F175CE04F, 0x0F8511860666D227, 0x00004EA07CFF6E7F}, | |||
A: FpElement{ | |||
0x00000000000124D6, 0x0000000000000000, 0x0000000000000000, | |||
0x0000000000000000, 0x0000000000000000, 0xB8E0000000000000, | |||
0x9C8A2434C0AA7287, 0xA206996CA9A378A3, 0x6876280D41A41B52, | |||
0xE903B49F175CE04F, 0x0F8511860666D227, 0x00004EA07CFF6E7F}, | |||
} |
@@ -2,9 +2,9 @@ package p751 | |||
import ( | |||
"bytes" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"testing" | |||
"testing/quick" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
) | |||
func TestOne(t *testing.T) { | |||
@@ -164,9 +164,9 @@ func TestPointTripleVersusAddDouble(t *testing.T) { | |||
eqivParams3 := kCurveOps.CalcCurveParamsEquiv3(¶ms.Cparam) | |||
P2 = params.Point | |||
P3 = params.Point | |||
kCurveOps.Pow2k(&P2, &eqivParams4, 1) // = x([2]P) | |||
kCurveOps.Pow3k(&P3, &eqivParams3, 1) // = x([3]P) | |||
P2plusP = AddProjFp2(&P2, ¶ms.Point, ¶ms.Point) // = x([2]P + P) | |||
kCurveOps.Pow2k(&P2, &eqivParams4, 1) // = x([2]P) | |||
kCurveOps.Pow3k(&P3, &eqivParams3, 1) // = x([3]P) | |||
P2plusP = AddProjFp2(&P2, ¶ms.Point, ¶ms.Point) // = x([2]P + P) | |||
return VartimeEqProjFp2(&P3, &P2plusP) | |||
} | |||
@@ -3,8 +3,7 @@ package p751 | |||
import . "github.com/cloudflare/p751sidh/internal/isogeny" | |||
// 2*p751 | |||
var ( | |||
) | |||
var () | |||
//------------------------------------------------------------------------------ | |||
// Implementtaion of FieldOperations | |||
@@ -148,8 +147,8 @@ func (fp751Ops) ToMontgomery(x *Fp2Element) { | |||
var aRR FpElementX2 | |||
// convert to montgomery domain | |||
fp751Mul(&aRR, &x.A, &p751R2) // = a*R*R | |||
fp751MontgomeryReduce(&x.A, &aRR) // = a*R mod p | |||
fp751Mul(&aRR, &x.A, &p751R2) // = a*R*R | |||
fp751MontgomeryReduce(&x.A, &aRR) // = a*R mod p | |||
fp751Mul(&aRR, &x.B, &p751R2) | |||
fp751MontgomeryReduce(&x.B, &aRR) | |||
} | |||
@@ -164,9 +163,9 @@ func (fp751Ops) FromMontgomery(x *Fp2Element, out *Fp2Element) { | |||
// convert from montgomery domain | |||
copy(aR[:], x.A[:]) | |||
fp751MontgomeryReduce(&out.A, &aR) // = a mod p in [0, 2p) | |||
fp751StrongReduce(&out.A) // = a mod p in [0, p) | |||
for i:=range(aR) { | |||
fp751MontgomeryReduce(&out.A, &aR) // = a mod p in [0, 2p) | |||
fp751StrongReduce(&out.A) // = a mod p in [0, p) | |||
for i := range aR { | |||
aR[i] = 0 | |||
} | |||
copy(aR[:], x.B[:]) | |||
@@ -1,8 +1,8 @@ | |||
package p751 | |||
import ( | |||
"testing" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"testing" | |||
) | |||
func TestFourIsogenyVersusSage(t *testing.T) { | |||
@@ -4,119 +4,118 @@ package p751 | |||
import ( | |||
"fmt" | |||
"math/big" | |||
"math/rand" | |||
"reflect" | |||
"testing/quick" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"math/big" | |||
"math/rand" | |||
"reflect" | |||
"testing/quick" | |||
) | |||
/* ------------------------------------------------------------------------- | |||
Underlying field configuration | |||
-------------------------------------------------------------------------*/ | |||
var ( | |||
kFieldOps = FieldOperations() | |||
kParams = &SidhParams{ | |||
Op: kFieldOps, | |||
OneFp2: P751_OneFp2, | |||
HalfFp2: P751_HalfFp2, | |||
Bytelen: P751_Bytelen, | |||
} | |||
kCurveOps = &CurveOperations{Params: kParams} | |||
kFieldOps = FieldOperations() | |||
kParams = &SidhParams{ | |||
Op: kFieldOps, | |||
OneFp2: P751_OneFp2, | |||
HalfFp2: P751_HalfFp2, | |||
Bytelen: P751_Bytelen, | |||
} | |||
kCurveOps = &CurveOperations{Params: kParams} | |||
) | |||
/* ------------------------------------------------------------------------- | |||
Configure testing/quick | |||
-------------------------------------------------------------------------*/ | |||
var ( | |||
quickCheckScaleFactor = uint8(3) | |||
quickCheckConfig = &quick.Config{MaxCount: (1 << (12 + quickCheckScaleFactor))} | |||
quickCheckScaleFactor = uint8(3) | |||
quickCheckConfig = &quick.Config{MaxCount: (1 << (12 + quickCheckScaleFactor))} | |||
) | |||
/* ------------------------------------------------------------------------- | |||
Structure used by tests | |||
-------------------------------------------------------------------------*/ | |||
type GeneratedTestParams struct { | |||
Point ProjectivePoint | |||
Cparam ProjectiveCurveParameters | |||
ExtElem Fp2Element | |||
Point ProjectivePoint | |||
Cparam ProjectiveCurveParameters | |||
ExtElem Fp2Element | |||
} | |||
/* ------------------------------------------------------------------------- | |||
Test values | |||
-------------------------------------------------------------------------*/ | |||
Test values | |||
-------------------------------------------------------------------------*/ | |||
// A = 4385300808024233870220415655826946795549183378139271271040522089756750951667981765872679172832050962894122367066234419550072004266298327417513857609747116903999863022476533671840646615759860564818837299058134292387429068536219*i + 1408083354499944307008104531475821995920666351413327060806684084512082259107262519686546161682384352696826343970108773343853651664489352092568012759783386151707999371397181344707721407830640876552312524779901115054295865393760 | |||
var ( | |||
curve_A = Fp2Element{ | |||
A: FpElement{0x8319eb18ca2c435e, 0x3a93beae72cd0267, 0x5e465e1f72fd5a84, 0x8617fa4150aa7272, 0x887da24799d62a13, 0xb079b31b3c7667fe, 0xc4661b150fa14f2e, 0xd4d2b2967bc6efd6, 0x854215a8b7239003, 0x61c5302ccba656c2, 0xf93194a27d6f97a2, 0x1ed9532bca75}, | |||
B: FpElement{0xb6f541040e8c7db6, 0x99403e7365342e15, 0x457e9cee7c29cced, 0x8ece72dc073b1d67, 0x6e73cef17ad28d28, 0x7aed836ca317472, 0x89e1de9454263b54, 0x745329277aa0071b, 0xf623dfc73bc86b9b, 0xb8e3c1d8a9245882, 0x6ad0b3d317770bec, 0x5b406e8d502b}} | |||
// C = 933177602672972392833143808100058748100491911694554386487433154761658932801917030685312352302083870852688835968069519091048283111836766101703759957146191882367397129269726925521881467635358356591977198680477382414690421049768*i + 9088894745865170214288643088620446862479558967886622582768682946704447519087179261631044546285104919696820250567182021319063155067584445633834024992188567423889559216759336548208016316396859149888322907914724065641454773776307 | |||
curve_C = Fp2Element{ | |||
A: FpElement{0x4fb2358bbf723107, 0x3a791521ac79e240, 0x283e24ef7c4c922f, 0xc89baa1205e33cc, 0x3031be81cff6fee1, 0xaf7a494a2f6a95c4, 0x248d251eaac83a1d, 0xc122fca1e2550c88, 0xbc0451b11b6cfd3d, 0x9c0a114ab046222c, 0x43b957b32f21f6ea, 0x5b9c87fa61de}, | |||
B: FpElement{0xacf142afaac15ec6, 0xfd1322a504a071d5, 0x56bb205e10f6c5c6, 0xe204d2849a97b9bd, 0x40b0122202fe7f2e, 0xecf72c6fafacf2cb, 0x45dfc681f869f60a, 0x11814c9aff4af66c, 0x9278b0c4eea54fe7, 0x9a633d5baf7f2e2e, 0x69a329e6f1a05112, 0x1d874ace23e4}} | |||
// x(P) = 8172151271761071554796221948801462094972242987811852753144865524899433583596839357223411088919388342364651632180452081960511516040935428737829624206426287774255114241789158000915683252363913079335550843837650671094705509470594*i + 9326574858039944121604015439381720195556183422719505497448541073272720545047742235526963773359004021838961919129020087515274115525812121436661025030481584576474033630899768377131534320053412545346268645085054880212827284581557 | |||
affine_xP = Fp2Element{ | |||
A: FpElement{0xe8d05f30aac47247, 0x576ec00c55441de7, 0xbf1a8ec5fe558518, 0xd77cb17f77515881, 0x8e9852837ee73ec4, 0x8159634ad4f44a6b, 0x2e4eb5533a798c5, 0x9be8c4354d5bc849, 0xf47dc61806496b84, 0x25d0e130295120e0, 0xdbef54095f8139e3, 0x5a724f20862c}, | |||
B: FpElement{0x3ca30d7623602e30, 0xfb281eddf45f07b7, 0xd2bf62d5901a45bc, 0xc67c9baf86306dd2, 0x4e2bd93093f538ca, 0xcfd92075c25b9cbe, 0xceafe9a3095bcbab, 0x7d928ad380c85414, 0x37c5f38b2afdc095, 0x75325899a7b779f4, 0xf130568249f20fdd, 0x178f264767d1}} | |||
// x([2]P) = 1476586462090705633631615225226507185986710728845281579274759750260315746890216330325246185232948298241128541272709769576682305216876843626191069809810990267291824247158062860010264352034514805065784938198193493333201179504845*i + 3623708673253635214546781153561465284135688791018117615357700171724097420944592557655719832228709144190233454198555848137097153934561706150196041331832421059972652530564323645509890008896574678228045006354394485640545367112224 | |||
affine_xP2 = Fp2Element{ | |||
A: FpElement{0x2a77afa8576ce979, 0xab1360e69b0aeba0, 0xd79e3e3cbffad660, 0x5fd0175aa10f106b, 0x1800ebafce9fbdbc, 0x228fc9142bdd6166, 0x867cf907314e34c3, 0xa58d18c94c13c31c, 0x699a5bc78b11499f, 0xa29fc29a01f7ccf1, 0x6c69c0c5347eebce, 0x38ecee0cc57}, | |||
B: FpElement{0x43607fd5f4837da0, 0x560bad4ce27f8f4a, 0x2164927f8495b4dd, 0x621103fdb831a997, 0xad740c4eea7db2db, 0x2cde0442205096cd, 0x2af51a70ede8324e, 0x41a4e680b9f3466, 0x5481f74660b8f476, 0xfcb2f3e656ff4d18, 0x42e3ce0837171acc, 0x44238c30530c}} | |||
// x([3]P) = 9351941061182433396254169746041546943662317734130813745868897924918150043217746763025923323891372857734564353401396667570940585840576256269386471444236630417779544535291208627646172485976486155620044292287052393847140181703665*i + 9010417309438761934687053906541862978676948345305618417255296028956221117900864204687119686555681136336037659036201780543527957809743092793196559099050594959988453765829339642265399496041485088089691808244290286521100323250273 | |||
affine_xP3 = Fp2Element{ | |||
A: FpElement{0x2096e3f23feca947, 0xf36f635aa4ad8634, 0xdae3b1c6983c5e9a, 0xe08df6c262cb74b4, 0xd2ca4edc37452d3d, 0xfb5f3fe42f500c79, 0x73740aa3abc2b21f, 0xd535fd869f914cca, 0x4a558466823fb67f, 0x3e50a7a0e3bfc715, 0xf43c6da9183a132f, 0x61aca1e1b8b9}, | |||
B: FpElement{0x1e54ec26ea5077bd, 0x61380572d8769f9a, 0xc615170684f59818, 0x6309c3b93e84ef6e, 0x33c74b1318c3fcd0, 0xfe8d7956835afb14, 0x2d5a7b55423c1ecc, 0x869db67edfafea68, 0x1292632394f0a628, 0x10bba48225bfd141, 0x6466c28b408daba, 0x63cacfdb7c43}} | |||
// x([2^2]P) = 441719501189485559222919502512761433931671682884872259563221427434901842337947564993718830905758163254463901652874331063768876314142359813382575876106725244985607032091781306919778265250690045578695338669105227100119314831452*i + 6961734028200975729170216310486458180126343885294922940439352055937945948015840788921225114530454649744697857047401608073256634790353321931728699534700109268264491160589480994022419317695690866764726967221310990488404411684053 | |||
affine_xP4 = Fp2Element{ | |||
A: FpElement{0x6f9dbe4c39175153, 0xf2fec757eb99e88, 0x43d7361a93733d91, 0x3abd10ed19c85a3d, 0xc4de9ab9c5ef7181, 0x53e375901684c900, 0x68ffc3e7d71c41ff, 0x47adab62c8d942fe, 0x226a33fd6fbb381d, 0x87ef4c8fdd83309a, 0xaca1cf44c5fa8799, 0x6cbae86c755f}, | |||
B: FpElement{0x4c80c37fe68282a7, 0xbd8b9d7248bf553a, 0x1fb0e8e74d5e1762, 0xb63fa0e4e5f91482, 0xc675ab8a45a1439, 0xdfa6772deace7820, 0xf0d813d71d9a9255, 0x53a1a58c634534bd, 0x4ebfc6485fdfd888, 0x6991fe4358bcf169, 0xc0547bdaca85b6fd, 0xf461548d632}} | |||
// x([3^2]P) = 3957171963425208493644602380039721164492341594850197356580248639045894821895524981729970650520936632013218950972842867220898274664982599375786979902471523505057611521217523103474682939638645404445093536997296151472632038973463*i + 1357869545269286021642168835877253886774707209614159162748874474269328421720121175566245719916322684751967981171882659798149072149161259103020057556362998810229937432814792024248155991141511691087135859252304684633946087474060 | |||
affine_xP9 = Fp2Element{ | |||
A: FpElement{0x7c0daa0f04ded4e0, 0x52dc4f883d85e065, 0x91afbdc2c1714d0b, 0xb7b3db8e658cfeba, 0x43d4e72a692882f3, 0x535c56d83753da30, 0xc8a58724433cbf5d, 0x351153c0a5e74219, 0x2c81827d19f93dd5, 0x26ef8aca3370ea1a, 0x1cf939a6dd225dec, 0x3403cb28ad41}, | |||
B: FpElement{0x93e7bc373a9ff7b, 0x57b8cc47635ebc0f, 0x92eab55689106cf3, 0x93643111d421f24c, 0x1c58b519506f6b7a, 0xebd409fb998faa13, 0x5c86ed799d09d80e, 0xd9a1d764d6363562, 0xf95e87f92fb0c4cc, 0x6b2bbaf5632a5609, 0x2d9b6a809dfaff7f, 0x29c0460348b}} | |||
// m = 96550223052359874398280314003345143371473380422728857598463622014420884224892 | |||
mScalarBytes = [...]uint8{0x7c, 0x7b, 0x95, 0xfa, 0xb4, 0x75, 0x6c, 0x48, 0x8c, 0x17, 0x55, 0xb4, 0x49, 0xf5, 0x1e, 0xa3, 0xb, 0x31, 0xf0, 0xa4, 0xa6, 0x81, 0xad, 0x94, 0x51, 0x11, 0xe7, 0xf5, 0x5b, 0x7d, 0x75, 0xd5} | |||
// x([m]P) = 7893578558852400052689739833699289348717964559651707250677393044951777272628231794999463214496545377542328262828965953246725804301238040891993859185944339366910592967840967752138115122568615081881937109746463885908097382992642*i + 8293895847098220389503562888233557012043261770526854885191188476280014204211818299871679993460086974249554528517413590157845430186202704783785316202196966198176323445986064452630594623103149383929503089342736311904030571524837 | |||
affine_xaP = Fp2Element{ | |||
A: FpElement{0x2112f3c7d7f938bb, 0x704a677f0a4df08f, 0x825370e31fb4ef00, 0xddbf79b7469f902, 0x27640c899ea739fd, 0xfb7b8b19f244108e, 0x546a6679dd3baebc, 0xe9f0ecf398d5265f, 0x223d2b350e75e461, 0x84b322a0b6aff016, 0xfabe426f539f8b39, 0x4507a0604f50}, | |||
B: FpElement{0xac77737e5618a5fe, 0xf91c0e08c436ca52, 0xd124037bc323533c, 0xc9a772bf52c58b63, 0x3b30c8f38ef6af4d, 0xb9eed160e134f36e, 0x24e3836393b25017, 0xc828be1b11baf1d9, 0x7b7dab585df50e93, 0x1ca3852c618bd8e0, 0x4efa73bcb359fa00, 0x50b6a923c2d4}} | |||
// Inputs for testing 3-point-ladder | |||
threePointLadderInputs = []ProjectivePoint{ | |||
// x(P) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0xe8d05f30aac47247, 0x576ec00c55441de7, 0xbf1a8ec5fe558518, 0xd77cb17f77515881, 0x8e9852837ee73ec4, 0x8159634ad4f44a6b, 0x2e4eb5533a798c5, 0x9be8c4354d5bc849, 0xf47dc61806496b84, 0x25d0e130295120e0, 0xdbef54095f8139e3, 0x5a724f20862c}, | |||
B: FpElement{0x3ca30d7623602e30, 0xfb281eddf45f07b7, 0xd2bf62d5901a45bc, 0xc67c9baf86306dd2, 0x4e2bd93093f538ca, 0xcfd92075c25b9cbe, 0xceafe9a3095bcbab, 0x7d928ad380c85414, 0x37c5f38b2afdc095, 0x75325899a7b779f4, 0xf130568249f20fdd, 0x178f264767d1}}, | |||
Z: P751_OneFp2, | |||
}, | |||
// x(Q) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0x2b71a2a93ad1e10e, 0xf0b9842a92cfb333, 0xae17373615a27f5c, 0x3039239f428330c4, 0xa0c4b735ed7dcf98, 0x6e359771ddf6af6a, 0xe986e4cac4584651, 0x8233a2b622d5518, 0xbfd67bf5f06b818b, 0xdffe38d0f5b966a6, 0xa86b36a3272ee00a, 0x193e2ea4f68f}, | |||
B: FpElement{0x5a0f396459d9d998, 0x479f42250b1b7dda, 0x4016b57e2a15bf75, 0xc59f915203fa3749, 0xd5f90257399cf8da, 0x1fb2dadfd86dcef4, 0x600f20e6429021dc, 0x17e347d380c57581, 0xc1b0d5fa8fe3e440, 0xbcf035330ac20e8, 0x50c2eb5f6a4f03e6, 0x86b7c4571}}, | |||
Z: P751_OneFp2, | |||
}, | |||
// x(P-Q) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0x4aafa9f378f7b5ff, 0x1172a683aa8eee0, 0xea518d8cbec2c1de, 0xe191bcbb63674557, 0x97bc19637b259011, 0xdbeae5c9f4a2e454, 0x78f64d1b72a42f95, 0xe71cb4ea7e181e54, 0xe4169d4c48543994, 0x6198c2286a98730f, 0xd21d675bbab1afa5, 0x2e7269fce391}, | |||
B: FpElement{0x23355783ce1d0450, 0x683164cf4ce3d93f, 0xae6d1c4d25970fd8, 0x7807007fb80b48cf, 0xa005a62ec2bbb8a2, 0x6b5649bd016004cb, 0xbb1a13fa1330176b, 0xbf38e51087660461, 0xe577fddc5dd7b930, 0x5f38116f56947cd3, 0x3124f30b98c36fde, 0x4ca9b6e6db37}}, | |||
Z: P751_OneFp2, | |||
}, | |||
} | |||
curve = ProjectiveCurveParameters{A: curve_A, C: curve_C} | |||
cln16prime, _ = new(big.Int).SetString("10354717741769305252977768237866805321427389645549071170116189679054678940682478846502882896561066713624553211618840202385203911976522554393044160468771151816976706840078913334358399730952774926980235086850991501872665651576831", 10) | |||
curve_A = Fp2Element{ | |||
A: FpElement{0x8319eb18ca2c435e, 0x3a93beae72cd0267, 0x5e465e1f72fd5a84, 0x8617fa4150aa7272, 0x887da24799d62a13, 0xb079b31b3c7667fe, 0xc4661b150fa14f2e, 0xd4d2b2967bc6efd6, 0x854215a8b7239003, 0x61c5302ccba656c2, 0xf93194a27d6f97a2, 0x1ed9532bca75}, | |||
B: FpElement{0xb6f541040e8c7db6, 0x99403e7365342e15, 0x457e9cee7c29cced, 0x8ece72dc073b1d67, 0x6e73cef17ad28d28, 0x7aed836ca317472, 0x89e1de9454263b54, 0x745329277aa0071b, 0xf623dfc73bc86b9b, 0xb8e3c1d8a9245882, 0x6ad0b3d317770bec, 0x5b406e8d502b}} | |||
// C = 933177602672972392833143808100058748100491911694554386487433154761658932801917030685312352302083870852688835968069519091048283111836766101703759957146191882367397129269726925521881467635358356591977198680477382414690421049768*i + 9088894745865170214288643088620446862479558967886622582768682946704447519087179261631044546285104919696820250567182021319063155067584445633834024992188567423889559216759336548208016316396859149888322907914724065641454773776307 | |||
curve_C = Fp2Element{ | |||
A: FpElement{0x4fb2358bbf723107, 0x3a791521ac79e240, 0x283e24ef7c4c922f, 0xc89baa1205e33cc, 0x3031be81cff6fee1, 0xaf7a494a2f6a95c4, 0x248d251eaac83a1d, 0xc122fca1e2550c88, 0xbc0451b11b6cfd3d, 0x9c0a114ab046222c, 0x43b957b32f21f6ea, 0x5b9c87fa61de}, | |||
B: FpElement{0xacf142afaac15ec6, 0xfd1322a504a071d5, 0x56bb205e10f6c5c6, 0xe204d2849a97b9bd, 0x40b0122202fe7f2e, 0xecf72c6fafacf2cb, 0x45dfc681f869f60a, 0x11814c9aff4af66c, 0x9278b0c4eea54fe7, 0x9a633d5baf7f2e2e, 0x69a329e6f1a05112, 0x1d874ace23e4}} | |||
// x(P) = 8172151271761071554796221948801462094972242987811852753144865524899433583596839357223411088919388342364651632180452081960511516040935428737829624206426287774255114241789158000915683252363913079335550843837650671094705509470594*i + 9326574858039944121604015439381720195556183422719505497448541073272720545047742235526963773359004021838961919129020087515274115525812121436661025030481584576474033630899768377131534320053412545346268645085054880212827284581557 | |||
affine_xP = Fp2Element{ | |||
A: FpElement{0xe8d05f30aac47247, 0x576ec00c55441de7, 0xbf1a8ec5fe558518, 0xd77cb17f77515881, 0x8e9852837ee73ec4, 0x8159634ad4f44a6b, 0x2e4eb5533a798c5, 0x9be8c4354d5bc849, 0xf47dc61806496b84, 0x25d0e130295120e0, 0xdbef54095f8139e3, 0x5a724f20862c}, | |||
B: FpElement{0x3ca30d7623602e30, 0xfb281eddf45f07b7, 0xd2bf62d5901a45bc, 0xc67c9baf86306dd2, 0x4e2bd93093f538ca, 0xcfd92075c25b9cbe, 0xceafe9a3095bcbab, 0x7d928ad380c85414, 0x37c5f38b2afdc095, 0x75325899a7b779f4, 0xf130568249f20fdd, 0x178f264767d1}} | |||
// x([2]P) = 1476586462090705633631615225226507185986710728845281579274759750260315746890216330325246185232948298241128541272709769576682305216876843626191069809810990267291824247158062860010264352034514805065784938198193493333201179504845*i + 3623708673253635214546781153561465284135688791018117615357700171724097420944592557655719832228709144190233454198555848137097153934561706150196041331832421059972652530564323645509890008896574678228045006354394485640545367112224 | |||
affine_xP2 = Fp2Element{ | |||
A: FpElement{0x2a77afa8576ce979, 0xab1360e69b0aeba0, 0xd79e3e3cbffad660, 0x5fd0175aa10f106b, 0x1800ebafce9fbdbc, 0x228fc9142bdd6166, 0x867cf907314e34c3, 0xa58d18c94c13c31c, 0x699a5bc78b11499f, 0xa29fc29a01f7ccf1, 0x6c69c0c5347eebce, 0x38ecee0cc57}, | |||
B: FpElement{0x43607fd5f4837da0, 0x560bad4ce27f8f4a, 0x2164927f8495b4dd, 0x621103fdb831a997, 0xad740c4eea7db2db, 0x2cde0442205096cd, 0x2af51a70ede8324e, 0x41a4e680b9f3466, 0x5481f74660b8f476, 0xfcb2f3e656ff4d18, 0x42e3ce0837171acc, 0x44238c30530c}} | |||
// x([3]P) = 9351941061182433396254169746041546943662317734130813745868897924918150043217746763025923323891372857734564353401396667570940585840576256269386471444236630417779544535291208627646172485976486155620044292287052393847140181703665*i + 9010417309438761934687053906541862978676948345305618417255296028956221117900864204687119686555681136336037659036201780543527957809743092793196559099050594959988453765829339642265399496041485088089691808244290286521100323250273 | |||
affine_xP3 = Fp2Element{ | |||
A: FpElement{0x2096e3f23feca947, 0xf36f635aa4ad8634, 0xdae3b1c6983c5e9a, 0xe08df6c262cb74b4, 0xd2ca4edc37452d3d, 0xfb5f3fe42f500c79, 0x73740aa3abc2b21f, 0xd535fd869f914cca, 0x4a558466823fb67f, 0x3e50a7a0e3bfc715, 0xf43c6da9183a132f, 0x61aca1e1b8b9}, | |||
B: FpElement{0x1e54ec26ea5077bd, 0x61380572d8769f9a, 0xc615170684f59818, 0x6309c3b93e84ef6e, 0x33c74b1318c3fcd0, 0xfe8d7956835afb14, 0x2d5a7b55423c1ecc, 0x869db67edfafea68, 0x1292632394f0a628, 0x10bba48225bfd141, 0x6466c28b408daba, 0x63cacfdb7c43}} | |||
// x([2^2]P) = 441719501189485559222919502512761433931671682884872259563221427434901842337947564993718830905758163254463901652874331063768876314142359813382575876106725244985607032091781306919778265250690045578695338669105227100119314831452*i + 6961734028200975729170216310486458180126343885294922940439352055937945948015840788921225114530454649744697857047401608073256634790353321931728699534700109268264491160589480994022419317695690866764726967221310990488404411684053 | |||
affine_xP4 = Fp2Element{ | |||
A: FpElement{0x6f9dbe4c39175153, 0xf2fec757eb99e88, 0x43d7361a93733d91, 0x3abd10ed19c85a3d, 0xc4de9ab9c5ef7181, 0x53e375901684c900, 0x68ffc3e7d71c41ff, 0x47adab62c8d942fe, 0x226a33fd6fbb381d, 0x87ef4c8fdd83309a, 0xaca1cf44c5fa8799, 0x6cbae86c755f}, | |||
B: FpElement{0x4c80c37fe68282a7, 0xbd8b9d7248bf553a, 0x1fb0e8e74d5e1762, 0xb63fa0e4e5f91482, 0xc675ab8a45a1439, 0xdfa6772deace7820, 0xf0d813d71d9a9255, 0x53a1a58c634534bd, 0x4ebfc6485fdfd888, 0x6991fe4358bcf169, 0xc0547bdaca85b6fd, 0xf461548d632}} | |||
// x([3^2]P) = 3957171963425208493644602380039721164492341594850197356580248639045894821895524981729970650520936632013218950972842867220898274664982599375786979902471523505057611521217523103474682939638645404445093536997296151472632038973463*i + 1357869545269286021642168835877253886774707209614159162748874474269328421720121175566245719916322684751967981171882659798149072149161259103020057556362998810229937432814792024248155991141511691087135859252304684633946087474060 | |||
affine_xP9 = Fp2Element{ | |||
A: FpElement{0x7c0daa0f04ded4e0, 0x52dc4f883d85e065, 0x91afbdc2c1714d0b, 0xb7b3db8e658cfeba, 0x43d4e72a692882f3, 0x535c56d83753da30, 0xc8a58724433cbf5d, 0x351153c0a5e74219, 0x2c81827d19f93dd5, 0x26ef8aca3370ea1a, 0x1cf939a6dd225dec, 0x3403cb28ad41}, | |||
B: FpElement{0x93e7bc373a9ff7b, 0x57b8cc47635ebc0f, 0x92eab55689106cf3, 0x93643111d421f24c, 0x1c58b519506f6b7a, 0xebd409fb998faa13, 0x5c86ed799d09d80e, 0xd9a1d764d6363562, 0xf95e87f92fb0c4cc, 0x6b2bbaf5632a5609, 0x2d9b6a809dfaff7f, 0x29c0460348b}} | |||
// m = 96550223052359874398280314003345143371473380422728857598463622014420884224892 | |||
mScalarBytes = [...]uint8{0x7c, 0x7b, 0x95, 0xfa, 0xb4, 0x75, 0x6c, 0x48, 0x8c, 0x17, 0x55, 0xb4, 0x49, 0xf5, 0x1e, 0xa3, 0xb, 0x31, 0xf0, 0xa4, 0xa6, 0x81, 0xad, 0x94, 0x51, 0x11, 0xe7, 0xf5, 0x5b, 0x7d, 0x75, 0xd5} | |||
// x([m]P) = 7893578558852400052689739833699289348717964559651707250677393044951777272628231794999463214496545377542328262828965953246725804301238040891993859185944339366910592967840967752138115122568615081881937109746463885908097382992642*i + 8293895847098220389503562888233557012043261770526854885191188476280014204211818299871679993460086974249554528517413590157845430186202704783785316202196966198176323445986064452630594623103149383929503089342736311904030571524837 | |||
affine_xaP = Fp2Element{ | |||
A: FpElement{0x2112f3c7d7f938bb, 0x704a677f0a4df08f, 0x825370e31fb4ef00, 0xddbf79b7469f902, 0x27640c899ea739fd, 0xfb7b8b19f244108e, 0x546a6679dd3baebc, 0xe9f0ecf398d5265f, 0x223d2b350e75e461, 0x84b322a0b6aff016, 0xfabe426f539f8b39, 0x4507a0604f50}, | |||
B: FpElement{0xac77737e5618a5fe, 0xf91c0e08c436ca52, 0xd124037bc323533c, 0xc9a772bf52c58b63, 0x3b30c8f38ef6af4d, 0xb9eed160e134f36e, 0x24e3836393b25017, 0xc828be1b11baf1d9, 0x7b7dab585df50e93, 0x1ca3852c618bd8e0, 0x4efa73bcb359fa00, 0x50b6a923c2d4}} | |||
// Inputs for testing 3-point-ladder | |||
threePointLadderInputs = []ProjectivePoint{ | |||
// x(P) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0xe8d05f30aac47247, 0x576ec00c55441de7, 0xbf1a8ec5fe558518, 0xd77cb17f77515881, 0x8e9852837ee73ec4, 0x8159634ad4f44a6b, 0x2e4eb5533a798c5, 0x9be8c4354d5bc849, 0xf47dc61806496b84, 0x25d0e130295120e0, 0xdbef54095f8139e3, 0x5a724f20862c}, | |||
B: FpElement{0x3ca30d7623602e30, 0xfb281eddf45f07b7, 0xd2bf62d5901a45bc, 0xc67c9baf86306dd2, 0x4e2bd93093f538ca, 0xcfd92075c25b9cbe, 0xceafe9a3095bcbab, 0x7d928ad380c85414, 0x37c5f38b2afdc095, 0x75325899a7b779f4, 0xf130568249f20fdd, 0x178f264767d1}}, | |||
Z: P751_OneFp2, | |||
}, | |||
// x(Q) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0x2b71a2a93ad1e10e, 0xf0b9842a92cfb333, 0xae17373615a27f5c, 0x3039239f428330c4, 0xa0c4b735ed7dcf98, 0x6e359771ddf6af6a, 0xe986e4cac4584651, 0x8233a2b622d5518, 0xbfd67bf5f06b818b, 0xdffe38d0f5b966a6, 0xa86b36a3272ee00a, 0x193e2ea4f68f}, | |||
B: FpElement{0x5a0f396459d9d998, 0x479f42250b1b7dda, 0x4016b57e2a15bf75, 0xc59f915203fa3749, 0xd5f90257399cf8da, 0x1fb2dadfd86dcef4, 0x600f20e6429021dc, 0x17e347d380c57581, 0xc1b0d5fa8fe3e440, 0xbcf035330ac20e8, 0x50c2eb5f6a4f03e6, 0x86b7c4571}}, | |||
Z: P751_OneFp2, | |||
}, | |||
// x(P-Q) | |||
ProjectivePoint{ | |||
X: Fp2Element{ | |||
A: FpElement{0x4aafa9f378f7b5ff, 0x1172a683aa8eee0, 0xea518d8cbec2c1de, 0xe191bcbb63674557, 0x97bc19637b259011, 0xdbeae5c9f4a2e454, 0x78f64d1b72a42f95, 0xe71cb4ea7e181e54, 0xe4169d4c48543994, 0x6198c2286a98730f, 0xd21d675bbab1afa5, 0x2e7269fce391}, | |||
B: FpElement{0x23355783ce1d0450, 0x683164cf4ce3d93f, 0xae6d1c4d25970fd8, 0x7807007fb80b48cf, 0xa005a62ec2bbb8a2, 0x6b5649bd016004cb, 0xbb1a13fa1330176b, 0xbf38e51087660461, 0xe577fddc5dd7b930, 0x5f38116f56947cd3, 0x3124f30b98c36fde, 0x4ca9b6e6db37}}, | |||
Z: P751_OneFp2, | |||
}, | |||
} | |||
curve = ProjectiveCurveParameters{A: curve_A, C: curve_C} | |||
cln16prime, _ = new(big.Int).SetString("10354717741769305252977768237866805321427389645549071170116189679054678940682478846502882896561066713624553211618840202385203911976522554393044160468771151816976706840078913334358399730952774926980235086850991501872665651576831", 10) | |||
) | |||
/* ------------------------------------------------------------------------- | |||
@@ -126,17 +125,17 @@ var ( | |||
// Package-level storage for this field element is intended to deter | |||
// compiler optimizations. | |||
var ( | |||
benchmarkFpElement FpElement | |||
benchmarkFpElementX2 FpElementX2 | |||
bench_x = FpElement{17026702066521327207, 5108203422050077993, 10225396685796065916, 11153620995215874678, 6531160855165088358, 15302925148404145445, 1248821577836769963, 9789766903037985294, 7493111552032041328, 10838999828319306046, 18103257655515297935, 27403304611634} | |||
bench_y = FpElement{4227467157325093378, 10699492810770426363, 13500940151395637365, 12966403950118934952, 16517692605450415877, 13647111148905630666, 14223628886152717087, 7167843152346903316, 15855377759596736571, 4300673881383687338, 6635288001920617779, 30486099554235} | |||
bench_z = FpElementX2{1595347748594595712, 10854920567160033970, 16877102267020034574, 12435724995376660096, 3757940912203224231, 8251999420280413600, 3648859773438820227, 17622716832674727914, 11029567000887241528, 11216190007549447055, 17606662790980286987, 4720707159513626555, 12887743598335030915, 14954645239176589309, 14178817688915225254, 1191346797768989683, 12629157932334713723, 6348851952904485603, 16444232588597434895, 7809979927681678066, 14642637672942531613, 3092657597757640067, 10160361564485285723, 240071237} | |||
benchmarkFpElement FpElement | |||
benchmarkFpElementX2 FpElementX2 | |||
bench_x = FpElement{17026702066521327207, 5108203422050077993, 10225396685796065916, 11153620995215874678, 6531160855165088358, 15302925148404145445, 1248821577836769963, 9789766903037985294, 7493111552032041328, 10838999828319306046, 18103257655515297935, 27403304611634} | |||
bench_y = FpElement{4227467157325093378, 10699492810770426363, 13500940151395637365, 12966403950118934952, 16517692605450415877, 13647111148905630666, 14223628886152717087, 7167843152346903316, 15855377759596736571, 4300673881383687338, 6635288001920617779, 30486099554235} | |||
bench_z = FpElementX2{1595347748594595712, 10854920567160033970, 16877102267020034574, 12435724995376660096, 3757940912203224231, 8251999420280413600, 3648859773438820227, 17622716832674727914, 11029567000887241528, 11216190007549447055, 17606662790980286987, 4720707159513626555, 12887743598335030915, 14954645239176589309, 14178817688915225254, 1191346797768989683, 12629157932334713723, 6348851952904485603, 16444232588597434895, 7809979927681678066, 14642637672942531613, 3092657597757640067, 10160361564485285723, 240071237} | |||
) | |||
// Helpers | |||
func (primeElement primeFieldElement) String() string { | |||
b := toBigInt(&primeElement.A) | |||
return fmt.Sprintf("%X", b.String()) | |||
b := toBigInt(&primeElement.A) | |||
return fmt.Sprintf("%X", b.String()) | |||
} | |||
/* ------------------------------------------------------------------------- | |||
@@ -147,23 +146,23 @@ func (primeElement primeFieldElement) String() string { | |||
// | |||
// Returns xR to allow chaining. Safe to overlap xP, xQ, xR. | |||
func AddProjFp2(xP, xQ, xPmQ *ProjectivePoint) ProjectivePoint { | |||
// Algorithm 1 of Costello-Smith. | |||
var v0, v1, v2, v3, v4 Fp2Element | |||
var xR ProjectivePoint | |||
kFieldOps.Add(&v0, &xP.X, &xP.Z) // X_P + Z_P | |||
kFieldOps.Sub(&v1, &xQ.X, &xQ.Z) | |||
kFieldOps.Mul(&v1, &v1, &v0) // (X_Q - Z_Q)(X_P + Z_P) | |||
kFieldOps.Sub(&v0, &xP.X, &xP.Z) // X_P - Z_P | |||
kFieldOps.Add(&v2, &xQ.X, &xQ.Z) | |||
kFieldOps.Mul(&v2, &v2, &v0) // (X_Q + Z_Q)(X_P - Z_P) | |||
kFieldOps.Add(&v3, &v1, &v2) | |||
kFieldOps.Square(&v3, &v3) // 4(X_Q X_P - Z_Q Z_P)^2 | |||
kFieldOps.Sub(&v4, &v1, &v2) | |||
kFieldOps.Square(&v4, &v4) // 4(X_Q Z_P - Z_Q X_P)^2 | |||
kFieldOps.Mul(&v0, &xPmQ.Z, &v3) // 4X_{P-Q}(X_Q X_P - Z_Q Z_P)^2 | |||
kFieldOps.Mul(&xR.Z, &xPmQ.X, &v4) // 4Z_{P-Q}(X_Q Z_P - Z_Q X_P)^2 | |||
xR.X = v0 | |||
return xR | |||
// Algorithm 1 of Costello-Smith. | |||
var v0, v1, v2, v3, v4 Fp2Element | |||
var xR ProjectivePoint | |||
kFieldOps.Add(&v0, &xP.X, &xP.Z) // X_P + Z_P | |||
kFieldOps.Sub(&v1, &xQ.X, &xQ.Z) | |||
kFieldOps.Mul(&v1, &v1, &v0) // (X_Q - Z_Q)(X_P + Z_P) | |||
kFieldOps.Sub(&v0, &xP.X, &xP.Z) // X_P - Z_P | |||
kFieldOps.Add(&v2, &xQ.X, &xQ.Z) | |||
kFieldOps.Mul(&v2, &v2, &v0) // (X_Q + Z_Q)(X_P - Z_P) | |||
kFieldOps.Add(&v3, &v1, &v2) | |||
kFieldOps.Square(&v3, &v3) // 4(X_Q X_P - Z_Q Z_P)^2 | |||
kFieldOps.Sub(&v4, &v1, &v2) | |||
kFieldOps.Square(&v4, &v4) // 4(X_Q Z_P - Z_Q X_P)^2 | |||
kFieldOps.Mul(&v0, &xPmQ.Z, &v3) // 4X_{P-Q}(X_Q X_P - Z_Q Z_P)^2 | |||
kFieldOps.Mul(&xR.Z, &xPmQ.X, &v4) // 4Z_{P-Q}(X_Q Z_P - Z_Q X_P)^2 | |||
xR.X = v0 | |||
return xR | |||
} | |||
// Given xP = x(P) and cached curve parameters Aplus2C = A + 2*C, C4 = 4*C, | |||
@@ -171,24 +170,24 @@ func AddProjFp2(xP, xQ, xPmQ *ProjectivePoint) ProjectivePoint { | |||
// | |||
// Returns xQ to allow chaining. Safe to overlap xP, xQ. | |||
func DoubleProjFp2(xP *ProjectivePoint, Aplus2C, C4 *Fp2Element) ProjectivePoint { | |||
// Algorithm 2 of Costello-Smith, amended to work with projective curve coefficients. | |||
var v1, v2, v3, xz4 Fp2Element | |||
var xQ ProjectivePoint | |||
kFieldOps.Add(&v1, &xP.X, &xP.Z) // (X+Z)^2 | |||
kFieldOps.Square(&v1, &v1) | |||
kFieldOps.Sub(&v2, &xP.X, &xP.Z) // (X-Z)^2 | |||
kFieldOps.Square(&v2, &v2) | |||
kFieldOps.Sub(&xz4, &v1, &v2) // 4XZ = (X+Z)^2 - (X-Z)^2 | |||
kFieldOps.Mul(&v2, &v2, C4) // 4C(X-Z)^2 | |||
kFieldOps.Mul(&xQ.X, &v1, &v2) // 4C(X+Z)^2(X-Z)^2 | |||
kFieldOps.Mul(&v3, &xz4, Aplus2C) // 4XZ(A + 2C) | |||
kFieldOps.Add(&v3, &v3, &v2) // 4XZ(A + 2C) + 4C(X-Z)^2 | |||
kFieldOps.Mul(&xQ.Z, &v3, &xz4) // (4XZ(A + 2C) + 4C(X-Z)^2)4XZ | |||
// Now (xQ.x : xQ.z) | |||
// = (4C(X+Z)^2(X-Z)^2 : (4XZ(A + 2C) + 4C(X-Z)^2)4XZ ) | |||
// = ((X+Z)^2(X-Z)^2 : (4XZ((A + 2C)/4C) + (X-Z)^2)4XZ ) | |||
// = ((X+Z)^2(X-Z)^2 : (4XZ((a + 2)/4) + (X-Z)^2)4XZ ) | |||
return xQ | |||
// Algorithm 2 of Costello-Smith, amended to work with projective curve coefficients. | |||
var v1, v2, v3, xz4 Fp2Element | |||
var xQ ProjectivePoint | |||
kFieldOps.Add(&v1, &xP.X, &xP.Z) // (X+Z)^2 | |||
kFieldOps.Square(&v1, &v1) | |||
kFieldOps.Sub(&v2, &xP.X, &xP.Z) // (X-Z)^2 | |||
kFieldOps.Square(&v2, &v2) | |||
kFieldOps.Sub(&xz4, &v1, &v2) // 4XZ = (X+Z)^2 - (X-Z)^2 | |||
kFieldOps.Mul(&v2, &v2, C4) // 4C(X-Z)^2 | |||
kFieldOps.Mul(&xQ.X, &v1, &v2) // 4C(X+Z)^2(X-Z)^2 | |||
kFieldOps.Mul(&v3, &xz4, Aplus2C) // 4XZ(A + 2C) | |||
kFieldOps.Add(&v3, &v3, &v2) // 4XZ(A + 2C) + 4C(X-Z)^2 | |||
kFieldOps.Mul(&xQ.Z, &v3, &xz4) // (4XZ(A + 2C) + 4C(X-Z)^2)4XZ | |||
// Now (xQ.x : xQ.z) | |||
// = (4C(X+Z)^2(X-Z)^2 : (4XZ(A + 2C) + 4C(X-Z)^2)4XZ ) | |||
// = ((X+Z)^2(X-Z)^2 : (4XZ((A + 2C)/4C) + (X-Z)^2)4XZ ) | |||
// = ((X+Z)^2(X-Z)^2 : (4XZ((a + 2)/4) + (X-Z)^2)4XZ ) | |||
return xQ | |||
} | |||
// Given x(P) and a scalar m in little-endian bytes, compute x([m]P) using the | |||
@@ -200,142 +199,142 @@ func DoubleProjFp2(xP *ProjectivePoint, Aplus2C, C4 *Fp2Element) ProjectivePoint | |||
// | |||
// Safe to overlap the source with the destination. | |||
func ScalarMult(curve *ProjectiveCurveParameters, xP *ProjectivePoint, scalar []uint8) ProjectivePoint { | |||
var x0, x1, tmp ProjectivePoint | |||
var Aplus2C, C4 Fp2Element | |||
kFieldOps.Add(&Aplus2C, &curve.C, &curve.C) // = 2*C | |||
kFieldOps.Add(&C4, &Aplus2C, &Aplus2C) // = 4*C | |||
kFieldOps.Add(&Aplus2C, &Aplus2C, &curve.A) // = 2*C + A | |||
x0.X = P751_OneFp2 | |||
x1 = *xP | |||
// Iterate over the bits of the scalar, top to bottom | |||
prevBit := uint8(0) | |||
for i := len(scalar) - 1; i >= 0; i-- { | |||
scalarByte := scalar[i] | |||
for j := 7; j >= 0; j-- { | |||
bit := (scalarByte >> uint(j)) & 0x1 | |||
kCurveOps.Params.Op.CondSwap(&x0.X, &x0.Z, &x1.X, &x1.Z, (bit ^ prevBit)) | |||
//sProjectivePointConditionalSwap(&x0, &x1, (bit ^ prevBit)) | |||
tmp = DoubleProjFp2(&x0, &Aplus2C, &C4) | |||
x1 = AddProjFp2(&x0, &x1, xP) | |||
x0 = tmp | |||
prevBit = bit | |||
} | |||
} | |||
// now prevBit is the lowest bit of the scalar | |||
kCurveOps.Params.Op.CondSwap(&x0.X, &x0.Z, &x1.X, &x1.Z, prevBit) | |||
return x0 | |||
var x0, x1, tmp ProjectivePoint | |||
var Aplus2C, C4 Fp2Element | |||
kFieldOps.Add(&Aplus2C, &curve.C, &curve.C) // = 2*C | |||
kFieldOps.Add(&C4, &Aplus2C, &Aplus2C) // = 4*C | |||
kFieldOps.Add(&Aplus2C, &Aplus2C, &curve.A) // = 2*C + A | |||
x0.X = P751_OneFp2 | |||
x1 = *xP | |||
// Iterate over the bits of the scalar, top to bottom | |||
prevBit := uint8(0) | |||
for i := len(scalar) - 1; i >= 0; i-- { | |||
scalarByte := scalar[i] | |||
for j := 7; j >= 0; j-- { | |||
bit := (scalarByte >> uint(j)) & 0x1 | |||
kCurveOps.Params.Op.CondSwap(&x0.X, &x0.Z, &x1.X, &x1.Z, (bit ^ prevBit)) | |||
//sProjectivePointConditionalSwap(&x0, &x1, (bit ^ prevBit)) | |||
tmp = DoubleProjFp2(&x0, &Aplus2C, &C4) | |||
x1 = AddProjFp2(&x0, &x1, xP) | |||
x0 = tmp | |||
prevBit = bit | |||
} | |||
} | |||
// now prevBit is the lowest bit of the scalar | |||
kCurveOps.Params.Op.CondSwap(&x0.X, &x0.Z, &x1.X, &x1.Z, prevBit) | |||
return x0 | |||
} | |||
// Returns true if lhs = rhs. Takes variable time. | |||
func VartimeEqFp2(lhs, rhs *Fp2Element) bool { | |||
a := *lhs | |||
b := *rhs | |||
fp751StrongReduce(&a.A) | |||
fp751StrongReduce(&a.B) | |||
fp751StrongReduce(&b.A) | |||
fp751StrongReduce(&b.B) | |||
eq := true | |||
for i := 0; i < len(a.A)&&eq; i++ { | |||
eq = eq && (a.A[i] == b.A[i]) | |||
eq = eq && (a.B[i] == b.B[i]) | |||
} | |||
return eq | |||
a := *lhs | |||
b := *rhs | |||
fp751StrongReduce(&a.A) | |||
fp751StrongReduce(&a.B) | |||
fp751StrongReduce(&b.A) | |||
fp751StrongReduce(&b.B) | |||
eq := true | |||
for i := 0; i < len(a.A) && eq; i++ { | |||
eq = eq && (a.A[i] == b.A[i]) | |||
eq = eq && (a.B[i] == b.B[i]) | |||
} | |||
return eq | |||
} | |||
// Returns true if lhs = rhs. Takes variable time. | |||
func VartimeEqProjFp2(lhs, rhs *ProjectivePoint) bool { | |||
var t0,t1 Fp2Element | |||
kFieldOps.Mul(&t0, &lhs.X, &rhs.Z) | |||
kFieldOps.Mul(&t1, &lhs.Z, &rhs.X) | |||
return VartimeEqFp2(&t0, &t1) | |||
var t0, t1 Fp2Element | |||
kFieldOps.Mul(&t0, &lhs.X, &rhs.Z) | |||
kFieldOps.Mul(&t1, &lhs.Z, &rhs.X) | |||
return VartimeEqFp2(&t0, &t1) | |||
} | |||
func (GeneratedTestParams) generateFp2p751(rand *rand.Rand) Fp2Element { | |||
// Generation strategy: low limbs taken from [0,2^64); high limb | |||
// taken from smaller range | |||
// | |||
// Size hint is ignored since all elements are fixed size. | |||
// | |||
// Field elements taken in range [0,2p). Emulate this by capping | |||
// the high limb by the top digit of 2*p-1: | |||
// | |||
// sage: (2*p-1).digits(2^64)[-1] | |||
// 246065832128056 | |||
// | |||
// This still allows generating values >= 2p, but hopefully that | |||
// excess is OK (and if it's not, we'll find out, because it's for | |||
// testing...) | |||
// | |||
highLimb := rand.Uint64() % 246065832128056 | |||
fpElementGen := func() FpElement { | |||
return FpElement{ | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
highLimb, | |||
} | |||
} | |||
return Fp2Element{A: fpElementGen(), B: fpElementGen()} | |||
// Generation strategy: low limbs taken from [0,2^64); high limb | |||
// taken from smaller range | |||
// | |||
// Size hint is ignored since all elements are fixed size. | |||
// | |||
// Field elements taken in range [0,2p). Emulate this by capping | |||
// the high limb by the top digit of 2*p-1: | |||
// | |||
// sage: (2*p-1).digits(2^64)[-1] | |||
// 246065832128056 | |||
// | |||
// This still allows generating values >= 2p, but hopefully that | |||
// excess is OK (and if it's not, we'll find out, because it's for | |||
// testing...) | |||
// | |||
highLimb := rand.Uint64() % 246065832128056 | |||
fpElementGen := func() FpElement { | |||
return FpElement{ | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
rand.Uint64(), | |||
highLimb, | |||
} | |||
} | |||
return Fp2Element{A: fpElementGen(), B: fpElementGen()} | |||
} | |||
func (c GeneratedTestParams) Generate(rand *rand.Rand, size int) reflect.Value { | |||
return reflect.ValueOf( | |||
GeneratedTestParams{ | |||
ProjectivePoint{ | |||
X: c.generateFp2p751(rand), | |||
Z: c.generateFp2p751(rand), | |||
}, | |||
ProjectiveCurveParameters{ | |||
A: c.generateFp2p751(rand), | |||
C: c.generateFp2p751(rand), | |||
}, | |||
c.generateFp2p751(rand), | |||
}) | |||
return reflect.ValueOf( | |||
GeneratedTestParams{ | |||
ProjectivePoint{ | |||
X: c.generateFp2p751(rand), | |||
Z: c.generateFp2p751(rand), | |||
}, | |||
ProjectiveCurveParameters{ | |||
A: c.generateFp2p751(rand), | |||
C: c.generateFp2p751(rand), | |||
}, | |||
c.generateFp2p751(rand), | |||
}) | |||
} | |||
func (x primeFieldElement) Generate(rand *rand.Rand, size int) reflect.Value { | |||
return reflect.ValueOf(primeFieldElement{ | |||
A: new(GeneratedTestParams).generateFp2p751(rand).A}) | |||
return reflect.ValueOf(primeFieldElement{ | |||
A: new(GeneratedTestParams).generateFp2p751(rand).A}) | |||
} | |||
// Convert an FpElement to a big.Int for testing. Because this is only | |||
// for testing, no big.Int to FpElement conversion is provided. | |||
func radix64ToBigInt(x []uint64) *big.Int { | |||
radix := new(big.Int) | |||
// 2^64 | |||
radix.UnmarshalText(([]byte)("18446744073709551616")) | |||
base := new(big.Int).SetUint64(1) | |||
val := new(big.Int).SetUint64(0) | |||
tmp := new(big.Int) | |||
for _, xi := range x { | |||
tmp.SetUint64(xi) | |||
tmp.Mul(tmp, base) | |||
val.Add(val, tmp) | |||
base.Mul(base, radix) | |||
} | |||
return val | |||
radix := new(big.Int) | |||
// 2^64 | |||
radix.UnmarshalText(([]byte)("18446744073709551616")) | |||
base := new(big.Int).SetUint64(1) | |||
val := new(big.Int).SetUint64(0) | |||
tmp := new(big.Int) | |||
for _, xi := range x { | |||
tmp.SetUint64(xi) | |||
tmp.Mul(tmp, base) | |||
val.Add(val, tmp) | |||
base.Mul(base, radix) | |||
} | |||
return val | |||
} | |||
// Converts number from Montgomery domain and returns big.Int | |||
func toBigInt(x *FpElement) *big.Int { | |||
var fp Fp2Element | |||
var in = Fp2Element{A:*x} | |||
kFieldOps.FromMontgomery(&in, &fp) | |||
return radix64ToBigInt(fp.A[:]) | |||
var fp Fp2Element | |||
var in = Fp2Element{A: *x} | |||
kFieldOps.FromMontgomery(&in, &fp) | |||
return radix64ToBigInt(fp.A[:]) | |||
} |
@@ -2,8 +2,8 @@ package sidh | |||
import ( | |||
"errors" | |||
"io" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
"io" | |||
) | |||
// Id's correspond to bitlength of the prime field characteristic | |||
@@ -189,7 +189,7 @@ func (prv *PrivateKey) Generate(rand io.Reader) error { | |||
// Generates public key. | |||
// | |||
// Constant time. | |||
func (prv *PrivateKey) GeneratePublicKey() (*PublicKey) { | |||
func (prv *PrivateKey) GeneratePublicKey() *PublicKey { | |||
if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A { | |||
return publicKeyGenA(prv) | |||
} | |||
@@ -1,9 +1,9 @@ | |||
package sidh | |||
import ( | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
p503 "github.com/cloudflare/p751sidh/p503" | |||
p751 "github.com/cloudflare/p751sidh/p751" | |||
. "github.com/cloudflare/p751sidh/internal/isogeny" | |||
) | |||
// Keeps mapping: SIDH prime field ID to domain parameters | |||
@@ -28,7 +28,7 @@ func init() { | |||
Affine_Q: p503.P503_affine_QA, | |||
Affine_R: p503.P503_affine_RA, | |||
SecretBitLen: p503.P503_SecretBitLenA, | |||
SecretByteLen: uint((p503.P503_SecretBitLenA+7)/8), | |||
SecretByteLen: uint((p503.P503_SecretBitLenA + 7) / 8), | |||
IsogenyStrategy: p503.P503_AliceIsogenyStrategy[:], | |||
}, | |||
B: DomainParams{ | |||
@@ -36,16 +36,16 @@ func init() { | |||
Affine_Q: p503.P503_affine_QB, | |||
Affine_R: p503.P503_affine_RB, | |||
SecretBitLen: p503.P503_SecretBitLenB, | |||
SecretByteLen: uint((p503.P503_SecretBitLenB+7)/8), | |||
SecretByteLen: uint((p503.P503_SecretBitLenB + 7) / 8), | |||
IsogenyStrategy: p503.P503_BobIsogenyStrategy[:], | |||
}, | |||
OneFp2: p503.P503_OneFp2, | |||
HalfFp2: p503.P503_HalfFp2, | |||
MsgLen: 24, | |||
MsgLen: 24, | |||
// SIKEp751 provides 128 bit of classical security ([SIKE], 5.1) | |||
KemSize: 16, | |||
KemSize: 16, | |||
Bytelen: p503.P503_Bytelen, | |||
Op: p503.FieldOperations(), | |||
Op: p503.FieldOperations(), | |||
} | |||
p751 := SidhParams{ | |||
@@ -58,7 +58,7 @@ func init() { | |||
Affine_R: p751.P751_affine_RA, | |||
IsogenyStrategy: p751.P751_AliceIsogenyStrategy[:], | |||
SecretBitLen: p751.P751_SecretBitLenA, | |||
SecretByteLen: uint((p751.P751_SecretBitLenA+7)/8), | |||
SecretByteLen: uint((p751.P751_SecretBitLenA + 7) / 8), | |||
}, | |||
B: DomainParams{ | |||
Affine_P: p751.P751_affine_PB, | |||
@@ -66,15 +66,15 @@ func init() { | |||
Affine_R: p751.P751_affine_RB, | |||
IsogenyStrategy: p751.P751_BobIsogenyStrategy[:], | |||
SecretBitLen: p751.P751_SecretBitLenB, | |||
SecretByteLen: uint((p751.P751_SecretBitLenB+7)/8), | |||
SecretByteLen: uint((p751.P751_SecretBitLenB + 7) / 8), | |||
}, | |||
OneFp2: p751.P751_OneFp2, | |||
HalfFp2: p751.P751_HalfFp2, | |||
MsgLen: 32, | |||
MsgLen: 32, | |||
// SIKEp751 provides 192 bit of classical security ([SIKE], 5.1) | |||
KemSize: 24, | |||
KemSize: 24, | |||
Bytelen: p751.P751_Bytelen, | |||
Op: p751.FieldOperations(), | |||
Op: p751.FieldOperations(), | |||
} | |||
sidhParams[FP_503] = p503 | |||
@@ -14,18 +14,18 @@ import ( | |||
/* ------------------------------------------------------------------------- | |||
Test data | |||
-------------------------------------------------------------------------*/ | |||
var tdata = map[PrimeFieldId]struct{ | |||
var tdata = map[PrimeFieldId]struct { | |||
name string | |||
PkA string | |||
PrA string | |||
PkB string | |||
PrB string | |||
PkA string | |||
PrA string | |||
PkB string | |||
PrB string | |||
}{ | |||
FP_503: { | |||
name: "P-503", | |||
PrA:"B0AD510708F4ABCF3E0D97DC2F2FF112D9D2AAE49D97FFD1E4267F21C6E71C03", | |||
PrB:"A885A8B889520A6DBAD9FB33365E5B77FDED629440A16A533F259A510F63A822", | |||
PkA:"A6BADBA04518A924B20046B59AC197DCDF0EA48014C9E228C4994CCA432F360E" + | |||
PrA: "B0AD510708F4ABCF3E0D97DC2F2FF112D9D2AAE49D97FFD1E4267F21C6E71C03", | |||
PrB: "A885A8B889520A6DBAD9FB33365E5B77FDED629440A16A533F259A510F63A822", | |||
PkA: "A6BADBA04518A924B20046B59AC197DCDF0EA48014C9E228C4994CCA432F360E" + | |||
"2D527AFB06CA7C96EE5CEE19BAD53BF9218A3961CAD7EC092BD8D9EBB22A3D51" + | |||
"33008895A3F1F6A023F91E0FE06A00A622FD6335DAC107F8EC4283DC2632F080" + | |||
"4E64B390DAD8A2572F1947C67FDF4F8787D140CE2C6B24E752DA9A195040EDFA" + | |||
@@ -53,12 +53,12 @@ var tdata = map[PrimeFieldId]struct{ | |||
FP_751: { | |||
name: "P-751", | |||
// PrA - Alice's Private Key: 2*randint(0,2^371) | |||
PrA:"C09957CC83045FB4C3726384D784476ACB6FFD92E5B15B3C2D451BA063F1BD4CED8FBCF682A98DD0954D3" + | |||
PrA: "C09957CC83045FB4C3726384D784476ACB6FFD92E5B15B3C2D451BA063F1BD4CED8FBCF682A98DD0954D3" + | |||
"7BCAF730E", | |||
// PrB - Bob's Private Key: 3*randint(0,3^238) | |||
PrB:"393E8510E78A16D2DC1AACA9C9D17E7E78DB630881D8599C7040D05BB5557ECAE8165C45D5366ECB37B00" + | |||
PrB: "393E8510E78A16D2DC1AACA9C9D17E7E78DB630881D8599C7040D05BB5557ECAE8165C45D5366ECB37B00" + | |||
"969740AF201", | |||
PkA:"74D8EF08CB74EC99BF08B6FBE4FB3D048873B67F018E44988B9D70C564D058401D20E093C7DF0C66F022C" + | |||
PkA: "74D8EF08CB74EC99BF08B6FBE4FB3D048873B67F018E44988B9D70C564D058401D20E093C7DF0C66F022C" + | |||
"823E5139D2EA0EE137804B4820E950B046A90B0597759A0B6A197C56270128EA089FA1A2007DDE3430B37" + | |||
"A3E6350BD47B7F513863741C125FA63DEDAFC475C13DB59E533055B7CBE4B2F32672DF2DF97E03E29617B" + | |||
"0E9B6A35B58ABB26527A721142701EB147C7050E1D9125DA577B08CD51C8BB50627B8B47FACFC9C7C07DD" + | |||
@@ -89,7 +89,6 @@ var tdata = map[PrimeFieldId]struct{ | |||
}, | |||
} | |||
/* ------------------------------------------------------------------------- | |||
Helpers | |||
-------------------------------------------------------------------------*/ | |||
@@ -102,8 +101,9 @@ func checkErr(t testing.TB, err error, msg string) { | |||
// Utility used for running same test with all registered prime fields | |||
type MultiIdTestingFunc func(testing.TB, PrimeFieldId) | |||
func Do(f MultiIdTestingFunc, t testing.TB) { | |||
for id,val:=range(tdata) { | |||
for id, val := range tdata { | |||
fmt.Printf("\tTesting: %s\n", val.name) | |||
f(t, id) | |||
} | |||
@@ -190,9 +190,9 @@ func testKeyAgreement(t testing.TB, id PrimeFieldId, pkA, prA, pkB, prB string) | |||
// KeyPairs | |||
alicePublic := convToPub(pkA, KeyVariant_SIDH_A, id) | |||
bobPublic := convToPub(pkB, KeyVariant_SIDH_B, id) | |||
alicePrivate:= convToPrv(prA, KeyVariant_SIDH_A, id) | |||
bobPrivate := convToPrv(prB, KeyVariant_SIDH_B, id) | |||
bobPublic := convToPub(pkB, KeyVariant_SIDH_B, id) | |||
alicePrivate := convToPrv(prA, KeyVariant_SIDH_A, id) | |||
bobPrivate := convToPrv(prB, KeyVariant_SIDH_B, id) | |||
// Do actual test | |||
s1, e := DeriveSecret(bobPrivate, alicePublic) | |||
@@ -255,10 +255,9 @@ func testImportExport(t testing.TB, id PrimeFieldId) { | |||
func testPrivateKeyBelowMax(t testing.TB, id PrimeFieldId) { | |||
params := Params(id) | |||
for variant,keySz:=range( | |||
map[KeyVariant]*DomainParams { | |||
KeyVariant_SIDH_A: ¶ms.A, | |||
KeyVariant_SIDH_B: ¶ms.B}){ | |||
for variant, keySz := range map[KeyVariant]*DomainParams{ | |||
KeyVariant_SIDH_A: ¶ms.A, | |||
KeyVariant_SIDH_B: ¶ms.B} { | |||
func(v KeyVariant, dp *DomainParams) { | |||
var blen = int(dp.SecretByteLen) | |||
@@ -270,13 +269,13 @@ func testPrivateKeyBelowMax(t testing.TB, id PrimeFieldId) { | |||
maxSecertVal.Sub(maxSecertVal, big.NewInt(1)) | |||
// Do same test 1000 times | |||
for i:=0; i<1000; i++ { | |||
for i := 0; i < 1000; i++ { | |||
err := prv.Generate(rand.Reader) | |||
checkErr(t, err, "Private key generation") | |||
// Convert to big-endian, as that's what expected by (*Int)SetBytes() | |||
secretBytes := prv.Export() | |||
for i:=0; i<int(blen/2); i++ { | |||
for i := 0; i < int(blen/2); i++ { | |||
tmp := secretBytes[i] ^ secretBytes[blen-i-1] | |||
secretBytes[i] = tmp ^ secretBytes[i] | |||
secretBytes[blen-i-1] = tmp ^ secretBytes[blen-i-1] | |||
@@ -287,12 +286,12 @@ func testPrivateKeyBelowMax(t testing.TB, id PrimeFieldId) { | |||
t.Error("Generated private key is wrong") | |||
} | |||
} | |||
}(variant,keySz) | |||
}(variant, keySz) | |||
} | |||
} | |||
func TestKeyAgreement(t *testing.T) { | |||
for id,val:=range(tdata) { | |||
for id, val := range tdata { | |||
fmt.Printf("\tTesting: %s\n", val.name) | |||
testKeyAgreement(t, id, tdata[id].PkA, tdata[id].PrA, tdata[id].PkB, tdata[id].PrB) | |||
} | |||
@@ -308,9 +307,9 @@ func TestKeyAgreementP751_AliceEvenNumber(t *testing.T) { | |||
/* ------------------------------------------------------------------------- | |||
Wrappers for 'testing' module | |||
-------------------------------------------------------------------------*/ | |||
func TestKeygen(t *testing.T) {Do(testKeygen, t)} | |||
func TestRoundtrip(t *testing.T) {Do(testRoundtrip, t)} | |||
func TestImportExport(t *testing.T) {Do(testImportExport, t)} | |||
func TestKeygen(t *testing.T) { Do(testKeygen, t) } | |||
func TestRoundtrip(t *testing.T) { Do(testRoundtrip, t) } | |||
func TestImportExport(t *testing.T) { Do(testImportExport, t) } | |||
/* ------------------------------------------------------------------------- | |||
Benchmarking | |||