main
go 112 lines 2.57 KB
Raw
1 package identity
2
3 import (
4 "crypto/rand"
5 "crypto/sha256"
6 "encoding/base64"
7 "encoding/hex"
8 "errors"
9 "net/netip"
10 "strings"
11
12 "golang.org/x/crypto/curve25519"
13 )
14
15 func NormalizeWireGuardPrivateKey(raw string) (string, error) {
16 key, err := decodeKey(raw)
17 if err != nil {
18 return "", err
19 }
20 clampPrivateKey(&key)
21 return base64.StdEncoding.EncodeToString(key[:]), nil
22 }
23
24 func GenerateWireGuardPrivateKey() (string, error) {
25 var key [32]byte
26 if _, err := rand.Read(key[:]); err != nil {
27 return "", err
28 }
29 clampPrivateKey(&key)
30 return base64.StdEncoding.EncodeToString(key[:]), nil
31 }
32
33 func WireGuardPublicKeyFromPrivate(raw string) (string, error) {
34 privateKey, err := decodeKey(raw)
35 if err != nil {
36 return "", err
37 }
38 clampPrivateKey(&privateKey)
39 var publicKey [32]byte
40 curve25519.ScalarBaseMult(&publicKey, &privateKey)
41 return base64.StdEncoding.EncodeToString(publicKey[:]), nil
42 }
43
44 func DeriveWireGuardOverlayIPv4(publicKey string) (string, error) {
45 decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(publicKey))
46 if err != nil {
47 return "", errors.New("wireguard public key must be base64 encoded")
48 }
49 if len(decoded) != 32 {
50 return "", errors.New("wireguard public key must be 32 bytes")
51 }
52
53 sum := sha256.Sum256(decoded)
54 return netip.AddrFrom4([4]byte{
55 100,
56 64 + (sum[0] & 0x3f),
57 sum[1],
58 1 + (sum[2] % 254),
59 }).String(), nil
60 }
61
62 func WireGuardKeyHex(raw string) (string, error) {
63 key, err := decodeKey(raw)
64 if err != nil {
65 return "", err
66 }
67 return hex.EncodeToString(key[:]), nil
68 }
69
70 func ValidateWireGuardPublicKey(raw string) error {
71 key := strings.TrimSpace(raw)
72 if key == "" {
73 return errors.New("wireguard_public_key is required")
74 }
75 decoded, err := base64.StdEncoding.DecodeString(key)
76 if err != nil {
77 return errors.New("wireguard_public_key must be base64 encoded")
78 }
79 if len(decoded) != 32 {
80 return errors.New("wireguard_public_key must be 32 bytes")
81 }
82 return nil
83 }
84
85 func decodeKey(raw string) ([32]byte, error) {
86 var key [32]byte
87 value := strings.TrimSpace(raw)
88 if value == "" {
89 return key, errors.New("wireguard key is required")
90 }
91
92 var decoded []byte
93 var err error
94 if len(value) == 64 && !strings.Contains(value, "=") {
95 decoded, err = hex.DecodeString(value)
96 } else {
97 decoded, err = base64.StdEncoding.DecodeString(value)
98 }
99 if err != nil {
100 return key, errors.New("wireguard key must be base64 or hex encoded")
101 }
102 if len(decoded) != len(key) {
103 return key, errors.New("wireguard key must be 32 bytes")
104 }
105 copy(key[:], decoded)
106 return key, nil
107 }
108
109 func clampPrivateKey(key *[32]byte) {
110 key[0] &= 248
111 key[31] = (key[31] & 127) | 64
112 }