adding PBKDF2_SHA256 from 389-ds
This commit is contained in:
parent
afde7b4e37
commit
46611904ba
2 changed files with 64 additions and 2 deletions
|
@ -1,7 +1,11 @@
|
|||
package org.xbib.groovy.crypt
|
||||
|
||||
import javax.crypto.Mac
|
||||
import javax.crypto.SecretKeyFactory
|
||||
import javax.crypto.spec.PBEKeySpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
|
@ -79,6 +83,33 @@ class CryptUtil {
|
|||
base64Digest(plainText, salt, 'SHA-512', 'ssha512')
|
||||
}
|
||||
|
||||
static String pbkdf2(String plainText) {
|
||||
// the 389-ds parameters for PBKDF2-SHA256
|
||||
pbkdf2(plainText, randomHexString(64), 30000, 256)
|
||||
}
|
||||
|
||||
static String pbkdf2(String plainText, String salt) {
|
||||
// the 389-ds parameters for PBKDF2-SHA256: 30000 iterations, 64 bytes (128 hex) salt, 256 bytes hash length
|
||||
if (salt.length() != 128) {
|
||||
throw new IllegalArgumentException("salt must be 64 bytes")
|
||||
}
|
||||
pbkdf2(plainText, salt, 30000, 256)
|
||||
}
|
||||
|
||||
static String pbkdf2(String plainText, String salt, int iterations, int hashLength) {
|
||||
byte[] n = htonl(iterations).array() // 4 bytes for network byte order = native byte order
|
||||
byte[] b = salt.decodeHex()
|
||||
byte[] hash = pbkdf2(plainText.toCharArray(), b, iterations, hashLength * 8)
|
||||
int len = n.length + b .length + hash.length
|
||||
byte[] result = new byte[len]
|
||||
ByteBuffer buffer = ByteBuffer.wrap(result)
|
||||
buffer.put(n)
|
||||
buffer.put(b)
|
||||
buffer.put(hash)
|
||||
// 4 + 64 + 256 = 324 bytes
|
||||
"{PBKDF2_SHA256}${result.encodeBase64()}"
|
||||
}
|
||||
|
||||
static String hmacSHA1(String plainText, String secret) {
|
||||
hmac(plainText.getBytes(StandardCharsets.UTF_8), secret.getBytes(StandardCharsets.UTF_8), "HmacSHA1")
|
||||
}
|
||||
|
@ -105,9 +136,32 @@ class CryptUtil {
|
|||
mac.doFinal(plainText).encodeHex()
|
||||
}
|
||||
|
||||
static String random(int length) {
|
||||
/**
|
||||
* Computes the PBKDF2 hash of a password.
|
||||
*
|
||||
* @param password the password to hash.
|
||||
* @param salt the salt
|
||||
* @param iterations the iteration count (slowness factor)
|
||||
* @param bytes the length of the hash to compute in bytes
|
||||
* @return the PBDKF2 hash of the password
|
||||
*/
|
||||
static byte[] pbkdf2(char[] plainText, byte[] salt, int iterations, int len) {
|
||||
PBEKeySpec spec = new PBEKeySpec(plainText, salt, iterations, len)
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
|
||||
skf.generateSecret(spec).getEncoded()
|
||||
}
|
||||
|
||||
static String randomHexString(int length) {
|
||||
randomBytes(length).encodeHex()
|
||||
}
|
||||
|
||||
static byte[] randomBytes(int length) {
|
||||
byte[] b = new byte[length]
|
||||
random.nextBytes(b)
|
||||
b.encodeHex()
|
||||
b
|
||||
}
|
||||
|
||||
static ByteBuffer htonl(int value) {
|
||||
ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,4 +169,12 @@ class CryptTest {
|
|||
String code = CryptUtil.ssha512(plaintext, salt)
|
||||
assertEquals('{ssha512}jeWuCXRjsvKh/vK548GP9ZCs4q9Sh1u700C8eONyV+EL/P810C8vlx9Eu4vRjHq/TDoGW8FE1l/P2KG3w9lHITxo8fR/Qdgv', code,'test SSHA-512 method')
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPBKDF2() {
|
||||
String plaintext = 'geheim'
|
||||
String salt = "3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f3c68f1f47f41d82f"
|
||||
String code = CryptUtil.pbkdf2(plaintext, salt)
|
||||
assertEquals("{PBKDF2_SHA256}MHUAADxo8fR/QdgvPGjx9H9B2C88aPH0f0HYLzxo8fR/QdgvPGjx9H9B2C88aPH0f0HYLzxo8fR/QdgvPGjx9H9B2C9DUj6t+vF3mSI5b6nExWWcUnA6DXTbEa25BIMZ5ERe9JIqjkBr2p0ot9D5x4LZx9evQNexOWb+ea/stJkmi3wWKwS/uzSpEc4NZSv/+W1ZWtnK6NMkxxRJPjXEOCrjbKCOktDwCjSelBAe/rt0DABUYoMw69c8qZ1toAIz1x6oN5y58ImMpVsPK/CkbmbeK0QtDbWYZK8V1SZ6cZlF6kngpGWnAcEilIHqCVjM1HZMI+mZz86h86ZHcbxp9twuENu3DHi3nIZRzILrRIsjWAkruSDw7W/jXseGmVeBj/22xbKSybZmXawFGM59k3U5fE+1WvudOfVzwFyVAxDxispF", code)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue