KDF2 算法

 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&ouml;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;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值