use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class SessionEncryptionTest method testNoSessions2.
public void testNoSessions2() 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);
byte[] msg = DataHelper.getASCII("msg 2");
byte[] emsg = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, null, null, 64);
byte[] dmsg = _context.elGamalAESEngine().decrypt(emsg, privKey, skm);
assertTrue(DataHelper.eq(dmsg, msg));
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class ElGamalAESEngine method decrypt.
/**
* Decrypt the message using the given private key
* and using tags from the specified key manager.
* This works according to the
* ElGamal+AES algorithm in the data structure spec.
*
* Warning - use the correct SessionKeyManager. Clients should instantiate their own.
* Clients using I2PAppContext.sessionKeyManager() may be correlated with the router,
* unless you are careful to use different keys.
*
* @return decrypted data or null on failure
*/
public byte[] decrypt(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) throws DataFormatException {
if (data == null) {
if (_log.shouldLog(Log.ERROR))
_log.error("Null data being decrypted?");
return null;
} else if (data.length < MIN_ENCRYPTED_SIZE) {
if (_log.shouldLog(Log.ERROR))
_log.error("Data is less than the minimum size (" + data.length + " < " + MIN_ENCRYPTED_SIZE + ")");
return null;
}
byte[] tag = new byte[32];
System.arraycopy(data, 0, tag, 0, 32);
SessionTag st = new SessionTag(tag);
SessionKey key = keyManager.consumeTag(st);
SessionKey foundKey = new SessionKey();
SessionKey usedKey = new SessionKey();
Set<SessionTag> foundTags = new HashSet<SessionTag>();
byte[] decrypted = null;
boolean wasExisting = false;
if (key != null) {
// if (_log.shouldLog(Log.DEBUG)) _log.debug("Key is known for tag " + st);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Decrypting existing session encrypted with tag: " + st.toString() + ": key: " + key.toBase64() + ": " + data.length + " bytes ");
decrypted = decryptExistingSession(data, key, targetPrivateKey, foundTags, usedKey, foundKey);
if (decrypted != null) {
_context.statManager().updateFrequency("crypto.elGamalAES.decryptExistingSession");
if ((!foundTags.isEmpty()) && (_log.shouldLog(Log.DEBUG)))
_log.debug("ElG/AES decrypt success with " + st + ": found tags: " + foundTags);
wasExisting = true;
} else {
_context.statManager().updateFrequency("crypto.elGamalAES.decryptFailed");
if (_log.shouldLog(Log.WARN)) {
_log.warn("ElG decrypt fail: known tag [" + st + "], failed decrypt");
}
}
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Key is NOT known for tag " + st);
decrypted = decryptNewSession(data, targetPrivateKey, foundTags, usedKey, foundKey);
if (decrypted != null) {
_context.statManager().updateFrequency("crypto.elGamalAES.decryptNewSession");
if ((!foundTags.isEmpty()) && (_log.shouldLog(Log.DEBUG)))
_log.debug("ElG decrypt success: found tags: " + foundTags);
} else {
_context.statManager().updateFrequency("crypto.elGamalAES.decryptFailed");
if (_log.shouldLog(Log.WARN))
_log.warn("ElG decrypt fail: unknown tag: " + st);
}
}
if ((key == null) && (decrypted == null)) {
// _log.debug("Unable to decrypt the data starting with tag [" + st + "] - did the tag expire recently?", new Exception("Decrypt failure"));
}
if (!foundTags.isEmpty()) {
if (foundKey.getData() != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Found key: " + foundKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting);
keyManager.tagsReceived(foundKey, foundTags);
} else if (usedKey.getData() != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Used key: " + usedKey.toBase64() + " tags: " + foundTags + " wasExisting? " + wasExisting);
keyManager.tagsReceived(usedKey, foundTags);
}
}
return decrypted;
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class HMAC256Generator method calculate.
/**
* Calculate the HMAC of the data with the given key.
* Outputs 32 bytes to target starting at targetOffset.
*
* @throws UnsupportedOperationException if the JVM does not support it
* @throws IllegalArgumentException for bad key or target too small
* @since 0.9.12 overrides HMACGenerator
*/
@Override
public void calculate(SessionKey key, byte[] data, int offset, int length, byte[] target, int targetOffset) {
try {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA256");
Key keyObj = new SecretKeySpec(key.getData(), "HmacSHA256");
mac.init(keyObj);
mac.update(data, offset, length);
mac.doFinal(target, targetOffset);
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException("HmacSHA256", e);
} catch (GeneralSecurityException e) {
throw new IllegalArgumentException("HmacSHA256", e);
}
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class KeyGenerator method generateSessionKey.
/**
* Generate a private 256 bit session key
* @return session key
*/
public SessionKey generateSessionKey() {
// 256bit random # as a session key
SessionKey key = new SessionKey();
byte[] data = new byte[SessionKey.KEYSIZE_BYTES];
_context.random().nextBytes(data);
key.setData(data);
return key;
}
use of net.i2p.data.SessionKey in project i2p.i2p by i2p.
the class RequestLeaseSetMessageHandler method signLeaseSet.
/**
* Finish creating and signing the new LeaseSet
* @since 0.9.7
*/
protected synchronized void signLeaseSet(LeaseSet leaseSet, I2PSessionImpl session) {
Destination dest = session.getMyDestination();
// also, if this session is connected to multiple routers, include other leases here
leaseSet.setDestination(dest);
// reuse the old keys for the client
LeaseInfo li = _existingLeaseSets.get(dest);
if (li == null) {
// [enctype:]b64 of private key
String spk = session.getOptions().getProperty("i2cp.leaseSetPrivateKey");
// [sigtype:]b64 of private key
String sspk = session.getOptions().getProperty("i2cp.leaseSetSigningPrivateKey");
PrivateKey privKey = null;
SigningPrivateKey signingPrivKey = null;
if (spk != null && sspk != null) {
boolean useOldKeys = true;
int colon = sspk.indexOf(':');
SigType type = dest.getSigType();
if (colon > 0) {
String stype = sspk.substring(0, colon);
SigType t = SigType.parseSigType(stype);
if (t == type)
sspk = sspk.substring(colon + 1);
else
useOldKeys = false;
}
colon = spk.indexOf(':');
// just ignore for now, no other types supported
if (colon >= 0)
spk = spk.substring(colon + 1);
if (useOldKeys) {
try {
signingPrivKey = new SigningPrivateKey(type);
signingPrivKey.fromBase64(sspk);
} catch (DataFormatException iae) {
useOldKeys = false;
signingPrivKey = null;
}
}
if (useOldKeys) {
try {
privKey = new PrivateKey();
privKey.fromBase64(spk);
} catch (DataFormatException iae) {
privKey = null;
}
}
}
if (privKey == null && !_existingLeaseSets.isEmpty()) {
// look for keypair from another dest using same pubkey
PublicKey pk = dest.getPublicKey();
for (Map.Entry<Destination, LeaseInfo> e : _existingLeaseSets.entrySet()) {
if (pk.equals(e.getKey().getPublicKey())) {
privKey = e.getValue().getPrivateKey();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating new leaseInfo keys for " + dest + " with private key from " + e.getKey());
break;
}
}
}
if (privKey != null) {
if (signingPrivKey != null) {
li = new LeaseInfo(privKey, signingPrivKey);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating new leaseInfo keys for " + dest + " WITH configured private keys");
} else {
li = new LeaseInfo(privKey, dest);
}
} else {
li = new LeaseInfo(dest);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Creating new leaseInfo keys for " + dest + " without configured private keys");
}
_existingLeaseSets.put(dest, li);
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Caching the old leaseInfo keys for " + dest);
}
leaseSet.setEncryptionKey(li.getPublicKey());
leaseSet.setSigningKey(li.getSigningPublicKey());
// SubSession options aren't updated via the gui, so use the primary options
Properties opts;
if (session instanceof SubSession)
opts = ((SubSession) session).getPrimaryOptions();
else
opts = session.getOptions();
boolean encrypt = Boolean.parseBoolean(opts.getProperty("i2cp.encryptLeaseSet"));
String sk = opts.getProperty("i2cp.leaseSetKey");
Hash h = dest.calculateHash();
if (encrypt && sk != null) {
SessionKey key = new SessionKey();
try {
key.fromBase64(sk);
leaseSet.encrypt(key);
_context.keyRing().put(h, key);
} catch (DataFormatException dfe) {
_log.error("Bad leaseset key: " + sk);
_context.keyRing().remove(h);
}
} else {
_context.keyRing().remove(h);
}
try {
leaseSet.sign(session.getPrivateKey());
// Workaround for unparsable serialized signing private key for revocation
// Send him a dummy DSA_SHA1 private key since it's unused anyway
// See CreateLeaseSetMessage.doReadMessage()
SigningPrivateKey spk = li.getSigningPrivateKey();
if (!_context.isRouterContext() && spk.getType() != SigType.DSA_SHA1) {
byte[] dummy = new byte[SigningPrivateKey.KEYSIZE_BYTES];
_context.random().nextBytes(dummy);
spk = new SigningPrivateKey(dummy);
}
session.getProducer().createLeaseSet(session, leaseSet, spk, li.getPrivateKey());
session.setLeaseSet(leaseSet);
} catch (DataFormatException dfe) {
session.propogateError("Error signing the leaseSet", dfe);
} catch (I2PSessionException ise) {
if (session.isClosed()) {
// race, closed while signing leaseset
// EOFExceptions are logged at WARN level (see I2PSessionImpl.propogateError())
// so the user won't see this
EOFException eof = new EOFException("Session closed while signing leaseset");
eof.initCause(ise);
session.propogateError("Session closed while signing leaseset", eof);
} else {
session.propogateError("Error sending the signed leaseSet", ise);
}
}
}
Aggregations