EndGame0/sourcecode/gobalance/pkg/stem/util/ed25519.go
2024-10-23 20:50:14 +05:30

343 lines
8.6 KiB
Go

package util
import (
"bytes"
"crypto/ed25519"
"crypto/sha512"
"fmt"
"math/big"
)
var b = 256
var d = bi(0).Mul(bi(-121665), inv(bi(121666)))
var d1 = biMod(biMul(bi(-121665), inv(bi(121666))), q)
var I = expmod(bi(2), biDiv(biSub(q, bi(1)), bi(4)), q)
var q = biSub(biExp(bi(2), bi(255)), bi(19))
var by = biMul(bi(4), inv(bi(5)))
var bx = xrecover(by)
var bB = []*big.Int{biMod(bx, q), biMod(by, q)}
var bB1 = []*big.Int{biMod(bx, q), biMod(by, q), bi(1), biMod(biMul(bx, by), q)}
var l = biAdd(biExp(bi(2), bi(252)), biFromStr("27742317777372353535851937790883648493"))
func biFromStr(v string) (out *big.Int) {
out = new(big.Int)
_, _ = fmt.Sscan(v, out)
return
}
// BlindedSignWithTorKey this is identical to stem's hidden_service.py:_blinded_sign() but takes an
// extended private key (i.e. in tor format) as its argument, instead of the
// standard format that hazmat does. It basically omits the "extended the key"
// step and does everything else the same.
func BlindedSignWithTorKey(msg []byte, identityKey ed25519.PrivateKey, blindedKey, blindingNonce []byte) []byte {
esk := identityKey.Seed()
return blindedSignP2(esk, msg, blindedKey, blindingNonce)
}
func BlindedSign(msg, identityKey, blindedKey, blindingNonce []byte) []byte {
identityKeyBytes := identityKey
// pad private identity key into an ESK (encrypted secret key)
tmp := sha512.Sum512(identityKeyBytes)
h := tmp[:]
sum := bi(0)
for i := int64(3); i < int64(b)-2; i++ {
sum = biAdd(sum, biMul(biExp(bi(2), bi(i)), bi(int64(Bit(h, i)))))
}
a := biAdd(biExp(bi(2), bi(int64(b-2))), sum)
tmpS := make([][]byte, 0)
for i := b / 8; i < b/4; i++ {
tmpS = append(tmpS, h[i:i+1])
}
k := bytes.Join(tmpS, []byte(""))
esk := append(encodeint(a), k...)
return blindedSignP2(esk, msg, blindedKey, blindingNonce)
}
func blindedSignP2(esk, msg, blindedKey, blindingNonce []byte) []byte {
// blind the ESK with this nonce
sum := bi(0)
for i := int64(3); i < int64(b-2); i++ {
bitRes := bi(int64(Bit(blindingNonce, i)))
sum = biAdd(sum, biMul(biExp(bi(2), bi(i)), bitRes))
}
mult := biAdd(biExp(bi(2), bi(int64(b-2))), sum)
s := decodeInt(esk[:32])
sPrime := biMod(biMul(s, mult), l)
k := esk[32:]
tmp := sha512.Sum512([]byte("Derive temporary signing key hash input" + string(k)))
kPrime := tmp[:32]
blindedEsk := append(encodeint(sPrime), kPrime...)
// finally, sign the message
a := decodeInt(blindedEsk[:32])
lines := make([][]byte, 0)
for i := b / 8; i < b/4; i++ {
lines = append(lines, blindedEsk[i:i+1])
}
toHint := append(bytes.Join(lines, []byte("")), msg...)
r := hint(toHint)
R := Scalarmult1(bB1, r)
S := biMod(biAdd(r, biMul(hint([]byte(string(Encodepoint(R))+string(blindedKey)+string(msg))), a)), l)
return append(Encodepoint(R), encodeint(S)...)
}
func hint(m []byte) *big.Int {
tmp := sha512.Sum512(m)
h := tmp[:]
sum := bi(0)
for i := 0; i < 2*b; i++ {
sum = biAdd(sum, biMul(biExp(bi(2), bi(int64(i))), bi(int64(Bit(h, int64(i))))))
}
return sum
}
//def Hint(m):
//h = H(m)
//return sum(2 ** i * bit(h, i) for i in range(2 * b))
func BlindedPubkey(identityKey ed25519.PublicKey, blindingNonce []byte) ed25519.PublicKey {
ed25519b := int64(256)
sum := bi(0)
for i := int64(3); i < ed25519b-2; i++ {
sum = biAdd(sum, biMul(biExp(bi(2), bi(i)), bi(int64(Bit(blindingNonce, i)))))
}
mult := biAdd(biExp(bi(2), bi(ed25519b-2)), sum)
P := Decodepoint(identityKey)
return Encodepoint(Scalarmult1(P, mult))
}
func Decodepoint(s []byte) []*big.Int {
sum := bi(0)
for i := 0; i < b-1; i++ {
sum = biAdd(sum, biMul(biExp(bi(2), bi(int64(i))), bi(int64(Bit(s, int64(i))))))
}
y := sum
x := xrecover(y)
if biAnd(x, bi(1)).Cmp(bi(int64(Bit(s, int64(b-1))))) != 0 {
x = biSub(q, x)
}
P := []*big.Int{x, y, bi(1), biMod(biMul(x, y), q)}
if !isoncurve(P) {
panic("decoding point that is not on curve")
}
return P
}
func decodeInt(s []uint8) *big.Int {
sum := bi(0)
for i := 0; i < 256; i++ {
tmpI := bi(int64(i))
base := bi(2)
e := bi(0).Exp(base, tmpI, nil)
m := bi(int64(Bit(s, int64(i))))
tmp := bi(0).Mul(e, m)
sum = sum.Add(sum, tmp)
}
return sum
}
func encodeint(y *big.Int) []byte {
bits := make([]*big.Int, 0)
for i := 0; i < b; i++ {
bits = append(bits, biAnd(biRsh(y, uint(i)), bi(1)))
}
final := make([]byte, 0)
for i := 0; i < b/8; i++ {
sum := bi(0)
for j := 0; j < 8; j++ {
sum = biAdd(sum, biLsh(bits[i*8+j], uint(j)))
}
final = append(final, byte(sum.Uint64()))
}
return final
}
func xrecover(y *big.Int) *big.Int {
xx := biMul(biSub(biMul(y, y), bi(1)), inv(biAdd(biMul(biMul(d, y), y), bi(1))))
x := expmod(xx, biDiv(biAdd(q, bi(3)), bi(8)), q)
if biMod(biSub(biMul(x, x), xx), q).Int64() != 0 {
x = biMod(biMul(x, I), q)
}
if biMod(x, bi(2)).Int64() != 0 {
x = biSub(q, x)
}
return x
}
func expmod(b, e, m *big.Int) *big.Int {
if e.Cmp(bi(0)) == 0 {
return bi(1)
}
t := biMod(biExp(expmod(b, biDiv(e, bi(2)), m), bi(2)), m)
if biAnd(e, bi(1)).Int64() == 1 {
t = biMod(biMul(t, b), m)
}
return t
}
func Bit(h []uint8, i int64) uint8 {
return (h[i/8] >> (i % 8)) & 1
}
func inv(x *big.Int) *big.Int {
return expmod(x, biSub(q, bi(2)), q)
}
func isoncurve(P []*big.Int) bool {
var d = biMod(biMul(bi(-121665), inv(bi(121666))), q)
var q = biSub(biExp(bi(2), bi(255)), bi(19))
x := P[0]
y := P[1]
z := P[2]
t := P[3]
return biMod(z, q).Cmp(bi(0)) != 0 &&
biMod(biMul(x, y), q).Cmp(biMod(biMul(z, t), q)) == 0 &&
biMod(biSub(biSub(biSub(biMul(y, y), biMul(x, x)), biMul(z, z)), biMul(biMul(d, t), t)), q).Int64() == 0
}
func edwardsAdd(P, Q []*big.Int) []*big.Int {
// This is formula sequence 'addition-add-2008-hwcd-3' from
// http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
x1 := P[0]
y1 := P[1]
z1 := P[2]
t1 := P[3]
x2 := Q[0]
y2 := Q[1]
z2 := Q[2]
t2 := Q[3]
a := biMod(biMul(biSub(y1, x1), biSub(y2, x2)), q)
b := biMod(biMul(biAdd(y1, x1), biAdd(y2, x2)), q)
c := biMod(biMul(biMul(biMul(t1, bi(2)), d1), t2), q)
dd := biMod(biMul(biMul(z1, bi(2)), z2), q)
e := biSub(b, a)
f := biSub(dd, c)
g := biAdd(dd, c)
h := biAdd(b, a)
x3 := biMul(e, f)
y3 := biMul(g, h)
t3 := biMul(e, h)
z3 := biMul(f, g)
return []*big.Int{biMod(x3, q), biMod(y3, q), biMod(z3, q), biMod(t3, q)}
}
func edwardsDouble(P []*big.Int) []*big.Int {
// This is formula sequence 'dbl-2008-hwcd' from
// http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
x1 := P[0]
y1 := P[1]
z1 := P[2]
a := biMod(biMul(x1, x1), q)
b := biMod(biMul(y1, y1), q)
c := biMod(biMul(biMul(bi(2), z1), z1), q)
e := biMod(biSub(biSub(biMul(biAdd(x1, y1), biAdd(x1, y1)), a), b), q)
g := biAdd(biMul(a, bi(-1)), b)
f := biSub(g, c)
h := biSub(biMul(a, bi(-1)), b)
x3 := biMul(e, f)
y3 := biMul(g, h)
t3 := biMul(e, h)
z3 := biMul(f, g)
return []*big.Int{biMod(x3, q), biMod(y3, q), biMod(z3, q), biMod(t3, q)}
}
func Scalarmult1(P []*big.Int, e *big.Int) []*big.Int {
if e.Cmp(bi(0)) == 0 {
return []*big.Int{bi(0), bi(1), bi(1), bi(0)}
}
Q := Scalarmult1(P, biDiv(e, bi(2)))
Q = edwardsDouble(Q)
if biAnd(e, bi(1)).Int64() == 1 {
//if e.And(e, bi(1)).Int64() == 1 {
Q = edwardsAdd(Q, P)
}
return Q
}
func Encodepoint(P []*big.Int) []byte {
x := P[0]
y := P[1]
z := P[2]
//t := P[3]
zi := inv(z)
x = biMod(biMul(x, zi), q)
y = biMod(biMul(y, zi), q)
bits := make([]uint8, 0)
for i := 0; i < b-1; i++ {
bits = append(bits, uint8(biAnd(biRsh(y, uint(i)), bi(1)).Int64()))
}
bits = append(bits, uint8(biAnd(x, bi(1)).Int64()))
by := make([]uint8, 0)
for i := 0; i < b/8; i++ {
sum := uint8(0)
for j := 0; j < 8; j++ {
sum += bits[i*8+j] << j
}
by = append(by, sum)
}
return by
}
//func Encodepoint(P []*big.Int) []byte {
// x := P[0]
// y := P[1]
// bits := make([]uint8, 0)
// for i := 0; i < b; i++ {
// bits = append(bits, uint8(biAnd(biRsh(y, uint(i)), bi(1)).Int64()))
// }
// by := make([]uint8, 0)
// bits = append(bits, uint8(biAnd(x, bi(1)).Int64()))
// for i := 0; i < b/8; i++ {
// sum := uint8(0)
// for j := 0; j < 8; j++ {
// sum += bits[i*8+j] << j
// }
// by = append(by, sum)
// }
// return by
//}
func bi(v int64) *big.Int {
return big.NewInt(v)
}
func biExp(a, b *big.Int) *big.Int {
return bi(0).Exp(a, b, nil)
}
func biDiv(a, b *big.Int) *big.Int {
return bi(0).Div(a, b)
}
func biSub(a, b *big.Int) *big.Int {
return bi(0).Sub(a, b)
}
func biAdd(a, b *big.Int) *big.Int {
return bi(0).Add(a, b)
}
func biAnd(a, b *big.Int) *big.Int {
return bi(0).And(a, b)
}
func biRsh(a *big.Int, b uint) *big.Int {
return bi(0).Rsh(a, b)
}
func biLsh(a *big.Int, b uint) *big.Int {
return bi(0).Lsh(a, b)
}
func biMul(a, b *big.Int) *big.Int {
return bi(0).Mul(a, b)
}
func biMod(a, b *big.Int) *big.Int {
return bi(0).Mod(a, b)
}