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
|
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package arq
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"hash"
"log"
"bitbucket.org/taruti/pbkdf2.go" // TODO: Pull in copy
)
type cryptoState struct {
c cipher.Block
iv []byte
salt []byte
}
func (c *cryptoState) unlock(pw string) {
const (
iter = 1000
keyLen = 48
aesKeyLen = 32
aesIVLen = 16
)
key1 := pbkdf2.Pbkdf2([]byte(pw), c.salt, iter, sha1.New, keyLen)
var key2 []byte
key2, c.iv = bytesToKey(sha1.New, c.salt, key1, iter, aesKeyLen, aesIVLen)
c.c, _ = aes.NewCipher(key2)
}
func (c *cryptoState) decrypt(data []byte) []byte {
dec := cipher.NewCBCDecrypter(c.c, c.iv)
if len(data)%aes.BlockSize != 0 {
log.Fatal("bad block")
}
dec.CryptBlocks(data, data)
// fmt.Printf("% x\n", data)
// fmt.Printf("%s\n", data)
// unpad
{
n := len(data)
p := int(data[n-1])
if p == 0 || p > aes.BlockSize {
log.Fatal("impossible padding")
}
for i := 0; i < p; i++ {
if data[n-1-i] != byte(p) {
log.Fatal("bad padding")
}
}
data = data[:n-p]
}
return data
}
func sha(data []byte) score {
h := sha1.New()
h.Write(data)
var sc score
copy(sc[:], h.Sum(nil))
return sc
}
func bytesToKey(hf func() hash.Hash, salt, data []byte, iter int, keySize, ivSize int) (key, iv []byte) {
h := hf()
var d, dcat []byte
sum := make([]byte, 0, h.Size())
for len(dcat) < keySize+ivSize {
// D_i = HASH^count(D_(i-1) || data || salt)
h.Reset()
h.Write(d)
h.Write(data)
h.Write(salt)
sum = h.Sum(sum[:0])
for j := 1; j < iter; j++ {
h.Reset()
h.Write(sum)
sum = h.Sum(sum[:0])
}
d = append(d[:0], sum...)
dcat = append(dcat, d...)
}
return dcat[:keySize], dcat[keySize : keySize+ivSize]
}
|