FileDocCategorySizeDatePackage
PRF.javaAPI DocAndroid 1.5 API7719Wed May 06 22:41:06 BST 2009org.apache.harmony.xnet.provider.jsse

PRF

public class PRF extends Object
This class provides functionality for computation of PRF values for TLS (http://www.ietf.org/rfc/rfc2246.txt) and SSL v3 (http://wp.netscape.com/eng/ssl3) protocols.

Fields Summary
private static Logger.Stream
logger
private static Mac
md5_mac
private static Mac
sha_mac
protected static MessageDigest
md5
protected static MessageDigest
sha
private static int
md5_mac_length
private static int
sha_mac_length
Constructors Summary
Methods Summary
static synchronized voidcomputePRF(byte[] out, byte[] secret, byte[] str_byts, byte[] seed)
Computes the value of TLS pseudo random function.

param
out: the buffer to fill up with the value of the function.
param
secret: the buffer containing the secret value to generate prf.
param
str_bytes: the label bytes to be used.
param
seed: the seed to be used.

        if (sha_mac == null) {
            init();
        }
        // Do concatenation of the label with the seed:
        // (metterings show that is is faster to concatenate the arrays
        // and to call HMAC.update on cancatenation, than twice call for
        // each of the part, i.e.:
        // time(HMAC.update(label+seed))
        //          < time(HMAC.update(label)) + time(HMAC.update(seed))
        // but it takes more memmory (approximaty on 4%)
        /*
        byte[] tmp_seed = new byte[seed.length + str_byts.length];
        System.arraycopy(str_byts, 0, tmp_seed, 0, str_byts.length);
        System.arraycopy(seed, 0, tmp_seed, str_byts.length, seed.length);
        seed = tmp_seed;
        */
        SecretKeySpec keyMd5;
        SecretKeySpec keySha1;
        if ((secret == null) || (secret.length == 0)) {
            secret = new byte[8];
            keyMd5 = new SecretKeySpec(secret, "HmacMD5");
            keySha1 = new SecretKeySpec(secret, "HmacSHA1");
        } else {
            int length = secret.length >> 1; // division by 2
            int offset = secret.length & 1;  // remainder
            keyMd5 = new SecretKeySpec(secret, 0, length + offset,
                    "HmacMD5");
            keySha1 = new SecretKeySpec(secret, length, length
                    + offset, "HmacSHA1");
        }

        //byte[] str_byts = label.getBytes();

        if (logger != null) {
            logger.println("secret["+secret.length+"]: ");
            logger.printAsHex(16, "", " ", secret);
            logger.println("label["+str_byts.length+"]: ");
            logger.printAsHex(16, "", " ", str_byts);
            logger.println("seed["+seed.length+"]: ");
            logger.printAsHex(16, "", " ", seed);
            logger.println("MD5 key:");
            logger.printAsHex(16, "", " ", keyMd5.getEncoded());
            logger.println("SHA1 key:");
            logger.printAsHex(16, "", " ", keySha1.getEncoded());
        }

        md5_mac.init(keyMd5);
        sha_mac.init(keySha1);

        int pos = 0;
        md5_mac.update(str_byts);
        byte[] hash = md5_mac.doFinal(seed); // A(1)
        while (pos < out.length) {
            md5_mac.update(hash);
            md5_mac.update(str_byts);
            md5_mac.update(seed);
            if (pos + md5_mac_length < out.length) {
                md5_mac.doFinal(out, pos);
                pos += md5_mac_length;
            } else {
                System.arraycopy(md5_mac.doFinal(), 0, out,
                        pos, out.length - pos);
                break;
            }
            // make A(i)
            hash = md5_mac.doFinal(hash);
        }
        if (logger != null) {
            logger.println("P_MD5:");
            logger.printAsHex(md5_mac_length, "", " ", out);
        }

        pos = 0;
        sha_mac.update(str_byts);
        hash = sha_mac.doFinal(seed); // A(1)
        byte[] sha1hash;
        while (pos < out.length) {
            sha_mac.update(hash);
            sha_mac.update(str_byts);
            sha1hash = sha_mac.doFinal(seed);
            for (int i = 0; (i < sha_mac_length) & (pos < out.length); i++) {
                out[pos++] ^= sha1hash[i];
            }
            // make A(i)
            hash = sha_mac.doFinal(hash);
        }

        if (logger != null) {
            logger.println("PRF:");
            logger.printAsHex(sha_mac_length, "", " ", out);
        }
    
static synchronized voidcomputePRF_SSLv3(byte[] out, byte[] secret, byte[] seed)
Computes the value of SSLv3 pseudo random function.

param
out: the buffer to fill up with the value of the function.
param
secret: the buffer containing the secret value to generate prf.
param
seed: the seed to be used.

        if (sha == null) {
            init();
        }
        int pos = 0;
        int iteration = 1;
        byte[] digest;
        while (pos < out.length) {
            byte[] pref = new byte[iteration];
            Arrays.fill(pref, (byte) (64 + iteration++));
            sha.update(pref);
            sha.update(secret);
            sha.update(seed);
            md5.update(secret);
            md5.update(sha.digest());
            digest = md5.digest(); // length == 16
            if (pos + 16 > out.length) {
                System.arraycopy(digest, 0, out, pos, out.length - pos);
                pos = out.length;
            } else {
                System.arraycopy(digest, 0, out, pos, 16);
                pos += 16;
            }
        }
    
private static voidinit()

    
        
        try {
            md5_mac = Mac.getInstance("HmacMD5");
            sha_mac = Mac.getInstance("HmacSHA1");
        } catch (NoSuchAlgorithmException e) {
            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
                    new SSLException(
                "There is no provider of HmacSHA1 or HmacMD5 "
                + "algorithms installed in the system"));
        }
        md5_mac_length = md5_mac.getMacLength();
        sha_mac_length = sha_mac.getMacLength();
        try {
            md5 = MessageDigest.getInstance("MD5");
            sha = MessageDigest.getInstance("SHA-1");
        } catch (Exception e) {
            throw new AlertException(AlertProtocol.INTERNAL_ERROR,
                    new SSLException(
                    "Could not initialize the Digest Algorithms."));
        }