-
Notifications
You must be signed in to change notification settings - Fork 100
/
genkeys.go
108 lines (92 loc) · 2.84 KB
/
genkeys.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"bufio"
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"log"
"os"
"strings"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/scrypt"
)
// DeterministicRand - Deterministic random function
type DeterministicRand struct {
pool []byte
pos int
}
var deterministicRand DeterministicRand
func initDeterministicRand(leKey []byte, poolLen int) {
key, err := scrypt.Key(leKey, []byte{}, 16384, 12, 1, poolLen)
if err != nil {
log.Panic(err)
}
deterministicRand.pool, deterministicRand.pos = key, 0
}
func (DeterministicRand) Read(p []byte) (n int, err error) {
reqLen := len(p)
left := len(deterministicRand.pool) - deterministicRand.pos
if left < reqLen {
log.Panic(fmt.Sprintf("rand pool exhaustion (%v left, %v needed)",
left, reqLen))
}
copy(p, deterministicRand.pool[deterministicRand.pos:deterministicRand.pos+reqLen])
for i := 0; i < reqLen; i++ {
deterministicRand.pool[i] = 0
}
deterministicRand.pos += reqLen
return reqLen, nil
}
func genKeys(conf Conf, configFile string, leKey string) {
randRead, randReader := rand.Read, io.Reader(nil)
if len(leKey) > 0 {
initDeterministicRand([]byte(leKey), 96)
randRead, randReader = deterministicRand.Read, deterministicRand
}
psk := make([]byte, 32)
if _, err := randRead(psk); err != nil {
log.Fatal(err)
}
pskHex := hex.EncodeToString(psk)
encryptSk := make([]byte, 32)
if _, err := randRead(encryptSk); err != nil {
log.Fatal(err)
}
encryptSkHex := hex.EncodeToString(encryptSk)
signPk, signSk, err := ed25519.GenerateKey(randReader)
if err != nil {
log.Fatal(err)
}
signPkHex := hex.EncodeToString(signPk)
signSkHex := hex.EncodeToString(signSk[0:32])
fmt.Printf("\n\n--- Create a file named %s with only the lines relevant to your configuration ---\n\n\n", configFile)
fmt.Printf("# Configuration for a client\n\n")
fmt.Printf("Connect = %q\t# Edit appropriately\n", conf.Connect)
fmt.Printf("Psk = %q\n", pskHex)
fmt.Printf("SignPk = %q\n", signPkHex)
fmt.Printf("SignSk = %q\n", signSkHex)
fmt.Printf("EncryptSk = %q\n", encryptSkHex)
fmt.Printf("\n\n")
fmt.Printf("# Configuration for a server\n\n")
fmt.Printf("Listen = %q\t# Edit appropriately\n", conf.Listen)
fmt.Printf("Psk = %q\n", pskHex)
fmt.Printf("SignPk = %q\n", signPkHex)
fmt.Printf("\n\n")
fmt.Printf("# Hybrid configuration\n\n")
fmt.Printf("Connect = %q\t# Edit appropriately\n", conf.Connect)
fmt.Printf("Listen = %q\t# Edit appropriately\n", conf.Listen)
fmt.Printf("Psk = %q\n", pskHex)
fmt.Printf("SignPk = %q\n", signPkHex)
fmt.Printf("SignSk = %q\n", signSkHex)
fmt.Printf("EncryptSk = %q\n", encryptSkHex)
}
func getPassword(prompt string) string {
os.Stdout.Write([]byte(prompt))
reader := bufio.NewReader(os.Stdin)
password, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
return strings.TrimSpace(password)
}