use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class ElGamalAESEngine method decryptAESBlock.
/**
* Decrypt the AES data with the session key and IV. The result should be:
* <pre>
* - 2 byte integer specifying the # of session tags
* - that many 32 byte session tags
* - 4 byte integer specifying data.length
* - SHA256 of data
* - 1 byte flag that, if == 1, is followed by a new SessionKey
* - data
* - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
* </pre>
*
* If anything doesn't match up in decryption, return null. Otherwise, return
* the decrypted data and update the session as necessary. If the sentTag is not null,
* consume it, but if it is null, record the keys, etc as part of a new session.
*
* @param foundTags set which is filled with any sessionTags found during decryption
* @param foundKey out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption
* @return decrypted data or null on failure
*/
/**
**
* private byte[] decryptAESBlock(byte encrypted[], SessionKey key, byte iv[],
* byte sentTag[], Set foundTags, SessionKey foundKey) throws DataFormatException {
* return decryptAESBlock(encrypted, 0, encrypted.length, key, iv, sentTag, foundTags, foundKey);
* }
***
*/
/*
* Note: package private for ElGamalTest.testAES()
*/
byte[] decryptAESBlock(byte[] encrypted, int offset, int encryptedLen, SessionKey key, byte[] iv, byte[] sentTag, Set<SessionTag> foundTags, SessionKey foundKey) throws DataFormatException {
// _log.debug("iv for decryption: " + DataHelper.toString(iv, 16));
// _log.debug("decrypting AES block. encr.length = " + (encrypted == null? -1 : encrypted.length) + " sentTag: " + DataHelper.toString(sentTag, 32));
byte[] decrypted = new byte[encryptedLen];
_context.aes().decrypt(encrypted, offset, decrypted, 0, key, iv, encryptedLen);
// _log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
try {
SessionKey newKey = null;
List<SessionTag> tags = null;
// ByteArrayInputStream bais = new ByteArrayInputStream(decrypted);
int cur = 0;
long numTags = DataHelper.fromLong(decrypted, cur, 2);
if ((numTags < 0) || (numTags > MAX_TAGS_RECEIVED))
throw new IllegalArgumentException("Invalid number of session tags");
if (numTags > 0)
tags = new ArrayList<SessionTag>((int) numTags);
cur += 2;
// _log.debug("# tags: " + numTags);
if (numTags * SessionTag.BYTE_LENGTH > decrypted.length - 2) {
throw new IllegalArgumentException("# tags: " + numTags + " is too many for " + (decrypted.length - 2));
}
for (int i = 0; i < numTags; i++) {
byte[] tag = new byte[SessionTag.BYTE_LENGTH];
System.arraycopy(decrypted, cur, tag, 0, SessionTag.BYTE_LENGTH);
cur += SessionTag.BYTE_LENGTH;
tags.add(new SessionTag(tag));
}
long len = DataHelper.fromLong(decrypted, cur, 4);
cur += 4;
// _log.debug("len: " + len);
if ((len < 0) || (len > decrypted.length - cur - Hash.HASH_LENGTH - 1))
throw new IllegalArgumentException("Invalid size of payload (" + len + ", remaining " + (decrypted.length - cur) + ")");
// byte hashval[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(decrypted, cur, hashval, 0, Hash.HASH_LENGTH);
// readHash = new Hash();
// readHash.setData(hashval);
// readHash = Hash.create(decrypted, cur);
int hashIndex = cur;
cur += Hash.HASH_LENGTH;
byte flag = decrypted[cur++];
if (flag == 0x01) {
byte[] rekeyVal = new byte[SessionKey.KEYSIZE_BYTES];
System.arraycopy(decrypted, cur, rekeyVal, 0, SessionKey.KEYSIZE_BYTES);
cur += SessionKey.KEYSIZE_BYTES;
newKey = new SessionKey();
newKey.setData(rekeyVal);
}
byte[] unencrData = new byte[(int) len];
System.arraycopy(decrypted, cur, unencrData, 0, (int) len);
cur += (int) len;
// use alternate calculateHash() method to avoid object churn and caching
// Hash calcHash = _context.sha().calculateHash(unencrData);
// boolean eq = calcHash.equals(readHash);
byte[] calcHash = SimpleByteCache.acquire(32);
_context.sha().calculateHash(unencrData, 0, (int) len, calcHash, 0);
boolean eq = DataHelper.eq(decrypted, hashIndex, calcHash, 0, 32);
SimpleByteCache.release(calcHash);
if (eq) {
// everything matches. w00t.
if (tags != null)
foundTags.addAll(tags);
if (newKey != null)
foundKey.setData(newKey.getData());
return unencrData;
}
throw new RuntimeException("Hash does not match");
} catch (RuntimeException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to decrypt AES block", e);
return null;
}
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class KeyGenerator method generateSessionKey.
/**
* PBE the passphrase with the salt.
* Warning - SLOW
*/
public SessionKey generateSessionKey(byte[] salt, byte[] passphrase) {
byte[] salted = new byte[16 + passphrase.length];
System.arraycopy(salt, 0, salted, 0, Math.min(salt.length, 16));
System.arraycopy(passphrase, 0, salted, 16, passphrase.length);
byte[] h = _context.sha().calculateHash(salted).getData();
for (int i = 1; i < PBE_ROUNDS; i++) _context.sha().calculateHash(h, 0, Hash.HASH_LENGTH, h, 0);
return new SessionKey(h);
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class AES256Test method testShort.
public void testShort() {
I2PAppContext ctx = new I2PAppContext();
SessionKey key = ctx.keyGenerator().generateSessionKey();
byte[] iv = new byte[16];
RandomSource.getInstance().nextBytes(iv);
byte[] sbuf = new byte[16];
RandomSource.getInstance().nextBytes(sbuf);
byte[] se = new byte[16];
ctx.aes().encrypt(sbuf, 0, se, 0, key, iv, sbuf.length);
byte[] sd = new byte[16];
ctx.aes().decrypt(se, 0, sd, 0, key, iv, se.length);
assertTrue(DataHelper.eq(sd, sbuf));
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class AES256Test method testMultiple.
public void testMultiple() {
for (int i = 0; i < 100; i++) {
SessionKey key = _context.keyGenerator().generateSessionKey();
byte[] iv = new byte[16];
_context.random().nextBytes(iv);
byte[] plain = new byte[256];
_context.random().nextBytes(plain);
byte[] e = new byte[plain.length];
_context.aes().encrypt(plain, 0, e, 0, key, iv, plain.length);
byte[] d = new byte[e.length];
_context.aes().decrypt(e, 0, d, 0, key, iv, d.length);
boolean same = true;
assertTrue(DataHelper.eq(plain, d));
}
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class CryptixAESEngineTest method testED.
public void testED() {
I2PAppContext ctx = I2PAppContext.getGlobalContext();
SessionKey key = ctx.keyGenerator().generateSessionKey();
byte[] iv = new byte[16];
byte[] orig = new byte[128];
byte[] encrypted = new byte[128];
byte[] decrypted = new byte[128];
ctx.random().nextBytes(iv);
ctx.random().nextBytes(orig);
CryptixAESEngine aes = new CryptixAESEngine(ctx);
aes.encrypt(orig, 0, encrypted, 0, key, iv, orig.length);
aes.decrypt(encrypted, 0, decrypted, 0, key, iv, encrypted.length);
assertTrue(DataHelper.eq(decrypted, orig));
}
Aggregations