django 默认密码加密算法 pbkdf2-sha256 如何用 java 实现
加密后的密码例如:
pbkdf2_sha256$15000$ZdYJKwuyheny$6pZJnPwX5wk6yGOtNFrz4nu3ePtkdURtmqiXwI/agFM=
怎么用 java 实现呢?
网上找了几个语言的pbkdf2_sha256算法,计算出的结果都和python不一样。
试过php/java/nodejs/golang,最后只有golang结果和python一致,无奈只有用golang生成密码,java调用golang的http服务,下面贴出代码:
package main
import (
"crypto/sha256"
"encoding/base64"
"strconv"
"crypto/hmac"
"hash"
"io"
"net/http"
"strings"
"math/rand"
"time"
"fmt"
)
// djnago 的实现细节请参考 Python 和 djnago 文档:
// djnago.contrib.auth.hashers.make_password
// djnago.utils.crypto import pbkdf2
// hashlib.sha256
// base64
func main() {
http.HandleFunc("/djnagopwd", gendjnagopwd)
http.ListenAndServe(":7070", nil)
}
func gendjnagopwd(rw http.ResponseWriter, req *http.Request){
req.ParseForm();
attempted := req.FormValue("attempted");
var temp = req.FormValue("salt");
var salt []byte
if temp != ""{
salt = []byte (temp) // 盐,是一个随机字符串,每一个用户都不一样
}else{
salt = []byte(genSalt())
}
fmt.Println("-----------------salt::::: "+salt+" ----------------");
pwd := []byte(attempted) // 用户设置的原始密码
iterations := 15000 // 加密算法的迭代次数,15000 次
digest := sha256.New // digest 算法,使用 sha256
// 第一步:使用 pbkdf2 算法加密
dk := Key(pwd, salt, iterations, 32, digest)
// 第二步:Base64
str := base64.StdEncoding.EncodeToString(dk)
// 第三步:组合加密算法、迭代次数、盐、密码和分割符号 "$"
io.WriteString(rw, "pbkdf2_sha256" + "$" + strconv.FormatInt(int64(iterations), 10) + "$" + string(salt) + "$" + str);
}
func Key(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 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 = byte(block >> 24)
buf = byte(block >> 16)
buf = byte(block >> 8)
buf = 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]
}
/**
*生成随机字符
**/
func genSalt() string {
length := 12
rand.Seed(time.Now().UnixNano())
rs := make([]string, length)
for start := 0; start < length; start++ {
t := rand.Intn(3)
if t == 0 {
rs = append(rs, strconv.Itoa(rand.Intn(10)))
} else if t == 1 {
rs = append(rs, string(rand.Intn(26)+65))
} else {
rs = append(rs, string(rand.Intn(26)+97))
}
}
return strings.Join(rs, "")
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。