summaryrefslogtreecommitdiffhomepage
path: root/libtomcrypt/notes/etc/NoekeonVects.java
diff options
context:
space:
mode:
Diffstat (limited to 'libtomcrypt/notes/etc/NoekeonVects.java')
-rw-r--r--libtomcrypt/notes/etc/NoekeonVects.java249
1 files changed, 249 insertions, 0 deletions
diff --git a/libtomcrypt/notes/etc/NoekeonVects.java b/libtomcrypt/notes/etc/NoekeonVects.java
new file mode 100644
index 0000000..8ec542a
--- /dev/null
+++ b/libtomcrypt/notes/etc/NoekeonVects.java
@@ -0,0 +1,249 @@
+/*
+ NoekeonVects.java - Generate Noekeon test vectors using BouncyCastle.
+
+ Written in 2011 by Patrick Pelletier <code@funwithsoftware.org>
+
+ To the extent possible under law, the author(s) have dedicated all
+ copyright and related and neighboring rights to this software to
+ the public domain worldwide. This software is distributed without
+ any warranty.
+
+ This file is dedicated to the public domain with the CC0 Public Domain
+ Dedication: http://creativecommons.org/publicdomain/zero/1.0/legalcode.txt
+
+ You may also consider this file to be covered by the WTFPL, as contained
+ in the LibTomCrypt LICENSE file, if that makes you happier for some reason.
+
+ ----------------------------------------------------------------------
+
+ This program was inspired by the comment in Botan 1.10.1's
+ doc/examples/eax_test.cpp:
+
+ // Noekeon: unknown cause, though LTC's lone test vector does not
+ // match Botan
+
+ So, I investigated the discrepancy by comparing them with a third
+ implementation, BouncyCastle: http://www.bouncycastle.org/java.html
+
+ I determined that there are two reasons why LibTomCrypt's Noekeon does
+ not match Botan:
+
+ 1) Botan uses "indirect Noekeon" (with a key schedule), while
+ LibTomCrypt and BouncyCastle both use "direct Noekeon" (without
+ a key schedule). See slide 14 of
+ http://gro.noekeon.org/Noekeon-slides.pdf
+
+ 2) However, LibTomCrypt's direct Noekeon still does not match
+ BouncyCastle's direct Noekeon. This is because of a bug in
+ LibTomCrypt's PI1 and PI2 functions:
+ https://github.com/libtom/libtomcrypt/issues/5
+
+ This program uses BouncyCastle to produce test vectors which are
+ suitable for Botan (by explicitly scheduling the key, thus
+ building indirect Noekeon out of BouncyCastle's direct Noekeon),
+ and also produces test vectors which would be suitable for
+ LibTomCrypt (direct Noekeon) once its PI1 and PI2 functions are
+ fixed to match the Noekeon specification.
+
+ Although this program uses a PRNG from BouncyCastle to generate
+ data for the test vectors, it uses a fixed seed and thus will
+ produce the same output every time it is run.
+*/
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Locale;
+import org.bouncycastle.crypto.digests.RIPEMD128Digest;
+import org.bouncycastle.crypto.engines.NoekeonEngine;
+import org.bouncycastle.crypto.modes.EAXBlockCipher;
+import org.bouncycastle.crypto.params.AEADParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.prng.DigestRandomGenerator;
+import org.bouncycastle.util.encoders.HexEncoder;
+
+public class NoekeonVects
+{
+ private final DigestRandomGenerator r =
+ new DigestRandomGenerator(new RIPEMD128Digest());
+
+ private final HexEncoder h = new HexEncoder();
+
+ private final NoekeonEngine noekeon = new NoekeonEngine();
+
+ private final KeyParameter null_key = new KeyParameter(new byte[16]);
+
+ private final boolean schedule_key;
+
+ private final boolean botan_format;
+
+ private byte[] randomBytes(int n)
+ {
+ byte[] b = new byte[n];
+ r.nextBytes(b);
+ return b;
+ }
+
+ private void hexOut(byte[] b) throws IOException
+ {
+ // HexEncoder uses lowercase, and Botan's test vectors must
+ // be in uppercase, so...
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ h.encode(b, 0, b.length, os);
+ String s = os.toString("US-ASCII");
+ System.out.print(s.toUpperCase(Locale.US));
+ }
+
+ private void printCArray(byte[] a) throws IOException
+ {
+ byte[] b = new byte[1];
+ for (int i = 0; i < a.length; i++)
+ {
+ if (i > 0)
+ System.out.print(", ");
+ System.out.print("0x");
+ b[0] = a[i];
+ hexOut(b);
+ }
+ }
+
+ private void printVector(byte[] key, byte[] plaintext, byte[] ciphertext)
+ throws IOException
+ {
+ if (botan_format)
+ {
+ hexOut(plaintext);
+ System.out.print(":");
+ hexOut(ciphertext);
+ System.out.println(":\\");
+ hexOut(key);
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(" {");
+ System.out.println(" 16,");
+ System.out.print(" { ");
+ printCArray (key);
+ System.out.println(" },");
+ System.out.print(" { ");
+ printCArray (plaintext);
+ System.out.println(" },");
+ System.out.print(" { ");
+ printCArray (ciphertext);
+ System.out.println(" }");
+ System.out.println(" },");
+ }
+ }
+
+ private KeyParameter maybe_schedule_key(byte[] key)
+ {
+ if (schedule_key)
+ {
+ noekeon.init(true, null_key);
+ byte[] scheduled = new byte[16];
+ noekeon.processBlock(key, 0, scheduled, 0);
+ return new KeyParameter(scheduled);
+ }
+ else
+ return new KeyParameter(key);
+ }
+
+ private byte[] encrypt(byte[] plaintext, byte[] key)
+ {
+ KeyParameter kp = maybe_schedule_key(key);
+ noekeon.init(true, kp);
+ byte[] ciphertext = new byte[16];
+ noekeon.processBlock(plaintext, 0, ciphertext, 0);
+ return ciphertext;
+ }
+
+ public NoekeonVects(long seed, boolean schedule_key, boolean botan_format)
+ {
+ this.schedule_key = schedule_key;
+ this.botan_format = botan_format;
+ r.addSeedMaterial(seed);
+ }
+
+ public void ecb_vectors() throws IOException
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ byte[] key = randomBytes(16);
+ byte[] plaintext = randomBytes(16);
+ byte[] ciphertext = encrypt(plaintext, key);
+ printVector(key, plaintext, ciphertext);
+ }
+ }
+
+ public void eax_vectors() throws Exception
+ {
+ System.out.println("EAX-noekeon (16 byte key)");
+ EAXBlockCipher eax = new EAXBlockCipher(new NoekeonEngine());
+ byte[] output = new byte[48];
+ byte[] tag = new byte[16];
+
+ for (int j = 0; j < 16; j++)
+ tag[j] = (byte) j;
+
+ for (int i = 0; i <= 32; i++)
+ {
+ byte[] header_nonce_plaintext = new byte[i];
+ for (int j = 0; j < i; j++)
+ header_nonce_plaintext[j] = (byte) j;
+ AEADParameters params =
+ new AEADParameters(maybe_schedule_key(tag),
+ 128,
+ header_nonce_plaintext,
+ header_nonce_plaintext);
+ eax.init(true, params);
+ int off = eax.processBytes(header_nonce_plaintext, 0, i,
+ output, 0);
+ off += eax.doFinal(output, off);
+ if (off != i + 16)
+ throw new RuntimeException("didn't expect that");
+ byte[] ciphertext = new byte[i];
+ for (int j = 0; j < i; j++)
+ ciphertext[j] = output[j];
+ for (int j = 0; j < 16; j++)
+ tag[j] = output[i + j];
+ System.out.print(i < 10 ? " " : " ");
+ System.out.print(i);
+ System.out.print(": ");
+ hexOut(ciphertext);
+ System.out.print(", ");
+ hexOut(tag);
+ System.out.println();
+ }
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ NoekeonVects bot = new NoekeonVects(0xdefacedbadfacadeL, true, true);
+ NoekeonVects tom = new NoekeonVects(0xdefacedbadfacadeL, false, false);
+ System.out.println("# ECB vectors for indirect Noekeon, in Botan's");
+ System.out.println("# test vector format, suitable for insertion");
+ System.out.println("# into Botan's file checks/validate.dat");
+ System.out.println("# Block cipher format is plaintext:ciphertext:key");
+ bot.ecb_vectors();
+ System.out.println();
+ System.out.println("/* ECB vectors for direct Noekeon, as C arrays");
+ System.out.println(" * suitable for insertion into LibTomCrypt's");
+ System.out.println(" * noekeon_test() in src/ciphers/noekeon.c,");
+ System.out.println(" * once LTC's PI1/PI2 bug is fixed. */");
+ tom.ecb_vectors();
+ System.out.println();
+ System.out.println("# EAX vectors for indirect Noekeon, in the format");
+ System.out.println("# generated by LTC's demos/tv_gen.c and consumed");
+ System.out.println("# by Botan's doc/examples/eax_test.cpp, suitable");
+ System.out.println("# for insertion in Botan's doc/examples/eax.vec");
+ bot.eax_vectors();
+ System.out.println();
+ System.out.println("# EAX vectors for direct Noekeon, in the format");
+ System.out.println("# generated by LTC's demos/tv_gen.c and consumed");
+ System.out.println("# by Botan's doc/examples/eax_test.cpp, which");
+ System.out.println("# should match LTC's notes/eax_tv.txt, once");
+ System.out.println("# LTC's PI1/PI2 bug is fixed.");
+ tom.eax_vectors();
+ System.out.flush();
+ }
+}