-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathed25519.go
57 lines (52 loc) · 1.6 KB
/
ed25519.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package torgo
import (
"crypto/sha512"
"encoding/base32"
"encoding/base64"
"errors"
"strings"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/sha3"
)
// OnionFromEd25519 returns an Onion instance from an ED25519 private key which
// can be used to start a hidden service with controller.AddOnion.
func OnionFromEd25519(pri ed25519.PrivateKey) (*Onion, error) {
pub, ok := pri.Public().(ed25519.PublicKey)
if !ok {
return nil, errors.New("torgo: unable to extract ed25519.PublicKey")
}
serviceID, err := ServiceIDFromEd25519(pub)
if err != nil {
return nil, err
}
h := sha512.Sum512(pri[:32])
// Set bits so that h[:32] is private scalar "a"
h[0] &= 248
h[31] &= 127
h[31] |= 64
// Since h[32:] is RH, h is now (a || RH)
key := base64.StdEncoding.EncodeToString(h[:])
return &Onion{
Ports: make(map[int]string),
ServiceID: serviceID,
PrivateKey: key,
PrivateKeyType: "ED25519-V3",
}, nil
}
// ServiceIDFromEd25519 calculates a Tor service ID from an ed25519.PublicKey.
func ServiceIDFromEd25519(pub ed25519.PublicKey) (string, error) {
checkdigits := ed25519Checkdigits(pub)
combined := pub[:]
combined = append(combined, checkdigits...)
combined = append(combined, 0x03)
serviceID := base32.StdEncoding.EncodeToString(combined)
return strings.ToLower(serviceID), nil
}
// ed25519Checkdigits calculates tje check digits used to create service ID.
func ed25519Checkdigits(pub ed25519.PublicKey) []byte {
checkstr := []byte(".onion checksum")
checkstr = append(checkstr, pub...)
checkstr = append(checkstr, 0x03)
checksum := sha3.Sum256(checkstr)
return checksum[:2]
}