再接再厉:PKCS#5的实现:
PKCS#5主要讲了基于口令的加密标准,具体包括:
1.密钥派生:
1.1 密钥派生接口
package com.broadthinking.pkcs.pkcs_5;
/**
* A typical application of the key derivation functions defined here might
* include the following steps:
* 1. Select a salt S and an iteration count c, as outlined in Section 4.
* 2. Select a length in octets for the derived key,dkLen.
* 3. Apply the key derivation function to the password, the salt, the iteration
* count and the key length to produce a derived key.
* 4. Output the derived key.
*
* @author CaesarZou
*
*/
public interface IPBKDF {
/**
* produce a derived key.
* @param P
* @param S
* @param c
* @param dkLen
* @return DK
*/
public byte [] derive(byte [] P, byte [] S, long c, int dkLen) throws PKCS5Exception;
}
1.2密钥派生实现版本1
package com.broadthinking.pkcs.pkcs_5;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class PBKDF1 implements IPBKDF {
public PBKDF1(MessageDigest Hash) {
this.hash = Hash;
}
//default use SHA-1
public PBKDF1() {
try {
this.hash = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
}
}
/**
* PBKDF1 (P, S, c, dkLen)
* Options: Hash underlying hash function
* Input:
* P password, an octet string
* S salt, an eight-octet string
* c iteration count, a positive integer
* dkLen intended length in octets of derived key, a positive integer, at most
* 16 for MD2 or MD5 and 20 for SHA-1
* Output: DK derived key, a dkLen-octet string
* @throws PKCS5Exception
*
*/
@Override
public byte[] derive(byte[] P, byte[] S, long c, int dkLen) throws PKCS5Exception {
int hLen = hash.getDigestLength();
//1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output “derived key
// too long” and stop.
if(dkLen > hLen) {
throw new PKCS5Exception(PKCS5Exception.ERROR_PBKDF_DERIVEDKEY_TOO_LONG);
}
/*
* 2. Apply the underlying hash function Hash for c iterations to the
* concatenation of the password P and the salt S, then extract the
* first dkLen octets to produce a derived key DK: T1 = Hash (P || S) ,
* T2 = Hash (T1) , ... Tc = Hash (Tc-1) , DK = Tc<0..dkLen-1> .
*/
byte [] T = new byte [hLen];
try {
hash.reset();
hash.update(P);
hash.update(S);
for(long i=0;i<c;i++) {
hash.digest(T, 0, hLen);
hash.update(T);
}
} catch (DigestException e) {
//ignore
}
byte [] DK = new byte[(int)dkLen];
System.arraycopy(T, 0, DK, 0, (int)dkLen);
//3. Output the derived key DK.
return DK;
}
MessageDigest hash;
}
1.3密钥派生版本2
package com.broadthinking.pkcs.pkcs_5;
public class PBKDF2 implements IPBKDF {
public PBKDF2() {
prf = new HMAC_SHA_1();
}
/**
* PBKDF2 (P, S, c, dkLen)
* Options: PRF underlying pseudorandom function (hLen denotes the length in
* octets of the pseudorandom function output)
* Input:
* P password, an octet string
* S salt, an octet string
* c iteration count, a positive integer
* dkLen intended length in octets of the derived key, a positive integer, at
* most (232 – 1) × hLen
* Output: DK derived key, a dkLen-octet string
* @throws PKCS5Exception
*
*/
@Override
public byte[] derive(byte[] P, byte[] S, long c, int dkLen) throws PKCS5Exception {
//1. If dkLen > (2^32 – 1) × hLen, output “derived key too long” and stop.
//int value can never big then 2^32-1
byte [] DK = new byte[dkLen];
/*