KDF2算法,找了好久终于被我找到了,另外,需要注意的是,这里使用到了de.flexiprovider.core.CoreRegistry,由于该jar包中的构造方法是私有的,所以我不得已改了它,进而来注册KDF2,所以,各位要是有其他办法,希望能指教一二,如果没有,那就下包含该类的源码,并将CoreRegistry的构造方法改成public的吧.
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package com.zrrt.drm.util;
import de.flexiprovider.api.Instantiation;
import de.flexiprovider.api.KeyDerivation;
import de.flexiprovider.api.MessageDigest;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.common.kdf.interfaces.DHSecretKey;
import de.flexiprovider.common.math.FlexiBigInt;
import de.flexiprovider.core.CoreRegistry;
/**
* <tt>KDF2</tt> is a key derivation function, as descriped in IEEE P1363a.
* KDF2 is based on the construction in ANSI X9.42:2001 and X9.63. Almost
* similar to KeyDerivationX963 <br>
* <br>
* Example: <br>
* <tt>
* <br>
* KeyDerivation kdf = KeyDerivation.getInstance("KDF2");
* <br>
* kdf.init(secret_key.toByteArray());
* <br>
* kdf.setLength(int length);
* <br>
* kdf.setSharedInfo(shared_Info.toByteArray());
* <br>
* byte[] derived_Key = kdf.doFinal();
* <br>
* </tt> <br>
* <br>
* The derived key can be used for further communication between the parties who
* know the <tt>secret_key</tt> and the <tt>shared_Info</tt>.
*
* @author Jochen Hechler
* @author Marcus Stögbauer
* @see de.flexiprovider.api.KeyDerivation
*/
public class KDF2 extends KeyDerivation {
// * A shared info string
public KDF2() {
super();
/**
* TODO:wcf 2008.01.03
* 添加如下两行,用来注册算法,否则后面调用到SHA-1时将找不到算法
*/
CoreRegistry hehe = new CoreRegistry();
hehe.registerAlgorithms();
}
private byte[] sharedInfo = null;
// * The hash function
private MessageDigest md;
// * The length of the keydata which will be generated
private int keydatalen = -1;
// * The shared secret as a byte[]
private byte[] z_byte;
/**
* Initialize this <tt>KDF2</tt> with a secret key. This function will
* also convert the secret key to a byte array.
*
* @param key
* is the secret key, from which the key data will be derived
* @throws NoSuchAlgorithmException
* if the SAH1 hash function cannot be found in the provider
* @deprecated this was used for ECDHKeys, please use the functions with
* byte[] for the key
*/
public final void init(Key key) throws NoSuchAlgorithmException {
// md = Instantiation.getMessageDigest("SHA1");
//TODO: wcf 2008.01.03 修改
md = Instantiation.getMessageDigest("SHA-1");
if (key instanceof DHSecretKey) {
z_byte = ((DHSecretKey) key).getS().toByteArray();
}
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt> and a
* <tt>hash</tt> function name used in the provider. The used hash
* function will set the length for the derived key.
*
* @param key
* is the secret key, from which the key data will be derived
* @param hash
* is the name of a hash function in the standart provider
* @throws NoSuchAlgorithmException
* if the hash function cannot be found in the provider
* @deprecated this was used for ECDHKeys, please use the functions with
* byte[] for the key
*/
public final void init(Key key, String hash)
throws NoSuchAlgorithmException {
md = Instantiation.getMessageDigest(hash);
z_byte = key.getEncoded();
if (key instanceof DHSecretKey) {
z_byte = ((DHSecretKey) key).getS().toByteArray();
}
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt> and a
* <tt>hash</tt> function name used in the provider. The used hash
* function will set the length for the derived key.
*
* @param key
* is the secret key as a byte array, from which the key data
* will be derived
* @param hash
* is the choosen hash function
* @throws NoSuchAlgorithmException
* if the hash function cannot be found in the provider
*/
public final void init(byte[] key, String hash)
throws NoSuchAlgorithmException {
z_byte = key;
md = Instantiation.getMessageDigest(hash);
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt>.
*
* @param key
* is the secret key as a byte array, from which the key data
* will be derived
* @throws NoSuchAlgorithmException
* if the SHA1 hash function cannot be found in the provider
*/
public final void init(byte[] key) throws NoSuchAlgorithmException {
z_byte = key;
// md = Instantiation.getMessageDigest("SHA1");
//TODO: wcf 2008.01.03 修改
// MessageDigest md = MessageDigest.getInstance("SHA-1");
md = Instantiation.getMessageDigest("SHA-1");
}
/**
* This function does the actual key derivation. It uses the shared key
* value <tt>Z</tt> and <tt>keydatalen</tt> from above, with the desired
* hash function <tt>H</tt> and the optional <tt>shared-info</tt> and
* computes <br>
* <br>
* <tt>
* Hash(i) = H(Z + counter + [SharedInfo])
* </tt> <br>
* <br>
* Where + donates to string concat and the counter is a 32 bit string. The
* couner is increased by one, for every round. <br>
* if the keydatalen is not set, it will be set to 1024.
*
* @return the derived key data with length keydatalength as a byte[]
*/
public final byte[] doFinal() {
if (!isValidKeyDataLen(keydatalen)) {
keydatalen = 1024;
}
byte[] nuller = new byte[4];
nuller[0] = (byte) 0;
nuller[1] = (byte) 0;
nuller[2] = (byte) 0;
nuller[3] = (byte) 0;
FlexiBigInt counter = FlexiBigInt.valueOf(0);
int mdLength = md.getDigestLength();
final int d = (keydatalen + mdLength - 1) / mdLength;
byte[][] b = new byte[d][];
byte[] hash_tmp;
int sI = 0;
if (this.sharedInfo != null) {
sI = sharedInfo.length;
}
int i;
for (i = 0; i < d; i++) {
counter = counter.add(FlexiBigInt.valueOf(1));
System.arraycopy(counter.toByteArray(), 0, nuller, 4 - (counter
.toByteArray().length), counter.toByteArray().length);
hash_tmp = new byte[z_byte.length + nuller.length + sI];
System.arraycopy(z_byte, 0, hash_tmp, 0, z_byte.length);
System.arraycopy(nuller, 0, hash_tmp, z_byte.length, nuller.length);
if (this.sharedInfo != null) {
System.arraycopy(sharedInfo, 0, hash_tmp, z_byte.length
+ nuller.length, sharedInfo.length);
}
b[i] = md.digest(hash_tmp);
md.reset();
}
// index adjustment
int t = keydatalen / mdLength;
if (d != t) {
t = keydatalen - (t * md.getDigestLength());
b[d - 1] = getLeftMostBytes(b[d - 1], t);
}
byte[] ret = new byte[this.keydatalen];
for (i = 0; i < (d - 1); i++) {
System.arraycopy(b[i], 0, ret, md.getDigestLength() * i,
b[i].length);
}
System.arraycopy(b[d - 1], 0, ret, md.getDigestLength() * i,
b[d - 1].length);
// return KeyData as a byte array
return ret;
}
/**
* The keydatalength has to be set here.
*
* @param keydatalen
* is the length of the derived key data
* @return true, the derivation function length may be set
*/
public final boolean setLength(int keydatalen)
throws InvalidAlgorithmParameterException {
if (!isValidKeyDataLen(keydatalen)) {
throw new InvalidAlgorithmParameterException("" + keydatalen
+ " is not an valid integer.");
}
this.keydatalen = keydatalen;
return true;
}
/**
* This function can be used to update the sharedInfo NOTE: This derivation
* function needs a sharedinfo
*
* @param sharedInfo
* is a byte array with the sharedInfo
* @return true, the derivation function may use a shared info
*/
public final boolean setSharedInfo(byte[] sharedInfo) {
this.sharedInfo = sharedInfo;
return true;
}
/**
* Checks if the keydatalen is valid (you wouldn't have guessed it :)
*
* @params the keydatalength (in bytes)
* @return true, if the keydatalength is in the secure range
*/
private boolean isValidKeyDataLen(int len) {
if (len < 0) {
return false;
}
int h_len = md.getDigestLength();
long maxLen = ((long) h_len << 29) - h_len;
return len < maxLen;
}
/**
* Returns the len leftmost bytes from the byte[] byt.
*
* @params byt is the byte[]
* @params len is the number of bytes to return from <tt>byt</tt>
* @return byte[] with the leftmost bytes
*/
private byte[] getLeftMostBytes(byte[] byt, int len) {
byte[] ret = new byte[len];
System.arraycopy(byt, 0, ret, 0, len);
return ret;
}
}
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package com.zrrt.drm.util;
import de.flexiprovider.api.Instantiation;
import de.flexiprovider.api.KeyDerivation;
import de.flexiprovider.api.MessageDigest;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.common.kdf.interfaces.DHSecretKey;
import de.flexiprovider.common.math.FlexiBigInt;
import de.flexiprovider.core.CoreRegistry;
/**
* <tt>KDF2</tt> is a key derivation function, as descriped in IEEE P1363a.
* KDF2 is based on the construction in ANSI X9.42:2001 and X9.63. Almost
* similar to KeyDerivationX963 <br>
* <br>
* Example: <br>
* <tt>
* <br>
* KeyDerivation kdf = KeyDerivation.getInstance("KDF2");
* <br>
* kdf.init(secret_key.toByteArray());
* <br>
* kdf.setLength(int length);
* <br>
* kdf.setSharedInfo(shared_Info.toByteArray());
* <br>
* byte[] derived_Key = kdf.doFinal();
* <br>
* </tt> <br>
* <br>
* The derived key can be used for further communication between the parties who
* know the <tt>secret_key</tt> and the <tt>shared_Info</tt>.
*
* @author Jochen Hechler
* @author Marcus Stögbauer
* @see de.flexiprovider.api.KeyDerivation
*/
public class KDF2 extends KeyDerivation {
// * A shared info string
public KDF2() {
super();
/**
* TODO:wcf 2008.01.03
* 添加如下两行,用来注册算法,否则后面调用到SHA-1时将找不到算法
*/
CoreRegistry hehe = new CoreRegistry();
hehe.registerAlgorithms();
}
private byte[] sharedInfo = null;
// * The hash function
private MessageDigest md;
// * The length of the keydata which will be generated
private int keydatalen = -1;
// * The shared secret as a byte[]
private byte[] z_byte;
/**
* Initialize this <tt>KDF2</tt> with a secret key. This function will
* also convert the secret key to a byte array.
*
* @param key
* is the secret key, from which the key data will be derived
* @throws NoSuchAlgorithmException
* if the SAH1 hash function cannot be found in the provider
* @deprecated this was used for ECDHKeys, please use the functions with
* byte[] for the key
*/
public final void init(Key key) throws NoSuchAlgorithmException {
// md = Instantiation.getMessageDigest("SHA1");
//TODO: wcf 2008.01.03 修改
md = Instantiation.getMessageDigest("SHA-1");
if (key instanceof DHSecretKey) {
z_byte = ((DHSecretKey) key).getS().toByteArray();
}
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt> and a
* <tt>hash</tt> function name used in the provider. The used hash
* function will set the length for the derived key.
*
* @param key
* is the secret key, from which the key data will be derived
* @param hash
* is the name of a hash function in the standart provider
* @throws NoSuchAlgorithmException
* if the hash function cannot be found in the provider
* @deprecated this was used for ECDHKeys, please use the functions with
* byte[] for the key
*/
public final void init(Key key, String hash)
throws NoSuchAlgorithmException {
md = Instantiation.getMessageDigest(hash);
z_byte = key.getEncoded();
if (key instanceof DHSecretKey) {
z_byte = ((DHSecretKey) key).getS().toByteArray();
}
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt> and a
* <tt>hash</tt> function name used in the provider. The used hash
* function will set the length for the derived key.
*
* @param key
* is the secret key as a byte array, from which the key data
* will be derived
* @param hash
* is the choosen hash function
* @throws NoSuchAlgorithmException
* if the hash function cannot be found in the provider
*/
public final void init(byte[] key, String hash)
throws NoSuchAlgorithmException {
z_byte = key;
md = Instantiation.getMessageDigest(hash);
}
/**
* Initialize this <tt>KDF2</tt> with a <tt>secret key</tt>.
*
* @param key
* is the secret key as a byte array, from which the key data
* will be derived
* @throws NoSuchAlgorithmException
* if the SHA1 hash function cannot be found in the provider
*/
public final void init(byte[] key) throws NoSuchAlgorithmException {
z_byte = key;
// md = Instantiation.getMessageDigest("SHA1");
//TODO: wcf 2008.01.03 修改
// MessageDigest md = MessageDigest.getInstance("SHA-1");
md = Instantiation.getMessageDigest("SHA-1");
}
/**
* This function does the actual key derivation. It uses the shared key
* value <tt>Z</tt> and <tt>keydatalen</tt> from above, with the desired
* hash function <tt>H</tt> and the optional <tt>shared-info</tt> and
* computes <br>
* <br>
* <tt>
* Hash(i) = H(Z + counter + [SharedInfo])
* </tt> <br>
* <br>
* Where + donates to string concat and the counter is a 32 bit string. The
* couner is increased by one, for every round. <br>
* if the keydatalen is not set, it will be set to 1024.
*
* @return the derived key data with length keydatalength as a byte[]
*/
public final byte[] doFinal() {
if (!isValidKeyDataLen(keydatalen)) {
keydatalen = 1024;
}
byte[] nuller = new byte[4];
nuller[0] = (byte) 0;
nuller[1] = (byte) 0;
nuller[2] = (byte) 0;
nuller[3] = (byte) 0;
FlexiBigInt counter = FlexiBigInt.valueOf(0);
int mdLength = md.getDigestLength();
final int d = (keydatalen + mdLength - 1) / mdLength;
byte[][] b = new byte[d][];
byte[] hash_tmp;
int sI = 0;
if (this.sharedInfo != null) {
sI = sharedInfo.length;
}
int i;
for (i = 0; i < d; i++) {
counter = counter.add(FlexiBigInt.valueOf(1));
System.arraycopy(counter.toByteArray(), 0, nuller, 4 - (counter
.toByteArray().length), counter.toByteArray().length);
hash_tmp = new byte[z_byte.length + nuller.length + sI];
System.arraycopy(z_byte, 0, hash_tmp, 0, z_byte.length);
System.arraycopy(nuller, 0, hash_tmp, z_byte.length, nuller.length);
if (this.sharedInfo != null) {
System.arraycopy(sharedInfo, 0, hash_tmp, z_byte.length
+ nuller.length, sharedInfo.length);
}
b[i] = md.digest(hash_tmp);
md.reset();
}
// index adjustment
int t = keydatalen / mdLength;
if (d != t) {
t = keydatalen - (t * md.getDigestLength());
b[d - 1] = getLeftMostBytes(b[d - 1], t);
}
byte[] ret = new byte[this.keydatalen];
for (i = 0; i < (d - 1); i++) {
System.arraycopy(b[i], 0, ret, md.getDigestLength() * i,
b[i].length);
}
System.arraycopy(b[d - 1], 0, ret, md.getDigestLength() * i,
b[d - 1].length);
// return KeyData as a byte array
return ret;
}
/**
* The keydatalength has to be set here.
*
* @param keydatalen
* is the length of the derived key data
* @return true, the derivation function length may be set
*/
public final boolean setLength(int keydatalen)
throws InvalidAlgorithmParameterException {
if (!isValidKeyDataLen(keydatalen)) {
throw new InvalidAlgorithmParameterException("" + keydatalen
+ " is not an valid integer.");
}
this.keydatalen = keydatalen;
return true;
}
/**
* This function can be used to update the sharedInfo NOTE: This derivation
* function needs a sharedinfo
*
* @param sharedInfo
* is a byte array with the sharedInfo
* @return true, the derivation function may use a shared info
*/
public final boolean setSharedInfo(byte[] sharedInfo) {
this.sharedInfo = sharedInfo;
return true;
}
/**
* Checks if the keydatalen is valid (you wouldn't have guessed it :)
*
* @params the keydatalength (in bytes)
* @return true, if the keydatalength is in the secure range
*/
private boolean isValidKeyDataLen(int len) {
if (len < 0) {
return false;
}
int h_len = md.getDigestLength();
long maxLen = ((long) h_len << 29) - h_len;
return len < maxLen;
}
/**
* Returns the len leftmost bytes from the byte[] byt.
*
* @params byt is the byte[]
* @params len is the number of bytes to return from <tt>byt</tt>
* @return byte[] with the leftmost bytes
*/
private byte[] getLeftMostBytes(byte[] byt, int len) {
byte[] ret = new byte[len];
System.arraycopy(byt, 0, ret, 0, len);
return ret;
}
}