use of net.i2p.data.SessionTag in project i2p.i2p by i2p.
the class TransientSessionKeyManager method aggressiveExpire.
/**
* Aggressively expire inbound tag sets and outbound sessions
*
* @return number of tag sets expired (bogus as it overcounts inbound)
*/
private int aggressiveExpire() {
int removed = 0;
int remaining = 0;
long now = _context.clock().now();
synchronized (_inboundTagSets) {
for (Iterator<TagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext(); ) {
TagSet ts = iter.next();
// for inbound tagsets, getDate() is the expire time
if (ts.getDate() <= now) {
iter.remove();
// bug, this counts inbound tags, not tag sets
removed++;
}
}
remaining = _inboundTagSets.size();
if (remaining > 500) {
// find SessionKeys with a large number of TagSets and trim them
Map<SessionKey, Set<TagSet>> inboundSets = getInboundTagSetsBySessionKey();
for (Map.Entry<SessionKey, Set<TagSet>> e : inboundSets.entrySet()) {
SessionKey skey = e.getKey();
Set<TagSet> sets = e.getValue();
int count = sets.size();
if (count >= 10) {
if (_log.shouldInfo())
_log.info("Session key " + skey.toBase64() + " has " + count + " tag sets");
// for any session key with at least 10 tagsets,
// remove all tagsets larger than 8 tags that haven't been used and
// are old. The more the tagsets, the more aggressively we expire.
// From 9 minutes at 10 down to one minute at 50
long age = Math.min(5 * 60 * 1000, Math.max(60 * 1000, 9 * 60 * 1000 - ((count - 10) * 8 * 60 * 1000 / 40)));
for (TagSet ts : sets) {
Set<SessionTag> tags = ts.getTags();
int curSize = tags.size();
int origSize = ts.getOriginalSize();
long expires = ts.getDate();
if (curSize == origSize && curSize > 8 && expires < now + SESSION_LIFETIME_MAX_MS - age) {
if (_log.shouldInfo())
_log.info("Removed unused tag set " + ts);
for (SessionTag tag : tags) {
_inboundTagSets.remove(tag);
}
removed += curSize;
}
}
}
}
remaining = _inboundTagSets.size();
}
}
_context.statManager().addRateData("crypto.sessionTagsRemaining", remaining, 0);
if (removed > 0 && _log.shouldInfo())
_log.info("Expired inbound: " + removed);
int oremoved = 0;
synchronized (_outboundSessions) {
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext(); ) {
OutboundSession sess = iter.next();
oremoved += sess.expireTags();
// don't kill a new session or one that's temporarily out of tags
if (sess.getLastUsedDate() < now - (SESSION_LIFETIME_MAX_MS / 2) && sess.availableTags() <= 0) {
iter.remove();
// just to have a non-zero return value?
oremoved++;
}
}
}
if (oremoved > 0 && _log.shouldInfo())
_log.info("Expired outbound: " + oremoved);
return removed + oremoved;
}
use of net.i2p.data.SessionTag in project i2p.i2p by i2p.
the class DatabaseLookupMessage method readMessage.
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
if (type != MESSAGE_TYPE)
throw new I2NPMessageException("Message type is incorrect for this message");
int curIndex = offset;
// byte keyData[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, curIndex, keyData, 0, Hash.HASH_LENGTH);
_key = Hash.create(data, curIndex);
curIndex += Hash.HASH_LENGTH;
// _key = new Hash(keyData);
// byte fromData[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, curIndex, fromData, 0, Hash.HASH_LENGTH);
_fromHash = Hash.create(data, curIndex);
curIndex += Hash.HASH_LENGTH;
// _fromHash = new Hash(fromData);
// as of 0.9.6, ignore other 7 bits of the flag byte
// TODO store the whole flag byte
boolean tunnelSpecified = (data[curIndex] & FLAG_TUNNEL) != 0;
boolean replyKeySpecified = (data[curIndex] & FLAG_ENCRYPT) != 0;
switch(data[curIndex] & FLAG_TYPE_MASK) {
case FLAG_TYPE_LS:
_type = Type.LS;
break;
case FLAG_TYPE_RI:
_type = Type.RI;
break;
case FLAG_TYPE_EXPL:
_type = Type.EXPL;
break;
case FLAG_TYPE_ANY:
default:
_type = Type.ANY;
break;
}
curIndex++;
if (tunnelSpecified) {
_replyTunnel = new TunnelId(DataHelper.fromLong(data, curIndex, 4));
curIndex += 4;
}
int numPeers = (int) DataHelper.fromLong(data, curIndex, 2);
curIndex += 2;
if ((numPeers < 0) || (numPeers > MAX_NUM_PEERS))
throw new I2NPMessageException("Invalid number of peers - " + numPeers);
List<Hash> peers = numPeers > 0 ? new ArrayList<Hash>(numPeers) : null;
for (int i = 0; i < numPeers; i++) {
// byte peer[] = new byte[Hash.HASH_LENGTH];
// System.arraycopy(data, curIndex, peer, 0, Hash.HASH_LENGTH);
Hash p = Hash.create(data, curIndex);
curIndex += Hash.HASH_LENGTH;
peers.add(p);
}
_dontIncludePeers = peers;
if (replyKeySpecified) {
byte[] rk = new byte[SessionKey.KEYSIZE_BYTES];
System.arraycopy(data, curIndex, rk, 0, SessionKey.KEYSIZE_BYTES);
_replyKey = new SessionKey(rk);
curIndex += SessionKey.KEYSIZE_BYTES;
// number of tags, assume always 1 for now
curIndex++;
byte[] rt = new byte[SessionTag.BYTE_LENGTH];
System.arraycopy(data, curIndex, rt, 0, SessionTag.BYTE_LENGTH);
_replyTag = new SessionTag(rt);
}
}
use of net.i2p.data.SessionTag in project i2p.i2p by i2p.
the class ElGamalTest method testAES.
public void testAES() {
SessionKey sessionKey = KeyGenerator.getInstance().generateSessionKey();
Hash h = SHA256Generator.getInstance().calculateHash(sessionKey.getData());
byte[] iv = new byte[16];
System.arraycopy(h.getData(), 0, iv, 0, 16);
String msg = "Hello world";
byte[] encrypted = _context.elGamalAESEngine().encryptAESBlock(DataHelper.getASCII(msg), sessionKey, iv, null, null, 64);
Set<SessionTag> foundTags = new HashSet<SessionTag>();
SessionKey foundKey = new SessionKey();
byte[] decrypted = null;
try {
decrypted = _context.elGamalAESEngine().decryptAESBlock(encrypted, 0, encrypted.length, sessionKey, iv, null, foundTags, foundKey);
} catch (DataFormatException dfe) {
dfe.printStackTrace();
fail();
}
assertNotNull(decrypted);
String read = new String(decrypted);
assertEquals(msg, read);
}
use of net.i2p.data.SessionTag in project i2p.i2p by i2p.
the class SessionEncryptionTest method testRekeying.
/**
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes yes
* 4 no yes no
* 5 no yes no
*/
public void testRekeying() throws Exception {
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey) keys[0];
PrivateKey privKey = (PrivateKey) keys[1];
SessionKeyManager skm = new TransientSessionKeyManager(_context);
SessionKey curKey = skm.createSession(pubKey);
SessionKey nextKey = KeyGenerator.getInstance().generateSessionKey();
SessionTag tag1 = new SessionTag(true);
SessionTag tag2 = new SessionTag(true);
SessionTag tag3 = new SessionTag(true);
SessionTag tag4 = new SessionTag(true);
HashSet<SessionTag> firstTags = new HashSet<SessionTag>();
firstTags.add(tag1);
firstTags.add(tag2);
HashSet<SessionTag> secondTags = new HashSet<SessionTag>();
secondTags.add(tag3);
secondTags.add(tag4);
byte[] msg1 = DataHelper.getASCII("msg 1");
byte[] msg2 = DataHelper.getASCII("msg 2");
byte[] msg3 = DataHelper.getASCII("msg 3");
byte[] msg4 = DataHelper.getASCII("msg 4");
byte[] msg5 = DataHelper.getASCII("msg 5");
byte[] emsg1 = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, null, 64);
byte[] dmsg1 = _context.elGamalAESEngine().decrypt(emsg1, privKey, skm);
assertTrue(DataHelper.eq(dmsg1, msg1));
TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, firstTags);
skm.tagsAcked(pubKey, curKey, tsh);
curKey = skm.getCurrentKey(pubKey);
SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
byte[] emsg2 = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64);
byte[] dmsg2 = _context.elGamalAESEngine().decrypt(emsg2, privKey, skm);
assertTrue(DataHelper.eq(dmsg2, msg2));
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg3 = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, nextKey, 64);
byte[] dmsg3 = _context.elGamalAESEngine().decrypt(emsg3, privKey, skm);
assertTrue(DataHelper.eq(dmsg3, msg3));
// note nextKey not curKey
tsh = skm.tagsDelivered(pubKey, nextKey, secondTags);
skm.tagsAcked(pubKey, nextKey, tsh);
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg4 = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64);
byte[] dmsg4 = _context.elGamalAESEngine().decrypt(emsg4, privKey, skm);
assertTrue(DataHelper.eq(dmsg4, msg4));
curKey = skm.getCurrentKey(pubKey);
curTag = skm.consumeNextAvailableTag(pubKey, curKey);
assertNotNull(curTag);
assertNotNull(curKey);
byte[] emsg5 = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64);
byte[] dmsg5 = _context.elGamalAESEngine().decrypt(emsg5, privKey, skm);
assertTrue(DataHelper.eq(dmsg5, msg5));
}
use of net.i2p.data.SessionTag in project i2p.i2p by i2p.
the class SessionEncryptionTest method testLongSession.
/**
* 20 tags every 10 messages, rekey every 50
*/
public void testLongSession() throws Exception {
Object[] keys = KeyGenerator.getInstance().generatePKIKeypair();
PublicKey pubKey = (PublicKey) keys[0];
PrivateKey privKey = (PrivateKey) keys[1];
SessionKeyManager skm = new TransientSessionKeyManager(_context);
SessionKey curKey = skm.createSession(pubKey);
for (int i = 0; i < 1000; i++) {
Set<SessionTag> tags = null;
SessionKey nextKey = null;
curKey = skm.getCurrentKey(pubKey);
SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey);
int availTags = skm.getAvailableTags(pubKey, curKey);
if ((availTags < 1)) {
tags = generateNewTags(50);
}
if (i % 50 == 0)
nextKey = KeyGenerator.getInstance().generateSessionKey();
byte[] msg = DataHelper.getASCII("msg " + i);
byte[] emsg = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, tags, curTag, nextKey, 64);
byte[] dmsg = _context.elGamalAESEngine().decrypt(emsg, privKey, skm);
assertTrue(DataHelper.eq(dmsg, msg));
if ((tags != null) && (tags.size() > 0)) {
if (nextKey == null) {
TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, tags);
skm.tagsAcked(pubKey, curKey, tsh);
} else {
TagSetHandle tsh = skm.tagsDelivered(pubKey, nextKey, tags);
skm.tagsAcked(pubKey, nextKey, tsh);
}
}
}
}
Aggregations