概述
PBKDF2通过password和salt进行hash,然后将结果作为salt在与password进行hash,多次重复此过程,生成最终的密文。
package eu.digient.sdk.security
import eu.digient.sdk.util.AssertUtil
import eu.digient.sdk.util.Base64Util
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
/**
* Encrypt password with PBKDF2 algorithm
*/
class PBKDF2Helper {
static final int SALT_SIZE = 16
private static final int ITERATION_TIMES = 2000
private static final int ENCODED_BYTES_LENGTH = 64 * 8
private static final String SHA1PRNG = "SHA1PRNG"
/**
* Match password
* @param rawPassword - input password
* @param encryptedPassword - encrypted password
* @return
*/
static Boolean matches(final String rawPassword, final String encryptedPassword) {
AssertUtil.notNull(rawPassword, 'rawPassword is required')
AssertUtil.notNull(encryptedPassword, 'encryptedPassword is required')
byte[] decodedPwd = Base64Util.decode(encryptedPassword)
byte[] salt = truncateBytes(decodedPwd, SALT_SIZE)
return encryptedPassword == encryptWithPBKDF2(rawPassword, salt)
}
/**
* Encrypt password with PBKDF2 algorithm.
* @param rawPassword - password to be encoded
* @param salt - randomly generated salt array
* @return
*/
static String encryptWithPBKDF2(final String rawPassword, final byte[] salt) {
AssertUtil.notNull(rawPassword, 'password is required')
AssertUtil.notNull(salt, 'salt is required')
if (salt.length != SALT_SIZE) {
throw new IllegalArgumentException("salt size must be ${SALT_SIZE}")
}
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Pbkdf2Algorithm.PBKDF2WithHmacSHA256.name())
PBEKeySpec keySpec = new PBEKeySpec(rawPassword.toCharArray(), salt, ITERATION_TIMES, ENCODED_BYTES_LENGTH)
byte[] encodedPwd = keyFactory.generateSecret(keySpec).getEncoded()
byte[] combineWithSalt = concatBytes(salt, encodedPwd)
return Base64Util.encodeBytesToString(combineWithSalt)
}
/**
* generate random salt arrays
*
*/
static byte[] generateSalt() throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstance(SHA1PRNG)
byte[] bytes = new byte[SALT_SIZE]
random.nextBytes(bytes)
return bytes
}
/**
* Concatenate two byte arrays into one array
* @param bytes1
* @param bytes2
* @return
*/
private static byte[] concatBytes(final byte[] bytes1, final byte[] bytes2) {
int length = bytes1.length + bytes2.length
byte[] targetBytes = new byte[length]
System.arraycopy(bytes1, 0, targetBytes, 0, bytes1.length)
System.arraycopy(bytes2, 0, targetBytes, bytes1.length, bytes2.length)
return targetBytes
}
/**
* Truncate bytes array by length
* @param originBytes - to be truncated byte array
* @param length - truncate length
* @return
*/
private static byte[] truncateBytes(final byte[] originBytes, final int length) {
byte[] newBytes = new byte[length]
System.arraycopy(originBytes, 0, newBytes, 0, length)
return newBytes
}
enum Pbkdf2Algorithm {
PBKDF2WithHmacSHA1,
PBKDF2WithHmacSHA256,
PBKDF2WithHmacSHA512
}
}
test:
class PBKDF2HelperTest {
@Test void matches() {
assertTrue(PBKDF2Helper.matches("some-password", "kfR92MqruX2UcChISEyKIx1OTtaPbMBPdMRFQD8q2e/RDqLckSzDUUG5RXBbVsAF1qjh7qw9XKwiUpoUaGc1didsMbsHXpW/2kaxIShWVo8="))
assertTrue(PBKDF2Helper.matches("some-password1", "E2D+neHoQhPNhDO2pob8NGlZZ0w10I+4/LmsjVeS85YME8b+CZPhSIRcnDq05WcVRxGyw0C1CGZ/A1RUaLhORlaNcN9Jo4nlYKtuw1wgJQA="))
assertTrue(PBKDF2Helper.matches("some-password2", "5rnJlt+677BCMGn53SPM3+Winuc2+96P21bUrA+EjuWpnOSwMZfs2F56W+ol/0TUsO2H60Pm6X9K1UN2oaCIXb4w7WkeudUe9s+g4VTqDSk="))
assertTrue(PBKDF2Helper.matches("some-password3", "i/Cek42KWwGBSvKq4Uv7jXqYa5DtcfluTEU9qdMArIRqFSG6RbIRXymtDDMK1NfzAWkxciDj3U5UWbBzANQjFVCmTWEKJL03n+/odHBbjO8="))
assertTrue(PBKDF2Helper.matches("some-password4", "zXpJftOhs6Tk9FTW8LbsXC9XnQeq7FQJfquKNkQknf8DofKpTEN9zTuDuccVM7AJbl1+mZoG0Fc7xyaVZ4/qlB2TUFZFj/k8onRqQ8ht6BU="))
}
@Test void encryptPassword() {
byte[] salt = PBKDF2Helper.generateSalt()
String encodedPwd = PBKDF2Helper.encryptWithPBKDF2("some-password", salt)
assertNotNull(encodedPwd)
byte[] salt2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
assertEquals("AAECAwQFBgcICQoLDA0ODx273j5Q3RO9lgARLKmwYL/TGYNMd8D6sDFrOJ7mult6A2fc3JgFne8R0sf2pP11YnOAnBBsz/id/tzLbvKmEFg=", PBKDF2Helper.encryptWithPBKDF2("some-password", salt2))
}
@Test void generateSalt() {
for (int i = 0; i < 100; i++) {
byte[] r1 = PBKDF2Helper.generateSalt()
byte[] r2 = PBKDF2Helper.generateSalt()
assertNotEquals(r1, r2)
assertEquals(PBKDF2Helper.SALT_SIZE, r1.size())
}
}
}
最后
以上就是认真镜子为你收集整理的PBKDF2加密算法集成的全部内容,希望文章能够帮你解决PBKDF2加密算法集成所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复