(Cryptix Application Note #5 --November 1997)
Table of Contents
Return to the Application Notes Index or the FAQ or the Overview.
Assessing the correctness of a cipher or message digest algorithm implementation involves running the algorithm with a known set of parameter values and checking the results against pre-computed values obtained either manually or with another correct implementation.
The process of writing the test class is a time-consuming one and, most of the time, requires the programmer to use repetitive tasks slightly adapted to the specifics of the algorithm being tested.
The abstract nature of the java implementations of such algorithms and test procedures, inherent to the language being an Object-Oriented one, implies a more abstract method of testing that can save Quality Assurance people as well as programmers time and resources.
This dissociation between the algorithms and the data for their most common test protocols is emphasised by the Sun JCE API and Cryptix's clean-room implementation known as the IJCE (International JCE).
The cryptix.util.test.Maker class is a simple interpreter for a basic data definition language that can be used to test the correctness of cipher algorithm and message digest implementations. In essence instead of having a Test class for each implementation, incorporating the code and the test data, the user invokes Maker with as many test data files as needed or required. The syntax of such data files is simple enough that non-programmers can create them and indeed conduct the tests.
A simple example of a test data input file for Maker follows:
// // MD2 test data // md MD2 data "" <8350E5A3E24C153DF2275C9F80692773> "a" <32EC01EC4A6DAC72C0AB96FB34C0B5D1> "abc" <DA853B0D3F88D99B30283A69E6DED6BB> "message digest" <AB4F496BFB2A530B219FF33031FE06B0> "abcdefghijklmnopqrstuvwxyz" <4E8DDFF3650292AB5A4108C3AA47940B> |
The first three lines are comments. A comment starts with the two characters // and runs until an end-of-line is encountered. Maker ignores all comments. They are defined to allow an additional level of meta-information for use by the users.
A comment need not start at the beginning of a line.
The md keyword tells Maker that the subsequent information is to be used with a java.security.MessageDigest subclass. It is followed by an Identifier that has to match with a message digest algorithm implementation class name, or an alias of the latter. Aliases are defined in the security provider properties file, which for the Cryptix strong cryptographic library is Cryptix.properties found in the cryptix-lib package.
The data keyword tells Maker that the subsequent information is to be interpreted as test data for the algorithm last defined.
The structure of data elements differ depending on whether the algorithm is a MessageDigest (indicated with an md keyword) or a Cipher (indicated with the cipher keyword) one.
For message digest test data are defined as either single-iteration or multi-iteration.
A single iteration is a pair of data formed by a string-literal and a hexadecimal-literal separated by a white space (one or more space, tab, new line or carriage return characters).
The semantics of the single-iteration statement is that Maker has to digest the input string literal and check if the result matches the given hexadecimal literal.
A multi-iteration test data consists of:
Maker will update the message digest object n times using as input the string literal and finally check the result against the designated hexadecimal literal.
Here is an example of a Maker input file using the multi-iteration test data syntax:
// // RIPEMD128 test data // md RIPEMD128 data "" <CDF26213A150DC3ECB610F18F6B38B46> "a" <86BE7AFA339D0FC7CFC785E72F578D33> ... 1000000 * "a" <4A7F5723F954EBA1216C9D8F6320431F> |
A simple Maker input file for testing a cipher implementation follows:
// // CAST5 test data // cipher CAST5 // test #1 data // key input output <0123456712345678234567893456789A> <0123456789ABCDEF> <238B4FE5847E44B2> <01234567123456782345> <0123456789ABCDEF> <EB6A711A2C02271B> <0123456712> <0123456789ABCDEF> <7AC816D16E9B302E> // test #2 data <0123456712> <0123456789ABCDEF> speed |
Similar to md, the cipher keyword tells Maker that the subsequent information is to be used with a java.security.Cipher subclass. It is always followed by an Identifier that has to match with a cipher algorithm implementation class name, or an alias of the latter.
For a cipher object, the data elements can be: two-way test data, symmetric test data or speed test data.
A two-way test data is formed by a triplet of hexadecimal literals to be interpreted as the key, an input value and the certified output value respectively. When Maker recognises a two-way test data statement, it:
The speed keyword indicates a speed test data to be conducted on a cipher implementation. It is the last element of a triplet where the first two are similar to those found in a two-way test data; ie: key and input.
When Maker parses the speed keyword, it runs the cipher 100,000 times updating the same input value and printing both the start and finish date/times. It then decrypts the so far obtained result the same number of times and check if the final result matches the given input, printing along the timing information.
A symmetric test data is a triplet consisting of two hexadecimal literals and the keyword auto. Here is an example:
// // RC2 test data // cipher RC2 data <0123456789abcdef> < 7595C3E6 114A0978 0C4AD452 338E1FFD 9A1BE949 8F813D76 533449B6 778DCAD8 C78A8D2B A9AC6608 5D0E53D5 9C26C2D1 C490C1EB BE0CE66D 1B6B1B13 B6B919B8 47C25A91 447A95E7 5E4EF167 79CDE8BF 0A95850E 32AF9689 444FD377 108F98FD CBD4E726 56750099 0BCC7E0C A3C4AAA3 04A387D2 0F3B8FBB CD42A1BD 311D7A43 03DDA5AB 078896AE 80C18B0A F66DFF31 9616EB78 4E495AD2 CE90D7F7 72A81747 B65F6209 3B1E0DB9 E5BA532F AFEC4750 8323E671 327DF944 4432CB73 67CEC82F 5D44C0D0 0B67D650 A075CD4B 70DEDD77 EB9B1023 1B6B5B74 1347396D 62897421 D43DF9B4 2E446E35 8E9C11A9 B2184ECB EF0CD8E7 A877EF96 8F1390EC 9B3D35A5 585CB009 290E2FCD E7B5EC66 D9084BE4 4055A619 D9DD7FC3 166F9487 F7CB2729 12426445 998514C1 5D53A18C 864CE3A2 B7555793 98812652 0EACF2E3 066E230C 91BEE4DD 5304F5FD 0405B35B D99C7313 5D3D9BC3 35EE049E F69B3867 BF2D7BD1 EAA595D8 BFC0066F F8D31509 EB0C6CAA 006C807A 623EF84C 3D33C195 D23EE320 C40DE055 8157C822 D4B8C569 D849AED5 9D4E0FD7 F379586B 4B7FF684 ED6A189F 7486D49B 9C4BAD9B A24B96AB F924372C 8A8FFFB1 0D553549 00A77A3D B5F205E1 B99FCD86 60863A15 9AD4ABE4 0FA48934 163DDDE5 42A65855 40FD683C BFD8C00F 12129A28 4DEACC4C DEFE58BE 7137541C 047126C8 D49E2755 AB181AB7 E940B0C0 > auto |
When Maker recognises the auto keyword, it encrypts the input value, then decrypts and check if the final result matches the given input.
Symmetric ciphers can be run in different modes of operations, with or without padding. Some modes require initialisation data known as Initialisation Vector or IV. In addition certain algorithms are designed to run in a variable number of rounds and a varying degree of cryptographic strengths.
Maker allows the user to set specific values for these parameters with the properties keyword. Here is a fragment from the SAFER test data file (SAFER.mtest):
properties mode CBC padding NONE iv <74536EBDC211484A> variant = "K-128" rounds = 10 data // key <42431BA40D291F81D66083C605D3A4D6> // input < 00000000 00000000 01020304 05060708 00000000 00000000 01020304 05060708 00010203 04050607 08090A0B 0C0D0E0F 10111213 14151617 18191A1B 1C1D1E1F 20212223 24252627 28292A2B 2C2D2E2F 30313233 34353637 38393A3B 3C3D3E3F |
As you can see, the properties block has to appear before the data block.
Some properties have their own keywords while algorithm-specific ones don't. Algorithm-specific properties are defined using the following syntax:
property-name = property-value
Where property-name is the name of a property known to the cipher implementation and property-value is either a numeric or a string literal. When Maker encounters a statement of the sort, it calls the cipher object with the setParameter() method defined in the cipher object's superclass; ie. jave.security.Cipher.
If the value is invalid or is of the wrong type, the cipher object itself will reject it and Maker will throw an Error and halts.
In the example above, the data implies that the SAFER implementation knows how to handle two properties named: rounds and variant with the first being a numeric while the last is a string.
The mode keyword should be followed by a java.security.Mode subclass class name. It indicates the mode in which the cipher object will be run.
The padding keyword should be followed by a java.security.PaddingScheme subclass class name. It indicates the padding method to apply for the cipher data.
The iv keyword should be followed by a hexadecimal literal. This literal will be used to set the iv for the cipher being tested.
The include keyword should be followed by a string literal. Once Maker recognises this statement it instantiates a new copy of Maker (itself) and runs it using the string literal as the name of the data input file. Here is an example:
// // test include statement of Maker language // include "MDx.mtest" include "RIPEMD1xx.mtest" |
A hexadecimal literal is a sequence of hexadecimal characters enclosed within a pair of angle brackets: <>. Maker removes all white space characters from the enclosed sequence before converting it to a byte array.
Maker is written in JavaCC, the Java equivalent to lex/yacc. The source code is defined in Maker.jj. You can use the already generated java classes or you can recreate them. Here is how:
javacc Maker.jj
java cryptix.util.test.Maker input-file > output-file
The formal syntax of Maker in extended Backus-Naur form, as generated by jjDoc a utility included in the JavaCC package, is available.
Copyright © 1996-1997 Systemics Ltd
on behalf of the Cryptix Development Team.
All rights reserved.
Cryptix is a trademark of Systemics Ltd.