|
|
|
@ -5,14 +5,12 @@
|
|
|
|
|
package base |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"crypto/hmac" |
|
|
|
|
"crypto/md5" |
|
|
|
|
"crypto/rand" |
|
|
|
|
"crypto/sha1" |
|
|
|
|
"encoding/base64" |
|
|
|
|
"encoding/hex" |
|
|
|
|
"fmt" |
|
|
|
|
"hash" |
|
|
|
|
"html/template" |
|
|
|
|
"math" |
|
|
|
|
"math/big" |
|
|
|
@ -110,45 +108,6 @@ func randomInt(max *big.Int) (int, error) {
|
|
|
|
|
return int(rand.Int64()), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
|
|
|
|
|
// FIXME: use https://godoc.org/golang.org/x/crypto/pbkdf2?
|
|
|
|
|
func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { |
|
|
|
|
prf := hmac.New(h, password) |
|
|
|
|
hashLen := prf.Size() |
|
|
|
|
numBlocks := (keyLen + hashLen - 1) / hashLen |
|
|
|
|
|
|
|
|
|
var buf [4]byte |
|
|
|
|
dk := make([]byte, 0, numBlocks*hashLen) |
|
|
|
|
U := make([]byte, hashLen) |
|
|
|
|
for block := 1; block <= numBlocks; block++ { |
|
|
|
|
// N.B.: || means concatenation, ^ means XOR
|
|
|
|
|
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
|
|
|
|
// U_1 = PRF(password, salt || uint(i))
|
|
|
|
|
prf.Reset() |
|
|
|
|
prf.Write(salt) |
|
|
|
|
buf[0] = byte(block >> 24) |
|
|
|
|
buf[1] = byte(block >> 16) |
|
|
|
|
buf[2] = byte(block >> 8) |
|
|
|
|
buf[3] = byte(block) |
|
|
|
|
prf.Write(buf[:4]) |
|
|
|
|
dk = prf.Sum(dk) |
|
|
|
|
T := dk[len(dk)-hashLen:] |
|
|
|
|
copy(U, T) |
|
|
|
|
|
|
|
|
|
// U_n = PRF(password, U_(n-1))
|
|
|
|
|
for n := 2; n <= iter; n++ { |
|
|
|
|
prf.Reset() |
|
|
|
|
prf.Write(U) |
|
|
|
|
U = U[:0] |
|
|
|
|
U = prf.Sum(U) |
|
|
|
|
for x := range U { |
|
|
|
|
T[x] ^= U[x] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return dk[:keyLen] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// verify time limit code
|
|
|
|
|
func VerifyTimeLimitCode(data string, minutes int, code string) bool { |
|
|
|
|
if len(code) <= 18 { |
|
|
|
|