forked from I2P_Developers/i2p.i2p
Ratchet: Hook in MuxedEngine decrypt
This commit is contained in:
@ -14,7 +14,6 @@ import com.southernstorm.noise.protocol.CipherStatePair;
|
||||
import com.southernstorm.noise.protocol.DHState;
|
||||
import com.southernstorm.noise.protocol.HandshakeState;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.HKDF;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
@ -29,6 +28,7 @@ import net.i2p.data.SessionKey;
|
||||
import net.i2p.data.SessionTag;
|
||||
import net.i2p.data.i2np.GarlicClove;
|
||||
import static net.i2p.router.crypto.ratchet.RatchetPayload.*;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.message.CloveSet;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleByteCache;
|
||||
@ -42,8 +42,9 @@ import net.i2p.util.SimpleByteCache;
|
||||
* @since 0.9.44
|
||||
*/
|
||||
public final class ECIESAEADEngine {
|
||||
private final I2PAppContext _context;
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final MuxedEngine _muxedEngine;
|
||||
private final HKDF _hkdf;
|
||||
private final Elg2KeyFactory _edhThread;
|
||||
private boolean _isRunning;
|
||||
@ -70,9 +71,10 @@ public final class ECIESAEADEngine {
|
||||
*
|
||||
* startup() is called from RatchetSKM constructor so it's deferred until we need it.
|
||||
*/
|
||||
public ECIESAEADEngine(I2PAppContext ctx) {
|
||||
public ECIESAEADEngine(RouterContext ctx) {
|
||||
_context = ctx;
|
||||
_log = _context.logManager().getLog(ECIESAEADEngine.class);
|
||||
_muxedEngine = new MuxedEngine(ctx);
|
||||
_hkdf = new HKDF(ctx);
|
||||
_edhThread = new Elg2KeyFactory(ctx);
|
||||
|
||||
@ -113,6 +115,17 @@ public final class ECIESAEADEngine {
|
||||
|
||||
//// start decrypt ////
|
||||
|
||||
/**
|
||||
* Try to decrypt the message with one or both of the given private keys
|
||||
*
|
||||
* @param elgKey must be ElG, non-null
|
||||
* @param ecKey must be EC, non-null
|
||||
* @return decrypted data or null on failure
|
||||
*/
|
||||
public CloveSet decrypt(byte data[], PrivateKey elgKey, PrivateKey ecKey, MuxedSKM keyManager) throws DataFormatException {
|
||||
return _muxedEngine.decrypt(data, elgKey, ecKey, keyManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the message using the given private key
|
||||
* and using tags from the specified key manager.
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.i2p.router.crypto.ratchet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.PrivateKey;
|
||||
@ -15,7 +13,7 @@ import net.i2p.util.Log;
|
||||
*
|
||||
* @since 0.9.44
|
||||
*/
|
||||
public final class MuxedEngine {
|
||||
final class MuxedEngine {
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
|
||||
@ -27,6 +25,8 @@ public final class MuxedEngine {
|
||||
/**
|
||||
* Decrypt the message with the given private keys
|
||||
*
|
||||
* @param elgKey must be ElG, non-null
|
||||
* @param ecKey must be EC, non-null
|
||||
* @return decrypted data or null on failure
|
||||
*/
|
||||
public CloveSet decrypt(byte data[], PrivateKey elgKey, PrivateKey ecKey, MuxedSKM keyManager) throws DataFormatException {
|
||||
@ -51,10 +51,13 @@ public final class MuxedEngine {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("ElG decrypt failed, trying ECIES", dfe);
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("ElG decrypt failed, trying ECIES");
|
||||
}
|
||||
}
|
||||
if (rv == null) {
|
||||
rv = _context.eciesEngine().decrypt(data, ecKey, keyManager.getECSKM());
|
||||
rv = _context.eciesEngine().decrypt(data, ecKey, keyManager.getECSKM());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import net.i2p.util.Log;
|
||||
public class GarlicMessageParser {
|
||||
private final Log _log;
|
||||
private final RouterContext _context;
|
||||
|
||||
|
||||
/**
|
||||
* Huge limit just to reduce chance of trouble. Typ. usage is 3.
|
||||
* As of 0.9.12. Was 255.
|
||||
@ -42,11 +42,11 @@ public class GarlicMessageParser {
|
||||
_context = context;
|
||||
_log = _context.logManager().getLog(GarlicMessageParser.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supports both ELGAMAL_2048 and ECIES_X25519.
|
||||
*
|
||||
* @param encryptionKey either type TODO need both for muxed
|
||||
* @param encryptionKey either type
|
||||
* @param skm use tags from this session key manager
|
||||
* @return null on error
|
||||
*/
|
||||
@ -108,7 +108,46 @@ public class GarlicMessageParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supports both ELGAMAL_2048 and ECIES_X25519.
|
||||
*
|
||||
* @param elgKey must be ElG, non-null
|
||||
* @param ecKey must be EC, non-null
|
||||
* @param skm use tags from this session key manager
|
||||
* @return null on error
|
||||
* @since 0.9.44
|
||||
*/
|
||||
CloveSet getGarlicCloves(GarlicMessage message, PrivateKey elgKey, PrivateKey ecKey, SessionKeyManager skm) {
|
||||
byte encData[] = message.getData();
|
||||
CloveSet rv;
|
||||
try {
|
||||
if (skm instanceof MuxedSKM) {
|
||||
MuxedSKM mskm = (MuxedSKM) skm;
|
||||
rv = _context.eciesEngine().decrypt(encData, elgKey, ecKey, mskm);
|
||||
} else if (skm instanceof RatchetSKM) {
|
||||
// unlikely, if we have two keys we should have a MuxedSKM
|
||||
RatchetSKM rskm = (RatchetSKM) skm;
|
||||
rv = _context.eciesEngine().decrypt(encData, ecKey, rskm);
|
||||
} else {
|
||||
// unlikely, if we have two keys we should have a MuxedSKM
|
||||
byte[] decrData = _context.elGamalAESEngine().decrypt(encData, elgKey, skm);
|
||||
if (decrData != null) {
|
||||
rv = readCloveSet(decrData, 0);
|
||||
} else {
|
||||
rv = null;
|
||||
}
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Muxed decrypt fail", dfe);
|
||||
rv = null;
|
||||
}
|
||||
if (rv == null &&_log.shouldWarn())
|
||||
_log.warn("Muxed decrypt fail");
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* ElGamal only
|
||||
*
|
||||
|
@ -57,6 +57,7 @@ public class GarlicMessageReceiver {
|
||||
|
||||
public void receive(GarlicMessage message) {
|
||||
PrivateKey decryptionKey;
|
||||
PrivateKey decryptionKey2 = null;
|
||||
SessionKeyManager skm;
|
||||
if (_clientDestination != null) {
|
||||
LeaseSetKeys keys = _context.keyManager().getKeys(_clientDestination);
|
||||
@ -64,13 +65,16 @@ public class GarlicMessageReceiver {
|
||||
if (keys != null && skm != null) {
|
||||
// TODO need to pass both keys if available for muxed decrypt
|
||||
decryptionKey = keys.getDecryptionKey();
|
||||
decryptionKey2 = keys.getDecryptionKey(EncType.ECIES_X25519);
|
||||
if (decryptionKey == null && decryptionKey2 == null) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("No key to decrypt for " + _clientDestination.toBase32());
|
||||
return;
|
||||
}
|
||||
if (decryptionKey == null) {
|
||||
decryptionKey = keys.getDecryptionKey(EncType.ECIES_X25519);
|
||||
if (decryptionKey == null) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("No key to decrypt for " + _clientDestination.toBase32());
|
||||
return;
|
||||
}
|
||||
// swap
|
||||
decryptionKey = decryptionKey2;
|
||||
decryptionKey2 = null;
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
@ -82,8 +86,12 @@ public class GarlicMessageReceiver {
|
||||
skm = _context.sessionKeyManager();
|
||||
}
|
||||
|
||||
// TODO need to pass both keys if available for muxed decrypt
|
||||
CloveSet set = _context.garlicMessageParser().getGarlicCloves(message, decryptionKey, skm);
|
||||
// Pass both keys if available for muxed decrypt
|
||||
CloveSet set;
|
||||
if (decryptionKey2 != null)
|
||||
set = _context.garlicMessageParser().getGarlicCloves(message, decryptionKey, decryptionKey2, skm);
|
||||
else
|
||||
set = _context.garlicMessageParser().getGarlicCloves(message, decryptionKey, skm);
|
||||
if (set != null) {
|
||||
for (int i = 0; i < set.getCloveCount(); i++) {
|
||||
GarlicClove clove = set.getClove(i);
|
||||
|
Reference in New Issue
Block a user