This repository has been archived by the owner on Feb 9, 2020. It is now read-only.
/
cmd-init.go
82 lines (76 loc) · 1.88 KB
/
cmd-init.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
package hush
import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"io"
"os"
)
// CmdInit initializes the user's hush file, if it does not exist.
// Informative user messages are written to w. User input, if needed,
// is taken from input.
//
// This function implements "hush init"
func CmdInit(w io.Writer, input *os.File) error {
// make sure hush file doesn't exist yet
hushFilename, err := HushPath()
if !os.IsNotExist(err) {
return fmt.Errorf(
"A hush file already exists at %s\nNo need to run init",
hushFilename,
)
}
// prompt for passwords
io.WriteString(w, "Preparing to initialize your hush file. Please provide\n")
io.WriteString(w, "and verify a password to use for encryption.\n")
io.WriteString(w, "\n")
password, err := AskPassword(w, "Password")
if err != nil {
return err
}
verify, err := AskPassword(w, "Verify password")
if err != nil {
return err
}
if !bytes.Equal(password, verify) {
return errors.New("Passwords don't match")
}
// generate keys
encryptionKey := make([]byte, 32) // 256-bit key for AES
_, err = rand.Read(encryptionKey)
if err != nil {
return err
}
macKey := make([]byte, 32) // 256-bit key for HMAC
_, err = rand.Read(macKey)
if err != nil {
return err
}
salt := make([]byte, 16) // double the RFC8018 minimum
_, err = rand.Read(salt)
if err != nil {
return err
}
pwKey := stretchPassword(password, salt)
t := newT(nil)
t.encryptionKey = encryptionKey
t.macKey = macKey
p := NewPath("hush-configuration/salt")
v := NewPlaintext(salt, Public)
t.set(p, v)
p = NewPath("hush-configuration/encryption-key")
v = NewPlaintext(encryptionKey, Private)
v = v.Ciphertext(pwKey)
t.set(p, v)
p = NewPath("hush-configuration/mac-key")
v = NewPlaintext(macKey, Private)
v = v.Ciphertext(pwKey)
t.set(p, v)
err = t.Save()
if err != nil {
return err
}
fmt.Fprintf(w, "Hush file created at %s\n", hushFilename)
return nil
}