...
1 package crypto
2
3 import (
4 "crypto/rand"
5 "encoding/base64"
6 "fmt"
7
8 "golang.org/x/crypto/curve25519"
9 )
10
11
12 const wireguardKeyLen = 32
13
14 type wireguardKeyPair struct {
15 publicKey string
16 privateKey string
17 }
18
19
20 func GenerateWireguardKeyPair() (AsymmetricKeyPair, error) {
21 privateKey, err := generateWireguardPrivateKey()
22 if err != nil {
23 return nil, err
24 }
25 publicKey := privateKey.PublicKey()
26
27 return &wireguardKeyPair{
28 publicKey: publicKey.String(),
29 privateKey: privateKey.String(),
30 }, nil
31 }
32
33 func (wgKeyPair *wireguardKeyPair) PublicKey() string {
34 return wgKeyPair.publicKey
35 }
36
37 func (wgKeyPair *wireguardKeyPair) PrivateKey() string {
38 return wgKeyPair.privateKey
39 }
40
41
42
43
44 type wireguardKey [wireguardKeyLen]byte
45
46
47
48 func newWireguardKey(bytes []byte) (wireguardKey, error) {
49 if len(bytes) != wireguardKeyLen {
50 return wireguardKey{}, fmt.Errorf("incorrect key size: %d", len(bytes))
51 }
52
53 var wgKey wireguardKey
54 copy(wgKey[:], bytes)
55
56 return wgKey, nil
57 }
58
59
60
61 func (wgKey wireguardKey) PublicKey() wireguardKey {
62 var (
63 publicKey [wireguardKeyLen]byte
64 privateKey = [wireguardKeyLen]byte(wgKey)
65 )
66
67
68
69 curve25519.ScalarBaseMult(&publicKey, &privateKey)
70
71 return wireguardKey(publicKey)
72 }
73
74
75 func (wgKey wireguardKey) String() string {
76 return base64.StdEncoding.EncodeToString(wgKey[:])
77 }
78
79
80
81 func generateWireguardPrivateKey() (wireguardKey, error) {
82 wgKey, err := generateWireguardKey()
83 if err != nil {
84 return wireguardKey{}, err
85 }
86
87
88
89 wgKey[0] &= 248
90 wgKey[31] &= 127
91 wgKey[31] |= 64
92
93 return wgKey, nil
94 }
95
96
97
98
99
100
101 func generateWireguardKey() (wireguardKey, error) {
102 bytes := make([]byte, wireguardKeyLen)
103 if _, err := rand.Read(bytes); err != nil {
104 return wireguardKey{}, fmt.Errorf("failed to read random bytes: %v", err)
105 }
106
107 return newWireguardKey(bytes)
108 }
109
View as plain text