-
Notifications
You must be signed in to change notification settings - Fork 4
/
kdf.go
111 lines (97 loc) · 2.07 KB
/
kdf.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
109
110
111
package main
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"flag"
"fmt"
"hash"
"io"
"log"
"os"
"strconv"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/pbkdf2"
)
var flags struct {
alg string
hash string
secret string
salt string
info string
iter int
}
func main() {
log.SetFlags(0)
log.SetPrefix("kdf: ")
parseflags()
var out, salt, info []byte
if flags.salt != "" {
salt = []byte(flags.salt)
}
if flags.info != "" {
info = []byte(flags.info)
}
secret, err := os.ReadFile(flag.Arg(0))
check(err)
keylen, err := strconv.Atoi(flag.Arg(1))
check(err)
h := gethash(flags.hash)
switch flags.alg {
case "hkdf":
r := hkdf.New(h, secret, salt, info)
out = make([]byte, keylen)
_, err = io.ReadAtLeast(r, out, keylen)
check(err)
case "pbkdf2":
out = pbkdf2.Key(secret, salt, flags.iter, keylen, h)
}
fmt.Printf("%x\n", out)
}
func parseflags() {
flag.Usage = usage
flag.StringVar(&flags.alg, "alg", "hkdf", "kdf algorithm to use")
flag.StringVar(&flags.hash, "hash", "sha512", "hash algorithm to use")
flag.StringVar(&flags.salt, "salt", "salt", "specify salt")
flag.StringVar(&flags.info, "info", "label", "specify info [hkdf]")
flag.IntVar(&flags.iter, "iter", 4096, "specify iterations [pbkdf2]")
flag.Parse()
if flag.NArg() != 2 {
usage()
}
}
func usage() {
fmt.Fprintln(os.Stderr, "usage: [options] <secret_file> <keylen>")
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "available algorithms: hkdf pbkdf2")
fmt.Fprintln(os.Stderr, "available hashes: md5 sha1 sha224 sha256 sha384 sha512_224 sha512_256 sha512")
os.Exit(2)
}
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
func gethash(name string) func() hash.Hash {
switch name {
case "md5":
return md5.New
case "sha1":
return sha1.New
case "sha224":
return sha256.New224
case "sha256":
return sha256.New
case "sha384":
return sha512.New384
case "sha512_224":
return sha512.New512_224
case "sha512_256":
return sha512.New512_256
case "sha512":
return sha512.New
}
log.Fatalf("unknown hash %q", name)
return nil
}