Changeset 3d5beec


Ignore:
Timestamp:
Sep 6, 2011 12:11:55 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
5030a86
Parents:
19905e9
Message:
  • Crypto: Rework use of SHA256 for efficiency and to avoid clogging the Hash cache with one-time hashes, and avoiding the global cache lock. This also greatly increases Hash cache hit rates. Also use SimpleByteCache? for temporary byte buffers.
Location:
core/java/src/net/i2p/crypto
Files:
3 edited

Legend:

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

    r19905e9 r3d5beec  
    1616import net.i2p.util.Log;
    1717import net.i2p.util.RandomSource;
     18import net.i2p.util.SimpleByteCache;
    1819
    1920/**
     
    6566
    6667    /**
    67      * Encrypt the SHA-256 Hash of the payload, the 4 byte length, and the payload,
     68     * Encrypt the SHA-256 Hash of the IV, the 4 byte length, and the payload,
    6869     * with random padding up to the paddedSize, rounded up to the next multiple of 16.
    6970     *
     
    8283       
    8384        byte data[] = new byte[size + padding];
    84         Hash h = _context.sha().calculateHash(iv);
    85        
    86         int cur = 0;
    87         System.arraycopy(h.getData(), 0, data, cur, Hash.HASH_LENGTH);
    88         cur += Hash.HASH_LENGTH;
     85        _context.sha().calculateHash(iv, 0, 16, data, 0);
     86        int cur = Hash.HASH_LENGTH;
    8987       
    9088        DataHelper.toLong(data, cur, 4, payload.length);
     
    117115        }
    118116
    119         int cur = 0;
    120         byte h[] = _context.sha().calculateHash(iv).getData();
    121         for (int i = 0; i < Hash.HASH_LENGTH; i++) {
    122             if (decr[i] != h[i]) {
     117        byte h[] = SimpleByteCache.acquire(Hash.HASH_LENGTH);
     118        _context.sha().calculateHash(iv, 0, 16, h, 0);
     119        boolean eq = DataHelper.eq(decr, 0, h, 0, Hash.HASH_LENGTH);
     120        SimpleByteCache.release(h);
     121        if (!eq) {
    123122                _log.error("Hash does not match [key=" + sessionKey + " / iv =" + DataHelper.toString(iv, iv.length)
    124123                           + "]", new Exception("Hash error"));
    125124                return null;
    126             }
    127125        }
    128         cur += Hash.HASH_LENGTH;
     126        int cur = Hash.HASH_LENGTH;
    129127       
    130128        long len = DataHelper.fromLong(decr, cur, 4);
  • core/java/src/net/i2p/crypto/ElGamalAESEngine.java

    r19905e9 r3d5beec  
    2727import net.i2p.data.SessionTag;
    2828import net.i2p.util.Log;
     29import net.i2p.util.SimpleByteCache;
    2930
    3031/**
     
    8889
    8990        byte tag[] = new byte[32];
    90         System.arraycopy(data, 0, tag, 0, tag.length);
     91        System.arraycopy(data, 0, tag, 0, 32);
    9192        SessionTag st = new SessionTag(tag);
    9293        SessionKey key = keyManager.consumeTag(st);
     
    186187        }
    187188
    188         byte preIV[] = null;
    189        
    190189        int offset = 0;
    191190        byte key[] = new byte[SessionKey.KEYSIZE_BYTES];
     
    193192        offset += SessionKey.KEYSIZE_BYTES;
    194193        usedKey.setData(key);
    195         preIV = new byte[32];
     194        byte[] preIV = SimpleByteCache.acquire(32);
    196195        System.arraycopy(elgDecr, offset, preIV, 0, 32);
    197196        offset += 32;
     
    199198        //_log.debug("Pre IV for decryptNewSession: " + DataHelper.toString(preIV, 32));
    200199        //_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32));
    201         Hash ivHash = _context.sha().calculateHash(preIV);
    202         byte iv[] = new byte[16];
    203         System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     200
     201        // use alternate calculateHash() method to avoid object churn and caching
     202        //Hash ivHash = _context.sha().calculateHash(preIV);
     203        //byte iv[] = new byte[16];
     204        //System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     205        byte[] iv = halfHash(preIV);
     206        SimpleByteCache.release(preIV);
    204207
    205208        // feed the extra bytes into the PRNG
     
    207210
    208211        byte aesDecr[] = decryptAESBlock(data, 514, data.length-514, usedKey, iv, null, foundTags, foundKey);
     212        SimpleByteCache.release(iv);
    209213
    210214        //if (_log.shouldLog(Log.DEBUG))
     
    239243    private byte[] decryptExistingSession(byte data[], SessionKey key, PrivateKey targetPrivateKey, Set foundTags,
    240244                                         SessionKey usedKey, SessionKey foundKey) throws DataFormatException {
    241         byte preIV[] = new byte[32];
    242         System.arraycopy(data, 0, preIV, 0, preIV.length);
    243         Hash ivHash = _context.sha().calculateHash(preIV);
    244         byte iv[] = new byte[16];
    245         System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     245        byte preIV[] = SimpleByteCache.acquire(32);
     246        System.arraycopy(data, 0, preIV, 0, 32);
     247        // use alternate calculateHash() method to avoid object churn and caching
     248        //Hash ivHash = _context.sha().calculateHash(preIV);
     249        //byte iv[] = new byte[16];
     250        //System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     251        byte[] iv = halfHash(preIV);
     252        SimpleByteCache.release(preIV);
    246253
    247254        //_log.debug("Pre IV for decryptExistingSession: " + DataHelper.toString(preIV, 32));
    248255        //_log.debug("SessionKey for decryptNewSession: " + DataHelper.toString(key.getData(), 32));
    249256        byte decrypted[] = decryptAESBlock(data, 32, data.length-32, key, iv, preIV, foundTags, foundKey);
     257        SimpleByteCache.release(iv);
    250258        if (decrypted == null) {
    251259            // it begins with a valid session tag, but thats just a coincidence.
     
    337345            //readHash = new Hash();
    338346            //readHash.setData(hashval);
    339             readHash = Hash.create(decrypted, cur);
     347            //readHash = Hash.create(decrypted, cur);
     348            int hashIndex = cur;
    340349            cur += Hash.HASH_LENGTH;
    341350            byte flag = decrypted[cur++];
     
    349358            byte unencrData[] = new byte[(int) len];
    350359            System.arraycopy(decrypted, cur, unencrData, 0, (int)len);
    351             cur += len;
    352             Hash calcHash = _context.sha().calculateHash(unencrData);
    353             boolean eq = calcHash.equals(readHash);
     360            cur += (int) len;
     361            // use alternate calculateHash() method to avoid object churn and caching
     362            //Hash calcHash = _context.sha().calculateHash(unencrData);
     363            //boolean eq = calcHash.equals(readHash);
     364            byte[] calcHash = SimpleByteCache.acquire(32);
     365            _context.sha().calculateHash(unencrData, 0, (int) len, calcHash, 0);
     366            boolean eq = DataHelper.eq(decrypted, hashIndex, calcHash, 0, 32);
     367            SimpleByteCache.release(calcHash);
    354368           
    355369            if (eq) {
     
    458472        byte elgSrcData[] = new byte[SessionKey.KEYSIZE_BYTES+32+158];
    459473        System.arraycopy(key.getData(), 0, elgSrcData, 0, SessionKey.KEYSIZE_BYTES);
    460         byte preIV[] = new byte[32];
     474        byte preIV[] = SimpleByteCache.acquire(32);
    461475        _context.random().nextBytes(preIV);
    462476        System.arraycopy(preIV, 0, elgSrcData, SessionKey.KEYSIZE_BYTES, 32);
     
    485499        // should we also feed the encrypted elG block into the harvester?
    486500
    487         Hash ivHash = _context.sha().calculateHash(preIV);
    488         byte iv[] = new byte[16];
    489         System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     501        // use alternate calculateHash() method to avoid object churn and caching
     502        //Hash ivHash = _context.sha().calculateHash(preIV);
     503        //byte iv[] = new byte[16];
     504        //System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     505        byte[] iv = halfHash(preIV);
     506        SimpleByteCache.release(preIV);
     507
    490508        byte aesEncr[] = encryptAESBlock(data, key, iv, tagsForDelivery, newKey, paddedSize);
     509        SimpleByteCache.release(iv);
    491510        //_log.debug("AES encrypted length: " + aesEncr.length);
    492511
     
    523542        //_log.debug("Pre IV for encryptExistingSession (aka tag): " + currentTag.toString());
    524543        //_log.debug("SessionKey for encryptNewSession: " + DataHelper.toString(key.getData(), 32));
    525         Hash ivHash = _context.sha().calculateHash(rawTag);
    526         byte iv[] = new byte[16];
    527         System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     544        // use alternate calculateHash() method to avoid object churn and caching
     545        //Hash ivHash = _context.sha().calculateHash(rawTag);
     546        //byte iv[] = new byte[16];
     547        //System.arraycopy(ivHash.getData(), 0, iv, 0, 16);
     548        byte[] iv = halfHash(rawTag);
    528549       
    529550        byte aesEncr[] = encryptAESBlock(data, key, iv, tagsForDelivery, newKey, paddedSize, SessionTag.BYTE_LENGTH);
     551        SimpleByteCache.release(iv);
    530552        // that prepended SessionTag.BYTE_LENGTH bytes at the beginning of the buffer
    531553        System.arraycopy(rawTag, 0, aesEncr, 0, rawTag.length);
    532554        return aesEncr;
     555    }
     556
     557    /**
     558     *  Generate the first 16 bytes of the SHA-256 hash of the data.
     559     *
     560     *  Here we are careful to use the SHA256Generator method that does not
     561     *  generate a Hash object or cache the result.
     562     *
     563     *  @param preIV the 32 byte pre-IV. Caller should call SimpleByteCache.release(data) after use.
     564     *  @return a 16 byte array. Caller should call SimpleByteCache.release(rv) after use.
     565     *  @since 0.8.9
     566     */
     567    private byte[] halfHash(byte[] preIV) {
     568        byte[] ivHash = SimpleByteCache.acquire(32);
     569        _context.sha().calculateHash(preIV, 0, 32, ivHash, 0);
     570        byte iv[] = SimpleByteCache.acquire(16);
     571        System.arraycopy(ivHash, 0, iv, 0, 16);
     572        SimpleByteCache.release(ivHash);
     573        return iv;
    533574    }
    534575
     
    582623        cur += 4;
    583624        //_log.debug("data length: " + data.length);
    584         Hash hash = _context.sha().calculateHash(data);
    585         System.arraycopy(hash.getData(), 0, aesData, cur, Hash.HASH_LENGTH);
     625        // use alternate calculateHash() method to avoid object churn and caching
     626        //Hash hash = _context.sha().calculateHash(data);
     627        //System.arraycopy(hash.getData(), 0, aesData, cur, Hash.HASH_LENGTH);
     628        _context.sha().calculateHash(data, 0, data.length, aesData, cur);
    586629        cur += Hash.HASH_LENGTH;
    587630       
  • core/java/src/net/i2p/crypto/ElGamalEngine.java

    r19905e9 r3d5beec  
    4242import net.i2p.util.NativeBigInteger;
    4343import net.i2p.util.RandomSource;
     44import net.i2p.util.SimpleByteCache;
    4445
    4546/**
     
    124125        // FIXME this isn't a random nonzero byte!
    125126        d2[0] = (byte)0xFF;
    126         Hash hash = _context.sha().calculateHash(data);
    127         System.arraycopy(hash.getData(), 0, d2, 1, Hash.HASH_LENGTH);
     127        _context.sha().calculateHash(data, 0, data.length, d2, 1);
    128128        System.arraycopy(data, 0, d2, 1+Hash.HASH_LENGTH, data.length);
    129129       
     
    222222        //System.arraycopy(val, i + 1, hashData, 0, Hash.HASH_LENGTH);
    223223        //Hash hash = new Hash(hashData);
    224         Hash hash = Hash.create(val, i + 1);
     224        //Hash hash = Hash.create(val, i + 1);
    225225        byte rv[] = new byte[payloadLen];
    226226        System.arraycopy(val, i + 1 + Hash.HASH_LENGTH, rv, 0, rv.length);
    227227
    228         Hash calcHash = _context.sha().calculateHash(rv);
    229         boolean ok = calcHash.equals(hash);
     228        byte[] calcHash = SimpleByteCache.acquire(Hash.HASH_LENGTH);
     229        _context.sha().calculateHash(rv, 0, payloadLen, calcHash, 0);
     230        boolean ok = DataHelper.eq(calcHash, 0, val, i + 1, Hash.HASH_LENGTH);
     231        SimpleByteCache.release(calcHash);
    230232       
    231233        long end = _context.clock().now();
     
    244246        }
    245247        if (_log.shouldLog(Log.DEBUG))
    246             _log.debug("Doesn't match hash [sent hash=" + hash + "]\ndata = "
     248            _log.debug("Doesn't match hash data = "
    247249                       + Base64.encode(rv), new Exception("Doesn't match"));
    248250        return null;
Note: See TracChangeset for help on using the changeset viewer.