137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
||
// Use of this source code is governed by a BSD-style
|
||
// license that can be found in the LICENSE file.
|
||
|
||
// We have a implementation in amd64 assembly so this code is only run on
|
||
// non-amd64 platforms. The amd64 assembly does not support gccgo.
|
||
// +build !amd64 gccgo
|
||
|
||
package curve25519
|
||
|
||
import (
|
||
"math/big"
|
||
)
|
||
|
||
// p is the prime order of the underlying field: 2^255-19
|
||
var p *big.Int
|
||
|
||
// pMinus2 is p-2
|
||
var pMinus2 *big.Int
|
||
|
||
// a is a parameter of the elliptic curve: 486662
|
||
var a *big.Int
|
||
|
||
func init() {
|
||
p, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
|
||
pMinus2, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb", 16)
|
||
a = new(big.Int).SetInt64(486662)
|
||
}
|
||
|
||
// context contains state shared throughout the computation, including scratch
|
||
// variables to save on allocation.
|
||
type context struct {
|
||
tmp1, tmp2, tmp3, tmp4 *big.Int
|
||
x1 *big.Int
|
||
}
|
||
|
||
// add sets (outx, outz) to the sum of two points in the elliptic curve group.
|
||
// See http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m
|
||
// outx and outz should not alias any of the other inputs.
|
||
func (c *context) add(outx, outz, xn, zn, xm, zm *big.Int) {
|
||
// x₃ = 4(x·x′ - z·z′)² · z1
|
||
// (z1 == 1 here)
|
||
c.tmp1.Mul(xn, xm)
|
||
c.tmp2.Mul(zn, zm)
|
||
c.tmp3.Sub(c.tmp1, c.tmp2)
|
||
outx.Mul(c.tmp3, c.tmp3)
|
||
outx.Lsh(outx, 2)
|
||
outx.Mod(outx, p)
|
||
|
||
// z₃ = 4(x·z′ - z·x′)² · x1
|
||
// (x1 == 1 here)
|
||
c.tmp1.Mul(xm, zn)
|
||
c.tmp2.Mul(zm, xn)
|
||
c.tmp3.Sub(c.tmp1, c.tmp2)
|
||
outz.Mul(c.tmp3, c.tmp3)
|
||
outz.Mul(outz, c.x1)
|
||
outz.Lsh(outz, 2)
|
||
outz.Mod(outz, p)
|
||
|
||
return
|
||
}
|
||
|
||
// double sets (outx, outz) to 2*(x,z) in the elliptic curve group. See
|
||
// http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m
|
||
// outx and outz should not alias any of the other inputs.
|
||
func (c *context) double(outx, outz, x, z *big.Int) {
|
||
// x₂ = (x² - z²)²
|
||
c.tmp1.Mul(x, x)
|
||
c.tmp2.Mul(z, z)
|
||
c.tmp3.Sub(c.tmp1, c.tmp2)
|
||
outx.Mul(c.tmp3, c.tmp3)
|
||
outx.Mod(outx, p)
|
||
|
||
// z₂ = 4xz·(x² + Axz + z²)
|
||
c.tmp3.Add(c.tmp1, c.tmp2)
|
||
c.tmp1.Mul(x, z)
|
||
c.tmp2.Mul(c.tmp1, a)
|
||
outz.Add(c.tmp3, c.tmp2)
|
||
c.tmp2.Lsh(c.tmp1, 2)
|
||
outz.Mul(outz, c.tmp2)
|
||
outz.Mod(outz, p)
|
||
|
||
return
|
||
}
|
||
|
||
func scalarMult(out, in, base *[32]byte) {
|
||
var baseReversed, inCopy [32]byte
|
||
for i := 0; i < 32; i++ {
|
||
baseReversed[31-i] = base[i]
|
||
inCopy[i] = in[i]
|
||
}
|
||
|
||
inCopy[31] &= 127
|
||
inCopy[31] |= 64
|
||
inCopy[0] &= 248
|
||
|
||
c := &context{new(big.Int), new(big.Int), new(big.Int), new(big.Int), nil}
|
||
c.x1 = new(big.Int).SetBytes(baseReversed[:])
|
||
|
||
x1 := new(big.Int).SetInt64(1)
|
||
z1 := new(big.Int)
|
||
x2 := new(big.Int).Set(c.x1)
|
||
z2 := new(big.Int).SetInt64(1)
|
||
outx := new(big.Int)
|
||
outz := new(big.Int)
|
||
|
||
for i := 0; i < 32; i++ {
|
||
b := inCopy[31-i]
|
||
for j := 0; j < 8; j++ {
|
||
if b&0x80 != 0 {
|
||
c.add(outx, outz, x1, z1, x2, z2)
|
||
x1, z1, outx, outz = outx, outz, x1, z1
|
||
c.double(outx, outz, x2, z2)
|
||
x2, z2, outx, outz = outx, outz, x2, z2
|
||
} else {
|
||
c.add(outx, outz, x1, z1, x2, z2)
|
||
x2, z2, outx, outz = outx, outz, x2, z2
|
||
c.double(outx, outz, x1, z1)
|
||
x1, z1, outx, outz = outx, outz, x1, z1
|
||
}
|
||
b <<= 1
|
||
}
|
||
}
|
||
|
||
c.tmp1.Exp(z1, pMinus2, p)
|
||
c.tmp2.Mul(x1, c.tmp1)
|
||
c.tmp3.Mod(c.tmp2, p)
|
||
|
||
outReversed := c.tmp3.Bytes()
|
||
for i := 0; i < len(outReversed); i++ {
|
||
out[i] = outReversed[len(outReversed)-(1+i)]
|
||
}
|
||
for i := len(outReversed); i < 32; i++ {
|
||
out[i] = 0
|
||
}
|
||
}
|