Skip to content

Commit

Permalink
Add a lousy benchmark to show that it's not slower
Browse files Browse the repository at this point in the history
  • Loading branch information
nextgens committed Jan 2, 2016
1 parent c0d7941 commit b9537f4
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 5 deletions.
65 changes: 60 additions & 5 deletions test/freenet/crypt/HMACTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@

import junit.framework.TestCase;

import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.security.Security;
import java.util.Random;

import freenet.support.TestProperty;
import freenet.support.TimeUtil;

public class HMACTest extends TestCase {

Random random;
// RFC4868 2.7.2.1 SHA256 Authentication Test Vector
static byte[] plaintext = "Hi There".getBytes();
static byte[] knownKey = Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
static byte[] knownSHA256 = Hex.decode("198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7");
static byte[] plaintext = "Hi There".getBytes();
static byte[]
knownKey =
Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
static byte[]
knownSHA256 =
Hex.decode("198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7");

protected void setUp() throws Exception {
super.setUp();
Expand Down Expand Up @@ -57,7 +67,52 @@ public void testWrongKeySize() {
}

public void testKnownVectors() {
byte[] hmac = HMAC.macWithSHA256(knownKey, plaintext);
assertEquals(Hex.toHexString(hmac),Hex.toHexString(knownSHA256));
byte[] hmac = HMAC.macWithSHA256(knownKey, plaintext);
assertEquals(Hex.toHexString(hmac), Hex.toHexString(knownSHA256));
}

// ant -Dtest.skip=false -Dtest.class=freenet.crypt.HMACTest -Dtest.benchmark=true unit
public void testBenchmark() {
if (!TestProperty.BENCHMARK) {
return;
}

int count = 0;
int ITERATIONS = 10000000;
System.out.println("We're getting ready to benchmark HMACs");
long t1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
byte[] r1 = HMAC_legacy.macWithSHA256(knownKey, plaintext, 32);
for (int j = 0; j < r1.length; j++) {
count += r1[j];
}
}
long legacyLength = System.currentTimeMillis() - t1;

t1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
byte[] r1 = HMAC.macWithSHA256(knownKey, plaintext);
for (int j = 0; j < r1.length; j++) {
count += r1[j];
}
}
long currentLength = System.currentTimeMillis() - t1;

t1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
byte[] r1 = new byte[32];
HMac hmac = new HMac(new SHA256Digest());
KeyParameter kp = new KeyParameter(knownKey);
hmac.init(kp);
hmac.update(plaintext, 0, plaintext.length);
hmac.doFinal(r1, 0);
for (int j = 0; j < r1.length; j++) {
count += r1[j];
}
}
long BCLength = System.currentTimeMillis() - t1;
System.out.println("Legacy HMAC took " + TimeUtil.formatTime(legacyLength, 6, true));
System.out.println("Current HMAC took " + TimeUtil.formatTime(legacyLength, 6, true));
System.out.println("BC HMAC took " + TimeUtil.formatTime(BCLength, 6, true));
}
}
154 changes: 154 additions & 0 deletions test/freenet/crypt/HMAC_legacy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.crypt;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import freenet.support.HexUtil;

/**
* Implements the HMAC Keyed Message Authentication function, as described
* in the draft FIPS standard.
*/
public class HMAC_legacy {

protected static final int B = 64;
protected static byte[] ipad = new byte[B];
protected static byte[] opad = new byte[B];

static {
for(int i = 0; i < B; i++) {
ipad[i] = (byte) 0x36;
opad[i] = (byte) 0x5c;
}
}
protected MessageDigest d;

public HMAC_legacy(MessageDigest md) {
this.d = md;
}

public boolean verify(byte[] K, byte[] text, byte[] mac) {
byte[] mac2 = mac(K, text, mac.length);

// this is constant-time; DO NOT 'optimize'
return MessageDigest.isEqual(mac, mac2);
}

public byte[] mac(byte[] K, byte[] text, int macbytes) {
byte[] K0 = null;

if(K.length == B) // Step 1
K0 = K;
else {
// Step 2
if(K.length > B)
K0 = K = Util.hashBytes(d, K);

if(K.length < B) { // Step 3
K0 = new byte[B];
System.arraycopy(K, 0, K0, 0, K.length);
}
}

// Step 4
byte[] IS1 = Util.xor(K0, ipad);

// Step 5/6
d.update(IS1);
d.update(text);
IS1 = d.digest();

// Step 7
byte[] IS2 = Util.xor(K0, opad);

// Step 8/9
d.update(IS2);
d.update(IS1);
IS1 = d.digest();

// Step 10
if(macbytes == IS1.length)
return IS1;
else {
byte[] rv = new byte[macbytes];
System.arraycopy(IS1, 0, rv, 0, Math.min(rv.length, IS1.length));
return rv;
}
}

public static void main(String[] args) throws UnsupportedEncodingException {
HMAC_legacy s = null;
try {
s = new HMAC_legacy(MessageDigest.getInstance("SHA1"));
} catch(NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] key = new byte[20];
System.err.println("20x0b, 'Hi There':");
byte[] text;
text = "Hi There".getBytes("UTF-8");

for(int i = 0; i < key.length; i++)
key[i] = (byte) 0x0b;

byte[] mv = s.mac(key, text, 20);
System.out.println(HexUtil.bytesToHex(mv, 0, mv.length));

System.err.println("20xaa, 50xdd:");
for(int i = 0; i < key.length; i++)
key[i] = (byte) 0xaa;
text = new byte[50];
for(int i = 0; i < text.length; i++)
text[i] = (byte) 0xdd;
mv = s.mac(key, text, 20);
System.out.println(HexUtil.bytesToHex(mv, 0, mv.length));

key = new byte[25];
System.err.println("25x[i+1], 50xcd:");
for(int i = 0; i < key.length; i++)
key[i] = (byte) (i + 1);
for(int i = 0; i < text.length; i++)
text[i] = (byte) 0xcd;
mv = s.mac(key, text, 20);
System.out.println(HexUtil.bytesToHex(mv, 0, mv.length));

key = new byte[20];
System.err.println("20x0c, 'Test With Truncation':");
for(int i = 0; i < key.length; i++)
key[i] = (byte) 0x0c;
text = "Test With Truncation".getBytes("UTF-8");
mv = s.mac(key, text, 20);
System.out.println(HexUtil.bytesToHex(mv, 0, mv.length));
mv = s.mac(key, text, 12);
System.out.println(HexUtil.bytesToHex(mv, 0, mv.length));

}

public static byte[] macWithSHA256(byte[] K, byte[] text, int macbytes) {
MessageDigest sha256 = null;
try {
sha256 = SHA256.getMessageDigest();
HMAC_legacy hash = new HMAC_legacy(sha256);
return hash.mac(K, text, macbytes);
} finally {
if(sha256 != null)
SHA256.returnMessageDigest(sha256);
}
}

public static boolean verifyWithSHA256(byte[] K, byte[] text, byte[] mac) {
MessageDigest sha256 = null;
try {
sha256 = SHA256.getMessageDigest();
HMAC_legacy hash = new HMAC_legacy(sha256);
return hash.verify(K, text, mac);
} finally {
if(sha256 != null)
SHA256.returnMessageDigest(sha256);
}
}
}

0 comments on commit b9537f4

Please sign in to comment.