Crypto: HMAC-SHA256 cleanup

Add byte[] key method to reduce object churn in NTCP2
Un-deprecate in context
This commit is contained in:
zzz
2018-12-11 12:19:46 +00:00
parent a63d2dccb2
commit fd23b23e56
3 changed files with 30 additions and 19 deletions

View File

@ -746,8 +746,9 @@ public class I2PAppContext {
} }
} }
/** @deprecated used only by syndie */ /**
@Deprecated * Un-deprecated in 0.9.38
*/
public HMAC256Generator hmac256() { public HMAC256Generator hmac256() {
if (!_hmac256Initialized) if (!_hmac256Initialized)
initializeHMAC256(); initializeHMAC256();

View File

@ -4,6 +4,7 @@ import java.security.GeneralSecurityException;
import java.security.Key; import java.security.Key;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
@ -19,7 +20,7 @@ import org.bouncycastle.oldcrypto.macs.I2PHMac;
* *
* As of 0.9.12, uses javax.crypto.Mac. * As of 0.9.12, uses javax.crypto.Mac.
* *
* Deprecated, used only by Syndie. * Warning - used by Syndie, don't break it.
*/ */
public final class HMAC256Generator extends HMACGenerator { public final class HMAC256Generator extends HMACGenerator {
@ -33,6 +34,7 @@ public final class HMAC256Generator extends HMACGenerator {
* @throws UnsupportedOperationException since 0.9.12 * @throws UnsupportedOperationException since 0.9.12
*/ */
@Override @Override
@Deprecated
protected I2PHMac acquire() { protected I2PHMac acquire() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -46,6 +48,7 @@ public final class HMAC256Generator extends HMACGenerator {
* @since 0.9.12 overrides HMACGenerator * @since 0.9.12 overrides HMACGenerator
*/ */
@Override @Override
@Deprecated
public Hash calculate(SessionKey key, byte data[]) { public Hash calculate(SessionKey key, byte data[]) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -60,9 +63,22 @@ public final class HMAC256Generator extends HMACGenerator {
*/ */
@Override @Override
public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) { public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) {
calculate(key.getData(), data, offset, length, target, targetOffset);
}
/**
* Calculate the HMAC of the data with the given key.
* Outputs 32 bytes to target starting at targetOffset.
*
* @param key 32 bytes
* @throws UnsupportedOperationException if the JVM does not support it
* @throws IllegalArgumentException for bad key or target too small
* @since 0.9.38
*/
public void calculate(byte[] key, byte data[], int offset, int length, byte target[], int targetOffset) {
try { try {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256");
Key keyObj = new SecretKeySpec(key.getData(), "HmacSHA256"); Key keyObj = new SecretKeySpec(key, "HmacSHA256");
mac.init(keyObj); mac.init(keyObj);
mac.update(data, offset, length); mac.update(data, offset, length);
mac.doFinal(target, targetOffset); mac.doFinal(target, targetOffset);

View File

@ -436,34 +436,28 @@ class OutboundNTCP2State implements EstablishState {
static byte[][] generateSipHashKeys(RouterContext ctx, HandshakeState state) { static byte[][] generateSipHashKeys(RouterContext ctx, HandshakeState state) {
// TODO use noise HMAC or HKDF method instead? // TODO use noise HMAC or HKDF method instead?
// ask_master = HKDF(ck, zerolen, info="ask") // ask_master = HKDF(ck, zerolen, info="ask")
SessionKey tk = new SessionKey(state.getChainingKey()); byte[] temp_key = doHMAC(ctx, state.getChainingKey(), ZEROLEN);
byte[] temp_key = doHMAC(ctx, tk, ZEROLEN); byte[] ask_master = doHMAC(ctx, temp_key, ASK);
tk = new SessionKey(temp_key);
byte[] ask_master = doHMAC(ctx, tk, ASK);
byte[] tmp = new byte[32 + SIPHASH.length]; byte[] tmp = new byte[32 + SIPHASH.length];
byte[] hash = state.getHandshakeHash(); byte[] hash = state.getHandshakeHash();
System.arraycopy(hash, 0, tmp, 0, 32); System.arraycopy(hash, 0, tmp, 0, 32);
System.arraycopy(SIPHASH, 0, tmp, 32, SIPHASH.length); System.arraycopy(SIPHASH, 0, tmp, 32, SIPHASH.length);
tk = new SessionKey(ask_master); temp_key = doHMAC(ctx, ask_master, tmp);
temp_key = doHMAC(ctx, tk, tmp); byte[] sip_master = doHMAC(ctx, temp_key, ONE);
tk = new SessionKey(temp_key); temp_key = doHMAC(ctx, sip_master, ZEROLEN);
byte[] sip_master = doHMAC(ctx, tk, ONE);
tk = new SessionKey(sip_master);
temp_key = doHMAC(ctx, tk, ZEROLEN);
tk = new SessionKey(temp_key);
// Output 1 // Output 1
byte[] sip_ab = doHMAC(ctx, tk, ONE); byte[] sip_ab = doHMAC(ctx, temp_key, ONE);
// Output 2 // Output 2
tmp = new byte[KEY_SIZE + 1]; tmp = new byte[KEY_SIZE + 1];
System.arraycopy(sip_ab, 0, tmp, 0, 32); System.arraycopy(sip_ab, 0, tmp, 0, 32);
tmp[32] = 2; tmp[32] = 2;
byte[] sip_ba = doHMAC(ctx, tk, tmp); byte[] sip_ba = doHMAC(ctx, temp_key, tmp);
Arrays.fill(temp_key, (byte) 0); Arrays.fill(temp_key, (byte) 0);
Arrays.fill(tmp, (byte) 0); Arrays.fill(tmp, (byte) 0);
return new byte[][] { sip_ab, sip_ba }; return new byte[][] { sip_ab, sip_ba };
} }
private static byte[] doHMAC(RouterContext ctx, SessionKey key, byte data[]) { private static byte[] doHMAC(RouterContext ctx, byte[] key, byte[] data) {
byte[] rv = new byte[32]; byte[] rv = new byte[32];
ctx.hmac256().calculate(key, data, 0, data.length, rv, 0); ctx.hmac256().calculate(key, data, 0, data.length, rv, 0);
return rv; return rv;