Package freenet.crypt

Source Code of freenet.crypt.PCFBModeTest

package freenet.crypt;

import java.util.Arrays;

import junit.framework.TestCase;

import freenet.crypt.ciphers.Rijndael;
import freenet.support.HexUtil;
import freenet.support.math.MersenneTwister;

// 256,256 PCFB is the same as 256,256 CFB, however JCA does not support 256-bit block size, so we can't
// test against JCA. We will move to the standard block size, and stop using PCFB, eventually, but we'll
// need PCFB for a while if only for old keys, so we need to test it.
public class PCFBModeTest extends TestCase {

  private MersenneTwister mt = new MersenneTwister(1634);

  // FIXME I don't think there are any standard test vectors?
  byte[] PCFB_256_ENCRYPT_KEY = HexUtil
      .hexToBytes("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
  // FIXME This IV was tailored for CTR mode and 128-bit block, maybe needs adjustement
  byte[] PCFB_256_ENCRYPT_IV = HexUtil
      .hexToBytes("f0f1f2f3f4f5f6f7f8f9fafbfcfdfefff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
  // FIXME This plaintext was tailored for 128-bit block, maybe needs adjustement
  byte[] PCFB_256_ENCRYPT_PLAINTEXT = HexUtil
      .hexToBytes("6bc1bee22e409f96e93d7e117393172a"
          + "ae2d8a571e03ac9c9eb76fac45af8e51"
          + "30c81c46a35ce411e5fbc1191a0a52ef"
          + "f69f2445df4f9b17ad2b417be66c3710");
  byte[] PCFB_256_ENCRYPT_CIPHERTEXT = HexUtil
      .hexToBytes("c964b00326e216214f1a68f5b0872608"
          + "1b403c92fe02898664a81f5bbbbf8341"
          + "fc1d04b2c1addfb826cca1eab6813127"
          + "2751b9d6cd536f78059b10b4867dbbd9");

  byte[] PCFB_256_DECRYPT_KEY = PCFB_256_ENCRYPT_KEY;
  byte[] PCFB_256_DECRYPT_IV = PCFB_256_ENCRYPT_IV;
  byte[] PCFB_256_DECRYPT_PLAINTEXT = PCFB_256_ENCRYPT_PLAINTEXT;
  byte[] PCFB_256_DECRYPT_CIPHERTEXT = PCFB_256_ENCRYPT_CIPHERTEXT;

  public void testKnownValues() throws UnsupportedCipherException {
    // Rijndael(256,256)
    checkKnownValues(256, PCFB_256_ENCRYPT_KEY, PCFB_256_ENCRYPT_IV,
        PCFB_256_ENCRYPT_PLAINTEXT, PCFB_256_ENCRYPT_CIPHERTEXT);
    checkKnownValues(256, PCFB_256_DECRYPT_KEY, PCFB_256_DECRYPT_IV,
        PCFB_256_DECRYPT_PLAINTEXT, PCFB_256_DECRYPT_CIPHERTEXT);
  }

  public void testKnownValuesRandomLength() throws UnsupportedCipherException {
    // Rijndael(256,256)
    checkKnownValuesRandomLength(256, PCFB_256_ENCRYPT_KEY, PCFB_256_ENCRYPT_IV,
        PCFB_256_ENCRYPT_PLAINTEXT, PCFB_256_ENCRYPT_CIPHERTEXT);
    checkKnownValuesRandomLength(256, PCFB_256_DECRYPT_KEY, PCFB_256_DECRYPT_IV,
        PCFB_256_DECRYPT_PLAINTEXT, PCFB_256_DECRYPT_CIPHERTEXT);
  }

  private void checkKnownValues(int bits, byte[] key, byte[] iv, byte[] plaintext,
      byte[] ciphertext) throws UnsupportedCipherException {
    Rijndael cipher = new Rijndael(bits, bits);
    cipher.initialize(key);
    PCFBMode ctr = PCFBMode.create(cipher);
    ctr.reset(iv);
    byte[] output = new byte[plaintext.length];
    System.arraycopy(plaintext, 0, output, 0, plaintext.length);
    //ctr.blockEncipher(plaintext, 0, plaintext.length, output, 0);
    ctr.blockEncipher(output, 0, output.length);
    //System.out.println(HexUtil.bytesToHex(output));
    assertTrue(Arrays.equals(output, ciphertext));
    ctr.reset(iv);
    //ctr.blockDecipher(output, 0, output.length, output, 0);
    ctr.blockDecipher(output, 0, output.length);
    assertTrue(Arrays.equals(output, plaintext));
  }
  private void checkKnownValuesRandomLength(int bits, byte[] key, byte[] iv,
      byte[] plaintext, byte[] ciphertext)
      throws UnsupportedCipherException {
    for (int i = 0; i < 1024; i++) {
      long seed = mt.nextLong();

      Rijndael cipher = new Rijndael(bits, bits);
      cipher.initialize(key);
      PCFBMode ctr = PCFBMode.create(cipher);
      ctr.reset(iv);
      byte[] output = new byte[plaintext.length];
      MersenneTwister random = new MersenneTwister(seed);
      int ptr = 0;
      System.arraycopy(plaintext, 0, output, 0, plaintext.length);
      while (ptr < plaintext.length) {
        int max = plaintext.length - ptr;
        int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
        /*ctr.blockEncipher(plaintext, ptr, count, output, ptr);*/
        ctr.blockEncipher(output, ptr, count);
        ptr += count;
      }
      assertTrue(Arrays.equals(output, ciphertext));
      ctr.reset(iv);
      ptr = 0;
      while (ptr < plaintext.length) {
        int max = plaintext.length - ptr;
        int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
        /*ctr.blockDecipher(output, ptr, count, output, ptr);*/
        ctr.blockDecipher(output, ptr, count);
        ptr += count;
      }
      assertTrue(Arrays.equals(output, plaintext));
    }
  }
 
  public void testRandom() throws UnsupportedCipherException {
    for(int i=0;i<1024;i++) {
      byte[] plaintext = new byte[mt.nextInt(4096)+1];
      byte[] key = new byte[32];
      byte[] iv = new byte[32];
      mt.nextBytes(plaintext);
      mt.nextBytes(key);
      mt.nextBytes(iv);
      // First encrypt as a block.
      Rijndael cipher = new Rijndael(256, 256);
      cipher.initialize(key);
      PCFBMode ctr = PCFBMode.create(cipher);
      ctr.reset(iv);
      byte[] ciphertext = new byte[plaintext.length];
      System.arraycopy(plaintext, 0, ciphertext, 0, ciphertext.length);
      //ctr.blockEncipher(plaintext, 0, plaintext.length, ciphertext, 0);
      ctr.blockEncipher(ciphertext, 0, ciphertext.length);
      // Now decrypt.
      ctr = PCFBMode.create(cipher);
      ctr.reset(iv);
      byte[] finalPlaintext = new byte[plaintext.length];
      System.arraycopy(ciphertext, 0, finalPlaintext, 0, ciphertext.length);
      //ctr.blockDecipher(ciphertext, 0, ciphertext.length, finalPlaintext, 0);
      ctr.blockDecipher(finalPlaintext, 0, finalPlaintext.length);
      assertTrue(Arrays.equals(finalPlaintext, plaintext));

      // Now encrypt again, in random pieces.
      cipher.initialize(key);
      ctr = PCFBMode.create(cipher);
      ctr.reset(iv);
      byte[] output = new byte[plaintext.length];

      MersenneTwister random = new MersenneTwister(mt.nextLong());
      int ptr = 0;
      System.arraycopy(plaintext, 0, output, 0, plaintext.length);
      while (ptr < plaintext.length) {
        int max = plaintext.length - ptr;
        int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
        //ctr.blockEncipher(plaintext, ptr, count, output, ptr);
        ctr.blockEncipher(output, ptr, count);
        ptr += count;
      }
      assertTrue(Arrays.equals(output, ciphertext));
      // ... and decrypt again, in random pieces.
      ptr = 0;
      ctr.reset(iv);
      while (ptr < plaintext.length) {
        int max = plaintext.length - ptr;
        int count = (max == 1) ? 1 : (random.nextInt(max - 1) + 1);
        //ctr.blockDecipher(output, ptr, count, output, ptr);
        ctr.blockDecipher(output, ptr, count);
        ptr += count;
      }
      assertTrue(Arrays.equals(output, plaintext));
     
    }
  }

}
TOP

Related Classes of freenet.crypt.PCFBModeTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.