forked from I2P_Developers/i2p.i2p
* HMAC:
- Replace BC MD5 with JVM version, refactor I2PHMAC to use MessageDigest instead of BC Digest (ticket #1189) - Use JVM HmacSHA256 instead of I2PHMAC for Syndie since it is standard
This commit is contained in:
@ -36,7 +36,7 @@ Public domain except as listed below:
|
|||||||
Copyright (c) 2003, TheCrypto
|
Copyright (c) 2003, TheCrypto
|
||||||
See licenses/LICENSE-ElGamalDSA.txt
|
See licenses/LICENSE-ElGamalDSA.txt
|
||||||
|
|
||||||
SHA256 and HMAC-SHA256:
|
SHA256 and HMAC:
|
||||||
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
||||||
See licenses/LICENSE-SHA256.txt
|
See licenses/LICENSE-SHA256.txt
|
||||||
|
|
||||||
|
@ -1,36 +1,101 @@
|
|||||||
package net.i2p.crypto;
|
package net.i2p.crypto;
|
||||||
|
|
||||||
import gnu.crypto.hash.Sha256Standalone;
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.data.Hash;
|
||||||
|
import net.i2p.data.SessionKey;
|
||||||
|
|
||||||
import org.bouncycastle.oldcrypto.Digest;
|
|
||||||
import org.bouncycastle.oldcrypto.macs.I2PHMac;
|
import org.bouncycastle.oldcrypto.macs.I2PHMac;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
|
* Calculate the HMAC-SHA256 of a key+message.
|
||||||
* in {@link org.bouncycastle.oldcrypto.macs.I2PHMac} and
|
* This is compatible with javax.crypto.Mac.getInstance("HmacSHA256").
|
||||||
* {@link gnu.crypto.hash.Sha256Standalone}.
|
|
||||||
*
|
*
|
||||||
* This should be compatible with javax.crypto.Mac.getInstance("HmacSHA256")
|
* As of 0.9.12, uses javax.crypto.Mac.
|
||||||
* but that is untested.
|
|
||||||
*
|
*
|
||||||
* deprecated used only by syndie
|
* Deprecated, used only by Syndie.
|
||||||
*/
|
*/
|
||||||
public class HMAC256Generator extends HMACGenerator {
|
public class HMAC256Generator extends HMACGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context unused
|
||||||
|
*/
|
||||||
public HMAC256Generator(I2PAppContext context) { super(context); }
|
public HMAC256Generator(I2PAppContext context) { super(context); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated unused (not even by Syndie)
|
||||||
|
* @throws UnsupportedOperationException since 0.9.12
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected I2PHMac acquire() {
|
protected I2PHMac acquire() {
|
||||||
I2PHMac rv = _available.poll();
|
throw new UnsupportedOperationException();
|
||||||
if (rv != null)
|
|
||||||
return rv;
|
|
||||||
// the HMAC is hardcoded to use SHA256 digest size
|
|
||||||
// for backwards compatability. next time we have a backwards
|
|
||||||
// incompatible change, we should update this by removing ", 32"
|
|
||||||
return new I2PHMac(new Sha256ForMAC());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the HMAC of the data with the given key
|
||||||
|
*
|
||||||
|
* @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
|
||||||
|
* @deprecated unused (not even by Syndie)
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
* @since 0.9.12 overrides HMACGenerator
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Hash calculate(SessionKey key, byte data[]) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the MAC inline, reducing some unnecessary memory churn.
|
||||||
|
*
|
||||||
|
* @param key session key to verify the MAC with
|
||||||
|
* @param curData MAC to verify
|
||||||
|
* @param curOffset index into curData to MAC
|
||||||
|
* @param curLength how much data in curData do we want to run the HMAC over
|
||||||
|
* @param origMAC what do we expect the MAC of curData to equal
|
||||||
|
* @param origMACOffset index into origMAC
|
||||||
|
* @param origMACLength how much of the MAC do we want to verify, use 32 for HMAC256
|
||||||
|
* @since 0.9.12 overrides HMACGenerator
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength,
|
||||||
|
byte origMAC[], int origMACOffset, int origMACLength) {
|
||||||
|
byte calc[] = acquireTmp();
|
||||||
|
calculate(key, curData, curOffset, curLength, calc, 0);
|
||||||
|
boolean eq = DataHelper.eq(calc, 0, origMAC, origMACOffset, origMACLength);
|
||||||
|
releaseTmp(calc);
|
||||||
|
return eq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******
|
||||||
private static class Sha256ForMAC extends Sha256Standalone implements Digest {
|
private static class Sha256ForMAC extends Sha256Standalone implements Digest {
|
||||||
public String getAlgorithmName() { return "sha256 for hmac"; }
|
public String getAlgorithmName() { return "sha256 for hmac"; }
|
||||||
public int getDigestSize() { return 32; }
|
public int getDigestSize() { return 32; }
|
||||||
@ -43,7 +108,6 @@ public class HMAC256Generator extends HMACGenerator {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
byte data[] = new byte[64];
|
byte data[] = new byte[64];
|
||||||
@ -53,4 +117,81 @@ public class HMAC256Generator extends HMACGenerator {
|
|||||||
System.out.println(Base64.encode(mac.getData()));
|
System.out.println(Base64.encode(mac.getData()));
|
||||||
}
|
}
|
||||||
******/
|
******/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the BC and the JVM's implementations for speed
|
||||||
|
*
|
||||||
|
* Results on 2012 hexcore box, OpenJDK 7:
|
||||||
|
* BC 9275 ms (before converting to MessageDigest)
|
||||||
|
* BC 8500 ms (after converting to MessageDigest)
|
||||||
|
* JVM 8065 ms
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/****
|
||||||
|
public static void main(String args[]) {
|
||||||
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
|
byte[] rand = new byte[32];
|
||||||
|
byte[] data = new byte[1500];
|
||||||
|
Key keyObj = new SecretKeySpec(rand, "HmacSHA256");
|
||||||
|
SessionKey key = new SessionKey(rand);
|
||||||
|
|
||||||
|
HMAC256Generator gen = new HMAC256Generator(I2PAppContext.getGlobalContext());
|
||||||
|
byte[] result = new byte[32];
|
||||||
|
javax.crypto.Mac mac;
|
||||||
|
try {
|
||||||
|
mac = javax.crypto.Mac.getInstance("HmacSHA256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.err.println("Fatal: " + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// warmup and comparison
|
||||||
|
System.out.println("Warmup and comparison:");
|
||||||
|
int RUNS = 25000;
|
||||||
|
for (int i = 0; i < RUNS; i++) {
|
||||||
|
ctx.random().nextBytes(rand);
|
||||||
|
ctx.random().nextBytes(data);
|
||||||
|
keyObj = new SecretKeySpec(rand, "HmacSHA256");
|
||||||
|
byte[] keyBytes = keyObj.getEncoded();
|
||||||
|
if (!DataHelper.eq(rand, keyBytes))
|
||||||
|
System.out.println("secret key in != out");
|
||||||
|
key = new SessionKey(rand);
|
||||||
|
gen.calculate(key, data, 0, data.length, result, 0);
|
||||||
|
try {
|
||||||
|
mac.init(keyObj);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
System.err.println("Fatal: " + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] result2 = mac.doFinal(data);
|
||||||
|
if (!DataHelper.eq(result, result2))
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// real thing
|
||||||
|
System.out.println("Passed");
|
||||||
|
System.out.println("BC Test:");
|
||||||
|
RUNS = 500000;
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < RUNS; i++) {
|
||||||
|
gen.calculate(key, data, 0, data.length, result, 0);
|
||||||
|
}
|
||||||
|
long time = System.currentTimeMillis() - start;
|
||||||
|
System.out.println("Time for " + RUNS + " HMAC-SHA256 computations:");
|
||||||
|
System.out.println("BC time (ms): " + time);
|
||||||
|
|
||||||
|
System.out.println("JVM Test:");
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < RUNS; i++) {
|
||||||
|
try {
|
||||||
|
mac.init(keyObj);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
System.err.println("Fatal: " + e);
|
||||||
|
}
|
||||||
|
byte[] sha = mac.doFinal(data);
|
||||||
|
}
|
||||||
|
time = System.currentTimeMillis() - start;
|
||||||
|
|
||||||
|
System.out.println("JVM time (ms): " + time);
|
||||||
|
}
|
||||||
|
****/
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.i2p.crypto;
|
package net.i2p.crypto;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
@ -16,7 +18,6 @@ import net.i2p.data.Hash;
|
|||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
import net.i2p.util.SimpleByteCache;
|
import net.i2p.util.SimpleByteCache;
|
||||||
|
|
||||||
import org.bouncycastle.oldcrypto.digests.MD5Digest;
|
|
||||||
import org.bouncycastle.oldcrypto.macs.I2PHMac;
|
import org.bouncycastle.oldcrypto.macs.I2PHMac;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +57,7 @@ public class HMACGenerator {
|
|||||||
* Calculate the HMAC of the data with the given key
|
* Calculate the HMAC of the data with the given key
|
||||||
*
|
*
|
||||||
* @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
|
* @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
|
||||||
* @deprecated unused
|
* @deprecated unused (not even by Syndie)
|
||||||
*/
|
*/
|
||||||
public Hash calculate(SessionKey key, byte data[]) {
|
public Hash calculate(SessionKey key, byte data[]) {
|
||||||
if ((key == null) || (key.getData() == null) || (data == null))
|
if ((key == null) || (key.getData() == null) || (data == null))
|
||||||
@ -69,6 +70,9 @@ public class HMACGenerator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the HMAC of the data with the given key
|
* Calculate the HMAC of the data with the given key
|
||||||
|
*
|
||||||
|
* @return the first 16 bytes contain the HMAC, the last 16 bytes are zero
|
||||||
|
* @throws IllegalArgumentException for bad key or target too small
|
||||||
*/
|
*/
|
||||||
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) {
|
||||||
if ((key == null) || (key.getData() == null) || (data == null))
|
if ((key == null) || (key.getData() == null) || (data == null))
|
||||||
@ -91,8 +95,10 @@ public class HMACGenerator {
|
|||||||
* @param origMAC what do we expect the MAC of curData to equal
|
* @param origMAC what do we expect the MAC of curData to equal
|
||||||
* @param origMACOffset index into origMAC
|
* @param origMACOffset index into origMAC
|
||||||
* @param origMACLength how much of the MAC do we want to verify
|
* @param origMACLength how much of the MAC do we want to verify
|
||||||
|
* @throws IllegalArgumentException for bad key
|
||||||
*/
|
*/
|
||||||
public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength, byte origMAC[], int origMACOffset, int origMACLength) {
|
public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength,
|
||||||
|
byte origMAC[], int origMACOffset, int origMACLength) {
|
||||||
if ((key == null) || (key.getData() == null) || (curData == null))
|
if ((key == null) || (key.getData() == null) || (curData == null))
|
||||||
throw new NullPointerException("Null arguments for HMAC");
|
throw new NullPointerException("Null arguments for HMAC");
|
||||||
|
|
||||||
@ -116,7 +122,12 @@ public class HMACGenerator {
|
|||||||
// for backwards compatability. next time we have a backwards
|
// for backwards compatability. next time we have a backwards
|
||||||
// incompatible change, we should update this by removing ", 32"
|
// incompatible change, we should update this by removing ", 32"
|
||||||
// SEE NOTES ABOVE
|
// SEE NOTES ABOVE
|
||||||
return new I2PHMac(new MD5Digest(), 32);
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
return new I2PHMac(md, 32);
|
||||||
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
|
throw new UnsupportedOperationException("MD5");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void release(I2PHMac mac) {
|
private void release(I2PHMac mac) {
|
||||||
@ -124,15 +135,15 @@ public class HMACGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not really tmp, just from the byte array cache.
|
* 32 bytes from the byte array cache.
|
||||||
* Does NOT zero.
|
* Does NOT zero.
|
||||||
*/
|
*/
|
||||||
private byte[] acquireTmp() {
|
protected byte[] acquireTmp() {
|
||||||
byte rv[] = SimpleByteCache.acquire(Hash.HASH_LENGTH);
|
byte rv[] = SimpleByteCache.acquire(Hash.HASH_LENGTH);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseTmp(byte tmp[]) {
|
protected void releaseTmp(byte tmp[]) {
|
||||||
SimpleByteCache.release(tmp);
|
SimpleByteCache.release(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ import net.i2p.data.Base64;
|
|||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
|
|
||||||
|
//import org.bouncycastle.oldcrypto.digests.MD5Digest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage both plaintext and salted/hashed password storage in
|
* Manage both plaintext and salted/hashed password storage in
|
||||||
* router.config.
|
* router.config.
|
||||||
@ -197,4 +199,43 @@ public class PasswordManager {
|
|||||||
} catch (NoSuchAlgorithmException nsae) {}
|
} catch (NoSuchAlgorithmException nsae) {}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* speed/comparison test before removing BC version;
|
||||||
|
* JVM was slightly faster
|
||||||
|
*/
|
||||||
|
/*****
|
||||||
|
public static void main(String[] args) {
|
||||||
|
RandomSource rand = RandomSource.getInstance();
|
||||||
|
byte[] d = new byte[1500];
|
||||||
|
MD5Digest md = new MD5Digest();
|
||||||
|
byte[] bc = new byte[16];
|
||||||
|
// warmup and comparison
|
||||||
|
int runs = 25000;
|
||||||
|
for (int i = 0; i < runs; i++) {
|
||||||
|
rand.nextBytes(d);
|
||||||
|
byte[] jvm = md5Sum(d);
|
||||||
|
md.update(d, 0, d.length);
|
||||||
|
md.doFinal(bc, 0);
|
||||||
|
if (!DataHelper.eq(jvm, bc))
|
||||||
|
throw new IllegalStateException();
|
||||||
|
md.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// real thing
|
||||||
|
runs = 500000;
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < runs; i++) {
|
||||||
|
md5Sum(d);
|
||||||
|
}
|
||||||
|
System.out.println("JVM " + (System.currentTimeMillis() - start));
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < runs; i++) {
|
||||||
|
md.update(d, 0, d.length);
|
||||||
|
md.doFinal(bc, 0);
|
||||||
|
md.reset();
|
||||||
|
}
|
||||||
|
System.out.println("BC " + (System.currentTimeMillis() - start));
|
||||||
|
}
|
||||||
|
*****/
|
||||||
}
|
}
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
package org.bouncycastle.oldcrypto;
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
|
||||||
* (http://www.bouncycastle.org)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
|
||||||
* obtaining a copy of this software and associated
|
|
||||||
* documentation files (the "Software"), to deal in the Software
|
|
||||||
* without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
* sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following
|
|
||||||
* conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* interface that a message digest conforms to.
|
|
||||||
*/
|
|
||||||
public interface Digest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* return the algorithm name
|
|
||||||
*
|
|
||||||
* @return the algorithm name
|
|
||||||
*/
|
|
||||||
public String getAlgorithmName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the size, in bytes, of the digest produced by this message digest.
|
|
||||||
*
|
|
||||||
* @return the size, in bytes, of the digest produced by this message digest.
|
|
||||||
*/
|
|
||||||
public int getDigestSize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update the message digest with a single byte.
|
|
||||||
*
|
|
||||||
* @param in the input byte to be entered.
|
|
||||||
*/
|
|
||||||
public void update(byte in);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update the message digest with a block of bytes.
|
|
||||||
*
|
|
||||||
* @param in the byte array containing the data.
|
|
||||||
* @param inOff the offset into the byte array where the data starts.
|
|
||||||
* @param len the length of the data.
|
|
||||||
*/
|
|
||||||
public void update(byte[] in, int inOff, int len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* close the digest, producing the final digest value. The doFinal
|
|
||||||
* call leaves the digest reset.
|
|
||||||
*
|
|
||||||
* @param out the array the digest is to be copied into.
|
|
||||||
* @param outOff the offset into the out array the digest is to start at.
|
|
||||||
*/
|
|
||||||
public int doFinal(byte[] out, int outOff);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reset the digest back to it's initial state.
|
|
||||||
*/
|
|
||||||
public void reset();
|
|
||||||
}
|
|
@ -1,154 +0,0 @@
|
|||||||
package org.bouncycastle.oldcrypto.digests;
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
|
||||||
* (http://www.bouncycastle.org)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
|
||||||
* obtaining a copy of this software and associated
|
|
||||||
* documentation files (the "Software"), to deal in the Software
|
|
||||||
* without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
* sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following
|
|
||||||
* conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.bouncycastle.oldcrypto.Digest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base implementation of MD4 family style digest as outlined in
|
|
||||||
* "Handbook of Applied Cryptography", pages 344 - 347.
|
|
||||||
*/
|
|
||||||
public abstract class GeneralDigest
|
|
||||||
implements Digest
|
|
||||||
{
|
|
||||||
private final byte[] xBuf;
|
|
||||||
private int xBufOff;
|
|
||||||
|
|
||||||
private long byteCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard constructor
|
|
||||||
*/
|
|
||||||
protected GeneralDigest()
|
|
||||||
{
|
|
||||||
xBuf = new byte[4];
|
|
||||||
xBufOff = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor. We are using copy constructors in place
|
|
||||||
* of the Object.clone() interface as this interface is not
|
|
||||||
* supported by J2ME.
|
|
||||||
*/
|
|
||||||
protected GeneralDigest(GeneralDigest t)
|
|
||||||
{
|
|
||||||
xBuf = new byte[t.xBuf.length];
|
|
||||||
System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
|
|
||||||
|
|
||||||
xBufOff = t.xBufOff;
|
|
||||||
byteCount = t.byteCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(
|
|
||||||
byte in)
|
|
||||||
{
|
|
||||||
xBuf[xBufOff++] = in;
|
|
||||||
|
|
||||||
if (xBufOff == xBuf.length)
|
|
||||||
{
|
|
||||||
processWord(xBuf, 0);
|
|
||||||
xBufOff = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
byteCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(
|
|
||||||
byte[] in,
|
|
||||||
int inOff,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// fill the current word
|
|
||||||
//
|
|
||||||
while ((xBufOff != 0) && (len > 0))
|
|
||||||
{
|
|
||||||
update(in[inOff]);
|
|
||||||
|
|
||||||
inOff++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// process whole words.
|
|
||||||
//
|
|
||||||
while (len > xBuf.length)
|
|
||||||
{
|
|
||||||
processWord(in, inOff);
|
|
||||||
|
|
||||||
inOff += xBuf.length;
|
|
||||||
len -= xBuf.length;
|
|
||||||
byteCount += xBuf.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// load in the remainder.
|
|
||||||
//
|
|
||||||
while (len > 0)
|
|
||||||
{
|
|
||||||
update(in[inOff]);
|
|
||||||
|
|
||||||
inOff++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finish()
|
|
||||||
{
|
|
||||||
long bitLength = (byteCount << 3);
|
|
||||||
|
|
||||||
//
|
|
||||||
// add the pad bytes.
|
|
||||||
//
|
|
||||||
update((byte)128);
|
|
||||||
|
|
||||||
while (xBufOff != 0)
|
|
||||||
{
|
|
||||||
update((byte)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
processLength(bitLength);
|
|
||||||
|
|
||||||
processBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
byteCount = 0;
|
|
||||||
|
|
||||||
xBufOff = 0;
|
|
||||||
for ( int i = 0; i < xBuf.length; i++ ) {
|
|
||||||
xBuf[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void processWord(byte[] in, int inOff);
|
|
||||||
|
|
||||||
protected abstract void processLength(long bitLength);
|
|
||||||
|
|
||||||
protected abstract void processBlock();
|
|
||||||
}
|
|
@ -1,303 +0,0 @@
|
|||||||
package org.bouncycastle.oldcrypto.digests;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
|
|
||||||
*/
|
|
||||||
public class MD5Digest
|
|
||||||
extends GeneralDigest
|
|
||||||
{
|
|
||||||
private static final int DIGEST_LENGTH = 16;
|
|
||||||
|
|
||||||
private int H1, H2, H3, H4; // IV's
|
|
||||||
|
|
||||||
private final int[] X = new int[16];
|
|
||||||
private int xOff;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard constructor
|
|
||||||
*/
|
|
||||||
public MD5Digest()
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor. This will copy the state of the provided
|
|
||||||
* message digest.
|
|
||||||
*/
|
|
||||||
public MD5Digest(MD5Digest t)
|
|
||||||
{
|
|
||||||
super(t);
|
|
||||||
|
|
||||||
H1 = t.H1;
|
|
||||||
H2 = t.H2;
|
|
||||||
H3 = t.H3;
|
|
||||||
H4 = t.H4;
|
|
||||||
|
|
||||||
System.arraycopy(t.X, 0, X, 0, t.X.length);
|
|
||||||
xOff = t.xOff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlgorithmName()
|
|
||||||
{
|
|
||||||
return "MD5";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDigestSize()
|
|
||||||
{
|
|
||||||
return DIGEST_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processWord(
|
|
||||||
byte[] in,
|
|
||||||
int inOff)
|
|
||||||
{
|
|
||||||
X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
|
|
||||||
| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
|
|
||||||
|
|
||||||
if (xOff == 16)
|
|
||||||
{
|
|
||||||
processBlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processLength(
|
|
||||||
long bitLength)
|
|
||||||
{
|
|
||||||
if (xOff > 14)
|
|
||||||
{
|
|
||||||
processBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
X[14] = (int)(bitLength & 0xffffffff);
|
|
||||||
X[15] = (int)(bitLength >>> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void unpackWord(
|
|
||||||
int word,
|
|
||||||
byte[] out,
|
|
||||||
int outOff)
|
|
||||||
{
|
|
||||||
out[outOff] = (byte)word;
|
|
||||||
out[outOff + 1] = (byte)(word >>> 8);
|
|
||||||
out[outOff + 2] = (byte)(word >>> 16);
|
|
||||||
out[outOff + 3] = (byte)(word >>> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int doFinal(
|
|
||||||
byte[] out,
|
|
||||||
int outOff)
|
|
||||||
{
|
|
||||||
finish();
|
|
||||||
|
|
||||||
unpackWord(H1, out, outOff);
|
|
||||||
unpackWord(H2, out, outOff + 4);
|
|
||||||
unpackWord(H3, out, outOff + 8);
|
|
||||||
unpackWord(H4, out, outOff + 12);
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
return DIGEST_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reset the chaining variables to the IV values.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
super.reset();
|
|
||||||
|
|
||||||
H1 = 0x67452301;
|
|
||||||
H2 = 0xefcdab89;
|
|
||||||
H3 = 0x98badcfe;
|
|
||||||
H4 = 0x10325476;
|
|
||||||
|
|
||||||
xOff = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i != X.length; i++)
|
|
||||||
{
|
|
||||||
X[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// round 1 left rotates
|
|
||||||
//
|
|
||||||
private static final int S11 = 7;
|
|
||||||
private static final int S12 = 12;
|
|
||||||
private static final int S13 = 17;
|
|
||||||
private static final int S14 = 22;
|
|
||||||
|
|
||||||
//
|
|
||||||
// round 2 left rotates
|
|
||||||
//
|
|
||||||
private static final int S21 = 5;
|
|
||||||
private static final int S22 = 9;
|
|
||||||
private static final int S23 = 14;
|
|
||||||
private static final int S24 = 20;
|
|
||||||
|
|
||||||
//
|
|
||||||
// round 3 left rotates
|
|
||||||
//
|
|
||||||
private static final int S31 = 4;
|
|
||||||
private static final int S32 = 11;
|
|
||||||
private static final int S33 = 16;
|
|
||||||
private static final int S34 = 23;
|
|
||||||
|
|
||||||
//
|
|
||||||
// round 4 left rotates
|
|
||||||
//
|
|
||||||
private static final int S41 = 6;
|
|
||||||
private static final int S42 = 10;
|
|
||||||
private static final int S43 = 15;
|
|
||||||
private static final int S44 = 21;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rotate int x left n bits.
|
|
||||||
*/
|
|
||||||
private static int rotateLeft(
|
|
||||||
int x,
|
|
||||||
int n)
|
|
||||||
{
|
|
||||||
return (x << n) | (x >>> (32 - n));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* F, G, H and I are the basic MD5 functions.
|
|
||||||
*/
|
|
||||||
private static int F(
|
|
||||||
int u,
|
|
||||||
int v,
|
|
||||||
int w)
|
|
||||||
{
|
|
||||||
return (u & v) | (~u & w);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int G(
|
|
||||||
int u,
|
|
||||||
int v,
|
|
||||||
int w)
|
|
||||||
{
|
|
||||||
return (u & w) | (v & ~w);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int H(
|
|
||||||
int u,
|
|
||||||
int v,
|
|
||||||
int w)
|
|
||||||
{
|
|
||||||
return u ^ v ^ w;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int K(
|
|
||||||
int u,
|
|
||||||
int v,
|
|
||||||
int w)
|
|
||||||
{
|
|
||||||
return v ^ (u | ~w);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processBlock()
|
|
||||||
{
|
|
||||||
int a = H1;
|
|
||||||
int b = H2;
|
|
||||||
int c = H3;
|
|
||||||
int d = H4;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Round 1 - F cycle, 16 times.
|
|
||||||
//
|
|
||||||
a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
|
|
||||||
d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
|
|
||||||
c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
|
|
||||||
b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
|
|
||||||
a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
|
|
||||||
d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
|
|
||||||
c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
|
|
||||||
b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
|
|
||||||
a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
|
|
||||||
d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
|
|
||||||
c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
|
|
||||||
b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
|
|
||||||
a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
|
|
||||||
d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
|
|
||||||
c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
|
|
||||||
b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Round 2 - G cycle, 16 times.
|
|
||||||
//
|
|
||||||
a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
|
|
||||||
d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
|
|
||||||
c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
|
|
||||||
b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
|
|
||||||
a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
|
|
||||||
d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
|
|
||||||
c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
|
|
||||||
b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
|
|
||||||
a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
|
|
||||||
d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
|
|
||||||
c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
|
|
||||||
b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
|
|
||||||
a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
|
|
||||||
d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
|
|
||||||
c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
|
|
||||||
b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Round 3 - H cycle, 16 times.
|
|
||||||
//
|
|
||||||
a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
|
|
||||||
d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
|
|
||||||
c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
|
|
||||||
b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
|
|
||||||
a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
|
|
||||||
d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
|
|
||||||
c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
|
|
||||||
b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
|
|
||||||
a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
|
|
||||||
d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
|
|
||||||
c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
|
|
||||||
b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
|
|
||||||
a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
|
|
||||||
d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
|
|
||||||
c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
|
|
||||||
b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Round 4 - K cycle, 16 times.
|
|
||||||
//
|
|
||||||
a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
|
|
||||||
d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
|
|
||||||
c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
|
|
||||||
b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
|
|
||||||
a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
|
|
||||||
d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
|
|
||||||
c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
|
|
||||||
b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
|
|
||||||
a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
|
|
||||||
d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
|
|
||||||
c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
|
|
||||||
b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
|
|
||||||
a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
|
|
||||||
d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
|
|
||||||
c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
|
|
||||||
b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
|
|
||||||
|
|
||||||
H1 += a;
|
|
||||||
H2 += b;
|
|
||||||
H3 += c;
|
|
||||||
H4 += d;
|
|
||||||
|
|
||||||
//
|
|
||||||
// reset the offset and clean out the word buffer.
|
|
||||||
//
|
|
||||||
xOff = 0;
|
|
||||||
for (int i = 0; i != X.length; i++)
|
|
||||||
{
|
|
||||||
X[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,11 +27,12 @@ package org.bouncycastle.oldcrypto.macs;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//import org.bouncycastle.crypto.CipherParameters;
|
//import org.bouncycastle.crypto.CipherParameters;
|
||||||
|
import java.security.DigestException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import net.i2p.util.SimpleByteCache;
|
import net.i2p.util.SimpleByteCache;
|
||||||
|
|
||||||
import org.bouncycastle.oldcrypto.Digest;
|
|
||||||
import org.bouncycastle.oldcrypto.Mac;
|
import org.bouncycastle.oldcrypto.Mac;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,10 @@ import org.bouncycastle.oldcrypto.Mac;
|
|||||||
* in the standard bouncycastle library, thus it conflicts in JVMs that contain the
|
* in the standard bouncycastle library, thus it conflicts in JVMs that contain the
|
||||||
* standard library (Android).
|
* standard library (Android).
|
||||||
*
|
*
|
||||||
|
* As of 0.9.12, refactored to use standard MessageDigest.
|
||||||
|
*
|
||||||
|
* Deprecated - Do not use outside of router or Syndie.
|
||||||
|
* To be moved to router.
|
||||||
*/
|
*/
|
||||||
public class I2PHMac
|
public class I2PHMac
|
||||||
implements Mac
|
implements Mac
|
||||||
@ -56,34 +61,34 @@ implements Mac
|
|||||||
private final static byte IPAD = (byte)0x36;
|
private final static byte IPAD = (byte)0x36;
|
||||||
private final static byte OPAD = (byte)0x5C;
|
private final static byte OPAD = (byte)0x5C;
|
||||||
|
|
||||||
private final Digest digest;
|
private final MessageDigest digest;
|
||||||
private final int digestSize;
|
private final int digestSize;
|
||||||
private final byte[] inputPad = new byte[BLOCK_LENGTH];
|
private final byte[] inputPad = new byte[BLOCK_LENGTH];
|
||||||
private final byte[] outputPad = new byte[BLOCK_LENGTH];
|
private final byte[] outputPad = new byte[BLOCK_LENGTH];
|
||||||
|
|
||||||
public I2PHMac(
|
/**
|
||||||
Digest digest)
|
* Standard HMAC, size == digest size.
|
||||||
{
|
* @deprecated Use javax.crypto.Mac
|
||||||
this(digest, digest.getDigestSize());
|
*/
|
||||||
|
public I2PHMac(MessageDigest digest) {
|
||||||
|
this(digest, digest.getDigestLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sz override the digest's size
|
* @param sz override the digest's size, nonstandard if different.
|
||||||
* SEE NOTES in HMACGenerator about why this isn't compatible with standard HmacMD5
|
* SEE NOTES in HMACGenerator about why this isn't compatible with standard HmacMD5
|
||||||
*/
|
*/
|
||||||
public I2PHMac(
|
public I2PHMac(MessageDigest digest, int sz) {
|
||||||
Digest digest, int sz)
|
|
||||||
{
|
|
||||||
this.digest = digest;
|
this.digest = digest;
|
||||||
this.digestSize = sz;
|
this.digestSize = sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlgorithmName()
|
public String getAlgorithmName()
|
||||||
{
|
{
|
||||||
return digest.getAlgorithmName() + "/HMAC";
|
return digest.getAlgorithm() + "/HMAC";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Digest getUnderlyingDigest()
|
public MessageDigest getUnderlyingDigest()
|
||||||
{
|
{
|
||||||
return digest;
|
return digest;
|
||||||
}
|
}
|
||||||
@ -100,7 +105,12 @@ implements Mac
|
|||||||
if (key.length > BLOCK_LENGTH)
|
if (key.length > BLOCK_LENGTH)
|
||||||
{
|
{
|
||||||
digest.update(key, 0, key.length);
|
digest.update(key, 0, key.length);
|
||||||
digest.doFinal(inputPad, 0);
|
try {
|
||||||
|
digest.digest(inputPad, 0, digestSize);
|
||||||
|
} catch (DigestException de) {
|
||||||
|
digest.reset();
|
||||||
|
throw new IllegalArgumentException(de);
|
||||||
|
}
|
||||||
for (int i = digestSize; i < inputPad.length; i++)
|
for (int i = digestSize; i < inputPad.length; i++)
|
||||||
{
|
{
|
||||||
inputPad[i] = 0;
|
inputPad[i] = 0;
|
||||||
@ -133,42 +143,32 @@ implements Mac
|
|||||||
digest.update(inputPad, 0, inputPad.length);
|
digest.update(inputPad, 0, inputPad.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMacSize()
|
public int getMacSize() {
|
||||||
{
|
|
||||||
return digestSize;
|
return digestSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(
|
public void update(byte in) {
|
||||||
byte in)
|
|
||||||
{
|
|
||||||
digest.update(in);
|
digest.update(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(
|
public void update(byte[] in, int inOff, int len) {
|
||||||
byte[] in,
|
|
||||||
int inOff,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
digest.update(in, inOff, len);
|
digest.update(in, inOff, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int doFinal(
|
public int doFinal(byte[] out, int outOff) {
|
||||||
byte[] out,
|
|
||||||
int outOff)
|
|
||||||
{
|
|
||||||
byte[] tmp = acquireTmp(digestSize);
|
byte[] tmp = acquireTmp(digestSize);
|
||||||
//byte[] tmp = new byte[digestSize];
|
//byte[] tmp = new byte[digestSize];
|
||||||
digest.doFinal(tmp, 0);
|
try {
|
||||||
|
digest.digest(tmp, 0, digestSize);
|
||||||
digest.update(outputPad, 0, outputPad.length);
|
digest.update(outputPad, 0, outputPad.length);
|
||||||
digest.update(tmp, 0, tmp.length);
|
digest.update(tmp, 0, tmp.length);
|
||||||
releaseTmp(tmp);
|
return digest.digest(out, outOff, digestSize);
|
||||||
|
} catch (DigestException de) {
|
||||||
int len = digest.doFinal(out, outOff);
|
throw new IllegalArgumentException(de);
|
||||||
|
} finally {
|
||||||
reset();
|
releaseTmp(tmp);
|
||||||
|
reset();
|
||||||
return len;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] acquireTmp(int sz) {
|
private static byte[] acquireTmp(int sz) {
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2014-02-17 zzz
|
||||||
|
* HMAC:
|
||||||
|
- Replace BC MD5 with JVM version, refactor I2PHMAC to use
|
||||||
|
MessageDigest instead of BC Digest (ticket #1189)
|
||||||
|
- Use JVM HmacSHA256 instead of I2PHMAC for Syndie since it is standard
|
||||||
|
|
||||||
2014-02-14 zzz
|
2014-02-14 zzz
|
||||||
* I2CP:
|
* I2CP:
|
||||||
- Add session limit, add new status code for refused
|
- Add session limit, add new status code for refused
|
||||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 4;
|
public final static long BUILD = 5;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user