Package com.subgraph.orchid.crypto

Source Code of com.subgraph.orchid.crypto.TorStreamCipher

package com.subgraph.orchid.crypto;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.subgraph.orchid.TorException;

public class TorStreamCipher {
  public static final int KEY_LEN = 16;
 
  public static TorStreamCipher createWithRandomKey() {
    final SecretKey randomKey = generateRandomKey();
    return new TorStreamCipher(randomKey.getEncoded());
  }
 
  public static TorStreamCipher createFromKeyBytes(byte[] keyBytes) {
    return new TorStreamCipher(keyBytes);
  }
 
  public static TorStreamCipher createFromKeyBytesWithIV(byte[] keyBytes, byte[] iv) {
    return new TorStreamCipher(keyBytes, iv);
  }

  private static final int BLOCK_SIZE = 16;
  private final Cipher cipher;
  private final byte[] counter;
  private final byte[] counterOut;
  /* Next byte of keystream in counterOut */
  private int keystreamPointer = -1;
  private final SecretKeySpec key;
 
 
  private TorStreamCipher(byte[] keyBytes) {
    this(keyBytes, null);
  }
 
  private TorStreamCipher(byte[] keyBytes, byte[] iv) {
    key = keyBytesToSecretKey(keyBytes);
    cipher = createCipher(key);
    counter = new byte[BLOCK_SIZE];
    counterOut = new byte[BLOCK_SIZE];
   
    if(iv != null) {
      applyIV(iv);
    }
  }
 
  private void applyIV(byte[] iv) {
    if(iv.length != BLOCK_SIZE) {
      throw new IllegalArgumentException();
    }
    System.arraycopy(iv, 0, counter, 0, BLOCK_SIZE);
  }
 
  public void encrypt(byte[] data) {
    encrypt(data, 0, data.length);
  }
 
  public synchronized void encrypt(byte[] data, int offset, int length) {
    for(int i = 0; i < length; i++)
      data[i + offset] ^= nextKeystreamByte();
  }
 
  public byte[] getKeyBytes() {
    return key.getEncoded();
  }
 
  private static SecretKeySpec keyBytesToSecretKey(byte[] keyBytes) {
    return new SecretKeySpec(keyBytes, "AES");
  }
 
  private static Cipher createCipher(SecretKeySpec keySpec) {
    try {
      final Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, keySpec);
      return cipher;
    } catch (GeneralSecurityException e) {
      throw new TorException(e);
    }
  }
 
  private static SecretKey generateRandomKey() {
    try {
      KeyGenerator generator = KeyGenerator.getInstance("AES");
      generator.init(128);
      return generator.generateKey();
    } catch (GeneralSecurityException e) {
      throw new TorException(e);
    }
  }
 
  private byte nextKeystreamByte() {
    if(keystreamPointer == -1 || (keystreamPointer >= BLOCK_SIZE))
      updateCounter();
    return counterOut[keystreamPointer++];
  }
  private void updateCounter() {
    encryptCounter();
    incrementCounter();
    keystreamPointer = 0;
  }
 
  private void encryptCounter() {
    try {
      cipher.doFinal(counter, 0, BLOCK_SIZE, counterOut, 0);
    } catch (GeneralSecurityException e) {
      throw new TorException(e);
    }
  }
 
  private void incrementCounter() {
    int carry = 1;
    for(int i = counter.length - 1; i >= 0; i--) {
      int x = (counter[i] & 0xff) + carry;
      if(x > 0xff)
        carry = 1;
      else
        carry = 0;
      counter[i] = (byte)x;
    }
  }

}
TOP

Related Classes of com.subgraph.orchid.crypto.TorStreamCipher

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.