diff options
Diffstat (limited to 'pkg/onionkey')
| -rw-r--r-- | pkg/onionkey/key.go | 22 | ||||
| -rw-r--r-- | pkg/onionkey/v3.go | 76 |
2 files changed, 98 insertions, 0 deletions
diff --git a/pkg/onionkey/key.go b/pkg/onionkey/key.go new file mode 100644 index 0000000..895edae --- /dev/null +++ b/pkg/onionkey/key.go @@ -0,0 +1,22 @@ +package onionkey + +import ( + "github.com/wybiral/torgo" +) + +// Key is generic interface type for Tor onion keys. +type Key interface { + WriteFile(path string) error + Onion() (*torgo.Onion, error) + ServiceID() string +} + +// GenerateKey generates a Tor onion key. +func GenerateKey() (Key, error) { + return generateV3() +} + +// ReadFile reads a Tor onion key from file path. +func ReadFile(path string) (Key, error) { + return readV3(path) +} diff --git a/pkg/onionkey/v3.go b/pkg/onionkey/v3.go new file mode 100644 index 0000000..155c6b1 --- /dev/null +++ b/pkg/onionkey/v3.go @@ -0,0 +1,76 @@ +package onionkey + +import ( + "crypto/rand" + "encoding/base32" + "encoding/base64" + "errors" + "io/ioutil" + "os" + "strings" + + "github.com/wybiral/torgo" + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/sha3" +) + +type v3Key ed25519.PrivateKey + +func generateV3() (v3Key, error) { + _, key, err := ed25519.GenerateKey(rand.Reader) + return v3Key(key), err +} + +func readV3(path string) (v3Key, error) { + raw, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + pk := strings.TrimSpace(string(raw)) + parts := strings.SplitN(pk, ":", 2) + if parts[0] != "v3" { + return nil, errors.New("Invalid key type") + } + seed, err := base64.StdEncoding.DecodeString(parts[1]) + if err != nil { + return nil, err + } + key := ed25519.NewKeyFromSeed(seed) + return v3Key(key), nil +} + +func (k v3Key) Onion() (*torgo.Onion, error) { + return torgo.OnionFromEd25519(ed25519.PrivateKey(k)) +} + +func (k v3Key) WriteFile(path string) error { + seed := ed25519.PrivateKey(k).Seed() + b64 := base64.StdEncoding.EncodeToString(seed) + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + _, err = f.WriteString("v3:" + b64) + if err != nil { + return err + } + return nil +} + +func (k v3Key) ServiceID() string { + // Get ed25519 public key + pub := ed25519.PrivateKey(k).Public().(ed25519.PublicKey) + // Calculate check digits + checkstr := []byte(".onion checksum") + checkstr = append(checkstr, pub...) + checkstr = append(checkstr, 0x03) + checksum := sha3.Sum256(checkstr) + checkdigits := checksum[:2] + // Calculate service ID + combined := pub[:] + combined = append(combined, checkdigits...) + combined = append(combined, 0x03) + serviceID := base32.StdEncoding.EncodeToString(combined) + return strings.ToLower(serviceID) +} |
