Changeset 761ad38b


Ignore:
Timestamp:
Jun 2, 2011 1:37:35 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
fe15db5
Parents:
2a5ed93
Message:
Location:
core/java/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/crypto/HMACGenerator.java

    r2a5ed93 r761ad38b  
    44import java.util.concurrent.LinkedBlockingQueue;
    55
     6// following are for main() tests
     7//import java.security.InvalidKeyException;
     8//import java.security.Key;
     9//import java.security.NoSuchAlgorithmException;
     10//import javax.crypto.spec.SecretKeySpec;
     11//import net.i2p.data.Base64;
     12
    613import net.i2p.I2PAppContext;
    714import net.i2p.data.DataHelper;
    815import net.i2p.data.Hash;
    916import net.i2p.data.SessionKey;
     17import net.i2p.util.SimpleByteCache;
    1018
    1119import org.bouncycastle.crypto.digests.MD5Digest;
     
    1422
    1523/**
    16  * Calculate the HMAC-MD5 of a key+message.  All the good stuff occurs
     24 * Calculate the HMAC-MD5-128 of a key+message.  All the good stuff occurs
    1725 * in {@link org.bouncycastle.crypto.macs.I2PHMac} and
    1826 * {@link org.bouncycastle.crypto.digests.MD5Digest}.
    1927 *
     28 * Keys are always 32 bytes.
     29 * This is used only by UDP.
     30 * Use deprecated outside the router, this may move to router.jar.
     31 *
     32 * NOTE THIS IS NOT COMPATIBLE with javax.crypto.Mac.getInstance("HmacMD5")
     33 * as we tell I2PHMac that the digest length is 32 bytes, so it generates
     34 * a different result.
     35 *
     36 * Quote jrandom:
     37 * "The HMAC is hardcoded to use SHA256 digest size
     38 * for backwards compatability.  next time we have a backwards
     39 * incompatible change, we should update this."
     40 *
     41 * Does this mean he intended it to be compatible with MD5?
     42 * See also 2005-07-05 status notes.
     43 *
    2044 */
    2145public class HMACGenerator {
    22     private I2PAppContext _context;
    2346    /** set of available HMAC instances for calculate */
    2447    protected final LinkedBlockingQueue<I2PHMac> _available;
    25     /** set of available byte[] buffers for verify */
    26     private final LinkedBlockingQueue<byte[]> _availableTmp;
    2748   
     49    /**
     50     *  @param context unused
     51     */
    2852    public HMACGenerator(I2PAppContext context) {
    29         _context = context;
    3053        _available = new LinkedBlockingQueue(32);
    31         _availableTmp = new LinkedBlockingQueue(32);
    3254    }
    3355   
    3456    /**
    3557     * Calculate the HMAC of the data with the given key
     58     *
     59     * @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
     60     * @deprecated unused
    3661     */
    3762    public Hash calculate(SessionKey key, byte data[]) {
    3863        if ((key == null) || (key.getData() == null) || (data == null))
    3964            throw new NullPointerException("Null arguments for HMAC");
    40         byte rv[] = new byte[Hash.HASH_LENGTH];
     65        byte rv[] = acquireTmp();
     66        Arrays.fill(rv, (byte)0x0);
    4167        calculate(key, data, 0, data.length, rv, 0);
    4268        return new Hash(rv);
     
    5379        mac.init(key.getData());
    5480        mac.update(data, offset, length);
    55         //byte rv[] = new byte[Hash.HASH_LENGTH];
    5681        mac.doFinal(target, targetOffset);
    5782        release(mac);
    58         //return new Hash(rv);
    5983    }
    6084   
     
    78102        mac.update(curData, curOffset, curLength);
    79103        byte rv[] = acquireTmp();
    80         //byte rv[] = new byte[Hash.HASH_LENGTH];
    81104        mac.doFinal(rv, 0);
    82105        release(mac);
     
    94117        // for backwards compatability.  next time we have a backwards
    95118        // incompatible change, we should update this by removing ", 32"
     119        // SEE NOTES ABOVE
    96120        return new I2PHMac(new MD5Digest(), 32);
    97121    }
     
    101125    }
    102126
    103     // temp buffers for verify(..)
     127    /**
     128     * Not really tmp, just from the byte array cache.
     129     * Does NOT zero.
     130     */
    104131    private byte[] acquireTmp() {
    105         byte rv[] = _availableTmp.poll();
    106         if (rv != null)
    107             Arrays.fill(rv, (byte)0x0);
    108         else
    109             rv = new byte[Hash.HASH_LENGTH];
     132        byte rv[] = SimpleByteCache.acquire(Hash.HASH_LENGTH);
    110133        return rv;
    111134    }
    112135
    113136    private void releaseTmp(byte tmp[]) {
    114         _availableTmp.offer(tmp);
     137        SimpleByteCache.release(tmp);
    115138    }
     139
     140    //private static final int RUNS = 100000;
     141
     142    /**
     143     *  Test the BC and the JVM's implementations for speed
     144     */
     145/****  All this did was prove that we aren't compatible with standard HmacMD5
     146    public static void main(String args[]) {
     147        if (args.length != 2) {
     148            System.err.println("Usage: HMACGenerator keySeedString dataString");
     149            return;
     150        }
     151
     152        byte[] rand = SHA256Generator.getInstance().calculateHash(args[0].getBytes()).getData();
     153        byte[] data = args[1].getBytes();
     154        Key keyObj = new SecretKeySpec(rand, "HmacMD5");
     155
     156        byte[] keyBytes = keyObj.getEncoded();
     157        System.out.println("key bytes (" + keyBytes.length + ") is [" + Base64.encode(keyBytes) + "]");
     158        SessionKey key = new SessionKey(keyBytes);
     159        System.out.println("session key is [" + key);
     160        System.out.println("key object is [" + keyObj);
     161
     162        HMACGenerator gen = new HMACGenerator(I2PAppContext.getGlobalContext());
     163        byte[] result = new byte[16];
     164        long start = System.currentTimeMillis();
     165        for (int i = 0; i < RUNS; i++) {
     166            gen.calculate(key, data, 0, data.length, result, 0);
     167            if (i == 0)
     168                System.out.println("MAC [" + Base64.encode(result) + "]");
     169        }
     170        long time = System.currentTimeMillis() - start;
     171        System.out.println("Time for " + RUNS + " HMAC-MD5 computations:");
     172        System.out.println("BC time (ms): " + time);
     173
     174        start = System.currentTimeMillis();
     175        javax.crypto.Mac mac;
     176        try {
     177            mac = javax.crypto.Mac.getInstance("HmacMD5");
     178        } catch (NoSuchAlgorithmException e) {
     179            System.err.println("Fatal: " + e);
     180            return;
     181        }
     182        for (int i = 0; i < RUNS; i++) {
     183            try {
     184                mac.init(keyObj);
     185            } catch (InvalidKeyException e) {
     186                System.err.println("Fatal: " + e);
     187            }
     188            byte[] sha = mac.doFinal(data);
     189            if (i == 0)
     190                System.out.println("MAC [" + Base64.encode(sha) + "]");
     191        }
     192        time = System.currentTimeMillis() - start;
     193
     194        System.out.println("JVM time (ms): " + time);
     195    }
     196****/
    116197}
  • core/java/src/org/bouncycastle/crypto/macs/I2PHMac.java

    r2a5ed93 r761ad38b  
    2828
    2929//import org.bouncycastle.crypto.CipherParameters;
    30 import java.util.ArrayList;
    3130import java.util.Arrays;
     31
     32import net.i2p.util.SimpleByteCache;
    3233
    3334import org.bouncycastle.crypto.Digest;
     
    6667        this(digest, digest.getDigestSize());
    6768    }
     69
     70    /**
     71     *  @param sz override the digest's size
     72     *  SEE NOTES in HMACGenerator about why this isn't compatible with standard HmacMD5
     73     */
    6874    public I2PHMac(
    6975        Digest digest, int sz)
     
    166172    }
    167173   
    168     /**
    169      * list of buffers - index 0 is the cache for 32 byte arrays, while index 1 is the cache for 16 byte arrays
    170      */
    171     private static ArrayList _tmpBuf[] = new ArrayList[] { new ArrayList(), new ArrayList() };
    172174    private static byte[] acquireTmp(int sz) {
    173         byte rv[] = null;
    174         synchronized (_tmpBuf[sz == 32 ? 0 : 1]) {
    175             if (!_tmpBuf[sz == 32 ? 0 : 1].isEmpty())
    176                 rv = (byte[])_tmpBuf[sz == 32 ? 0 : 1].remove(0);
    177         }
    178         if (rv != null)
    179             Arrays.fill(rv, (byte)0x0);
    180         else
    181             rv = new byte[sz];
     175        byte[] rv = SimpleByteCache.acquire(sz);
     176        Arrays.fill(rv, (byte)0x0);
    182177        return rv;
    183178    }
     179
    184180    private static void releaseTmp(byte buf[]) {
    185         if (buf == null) return;
    186         synchronized (_tmpBuf[buf.length == 32 ? 0 : 1]) {
    187             if (_tmpBuf[buf.length == 32 ? 0 : 1].size() < 100)
    188                 _tmpBuf[buf.length == 32 ? 0 : 1].add((Object)buf);
    189         }
     181        SimpleByteCache.release(buf);
    190182    }
    191183
Note: See TracChangeset for help on using the changeset viewer.