mirror of
https://github.com/Egida/EndGame0.git
synced 2025-08-02 19:36:03 -04:00
343 lines
8.6 KiB
Go
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)
|
|
}
|