package org.araqne.storage.crypto.impl;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.araqne.storage.crypto.BlockCipher;
import org.araqne.storage.crypto.LogCryptoException;
public class JavaBlockCipher implements BlockCipher {
private String algorithm;
private byte[] cipherKey;
private ThreadLocal<Cipher> c;
private SecretKeySpec cipherKeySpec;
public JavaBlockCipher(String algorithm, byte[] cipherKey) throws LogCryptoException {
this.algorithm = algorithm;
this.cipherKey = cipherKey;
try {
// test if algorithm is available
Cipher.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new LogCryptoException(algorithm, e);
} catch (NoSuchPaddingException e) {
throw new LogCryptoException(algorithm, e);
}
c = new ThreadLocal<Cipher>() {
@Override
protected Cipher initialValue() {
try {
return Cipher.getInstance(JavaBlockCipher.this.algorithm);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
} catch (NoSuchPaddingException e) {
throw new IllegalStateException(e);
}
}
};
cipherKeySpec = new SecretKeySpec(cipherKey, algorithm.split("[/-]")[0]);
}
@Override
public byte[] encrypt(byte[] iv, byte[] input) throws LogCryptoException {
if (cipherKey == null)
throw new IllegalArgumentException("cipher key is not supplied");
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
c.get().init(Cipher.ENCRYPT_MODE, cipherKeySpec, ivSpec);
return c.get().doFinal(input);
} catch (InvalidKeyException e) {
throw new LogCryptoException(algorithm, e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(algorithm, e);
} catch (BadPaddingException e) {
throw new LogCryptoException(algorithm, e);
} catch (InvalidAlgorithmParameterException e) {
throw new LogCryptoException(algorithm, e);
}
}
@Override
public byte[] encrypt(byte[] iv, byte[] input, int offset, int limit)
throws LogCryptoException {
if (cipherKey == null)
throw new IllegalArgumentException("cipher key is not supplied");
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
c.get().init(Cipher.ENCRYPT_MODE, cipherKeySpec, ivSpec);
return c.get().doFinal(input, offset, limit);
} catch (InvalidKeyException e) {
throw new LogCryptoException(algorithm, e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(algorithm, e);
} catch (BadPaddingException e) {
throw new LogCryptoException(algorithm, e);
} catch (InvalidAlgorithmParameterException e) {
throw new LogCryptoException(algorithm, e);
}
}
@Override
public byte[] decrypt(byte[] iv, byte[] input) throws LogCryptoException {
if (cipherKey == null)
throw new IllegalArgumentException("cipher key is not supplied");
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
c.get().init(Cipher.DECRYPT_MODE, cipherKeySpec, ivSpec);
return c.get().doFinal(input);
} catch (InvalidKeyException e) {
throw new LogCryptoException(algorithm, e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(algorithm, e);
} catch (BadPaddingException e) {
throw new LogCryptoException(algorithm, e);
} catch (InvalidAlgorithmParameterException e) {
throw new LogCryptoException(algorithm, e);
}
}
@Override
public byte[] decrypt(byte[] iv, byte[] input, int offset, int limit)
throws LogCryptoException {
if (cipherKey == null)
throw new IllegalArgumentException("cipher key is not supplied");
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
c.get().init(Cipher.DECRYPT_MODE, cipherKeySpec, ivSpec);
return c.get().doFinal(input, offset, limit);
} catch (InvalidKeyException e) {
throw new LogCryptoException(algorithm, e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(algorithm, e);
} catch (BadPaddingException e) {
throw new LogCryptoException(algorithm, e);
} catch (InvalidAlgorithmParameterException e) {
throw new LogCryptoException(algorithm, e);
}
}
}