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) }