v2 / vlib / crypto / pbkdf2 / pbkdf2.v
67 lines · 62 sloc · 1.44 KB · 90278d0fbf2101feb168edfee6b414ffc4fe1869
Raw
1// Based off: https://golang.org/x/crypto/pbkdf2
2module pbkdf2
3
4import crypto.hmac
5import crypto.sha256
6import crypto.sha512
7import hash
8
9// key derives a key from the password, salt and iteration count
10// example pbkdf2.key('test'.bytes(), '123456'.bytes(), 1000, 64, sha512.new())
11pub fn key(password []u8, salt []u8, count int, key_length int, h hash.Hash) ![]u8 {
12 mut fun := fn (b []u8) []u8 {
13 return []u8{}
14 }
15 mut block_size := 0
16 mut size := 0
17 match h {
18 sha256.Digest {
19 block_size = h.block_size()
20 size = h.size()
21 if size == sha256.size224 {
22 fun = sha256.sum224
23 } else {
24 fun = sha256.sum256
25 }
26 }
27 sha512.Digest {
28 block_size = h.block_size()
29 size = h.size()
30 if size == sha512.size384 {
31 fun = sha512.sum384
32 } else {
33 fun = sha512.sum512
34 }
35 }
36 else {
37 return error('Unsupported hash')
38 }
39 }
40
41 hash_length := size
42 block_count := (key_length + hash_length - 1) / hash_length
43 mut output := []u8{}
44 mut last := []u8{}
45 mut buf := []u8{len: 4}
46 for i := 1; i <= block_count; i++ {
47 last.clear()
48 last << salt
49
50 buf[0] = u8(i >> 24)
51 buf[1] = u8(i >> 16)
52 buf[2] = u8(i >> 8)
53 buf[3] = u8(i)
54
55 last << buf
56 mut xorsum := hmac.new(password, last, fun, block_size)
57 mut last_hash := xorsum.clone()
58 for j := 1; j < count; j++ {
59 last_hash = hmac.new(password, last_hash, fun, block_size)
60 for k in 0 .. xorsum.len {
61 xorsum[k] ^= last_hash[k]
62 }
63 }
64 output << xorsum
65 }
66 return output[..key_length]
67}
68