package com.dgrid.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Encryption {
public static final String RSA = "RSA";
public static final String RSA_PADDED = "RSA/NONE/OAEPWithSHA1AndMGF1Padding";
public static final String DSA = "DSA";
public static final String DES = "DES";
public static final String DES_PADDED = "DES/ECB/PKCS5Padding";
public static final String DH = "DH";
public static final String SHA1withRSA = "SHA1withRSA";
public static final int DEFAULT_KEY_SIZE = 1024;
public static final int PRIVATE = 0;
public static final int PUBLIC = 1;
private static final String pbeCipherName = "PBEWithMD5AndDES";
private static Log log = LogFactory.getLog(Encryption.class);
private static SecureRandom secureRandom = null;
static {
try {
secureRandom = initSecureRandom();
} catch (Exception e) {
log.error("Exception initializing encryption provider", e);
}
}
public static KeyPair generateKeyPair(String algorithm, int keySize)
throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
kpg.initialize(keySize, secureRandom);
KeyPair kp = kpg.generateKeyPair();
return (kp);
}
public static Key generateSecretKey(String algorithm)
throws NoSuchAlgorithmException {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
Key secret = kg.generateKey();
return secret;
}
public static byte[] sign(byte[] data, PrivateKey privateKey,
String algorithm) throws RuntimeException {
try {
Signature sig = Signature.getInstance(algorithm);
sig.initSign(privateKey);
sig.update(data);
return sig.sign();
} catch (Exception e) {
log.error("Exception in sign()", e);
throw new RuntimeException(e);
}
}
public static String signString(String data, PrivateKey privateKey,
String algorithm) throws RuntimeException {
byte[] sigBytes = sign(data.getBytes(), privateKey, algorithm);
return new String(Base64Encoder.base64Encode(sigBytes));
}
public static boolean verify(byte[] data, PublicKey publicKey,
String algorithm, byte[] signature) throws RuntimeException {
try {
Signature sig = Signature.getInstance(algorithm);
sig.initVerify(publicKey);
sig.update(data);
return sig.verify(signature);
} catch (Exception e) {
log.error("Exception in verify()", e);
throw new RuntimeException(e);
}
}
public static boolean verifyBase64(String data, PublicKey publicKey,
String algorithm, String signatureBase64) throws RuntimeException {
byte[] sig = Base64Encoder.base64Decode(signatureBase64.getBytes());
byte[] dataBytes = data.getBytes();
return verify(dataBytes, publicKey, algorithm, sig);
}
public static String encryptStringBase64(String plaintext,
String algorithm, Key publicKey) throws RuntimeException {
byte[] bytes = encryptString(plaintext, algorithm, publicKey);
byte[] encoded = Base64Encoder.base64Encode(bytes);
return (new String(encoded));
}
public static byte[] encryptString(String plaintext, String algorithm,
Key publicKey) throws RuntimeException {
try {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] input = plaintext.getBytes();
byte[] encryptedBytes = cipher.doFinal(input);
return encryptedBytes;
} catch (GeneralSecurityException e) {
log.error("GeneralSecurityException in encryptString()", e);
throw new RuntimeException(e);
}
}
public static String decryptStringBase64(String ciphertext,
String algorithm, Key privKey) throws RuntimeException {
try {
byte[] bytes = ciphertext.getBytes();
byte[] decoded = Base64Encoder.base64Decode(bytes);
String value = decryptString(decoded, algorithm, privKey);
return value;
} catch (Exception e) {
log.error("Exception in encryptString()", e);
throw new RuntimeException(e);
}
}
public static String decryptString(byte[] ciphertext, String algorithm,
Key privKey) throws RuntimeException {
try {
Cipher cipher = Cipher.getInstance(algorithm, "BC");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decryptedBytes = cipher.doFinal(ciphertext);
return new String(decryptedBytes);
} catch (Exception e) {
log.error("Exception in encryptString()", e);
throw new RuntimeException(e);
}
}
public static Key getKey(byte[] keyData, String keyType,
boolean isPrivateKey) throws RuntimeException {
log.trace("getKey()");
try {
// keyType should be RSA
KeyFactory kf = KeyFactory.getInstance(keyType);
Key key = null;
if (isPrivateKey) {
PKCS8EncodedKeySpec encodedPrivateKey = new PKCS8EncodedKeySpec(
keyData);
key = kf.generatePrivate(encodedPrivateKey);
} else {
X509EncodedKeySpec encodedPublicKey = new X509EncodedKeySpec(
keyData);
key = kf.generatePublic(encodedPublicKey);
}
return key;
} catch (Exception e) {
log.error("Exception in encryptString()", e);
throw new RuntimeException(e);
}
}
public static Key getSecretKey(String algorithm, byte[] keyData)
throws Exception {
log.trace("getSecretKey()");
SecretKeySpec keySpec = new SecretKeySpec(keyData, algorithm);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
return keyFactory.generateSecret(keySpec);
}
private static SecureRandom initSecureRandom()
throws NoSuchAlgorithmException, NoSuchProviderException,
FileNotFoundException, IOException {
log.trace("initSecureRandom()");
Security
.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
if (new File("/dev/urandom").exists()) {
log.info("Salting SecureRandom (SHA1PRNG) from /dev/urandom");
byte[] salt = new byte[8192];
FileInputStream fis = new FileInputStream("/dev/urandom");
fis.read(salt);
fis.close();
sr.setSeed(salt);
}
return sr;
}
}