Mercurial > dropbear
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 } |