package no.ntnu.item.cryptoutil;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Cryptoutil {
// Hashing
public static final String HASH_ALGORITHM = "SHA-256";
public static final int HASH_LENGTH = 256;
// Symmetric Cipher
public static final String SYM_CIPHER = "AES";
public static final String SYM_PADDING = "PKCS5Padding"; // TODO
public static final String SYM_MODE = "CBC";
public static final int SYM_SIZE = 128;
public static final int SYM_BLOCK_SIZE = 128;
// Asymmetric Cipher
public static final String ASYM_CIPHER = "RSA";
public static final int ASYM_SIZE = 1024;
// Signatures
public static final String SIGN_ALG = "SHA256withRSA";
// HMAC
public static final String HMAC_ALG = "HmacSHA256";
/**
* Hash the input with the configured hash algorithm
*
* @param input
* @param truncate_to
* @return
*/
public static byte[] hash(byte[] input, int truncate_to) {
byte result[] = null;
try {
MessageDigest md = MessageDigest
.getInstance(Cryptoutil.HASH_ALGORITHM);
md.update(input);
result = md.digest();
md.reset();
md.update(result);
result = md.digest();
} catch (NoSuchAlgorithmException e) {
// Should already be tested
}
if (truncate_to > 0 && truncate_to != result.length) {
byte[] tmp = new byte[truncate_to];
System.arraycopy(result, 0, tmp, 0, truncate_to);
result = tmp;
}
return result;
}
public static byte[] singlehash(byte[] input, int truncate_to) {
byte result[] = null;
try {
MessageDigest md = MessageDigest
.getInstance(Cryptoutil.HASH_ALGORITHM);
md.update(input);
result = md.digest();
} catch (NoSuchAlgorithmException e) {
// Should already be tested
}
if (truncate_to > 0) {
byte[] tmp = new byte[truncate_to];
System.arraycopy(result, 0, tmp, 0, truncate_to);
result = tmp;
}
return result;
}
/**
* Hash the input n number of times, output is truncated on each iteration
*
* @param input
* @param n
* @param truncate_to
* @return
*/
public static byte[] nHash(byte[] input, int n, int truncate_to) {
if (n < 1) {
return null;
}
byte[] result = input;
for (int i = 0; i < n; i++) {
result = hash(result, truncate_to);
}
return result;
}
/**
* Generate a Symmetric key used for encryption
*
* @return
*/
public static SecretKey generateSymmetricKey() {
try {
KeyGenerator keygen = KeyGenerator
.getInstance(Cryptoutil.SYM_CIPHER);
keygen.init(Cryptoutil.SYM_SIZE);
return keygen.generateKey();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* Generate a asymmetric key pair.
*
* @return
*/
public static KeyPair generateAsymmetricKeys() {
KeyPairGenerator keygen;
try {
keygen = KeyPairGenerator.getInstance(Cryptoutil.ASYM_CIPHER);
keygen.initialize(Cryptoutil.ASYM_SIZE);
return keygen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] symEncrypt(byte[] plainText, SecretKey key,
IvParameterSpec iv) {
try {
Cipher cipher = Cipher.getInstance(Cryptoutil.SYM_CIPHER + "/"
+ Cryptoutil.SYM_MODE + "/" + Cryptoutil.SYM_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
return cipher.doFinal(plainText);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] symECBEncrypt(byte[] plainText, SecretKey key) {
try {
Cipher cipher = Cipher.getInstance(Cryptoutil.SYM_CIPHER + "/"
+ "ECB" + "/" + Cryptoutil.SYM_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plainText);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] symECBDecrypt(byte[] cipherText, SecretKey key) {
try {
Cipher cipher = Cipher.getInstance(Cryptoutil.SYM_CIPHER + "/"
+ "ECB" + "/" + Cryptoutil.SYM_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherText);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] symDecrypt(byte[] cipherText, SecretKey key,
IvParameterSpec iv) {
try {
Cipher cipher = Cipher.getInstance(Cryptoutil.SYM_CIPHER + "/"
+ Cryptoutil.SYM_MODE + "/" + Cryptoutil.SYM_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(cipherText);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] generateIV() {
try {
Cipher cip = Cipher.getInstance(Cryptoutil.SYM_CIPHER + "/"
+ Cryptoutil.SYM_MODE + "/" + Cryptoutil.SYM_PADDING);
cip.init(Cipher.ENCRYPT_MODE, generateSymmetricKey());
return cip.getIV();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] signature(byte[] data, PrivateKey privateKey) {
try {
Signature sign = Signature.getInstance(SIGN_ALG);
sign.initSign(privateKey);
sign.update(data);
return sign.sign();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static boolean signature_valid(byte[] signature, byte[] data,
PublicKey pubKey) {
try {
Signature sign = Signature.getInstance(SIGN_ALG);
sign.initVerify(pubKey);
sign.update(data);
return sign.verify(signature);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public static byte[] hmac(byte[] msg, byte[] key) {
try {
Mac mac = Mac.getInstance(HMAC_ALG);
SecretKeySpec sks = new SecretKeySpec(key, Cryptoutil.SYM_CIPHER);
mac.init(sks);
return mac.doFinal(msg);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] serializePublicKey(RSAPublicKey pubKey) {
byte[] mod = pubKey.getModulus().toByteArray();
byte[] pubexp = pubKey.getPublicExponent().toByteArray();
byte[] all = new byte[mod.length + pubexp.length];
System.arraycopy(mod, 0, all, 0, mod.length);
System.arraycopy(pubexp, 0, all, mod.length, pubexp.length);
return all;
}
public static PublicKey createRSAPublicKey(byte key[]) {
// First comes modulus (129), then comes public exponent (3)
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
byte[] mod = new byte[Cryptoutil.ASYM_SIZE / 8 + 1];
byte[] publicK = new byte[3];
System.arraycopy(key, 0, mod, 0, mod.length);
System.arraycopy(key, mod.length, publicK, 0, publicK.length);
BigInteger modulus = new BigInteger(1, mod);
BigInteger publicExponent = new BigInteger(1, publicK);
RSAPublicKeySpec pubks = new RSAPublicKeySpec(modulus,
publicExponent);
return fact.generatePublic(pubks);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] serializePrivateKey(RSAPrivateKey privKey) {
byte[] mod = privKey.getModulus().toByteArray();
byte[] privexp = privKey.getPrivateExponent().toByteArray();
if (privexp.length == Cryptoutil.ASYM_SIZE / 8 + 1) {
byte[] tmp = new byte[privexp.length - 1];
System.arraycopy(privexp, 1, tmp, 0, tmp.length);
privexp = tmp;
}
byte[] all = new byte[mod.length + privexp.length];
System.arraycopy(mod, 0, all, 0, mod.length);
System.arraycopy(privexp, 0, all, mod.length, privexp.length);
return all;
}
public static PrivateKey createRSAPrivateKey(byte key[]) {
// First comes modulus , then comes public exponent (3)
try {
KeyFactory fact = KeyFactory.getInstance("RSA");
byte[] mod = new byte[Cryptoutil.ASYM_SIZE / 8 + 1];
byte[] privexpK = new byte[Cryptoutil.ASYM_SIZE / 8];
System.arraycopy(key, 0, mod, 0, mod.length);
System.arraycopy(key, mod.length, privexpK, 0, privexpK.length);
BigInteger modulus = new BigInteger(1, mod);
BigInteger privateExponent = new BigInteger(1, privexpK);
RSAPrivateKeySpec privKs = new RSAPrivateKeySpec(modulus,
privateExponent);
return fact.generatePrivate(privKs);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}