#

# A simple test data interpreter

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

Table of Contents

- Overview
- Message digest data definition syntax
  - Comments
  - The md keyword
  - The data keyword for a message digest implementation
    - Message digest single-iteration test data
    - Message digest multi-iteration test data
- Cipher data definition syntax
  - The cipher keyword
  - The data keyword for a cipher implementation
  - The speed keyword
  - The auto keyword
  - The property and properties keywords
  - The mode keyword
  - The padding keyword
  - The iv keyword
- Other syntax-related issues
  - The include keyword
  - The hexadecimal literal
- Generating cryptix.util.test.Maker
- Running Maker
- Maker syntax in EBNF

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.

- From the command line:

  >     java cryptix.util.test.Maker inputfile [> output] [options...]
  >     java cryptix.util.test.Maker [< input] [> output] [options...]

  >     Options:
  >         -verbose: print output even if all tests pass.

  In Cryptix 3.0.4 and later, Maker will not display complete output unless one or more tests fail. The -verbose option can be used to override this behaviour. Cryptix 3.0.3 and earlier act as if -verbose is always set.

- From a Java program (Cryptix 3.0.4 and later):

  >     import cryptix.util.test.Maker;

  >     InputStream is = getInputFileStream();
  >     Maker maker = new Maker(is);
  >     maker.run();

  Alternatively, more control can be obtained by using the following method:

  >     /**
  >      * Runs an instance of Maker.
  >      *
  >      * @param  options      an array of string options.
  >      * @param  name         a name for this test.
  >      * @param  includeDir   the directory that filenames of include files
  >      *                      are considered relative to. This may be null,
  >      *                      indicating the current directory.
  >      * @param  out          a PrintWriter to direct output to.
  >      * @exception cryptix.util.test.TestException if the test fails.
  >      * @since Cryptix 3.0.4
  >      */
  >     public void run(String[] options, String name, File includeDir, PrintWriter out)
  >     throws TestException { ... }

###

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.)

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