Cryptix logo

A simple test data interpreter

(Cryptix Application Note #5 --November 1997, updated February 1998.)

 Table of Contents

Return to the Application Notes Index or the FAQ.


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 time and resources for Quality Assurance people, as well as programmers.

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.

For more complicated situtations where specialised test code must be written, Maker files can include a Java class, allowing a single framework to be used to test all parts of Cryptix.


Message digest related data definition syntax

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>

Comments

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

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 a JCE standard message digest name, or alias. Aliases are defined in the security provider properties, which for the Cryptix strong cryptographic library are stored in the Cryptix.properties file, found in the cryptix-lib directory.

 

The data keyword for a message digest implementation

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 the md keyword) or a Cipher (indicated with the cipher keyword).

For message digest test data are defined as either single-iteration or multi-iteration.

Message digest single-iteration test data

A single iteration is a pair of data formed by a input string or hexadecimal literal, and an output hexadecimal literal, separated by 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 data (expressed either in hex or as an ASCII string) and check if the result matches the given output data.

Message digest multi-iteration test data

A multi-iteration test data consists of:

  1. Numeric literal, say n,
  2. The symbol "*",
  3. An input string or hexadecimal literal, and finally
  4. An output hexadecimal literal.

Maker will update the message digest object n times using the input data, and finally check the result against the designated output data.

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>


Cipher data definition syntax

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

The cipher keyword

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 a JCE standard cipher name or alias.

 

The data keyword for a cipher implementation

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 literals to be interpreted as the key, an input value and the certified output value respectively. The input value (plaintext) can be expressed either as hexadecimal or an ASCII string; the other values must be expressed in hexadecimal. When Maker recognises a two-way test data statement, it:

  1. initialises the cipher object for encryption using the given key;
  2. encrypts the input and
  3. test the result against the designated output; It then
  4. reinitialises the same cipher with the same key this time for decryption
  5. decrypts the output and
  6. test the result against the designated input.

 

The speed keyword

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; i.e.: 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.

 

The auto keyword

A symmetric test data is a triplet consisting of two literals corresponding to the plaintext and ciphertext, 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.

 

The property and properties keywords

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 with a variable number of rounds and a varying degree of cryptographic strength.

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, string, or hexadecimal literal. When Maker encounters a statement of this sort, it calls the cipher object with the setParameter() method defined in the cipher object's superclass; i.e. java.security.Cipher.

If the value is invalid or is of the wrong type, the cipher object itself will reject it by throwing an exception, and Maker will treat this as an error.

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 Java types that can be passed as algorithm-specific parameters by Maker are java.lang.Integer (for numeric values), java.lang.String (for values expressed as a string), and byte[] (for binary data).

 

The mode keyword

The mode keyword should be followed by the JCE standard name or alias for a java.security.Mode subclass. It indicates the mode in which the cipher object will be run.

 

The padding keyword

The padding keyword should be followed by the JCE standard name or alias for a java.security.PaddingScheme subclass. It indicates the padding method to apply for the cipher data.

 

The iv keyword

The iv keyword should be followed by a hexadecimal literal. This literal will be used to set the initialisation vector for the cipher being tested.


Other syntax-related issues

The include keyword

The include keyword should be followed by either the name of another Maker source file (as a string literal), or a fully qualified class name.

If the name of a file is used, a new copy of Maker is created, and run on that input file. Here is an example:

//
// test include statement of Maker language
//
 
include "MDx.mtest"
include "RIPEMD1xx.mtest"

Starting from Cryptix 3.0.4, included files are looked for relative to the directory of the parent file. For example, if the above source was in the file "Foo.mtest", and was run using:

java cryptix.util.test.Maker some_directory/Foo.mtest
the include statements would look for "some_directory/MDx.mtest" and "some_directory/RIPEMD1xx.mtest". This makes it easier to keep several source files together, that refer to each other using relative paths.

In place of a filename, the name of a Java class can also be specified, without any enclosing quotes. The class must be public, have a public constructor that takes no arguments, and extend cryptix.util.test.BaseTest (a full description of the BaseTest API is beyond the scope of this document; see the source or the Javadoc comments for that class). This feature was also added in Cryptix 3.0.4.

The hexadecimal literal

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.


Generating cryptix.util.test.Maker

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:

  1. If you want to use the existing Java classes skip to step 2, otherwise delete the following Java source files:
    1. ASCII_CharStream.java
    2. Maker.java
    3. MakerConstants.java
    4. MakerTokenManager.java
    5. ParseException.java
    6. Token.java
    7. TokenMgrError.java

  2. Run JavaCC:
    javacc Maker.jj
  3. JavaCC will generate all the files listed in step one above. Compile them with your Java compiler. A few warnings will be echoed pertaining to the fact that the JavaCC code uses deprecated methods. Just make sure there are not errors; just warnings.


Running Maker

Maker can be run either from the command line or programmatically.


Maker syntax in EBNF

The formal syntax of Maker in extended Backus-Naur form, as generated by jjDoc (a utility included in the JavaCC package), is available. (This is the Cryptix 3.0.4 version.)

 


Cryptix
Raif S. Naffah
Chatswood, 13 November 1997.
David Hopwood
Rainhill, 1 February 1998.

Copyright © 1996-1997 Systemics Ltd
on behalf of the Cryptix Development Team.
All rights reserved.
Cryptix is a trademark of Systemics Ltd.