All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gnu.crypto.tool.NistMCT Maven / Gradle / Ivy

The newest version!
package gnu.crypto.tool;

// ----------------------------------------------------------------------------
// $Id: NistMCT.java,v 1.8 2003/09/27 00:01:27 raif Exp $
//
// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
//
// This file is part of GNU Crypto.
//
// GNU Crypto is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// GNU Crypto is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to the
//
//    Free Software Foundation Inc.,
//    59 Temple Place - Suite 330,
//    Boston, MA 02111-1307
//    USA
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library.  Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give
// you permission to link this library with independent modules to
// produce an executable, regardless of the license terms of these
// independent modules, and to copy and distribute the resulting
// executable under terms of your choice, provided that you also meet,
// for each linked independent module, the terms and conditions of the
// license of that module.  An independent module is a module which is
// not derived from or based on this library.  If you modify this
// library, you may extend this exception to your version of the
// library, but you are not obligated to do so.  If you do not wish to
// do so, delete this exception statement from your version.
// ----------------------------------------------------------------------------

import gnu.crypto.cipher.CipherFactory;
import gnu.crypto.cipher.IBlockCipher;
import gnu.crypto.util.Util;
import java.security.InvalidKeyException;
import java.util.Arrays;
import java.util.HashMap;

/**
 * 

For a designated symmetric block cipher algorithm, this command generates * and exercises Monte Carlo Tests data for both Encryption and Decryption in * Electronic Codebook (ECB) and Cipher Block Chaining (CBC) modes.

* *

NistMCT's output file format is in conformance with the layout described * in Section 4 of NIST's document "Description of Known Answer Tests and Monte * Carlo Tests for Advanced Encryption Standard (AES) Candidate Algorithm * Submissions" dated January 7, 1998.

* *

References:

*
    *
  1. Known * Answer Test (KAT) and Monte Carlo Test (MCT) Information
  2. *
* * @version $Revision: 1.8 $ */ public class NistMCT { // Constants and variables // ------------------------------------------------------------------------- private String cipherName; private int keySize; // in bits private IBlockCipher cipher; // statistics fields private long encBlocks; // total count of encrypted blocks private long decBlocks; // total count of decrypted blocks private long keyCount; // total count of key creation requests // Constructor(s) // ------------------------------------------------------------------------- /** Trivial 0-arguments constructor to enforce usage through main(). */ private NistMCT(String cipherName, IBlockCipher cipher, int keySize) { super(); this.cipherName = cipherName; this.cipher = cipher; this.keySize = keySize; } // Class methods // ------------------------------------------------------------------------- /** *

The main entry point for the tool.

* *
    * Usage:
    *    gnu.crypto.tool.NistKat (options) cipher [key-size]
    *
    * Where:
    *    cipher
    *       The canonical name of the cipher algorithm.
    *    key-size
    *       The key-size in bits to use for the algorithm.  If unspecified,
    *       then the three NIST key-sizes 128, 192 and 256 shall be used.
    *
    * Options:
    *    -E | -C | -A
    *       Generate Monte Carlo Test (MCT) data for ECB mode only, CBC mode
    *       only, or both.  For backward compatibility, if this option is
    *       unspecified, then -A (both modes) is activated.
    *    -e | -d | -a
    *       Generate Monte Carlo Test (MCT) data for a designated cipher in
    *       the selected mode(s), for Encryption only, Decryption only, or
    *       both.  For backward compatibility, if this option is unspecified,
    *       then -a (both states) is activated.
    *    -h
    *       Print this help page.
    * 
*/ public static void main (String[] args) { if (args == null || args.length == 0) { printUsage(); return; } try { // set defaults boolean doECB = false; // set to true if -E or -A is specified boolean doCBC = false; // set to true if -C or -A is specified boolean doEnc = false; // set to true if -e or -a is specified boolean doDec = false; // set to true if -d or -a is specified String cipherName = null; String kSize = null; // parse arguments for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.startsWith("-")) { // an option String option = arg.substring(1); if (option.equals("E")) { // ECB ON doECB = true; continue; } if (option.equals("C")) { // CBC ON doCBC = true; continue; } if (option.equals("A")) { // both ON doECB = true; doCBC = true; continue; } if (option.equals("e")) { // encryption ON doEnc = true; continue; } if (option.equals("d")) { // decryption ON doDec = true; continue; } if (option.equals("a")) { // both ON doEnc = true; doDec = true; continue; } if (option.equals("h")) { printUsage(); continue; } } if (cipherName == null) { cipherName = args[i].trim(); continue; } if (kSize == null) { kSize = args[i].trim(); break; // ignore anything after this } } // validity checks if (!doECB && !doCBC) { // for backward compatibility turn'em ON doECB = true; doCBC = true; } if (!doEnc && !doDec) { // for backward compatibility turn'em ON doEnc = true; doDec = true; } if (cipherName == null || cipherName.equals("")) { System.err.println("Missing cipher name..."); printUsage(); return; } IBlockCipher cipher = CipherFactory.getInstance(cipherName); long time = -System.currentTimeMillis(); NistMCT[] cmd; if (kSize == null || kSize.equals("")) { cmd = new NistMCT[] { new NistMCT(cipherName, cipher, 128), new NistMCT(cipherName, cipher, 192), new NistMCT(cipherName, cipher, 256) }; } else { cmd = new NistMCT[] { new NistMCT(cipherName, cipher, Integer.parseInt(kSize)) }; } int i; if (doECB) { if (doEnc) { // print preamble System.out.println(); System.out.println("========================="); System.out.println(); System.out.println("Electronic Codebook (ECB) Mode - ENCRYPTION"); System.out.println("Monte Carlo Test"); System.out.println(); System.out.println("Algorithm Name: "+String.valueOf(cipherName)); System.out.println(); System.out.println("=========="); for (i = 0; i < cmd.length; i++) { cmd[i].ecbEncrypt(); } } if (doDec) { // print preamble System.out.println(); System.out.println("========================="); System.out.println(); System.out.println("Electronic Codebook (ECB) Mode - DECRYPTION"); System.out.println("Monte Carlo Test"); System.out.println(); System.out.println("Algorithm Name: "+String.valueOf(cipherName)); System.out.println(); System.out.println("=========="); for (i = 0; i < cmd.length; i++) { cmd[i].ecbDecrypt(); } } } if (doCBC) { if (doEnc) { // print preamble System.out.println(); System.out.println("========================="); System.out.println(); System.out.println("Cipher Block Chaining (CBC) Mode - ENCRYPTION"); System.out.println("Monte Carlo Test"); System.out.println(); System.out.println("Algorithm Name: "+String.valueOf(cipherName)); System.out.println(); System.out.println("=========="); for (i = 0; i < cmd.length; i++) { cmd[i].cbcEncrypt(); } } if (doDec) { // print preamble System.out.println(); System.out.println("========================="); System.out.println(); System.out.println("Cipher Block Chaining (CBC) Mode - DECRYPTION"); System.out.println("Monte Carlo Test"); System.out.println(); System.out.println("Algorithm Name: "+String.valueOf(cipherName)); System.out.println(); System.out.println("=========="); for (i = 0; i < cmd.length; i++) { cmd[i].cbcDecrypt(); } } } time += System.currentTimeMillis(); long encryptions = 0L; long decryptions = 0L; long keySetups = 0L; for (i = 0; i < cmd.length; i++) { encryptions += cmd[i].encBlocks; decryptions += cmd[i].decBlocks; keySetups += cmd[i].keyCount; } // print postamble System.out.println(); System.out.println("Total execution time (ms): "+String.valueOf(time)); System.out.println("During this time, "+String.valueOf(cipherName)+ ":"); System.out.println(" Encrypted "+String.valueOf(encryptions)+" blocks"); System.out.println(" Decrypted "+String.valueOf(decryptions)+" blocks"); System.out.println(" Created "+String.valueOf(keySetups)+" session keys"); } catch (Exception x) { x.printStackTrace(System.err); } } /** Prints a simple help page to System.err. */ private static final void printUsage() { System.err.println(); System.err.println("Usage:"); System.err.println(" gnu.crypto.tool.NistKat (options) cipher [key-size]"); System.err.println(); System.err.println("Where:"); System.err.println(" cipher"); System.err.println(" The canonical name of the cipher algorithm."); System.err.println(" key-size"); System.err.println(" The key-size in bits to use for the algorithm. If unspecified,"); System.err.println(" then the three NIST key-sizes 128, 192 and 256 shall be used."); System.err.println(); System.err.println("Options:"); System.err.println(" -E | -C | -A"); System.err.println(" Generate Monte Carlo Test (MCT) data for ECB mode only, CBC mode"); System.err.println(" only, or both. For backward compatibility, if this option is "); System.err.println(" unspecified, then -A (both modes) is activated."); System.err.println(" -e | -d | -a"); System.err.println(" Generate Monte Carlo Test (MCT) data for a designated cipher in"); System.err.println(" the selected mode(s), for Encryption only, Decryption only, or"); System.err.println(" both. For backward compatibility, if this option is unspecified,"); System.err.println(" then -a (both states) is activated."); System.err.println(" -h"); System.err.println(" Print this help page."); System.err.println(); } // Instance methods // ------------------------------------------------------------------------- // private void ecb() throws InvalidKeyException { // ecbEncrypt(); // ecbDecrypt(); // } private void ecbEncrypt() throws InvalidKeyException { int keylen = keySize / 8; // number of bytes in user key byte[] keyMaterial = new byte[keylen]; int size = cipher.defaultBlockSize(); // cipher block size in bytes byte[] pt = new byte[size]; // plaintext byte[] cpt = new byte[size]; // computed plaintext byte[] ct = new byte[size]; // ciphertext @round 9999 byte[] ct_1 = new byte[size]; // ciphertext @round 9998 int j, k, count; // temp vars System.out.println(); System.out.println("KEYSIZE="+String.valueOf(keySize)); System.out.println(); // step 1. will use all zeroes. HashMap map = new HashMap(); for (int i = 0; i < 400; i++) { // step 2 // Encryption System.out.println("I="+String.valueOf(i)); // step 2.a System.out.println("KEY="+Util.toString(keyMaterial)); System.out.println("PT="+Util.toString(pt)); map.put(IBlockCipher.KEY_MATERIAL, keyMaterial); cipher.init(map); keyCount++; cipher.encryptBlock(pt, 0, ct_1, 0); // step 2.b encBlocks++; for (j = 1; j < 9999; j++) { cipher.encryptBlock(ct_1, 0, ct_1, 0); encBlocks++; } cipher.encryptBlock(ct_1, 0, ct, 0); encBlocks++; System.out.println("CT="+Util.toString(ct)); // step 2.c // Decryption cipher.decryptBlock(ct, 0, cpt, 0); // step 2.b decBlocks++; for (j = 1; j < 10000; j++) { cipher.decryptBlock(cpt, 0, cpt, 0); decBlocks++; } if (!Arrays.equals(pt, cpt)) { // check if results match System.out.println(" *** ERROR ***"); throw new RuntimeException("ECB Encryption/Decryption mismatch"); } System.out.println(); cipher.reset(); // may throw ArrayIndexOutOfBoundsException with non-AES ciphers; ie. // those for which: keylen < size || keylen > 2*size j = 0; // step 2.d if (keylen > size) { count = keylen - size; k = size - count; while (j < count) { keyMaterial[j++] ^= ct_1[k++]; } } k = 0; while (j < keylen) { keyMaterial[j++] ^= ct[k++]; } System.arraycopy(ct, 0, pt, 0, size); // step 2.e } System.out.println("=========="); } void ecbDecrypt() throws InvalidKeyException { int keylen = keySize / 8; // number of bytes in user key byte[] keyMaterial = new byte[keylen]; int size = cipher.defaultBlockSize(); // cipher block size in bytes byte[] pt = new byte[size]; // plaintext byte[] cpt = new byte[size]; // computed plaintext byte[] ct = new byte[size]; // ciphertext @round 9999 byte[] ct_1 = new byte[size]; // ciphertext @round 9998 int j, k, count; // temp vars System.out.println(); System.out.println("KEYSIZE="+String.valueOf(keySize)); System.out.println(); // step 1. will use all zeroes. HashMap map = new HashMap(); for (int i = 0; i < 400; i++) { // step 2 map.put(IBlockCipher.KEY_MATERIAL, keyMaterial); cipher.init(map); keyCount++; // Encryption cipher.encryptBlock(pt, 0, ct_1, 0); // step 2.b encBlocks++; for (j = 1; j < 9999; j++) { cipher.encryptBlock(ct_1, 0, ct_1, 0); encBlocks++; } cipher.encryptBlock(ct_1, 0, ct, 0); encBlocks++; // Decryption System.out.println("I="+String.valueOf(i)); // step 2.a System.out.println("KEY="+Util.toString(keyMaterial)); System.out.println("CT="+Util.toString(ct)); cipher.decryptBlock(ct, 0, cpt, 0); // step 2.b decBlocks++; for (j = 1; j < 10000; j++) { cipher.decryptBlock(cpt, 0, cpt, 0); decBlocks++; } System.out.println("PT="+Util.toString(cpt)); // step 2.c if (!Arrays.equals(pt, cpt)) { // check if results match System.out.println(" *** ERROR ***"); throw new RuntimeException("ECB Encryption/Decryption mismatch"); } System.out.println(); cipher.reset(); // may throw ArrayIndexOutOfBoundsException with non-AES ciphers; ie. // those for which: keylen < size || keylen > 2*size j = 0; // step 2.d if (keylen > size) { count = keylen - size; k = size - count; while (j < count) { keyMaterial[j++] ^= ct_1[k++]; } } k = 0; while (j < keylen) { keyMaterial[j++] ^= ct[k++]; } System.arraycopy(ct, 0, pt, 0, size); // step 2.e (both) } System.out.println("=========="); } void cbc() throws InvalidKeyException { cbcEncrypt(); cbcDecrypt(); } void cbcEncrypt() throws InvalidKeyException { int keylen = keySize / 8; // number of bytes in user key material byte[] keyMaterial = new byte[keylen]; int size = cipher.defaultBlockSize(); // cipher block size in bytes byte[] pt = new byte[size]; // plaintext byte[] ct = new byte[size]; // ciphertext byte[] iv = new byte[size]; // initialization vector int j, k, count; // temp vars System.out.println(); System.out.println("KEYSIZE="+String.valueOf(keySize)); System.out.println(); HashMap map = new HashMap(); for (int i = 0; i < 400; i++) { // step 2 // step 2.a is implicit since we're handling cv as iv System.out.println("I="+String.valueOf(i)); // step 2.b System.out.println("KEY="+Util.toString(keyMaterial)); System.out.println("IV="+Util.toString(iv)); System.out.println("PT="+Util.toString(pt)); map.put(IBlockCipher.KEY_MATERIAL, keyMaterial); cipher.init(map); keyCount++; for (j = 0; j < 10000; j++) { // step 2.c for (k = 0; k < size; k++) { iv[k] ^= pt[k]; // step 2.c.i } System.arraycopy(ct, 0, pt, 0, size); // copy ct@(j-1) into pt cipher.encryptBlock(iv, 0, ct, 0); // step 2.c.ii encBlocks++; System.arraycopy(ct, 0, iv, 0, size); // set new iv/cv } System.out.println("CT="+Util.toString(ct)); // step 2.d System.out.println(); cipher.reset(); // may throw ArrayIndexOutOfBoundsException with non-AES ciphers; ie. // those for which: keylen < size || keylen > 2*size // remember: we keep ct@(j-1) values in pt... j = 0; // step 2.e if (keylen > size) { count = keylen - size; k = size - count; while (j < count) { keyMaterial[j++] ^= pt[k++]; } } k = 0; while (j < keylen) { keyMaterial[j++] ^= ct[k++]; } } System.out.println("=========="); } void cbcDecrypt() throws InvalidKeyException { int keylen = keySize / 8; // number of bytes in user key material byte[] keyMaterial = new byte[keylen]; int size = cipher.defaultBlockSize(); // cipher block size in bytes byte[] pt = new byte[size]; // plaintext byte[] ct = new byte[size]; // ciphertext byte[] iv = new byte[size]; // initialization vector int j, k, count; // temp vars System.out.println(); System.out.println("KEYSIZE="+String.valueOf(keySize)); System.out.println(); // step 1. use all-zeroes values HashMap map = new HashMap(); for (int i = 0; i < 400; i++) { // step 2 // step 2.a is implicit since we're handling cv as iv System.out.println("I="+String.valueOf(i)); // step 2.b System.out.println("KEY="+Util.toString(keyMaterial)); System.out.println("IV="+Util.toString(iv)); System.out.println("CT="+Util.toString(ct)); map.put(IBlockCipher.KEY_MATERIAL, keyMaterial); cipher.init(map); keyCount++; for (j = 0; j < 10000; j++) { // step 2.c cipher.decryptBlock(ct, 0, pt, 0); // steps 2.c.i + 2.c.ii decBlocks++; for (k = 0; k < size; k++) pt[k] ^= iv[k]; // step 2.c.iii System.arraycopy(ct, 0, iv, 0, size); // step 2.c.iv System.arraycopy(pt, 0, ct, 0, size); } System.out.println("PT="+Util.toString(pt)); // step 2.d System.out.println(); cipher.reset(); // may throw ArrayIndexOutOfBoundsException with non-AES ciphers; ie. // those for which: keylen < size || keylen > 2*size // remember: iv contains values of pt@(j-1) j = 0; // step 2.e if (keylen > size) { count = keylen - size; k = size - count; while (j < count) { keyMaterial[j++] ^= iv[k++]; } } k = 0; while (j < keylen) { keyMaterial[j++] ^= pt[k++]; } } System.out.println("=========="); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy