实现Django PBKDF2PasswordHasher 加密算法(Kotlin版)

之前Web业务框架是基于Python的Django。已有一定用户量,现需要集成和解析之前的密码规则。进而再逐步替换用户密码。

Django框架自带密码生成是基于pbkdf2_sha256加密方式的,有一点不同的是。
他是基于4个字符串值合并的集合。

哈希算法+算法迭代次数(工作因子)+随机Salt+最终的密码哈希值。
<algorithm>$<iterations>$<salt>$<hash>

具体的实现可以参考文后的Django中的密码管理。

以下的代码可以优化为自定义的iterations,slat值,看你们操作了 :)

package com.demo.utils

/**
 * @author watson haw
 * @date 2021/5/24 2:07 下午
 * 将密码转换为Django的pbkdf2_sha256
 */
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import kotlin.system.exitProcess


class HashHelper {
    val DEFAULT_ITERATIONS: Int = 10000;
    val algorithm: String = "pbkdf2_sha256";

    fun getEncodeHash(password: String, salt: String, iterations: Int): String {
        lateinit var keyFactory: SecretKeyFactory;
        try {
            keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
        } catch (e: InvalidKeySpecException) {
            println("Could NOT retrieve PBKDF2WithHmacSHA256 algorithm")
            exitProcess(1)
        }
        val keySpec: KeySpec = PBEKeySpec(
            password.toCharArray(),
            salt.toByteArray(),
            iterations,
            256
        )

        lateinit var secret: SecretKey;

        try {
            secret = keyFactory.generateSecret(keySpec)
        } catch (e: InvalidKeySpecException) {
            println("Could NOT generate secret key");
            e.printStackTrace()
        }

        val rawHash: ByteArray = secret.encoded
        val hashBase64: ByteArray = Base64.getEncoder().encode(rawHash)
        return String(hashBase64)
    }

    fun encode(password: String, salt: String, iterations: Int = DEFAULT_ITERATIONS): String {
        val hash: String = getEncodeHash(password, salt, iterations)
        return "%s$%d$%s$%s".format(algorithm, iterations, salt, hash)
    }

    fun checkPassword(password: String, hashedPassword: String): Boolean {
        val parts: List<String> = hashedPassword.split("$")
        if (parts.size != 4) return false
        val iterations: Int = parts[1].toInt()
        val salt = parts[2]
        val hash = encode(password, salt, iterations)
        return hash == hashedPassword
    }
}
复制代码

Spring Boot测试代码

package com.demo.utils

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest

/**
 * @author watson haw
 * @date 2021/5/24 3:32 下午
 */


@SpringBootTest
class HashHelperTests {
    @Test
    fun testCheckPassword() {
        val hasHelper = HashHelper()
        val passWord = "mystery"
        val hashPassword = "pbkdf2_sha256\$10000\$qx1ec0f4lu4l\$3G81rAm/4ng0tCCPTrx2aWohq7ztDBfFYczGNoUtiKQ="
        Assertions.assertTrue(hasHelper.checkPassword(passWord, hashPassword))
    }

    @Test
    fun testEncode() {
        val hashHelper = HashHelper()
        val password = "123456"
        val salt = "you_salt"
        val hashResult = hashHelper.encode(password, salt)
        Assertions.assertEquals(
            "pbkdf2_sha256\$10000\$you_salt\$VgKivkVxt2f+KKdosZAeGsO90GHXV5nXsOyOOjOy3mY=",
            hashResult
        )
    }

复制代码

参考的Java源码

Django中的密码管理

java实现Django的PBKDF2PasswordHasher加密算法 作者:CSDN土豆TM

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享