1
0
mirror of https://github.com/henrydcase/nobs.git synced 2024-11-26 17:11:22 +00:00
nobs/dh/sidh/sidh.go

303 lines
9.3 KiB
Go

package sidh
import (
. "github.com/henrydcase/nobs/dh/sidh/internal/isogeny"
)
// -----------------------------------------------------------------------------
// Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
//
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sidx int
var op = CurveOperations{Params: pub.params}
cparam := op.CalcCurveParamsEquiv4(curve)
phi := Newisogeny4(op.Params.Op)
strat := pub.params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sidx]
sidx++
op.Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR needed
// for public key generation.
func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sidx int
var op = CurveOperations{Params: pub.params}
cparam := op.CalcCurveParamsEquiv4(curve)
phi := Newisogeny4(op.Params.Op)
strat := pub.params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sidx]
sidx++
op.Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sidx int
var op = CurveOperations{Params: pub.params}
cparam := op.CalcCurveParamsEquiv3(curve)
phi := Newisogeny3(op.Params.Op)
strat := pub.params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sidx]
sidx++
op.Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sidx int
var op = CurveOperations{Params: pub.params}
cparam := op.CalcCurveParamsEquiv3(curve)
phi := Newisogeny3(op.Params.Op)
strat := pub.params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sidx]
sidx++
op.Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Generate a public key in the 2-torsion group
func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
var xPA, xQA, xRA ProjectivePoint
var xPB, xQB, xRB, xR ProjectivePoint
var invZP, invZQ, invZR Fp2Element
var tmp ProjectiveCurveParameters
pub = NewPublicKey(prv.params.Id, KeyVariant_SIDH_A)
var op = CurveOperations{Params: pub.params}
var phi = Newisogeny4(op.Params.Op)
// Load points for A
xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
// Load points for B
xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
// Find isogeny kernel
tmp.C = pub.params.OneFp2
xR = op.ScalarMul3Pt(&tmp, &xPA, &xQA, &xRA, prv.params.A.SecretBitLen, prv.Scalar)
// Reset params object and travers isogeny tree
tmp.C = pub.params.OneFp2
tmp.A.Zeroize()
traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB, pub)
// Secret isogeny
phi.GenerateCurve(&xR)
xPA = phi.EvaluatePoint(&xPB)
xQA = phi.EvaluatePoint(&xQB)
xRA = phi.EvaluatePoint(&xRB)
op.Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
op.Params.Op.Mul(&pub.affine_xP, &xPA.X, &invZP)
op.Params.Op.Mul(&pub.affine_xQ, &xQA.X, &invZQ)
op.Params.Op.Mul(&pub.affine_xQmP, &xRA.X, &invZR)
return
}
// Generate a public key in the 3-torsion group
func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) {
var xPB, xQB, xRB, xR ProjectivePoint
var xPA, xQA, xRA ProjectivePoint
var invZP, invZQ, invZR Fp2Element
var tmp ProjectiveCurveParameters
pub = NewPublicKey(prv.params.Id, prv.keyVariant)
var op = CurveOperations{Params: pub.params}
var phi = Newisogeny3(op.Params.Op)
// Load points for B
xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
// Load points for A
xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
tmp.C = pub.params.OneFp2
xR = op.ScalarMul3Pt(&tmp, &xPB, &xQB, &xRB, prv.params.B.SecretBitLen, prv.Scalar)
tmp.C = pub.params.OneFp2
tmp.A.Zeroize()
traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA, pub)
phi.GenerateCurve(&xR)
xPB = phi.EvaluatePoint(&xPA)
xQB = phi.EvaluatePoint(&xQA)
xRB = phi.EvaluatePoint(&xRA)
op.Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
op.Params.Op.Mul(&pub.affine_xP, &xPB.X, &invZP)
op.Params.Op.Mul(&pub.affine_xQ, &xQB.X, &invZQ)
op.Params.Op.Mul(&pub.affine_xQmP, &xRB.X, &invZR)
return
}
// -----------------------------------------------------------------------------
// Key agreement functions
//
// Establishing shared keys in in 2-torsion group
func deriveSecretA(prv *PrivateKey, pub *PublicKey) []byte {
var sharedSecret = make([]byte, pub.params.SharedSecretSize)
var cparam ProjectiveCurveParameters
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var op = CurveOperations{Params: prv.params}
var phi = Newisogeny4(op.Params.Op)
// Recover curve coefficients
cparam.C = pub.params.OneFp2
op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
// Find kernel of the morphism
xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.A.SecretBitLen, prv.Scalar)
// Traverse isogeny tree
traverseTreeSharedKeyA(&cparam, &xR, pub)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
op.RecoverCurveCoefficients4(&cparam, &c)
op.Jinvariant(&cparam, sharedSecret)
return sharedSecret
}
// Establishing shared keys in in 3-torsion group
func deriveSecretB(prv *PrivateKey, pub *PublicKey) []byte {
var sharedSecret = make([]byte, pub.params.SharedSecretSize)
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var cparam ProjectiveCurveParameters
var op = CurveOperations{Params: prv.params}
var phi = Newisogeny3(op.Params.Op)
// Recover curve coefficients
cparam.C = pub.params.OneFp2
op.RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
// Find kernel of the morphism
xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
xR = op.ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.B.SecretBitLen, prv.Scalar)
// Traverse isogeny tree
traverseTreeSharedKeyB(&cparam, &xR, pub)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
op.RecoverCurveCoefficients3(&cparam, &c)
op.Jinvariant(&cparam, sharedSecret)
return sharedSecret
}