use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class SessionEncryptionTest method testSessions.
/**
* Run tagsIncluded useTag rekey
* 1 yes (2) no no
* 2 no yes no
* 3 yes (2) yes no
* 4 no yes no
* 5 no yes no
*/
public void testSessions() 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);
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, 64);
byte[] dmsg3 = _context.elGamalAESEngine().decrypt(emsg3, privKey, skm);
assertTrue(DataHelper.eq(dmsg3, msg3));
tsh = skm.tagsDelivered(pubKey, curKey, secondTags);
skm.tagsAcked(pubKey, curKey, 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.SessionKey in project i2p.i2p by i2p.
the class DHSessionKeyBuilderTest method testDHSessionKeyBuilder.
public void testDHSessionKeyBuilder() {
I2PAppContext ctx = new I2PAppContext();
for (int i = 0; i < 5; i++) {
DHSessionKeyBuilder builder1 = new DHSessionKeyBuilder();
DHSessionKeyBuilder builder2 = new DHSessionKeyBuilder();
BigInteger pub1 = builder1.getMyPublicValue();
BigInteger pub2 = builder2.getMyPublicValue();
try {
builder2.setPeerPublicValue(pub1);
builder1.setPeerPublicValue(pub2);
} catch (DHSessionKeyBuilder.InvalidPublicParameterException ippe) {
assertTrue(ippe.getMessage(), true);
}
SessionKey key1 = builder1.getSessionKey();
SessionKey key2 = builder2.getSessionKey();
assertEquals(key1, key2);
byte[] iv = new byte[16];
RandomSource.getInstance().nextBytes(iv);
// 16 bytes max using AESEngine
String origVal = "1234567890123456";
byte[] enc = new byte[16];
byte[] dec = new byte[16];
ctx.aes().encrypt(DataHelper.getASCII(origVal), 0, enc, 0, key1, iv, 16);
ctx.aes().decrypt(enc, 0, dec, 0, key2, iv, 16);
String tranVal = new String(dec);
assertEquals(origVal, tranVal);
}
}
use of net.i2p.data.SessionKey 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.SessionKey in project i2p.i2p by i2p.
the class TransientSessionKeyManager method consumeTag.
/**
* Determine if we have received a session key associated with the given session tag,
* and if so, discard it (but keep track for frequent dups) and return the decryption
* key it was received with (via tagsReceived(...)). returns null if no session key
* matches
*/
@Override
public SessionKey consumeTag(SessionTag tag) {
TagSet tagSet;
synchronized (_inboundTagSets) {
tagSet = _inboundTagSets.remove(tag);
if (tagSet == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Cannot consume IB " + tag + " as it is not known");
return null;
}
tagSet.consume(tag);
}
SessionKey key = tagSet.getAssociatedKey();
if (_log.shouldLog(Log.DEBUG))
_log.debug("IB Tag consumed: " + tag + " from: " + tagSet);
return key;
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class TransientSessionKeyManager method getCurrentOrNewKey.
/**
* Retrieve the session key currently associated with encryption to the target.
* Generates a new session and session key if not previously exising.
*
* @return non-null
* @since 0.9
*/
@Override
public SessionKey getCurrentOrNewKey(PublicKey target) {
synchronized (_outboundSessions) {
OutboundSession sess = _outboundSessions.get(target);
if (sess != null) {
long now = _context.clock().now();
if (sess.getLastUsedDate() < now - SESSION_LIFETIME_MAX_MS)
sess = null;
}
if (sess == null) {
SessionKey key = _context.keyGenerator().generateSessionKey();
createAndReturnSession(target, key);
return key;
}
return sess.getCurrentKey();
}
}
Aggregations