comparison libtomcrypt/notes/etc/NoekeonVects.java @ 1471:6dba84798cd5

Update to libtomcrypt 1.18.1, merged with Dropbear changes
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 21:44:05 +0800
parents
children
comparison
equal deleted inserted replaced
1470:8bba51a55704 1471:6dba84798cd5
1 /*
2 NoekeonVects.java - Generate Noekeon test vectors using BouncyCastle.
3
4 Written in 2011 by Patrick Pelletier <[email protected]>
5
6 To the extent possible under law, the author(s) have dedicated all
7 copyright and related and neighboring rights to this software to
8 the public domain worldwide. This software is distributed without
9 any warranty.
10
11 This file is dedicated to the public domain with the CC0 Public Domain
12 Dedication: http://creativecommons.org/publicdomain/zero/1.0/legalcode.txt
13
14 You may also consider this file to be covered by the WTFPL, as contained
15 in the LibTomCrypt LICENSE file, if that makes you happier for some reason.
16
17 ----------------------------------------------------------------------
18
19 This program was inspired by the comment in Botan 1.10.1's
20 doc/examples/eax_test.cpp:
21
22 // Noekeon: unknown cause, though LTC's lone test vector does not
23 // match Botan
24
25 So, I investigated the discrepancy by comparing them with a third
26 implementation, BouncyCastle: http://www.bouncycastle.org/java.html
27
28 I determined that there are two reasons why LibTomCrypt's Noekeon does
29 not match Botan:
30
31 1) Botan uses "indirect Noekeon" (with a key schedule), while
32 LibTomCrypt and BouncyCastle both use "direct Noekeon" (without
33 a key schedule). See slide 14 of
34 http://gro.noekeon.org/Noekeon-slides.pdf
35
36 2) However, LibTomCrypt's direct Noekeon still does not match
37 BouncyCastle's direct Noekeon. This is because of a bug in
38 LibTomCrypt's PI1 and PI2 functions:
39 https://github.com/libtom/libtomcrypt/issues/5
40
41 This program uses BouncyCastle to produce test vectors which are
42 suitable for Botan (by explicitly scheduling the key, thus
43 building indirect Noekeon out of BouncyCastle's direct Noekeon),
44 and also produces test vectors which would be suitable for
45 LibTomCrypt (direct Noekeon) once its PI1 and PI2 functions are
46 fixed to match the Noekeon specification.
47
48 Although this program uses a PRNG from BouncyCastle to generate
49 data for the test vectors, it uses a fixed seed and thus will
50 produce the same output every time it is run.
51 */
52
53 import java.io.ByteArrayOutputStream;
54 import java.io.IOException;
55 import java.util.Locale;
56 import org.bouncycastle.crypto.digests.RIPEMD128Digest;
57 import org.bouncycastle.crypto.engines.NoekeonEngine;
58 import org.bouncycastle.crypto.modes.EAXBlockCipher;
59 import org.bouncycastle.crypto.params.AEADParameters;
60 import org.bouncycastle.crypto.params.KeyParameter;
61 import org.bouncycastle.crypto.prng.DigestRandomGenerator;
62 import org.bouncycastle.util.encoders.HexEncoder;
63
64 public class NoekeonVects
65 {
66 private final DigestRandomGenerator r =
67 new DigestRandomGenerator(new RIPEMD128Digest());
68
69 private final HexEncoder h = new HexEncoder();
70
71 private final NoekeonEngine noekeon = new NoekeonEngine();
72
73 private final KeyParameter null_key = new KeyParameter(new byte[16]);
74
75 private final boolean schedule_key;
76
77 private final boolean botan_format;
78
79 private byte[] randomBytes(int n)
80 {
81 byte[] b = new byte[n];
82 r.nextBytes(b);
83 return b;
84 }
85
86 private void hexOut(byte[] b) throws IOException
87 {
88 // HexEncoder uses lowercase, and Botan's test vectors must
89 // be in uppercase, so...
90 ByteArrayOutputStream os = new ByteArrayOutputStream();
91 h.encode(b, 0, b.length, os);
92 String s = os.toString("US-ASCII");
93 System.out.print(s.toUpperCase(Locale.US));
94 }
95
96 private void printCArray(byte[] a) throws IOException
97 {
98 byte[] b = new byte[1];
99 for (int i = 0; i < a.length; i++)
100 {
101 if (i > 0)
102 System.out.print(", ");
103 System.out.print("0x");
104 b[0] = a[i];
105 hexOut(b);
106 }
107 }
108
109 private void printVector(byte[] key, byte[] plaintext, byte[] ciphertext)
110 throws IOException
111 {
112 if (botan_format)
113 {
114 hexOut(plaintext);
115 System.out.print(":");
116 hexOut(ciphertext);
117 System.out.println(":\\");
118 hexOut(key);
119 System.out.println();
120 }
121 else
122 {
123 System.out.println(" {");
124 System.out.println(" 16,");
125 System.out.print(" { ");
126 printCArray (key);
127 System.out.println(" },");
128 System.out.print(" { ");
129 printCArray (plaintext);
130 System.out.println(" },");
131 System.out.print(" { ");
132 printCArray (ciphertext);
133 System.out.println(" }");
134 System.out.println(" },");
135 }
136 }
137
138 private KeyParameter maybe_schedule_key(byte[] key)
139 {
140 if (schedule_key)
141 {
142 noekeon.init(true, null_key);
143 byte[] scheduled = new byte[16];
144 noekeon.processBlock(key, 0, scheduled, 0);
145 return new KeyParameter(scheduled);
146 }
147 else
148 return new KeyParameter(key);
149 }
150
151 private byte[] encrypt(byte[] plaintext, byte[] key)
152 {
153 KeyParameter kp = maybe_schedule_key(key);
154 noekeon.init(true, kp);
155 byte[] ciphertext = new byte[16];
156 noekeon.processBlock(plaintext, 0, ciphertext, 0);
157 return ciphertext;
158 }
159
160 public NoekeonVects(long seed, boolean schedule_key, boolean botan_format)
161 {
162 this.schedule_key = schedule_key;
163 this.botan_format = botan_format;
164 r.addSeedMaterial(seed);
165 }
166
167 public void ecb_vectors() throws IOException
168 {
169 for (int i = 0; i < 8; i++)
170 {
171 byte[] key = randomBytes(16);
172 byte[] plaintext = randomBytes(16);
173 byte[] ciphertext = encrypt(plaintext, key);
174 printVector(key, plaintext, ciphertext);
175 }
176 }
177
178 public void eax_vectors() throws Exception
179 {
180 System.out.println("EAX-noekeon (16 byte key)");
181 EAXBlockCipher eax = new EAXBlockCipher(new NoekeonEngine());
182 byte[] output = new byte[48];
183 byte[] tag = new byte[16];
184
185 for (int j = 0; j < 16; j++)
186 tag[j] = (byte) j;
187
188 for (int i = 0; i <= 32; i++)
189 {
190 byte[] header_nonce_plaintext = new byte[i];
191 for (int j = 0; j < i; j++)
192 header_nonce_plaintext[j] = (byte) j;
193 AEADParameters params =
194 new AEADParameters(maybe_schedule_key(tag),
195 128,
196 header_nonce_plaintext,
197 header_nonce_plaintext);
198 eax.init(true, params);
199 int off = eax.processBytes(header_nonce_plaintext, 0, i,
200 output, 0);
201 off += eax.doFinal(output, off);
202 if (off != i + 16)
203 throw new RuntimeException("didn't expect that");
204 byte[] ciphertext = new byte[i];
205 for (int j = 0; j < i; j++)
206 ciphertext[j] = output[j];
207 for (int j = 0; j < 16; j++)
208 tag[j] = output[i + j];
209 System.out.print(i < 10 ? " " : " ");
210 System.out.print(i);
211 System.out.print(": ");
212 hexOut(ciphertext);
213 System.out.print(", ");
214 hexOut(tag);
215 System.out.println();
216 }
217 }
218
219 public static void main(String[] argv) throws Exception
220 {
221 NoekeonVects bot = new NoekeonVects(0xdefacedbadfacadeL, true, true);
222 NoekeonVects tom = new NoekeonVects(0xdefacedbadfacadeL, false, false);
223 System.out.println("# ECB vectors for indirect Noekeon, in Botan's");
224 System.out.println("# test vector format, suitable for insertion");
225 System.out.println("# into Botan's file checks/validate.dat");
226 System.out.println("# Block cipher format is plaintext:ciphertext:key");
227 bot.ecb_vectors();
228 System.out.println();
229 System.out.println("/* ECB vectors for direct Noekeon, as C arrays");
230 System.out.println(" * suitable for insertion into LibTomCrypt's");
231 System.out.println(" * noekeon_test() in src/ciphers/noekeon.c,");
232 System.out.println(" * once LTC's PI1/PI2 bug is fixed. */");
233 tom.ecb_vectors();
234 System.out.println();
235 System.out.println("# EAX vectors for indirect Noekeon, in the format");
236 System.out.println("# generated by LTC's demos/tv_gen.c and consumed");
237 System.out.println("# by Botan's doc/examples/eax_test.cpp, suitable");
238 System.out.println("# for insertion in Botan's doc/examples/eax.vec");
239 bot.eax_vectors();
240 System.out.println();
241 System.out.println("# EAX vectors for direct Noekeon, in the format");
242 System.out.println("# generated by LTC's demos/tv_gen.c and consumed");
243 System.out.println("# by Botan's doc/examples/eax_test.cpp, which");
244 System.out.println("# should match LTC's notes/eax_tv.txt, once");
245 System.out.println("# LTC's PI1/PI2 bug is fixed.");
246 tom.eax_vectors();
247 System.out.flush();
248 }
249 }