开发者社区> 问答> 正文

django 默认密码加密算法pbkdf2-sha256如何用java实现:报错 

加密后的密码例如:
pbkdf2_sha256$15000$ZdYJKwuyheny$6pZJnPwX5wk6yGOtNFrz4nu3ePtkdURtmqiXwI/agFM=
怎么用java实现呢?

展开
收起
kun坤 2020-06-04 21:16:26 1826 0
1 条回答
写回答
取消 提交回答
  • 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 [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]
    }
    /**
    *生成随机字符
    **/
    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, "")
    }

    已解决,网上找了几个语言的pbkdf2_sha256算法,计算出的结果都和python不一样。
    试过php/java/nodejs/golang,最后只有golang结果和python一致,无奈只有用golang生成密码,java调用golang的http服务,下面贴出代码:

    ######亲测可用

    2020-06-08 09:45:50
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载