Files
billbuchanan 44789e8d3a Update
2021-01-18 20:47:18 +00:00

108 lines
2.1 KiB
Go

// Elliptic Curve Demo for Password Hash to ECC Point
package main
import (
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"fmt"
"math/big"
"flag"
)
var (
c = elliptic.P256()
k = new(big.Int).SetBytes([]byte{164, 98, 192, 51, 205, 206, 226, 85, 22, 79, 248, 231, 248, 171, 160, 1, 248, 166, 173, 240, 47, 68, 92, 163, 33, 118, 150, 220, 69, 51, 98})
)
var one = new(big.Int).SetInt64(1)
// A invertible implements fast inverse mod Curve.Params().N
type invertible interface {
// Inverse returns the inverse of k in GF(P)
Inverse(k *big.Int) *big.Int
}
func randScalar(c elliptic.Curve) (k *big.Int, err error) {
params := c.Params()
k, err = rand.Int(rand.Reader, params.N)
return
}
func fermatInverse(k, N *big.Int) *big.Int {
two := big.NewInt(2)
nMinus2 := new(big.Int).Sub(N, two)
return new(big.Int).Exp(k, nMinus2, N)
}
func tryPoint(r []byte) (x, y *big.Int) {
hash := sha256.Sum256(r)
x = new(big.Int).SetBytes(hash[:])
x3 := new(big.Int).Mul(x, x)
x3.Mul(x3, x)
threeX := new(big.Int).Lsh(x, 1)
threeX.Add(threeX, x)
x3.Sub(x3, threeX)
x3.Add(x3, c.Params().B)
y = x3.ModSqrt(x3, c.Params().P)
return
}
func increment(counter []byte) {
for i := len(counter) - 1; i >= 0; i-- {
counter[i]++
if counter[i] != 0 {
break
}
}
}
func HashIntoCurvePoint(r []byte) (x, y *big.Int) {
t := make([]byte, 32)
copy(t, r)
x, y = tryPoint(t)
for y == nil || !c.IsOnCurve(x, y) {
increment(t)
x, y = tryPoint(t)
}
return
}
func main() {
flag.Parse()
args := flag.Args()
pwd:=args[0]
hash := sha256.Sum256([]byte(pwd))
pkx, pky := HashIntoCurvePoint(hash[:]) // Convert password hash into elliptic curve point.
fmt.Println("Password: ", pwd)
fmt.Println("\nHash to point:\t", pkx, pky)
r, _ := randScalar(c) // Random value to mask password
x, y := c.ScalarMult(pkx, pky, r.Bytes()) // Calculate point on elliptic curve
fmt.Println("\nRandom value:\t", r)
fmt.Println("\nMasked:\t", x, y)
rInv := fermatInverse(r, c.Params().N) // rInv = r ^-1
x1, y1 := c.ScalarMult(x, y, rInv.Bytes())
fmt.Println("\nUnmasked:\t", x1, y1)
}