package org.araqne.storage.crypto.impl;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.araqne.storage.crypto.LogCryptoException;
import org.araqne.storage.crypto.PkiCipher;
public class JavaPkiCipher implements PkiCipher {
private PublicKey publicKey;
private PrivateKey privateKey;
private ThreadLocal<Cipher> rsa;
public JavaPkiCipher(PublicKey publicKey) throws LogCryptoException {
this(publicKey, null);
}
public JavaPkiCipher(PublicKey publicKey, PrivateKey privateKey) throws LogCryptoException {
this.publicKey = publicKey;
this.privateKey = privateKey;
try {
// test if algorithm is available
Cipher.getInstance(JavaPkiCipher.this.publicKey.getAlgorithm());
} catch (NoSuchAlgorithmException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
} catch (NoSuchPaddingException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
}
rsa = new ThreadLocal<Cipher>() {
@Override
protected Cipher initialValue() {
try {
return Cipher.getInstance(JavaPkiCipher.this.publicKey.getAlgorithm());
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
} catch (NoSuchPaddingException e) {
throw new IllegalStateException(e);
}
}
};
}
@Override
public byte[] encrypt(byte[] input) throws LogCryptoException {
if (publicKey == null)
throw new IllegalArgumentException("public key is not supplied");
try {
rsa.get().init(Cipher.ENCRYPT_MODE, publicKey);
return rsa.get().doFinal(input);
} catch (InvalidKeyException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
} catch (BadPaddingException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
}
}
@Override
public byte[] encrypt(byte[] input, int offset, int limit) throws LogCryptoException {
if (publicKey == null)
throw new IllegalArgumentException("public key is not supplied");
try {
rsa.get().init(Cipher.ENCRYPT_MODE, publicKey);
return rsa.get().doFinal(input, offset, limit);
} catch (InvalidKeyException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
} catch (BadPaddingException e) {
throw new LogCryptoException(getKeyInfo(publicKey), e);
}
}
@Override
public byte[] decrypt(byte[] input) throws LogCryptoException {
if (privateKey == null)
throw new IllegalArgumentException("private key is not supplied");
try {
rsa.get().init(Cipher.DECRYPT_MODE, privateKey);
return rsa.get().doFinal(input);
} catch (InvalidKeyException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
} catch (BadPaddingException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
}
}
private String getKeyInfo(Key key) {
String algorithm = key.getAlgorithm();
String format = key.getFormat();
return algorithm + ", " + format;
}
@Override
public byte[] decrypt(byte[] input, int offset, int limit) throws LogCryptoException {
if (privateKey == null)
throw new IllegalArgumentException("private key is not supplied");
try {
rsa.get().init(Cipher.DECRYPT_MODE, privateKey);
return rsa.get().doFinal(input, offset, limit);
} catch (InvalidKeyException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
} catch (IllegalBlockSizeException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
} catch (BadPaddingException e) {
throw new LogCryptoException(getKeyInfo(privateKey), e);
}
}
}