package tr.gov.titck.recete.encryptor;

import java.security.SecureRandom;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import tr.gov.titck.recete.encryptor.Utils.ByteUtils;

class RenkliAes
{
  private final KEYSIZE keysize;
  private static final int IV_LENGTH = 16;
  
  public static enum KEYSIZE
  {
    AES_256(256);
    
    int value;
    
    private KEYSIZE(int value)
    {
      this.value = value;
    }
    
    public int getKeySize()
    {
      return value;
    }
  }
  





  private KeyParameter aes_key = null;
  
  RenkliAes()
  {
    keysize = KEYSIZE.AES_256;
  }
  
  private PaddedBufferedBlockCipher getCipher(byte[] iv)
  {
    ParametersWithIV ivKeyParam = new ParametersWithIV(aes_key, iv);
    org.bouncycastle.crypto.paddings.BlockCipherPadding padding = new PKCS7Padding();
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), padding);
    cipher.reset();
    cipher.init(true, ivKeyParam);
    
    return cipher;
  }
  
  byte[] encode(byte[] data) throws InvalidCipherTextException
  {
    byte[] iv = new byte[16];
    SecureRandom secure = new SecureRandom();
    secure.nextBytes(iv);
    PaddedBufferedBlockCipher cipher = getCipher(iv);
    
    int outSize = cipher.getOutputSize(data.length);
    byte[] enc = new byte[outSize];
    
    int length1 = cipher.processBytes(data, 0, data.length, enc, 0);
    cipher.doFinal(enc, length1);
    
    return ByteUtils.concatenate(iv, enc);
  }
  
  void generateKey(char[] password, byte[] salt)
  {
    PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator();
    
    byte[] passwordBytes = PKCS5S2ParametersGenerator.PKCS5PasswordToUTF8Bytes(password);
    generator.init(passwordBytes, salt, 20000);
    aes_key = ((KeyParameter)generator.generateDerivedParameters(keysize.getKeySize()));
  }
  
  byte[] getAesKey()
  {
    return aes_key.getKey();
  }
}
