dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

main.go (5275B)


      1 package main
      2 
      3 import (
      4 	"bytes"
      5 	"crypto/ed25519"
      6 	"crypto/sha512"
      7 	"encoding/base64"
      8 	"flag"
      9 	"fmt"
     10 	"math/big"
     11 	"os"
     12 )
     13 
     14 func main() {
     15 	var privKeyFile string
     16 	var fileName string
     17 	flag.StringVar(&privKeyFile, "s", "hs_ed25519_secret_key", "tor private key file")
     18 	flag.StringVar(&fileName, "c", "certificate.txt", "certificate to sign")
     19 	flag.Parse()
     20 	msg, err := os.ReadFile(fileName)
     21 	if err != nil {
     22 		panic(err)
     23 	}
     24 	pemKeyBytes, _ := os.ReadFile(privKeyFile)
     25 	identityPrivKey := loadTorKeyFromDisk(pemKeyBytes)
     26 	signature := sign(identityPrivKey, msg)
     27 	fmt.Println(base64.StdEncoding.EncodeToString(signature))
     28 }
     29 
     30 func loadTorKeyFromDisk(keyBytes []byte) ed25519.PrivateKey {
     31 	if !bytes.Equal(keyBytes[:29], []byte("== ed25519v1-secret: type0 ==")) {
     32 		panic("Tor key does not start with Tor header")
     33 	}
     34 	expandedSk := keyBytes[32:]
     35 	if len(expandedSk) != 64 {
     36 		panic("Tor private key has the wrong length")
     37 	}
     38 	return expandedSk
     39 }
     40 
     41 func sign(identityPrivKey, msg []byte) []byte {
     42 	return signatureWithESK(msg, identityPrivKey, publickeyFromESK(identityPrivKey))
     43 }
     44 
     45 var (
     46 	b  = 256
     47 	l  = biAdd(biExp(bi(2), bi(252)), biFromStr("27742317777372353535851937790883648493"))
     48 	by = biMul(bi(4), inv(bi(5)))
     49 	bx = xrecover(by)
     50 	q  = biSub(biExp(bi(2), bi(255)), bi(19))
     51 	bB = []*big.Int{biMod(bx, q), biMod(by, q)}
     52 	I  = expmod(bi(2), biDiv(biSub(q, bi(1)), bi(4)), q)
     53 	d  = bi(0).Mul(bi(-121665), inv(bi(121666)))
     54 )
     55 
     56 func publickeyFromESK(h []byte) ed25519.PublicKey {
     57 	a := decodeInt(h[:32])
     58 	A := scalarmult(bB, a)
     59 	return encodepoint(A)
     60 }
     61 
     62 func signatureWithESK(msg, blindedEsk, blindedKey []byte) []byte {
     63 	a := decodeInt(blindedEsk[:32])
     64 	lines := make([][]byte, 0)
     65 	for i := b / 8; i < b/4; i++ {
     66 		lines = append(lines, blindedEsk[i:i+1])
     67 	}
     68 	toHint := append(bytes.Join(lines, []byte("")), msg...)
     69 	r := hint(toHint)
     70 	R := scalarmult(bB, r)
     71 	S := biMod(biAdd(r, biMul(hint([]byte(string(encodepoint(R))+string(blindedKey)+string(msg))), a)), l)
     72 	return append(encodepoint(R), encodeint(S)...)
     73 }
     74 
     75 func edwards(P, Q []*big.Int) []*big.Int {
     76 	x1, y1 := P[0], P[1]
     77 	x2, y2 := Q[0], Q[1]
     78 	x3 := biMul(biAdd(biMul(x1, y2), biMul(x2, y1)), inv(biAdd(bi(1), biMul(biMul(biMul(biMul(d, x1), x2), y1), y2))))
     79 	y3 := biMul(biAdd(biMul(y1, y2), biMul(x1, x2)), inv(biSub(bi(1), biMul(biMul(biMul(biMul(d, x1), x2), y1), y2))))
     80 	return []*big.Int{biMod(x3, q), biMod(y3, q)}
     81 }
     82 
     83 func scalarmult(P []*big.Int, e *big.Int) []*big.Int {
     84 	if e.Cmp(bi(0)) == 0 {
     85 		return []*big.Int{bi(0), bi(1)}
     86 	}
     87 	Q := scalarmult(P, biDiv(e, bi(2)))
     88 	Q = edwards(Q, Q)
     89 	if biAnd(e, bi(1)).Int64() == 1 {
     90 		Q = edwards(Q, P)
     91 	}
     92 	return Q
     93 }
     94 
     95 func encodepoint(P []*big.Int) []byte {
     96 	x, y := P[0], P[1]
     97 	bits := make([]uint8, 0)
     98 	for i := 0; i < b-1; i++ {
     99 		bits = append(bits, uint8(biAnd(biRsh(y, uint(i)), bi(1)).Int64()))
    100 	}
    101 	bits = append(bits, uint8(biAnd(x, bi(1)).Int64()))
    102 	by := make([]uint8, 0)
    103 	for i := 0; i < b/8; i++ {
    104 		sum := uint8(0)
    105 		for j := 0; j < 8; j++ {
    106 			sum += bits[i*8+j] << j
    107 		}
    108 		by = append(by, sum)
    109 	}
    110 	return by
    111 }
    112 
    113 func hint(m []byte) *big.Int {
    114 	shaSum := sha512.Sum512(m)
    115 	h := shaSum[:]
    116 	sum := bi(0)
    117 	for i := 0; i < 2*b; i++ {
    118 		sum = biAdd(sum, biMul(biExp(bi(2), bi(int64(i))), bi(int64(Bit(h, int64(i))))))
    119 	}
    120 	return sum
    121 }
    122 
    123 func encodeint(y *big.Int) []byte {
    124 	bits := make([]*big.Int, 0)
    125 	for i := 0; i < b; i++ {
    126 		bits = append(bits, biAnd(biRsh(y, uint(i)), bi(1)))
    127 	}
    128 	final := make([]byte, 0)
    129 	for i := 0; i < b/8; i++ {
    130 		sum := bi(0)
    131 		for j := 0; j < 8; j++ {
    132 			sum = biAdd(sum, biLsh(bits[i*8+j], uint(j)))
    133 		}
    134 		final = append(final, byte(sum.Uint64()))
    135 	}
    136 	return final
    137 }
    138 
    139 func decodeInt(s []uint8) *big.Int {
    140 	sum := bi(0)
    141 	for i := 0; i < b; i++ {
    142 		e := biExp(bi(2), bi(int64(i)))
    143 		m := bi(int64(Bit(s, int64(i))))
    144 		sum = sum.Add(sum, biMul(e, m))
    145 	}
    146 	return sum
    147 }
    148 
    149 func xrecover(y *big.Int) *big.Int {
    150 	xx := biMul(biSub(biMul(y, y), bi(1)), inv(biAdd(biMul(biMul(d, y), y), bi(1))))
    151 	x := expmod(xx, biDiv(biAdd(q, bi(3)), bi(8)), q)
    152 	if biMod(biSub(biMul(x, x), xx), q).Int64() != 0 {
    153 		x = biMod(biMul(x, I), q)
    154 	}
    155 	if biMod(x, bi(2)).Int64() != 0 {
    156 		x = biSub(q, x)
    157 	}
    158 	return x
    159 }
    160 
    161 func expmod(b, e, m *big.Int) *big.Int {
    162 	if e.Cmp(bi(0)) == 0 {
    163 		return bi(1)
    164 	}
    165 	t := biMod(biExp(expmod(b, biDiv(e, bi(2)), m), bi(2)), m)
    166 	if biAnd(e, bi(1)).Int64() == 1 {
    167 		t = biMod(biMul(t, b), m)
    168 	}
    169 	return t
    170 }
    171 
    172 func biFromStr(v string) (out *big.Int) {
    173 	out = new(big.Int)
    174 	_, _ = fmt.Sscan(v, out)
    175 	return
    176 }
    177 
    178 func inv(x *big.Int) *big.Int           { return expmod(x, biSub(q, bi(2)), q) }
    179 func Bit(h []uint8, i int64) uint8      { return (h[i/8] >> (i % 8)) & 1 }
    180 func bi(v int64) *big.Int               { return big.NewInt(v) }
    181 func biAdd(a, b *big.Int) *big.Int      { return bi(0).Add(a, b) }
    182 func biSub(a, b *big.Int) *big.Int      { return bi(0).Sub(a, b) }
    183 func biMul(a, b *big.Int) *big.Int      { return bi(0).Mul(a, b) }
    184 func biDiv(a, b *big.Int) *big.Int      { return bi(0).Div(a, b) }
    185 func biAnd(a, b *big.Int) *big.Int      { return bi(0).And(a, b) }
    186 func biMod(a, b *big.Int) *big.Int      { return bi(0).Mod(a, b) }
    187 func biExp(a, b *big.Int) *big.Int      { return bi(0).Exp(a, b, nil) }
    188 func biLsh(a *big.Int, b uint) *big.Int { return bi(0).Lsh(a, b) }
    189 func biRsh(a *big.Int, b uint) *big.Int { return bi(0).Rsh(a, b) }