I am trying to decrypt using initialization vector and key at client side, but the GWT is not able to recognize it, I added crypto library but still it is not supported. How can I use initialization vector to make encryption and decryption more secure.
At server side i am able to encrypt but at client side i am not able to decrypt..
KeyGenerator and IvParameterSpec is not supported by GWT
private String encryptDES(String sessionKey) throws Exception {
KeyGenerator keygenerator = KeyGenerator.getInstance("DESede");
SecretKey myKey = keygenerator.generateKey();
SecureRandom sr = new SecureRandom();
byte [] iv = new byte[8];
sr.nextBytes(iv);
IvParameterSpec IV = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, myKey, IV);
String encrypted = Base64.encode(cipher.doFinal(sessionKey.getBytes()));
return encrypted;
}
please help me resolving it
Write a wrapper around cryptoJS
Should be less than 100 lines of code.
Inject for example aes from crypto.js
String url = GWT.getModuleBaseForStaticFiles() + "js/aes.js";
ScriptInjector.fromUrl(url).setWindow(ScriptInjector.TOP_WINDOW).inject();
Encrypt
/**
* Encrypt the given String with the given key.
*
* #param s The String to encrypt
* #param cipher The cipher
* #return The encrypted String
*/
public static native String encrypt(String s, String cipher)
/*-{
var key = $wnd.CryptoJS.enc.Utf8.parse(cipher);
var iv = $wnd.CryptoJS.enc.Utf8.parse(cipher);
var encrypted = $wnd.CryptoJS.AES.encrypt($wnd.CryptoJS.enc.Utf8.parse(s), key,
{
keySize: 128 / 8,
iv: iv,
mode: $wnd.CryptoJS.mode.CBC,
padding: $wnd.CryptoJS.pad.Pkcs7
});
return encrypted;
}-*/;
Decrypt
/**
* Decrypt the given String with the given key.
*
* #param s The String to decrypt
* #param cipher The key
* #return The decrypted String
*/
public static native String decrypt(String s, String cipher)
/*-{
var key = $wnd.CryptoJS.enc.Utf8.parse(cipher);
var iv = $wnd.CryptoJS.enc.Utf8.parse(cipher);
var decrypted = $wnd.CryptoJS.AES.decrypt(s, key,
{
keySize: 128 / 8,
iv: iv,
mode: $wnd.CryptoJS.mode.CBC,
padding: $wnd.CryptoJS.pad.Pkcs7
});
return decrypted.toString($wnd.CryptoJS.enc.Utf8);
}-*/;
Related
I am trying to change JAVA Encryption to PHP and produce exactly the same result.
I have the following guidelines.
AES ‐ CBC with PKCS5 Padding Symmetric Encryption Scheme:
Encryption key size would be of 128 bit size.
Initialization Vector (IV) :
-New Random IV would be used in each request.
-In a single web‐service request, same IV would be used while encrypting all the encrypted fields.
-This IV would be passed in SOAP Header with name as “IV”. IV value would be Base64 encoded.
I have tried this https://gist.github.com/thomasdarimont/fae409eaae2abcf83bd6633b961e7f00
public class AESEncryptionUtil {
public static final String CLASS_NAME = AESEncryptionUtil.class.getName(); private static final int KEY_SIZE = 16;
private static final String ALGORITHM_AES = "AES";
public final static String ALGORITHM_AES_CBC = "AES/CBC/PKCS5Padding";
private static Key generateKey(String keyValue) throws Exception { Key key = null ;
if (keyValue!=null && keyValue.length()==KEY_SIZE){
byte[] byteKey = keyValue.substring(0, KEY_SIZE).getBytes("UTF-8");
key = new SecretKeySpec(byteKey, ALGORITHM_AES);
}else{
System.out.println("Not generating the Key!! "+keyValue); }
return key;
}
/**
* Return Base64 Encoded value of IV *
* #param keyValue * #return
* #throws Exception */
public static String generateIV(String keyValue) throws Exception { String iv = null ;
Key key = generateKey(keyValue); if (key!=null){
Cipher cipher = Cipher.getInstance(ALGORITHM_AES_CBC); cipher.init(Cipher.ENCRYPT_MODE, key); AlgorithmParameters params = cipher.getParameters();
iv = new BASE64Encoder().encode(params.getParameterSpec(IvParameterSpec.class).getIV());
}else{
System.out.println("No IV generated ...");
}
return iv; }
/**
* Method to perform encryption of given data with AES Algorithm / Key and IV. * #param encKey -
*Encryption Key value * #param plainVal -
*Value to be encrypted * #return - encrypted String Value * #throws Exception
*/
public static String encrypt(String encKey, String plainVal, String currentIV) throws Exception {
String encryptedText = null ; Key key = generateKey(encKey);
if (key!=null && currentIV!=null && plainVal!=null){
Cipher c = Cipher.getInstance(ALGORITHM_AES_CBC);
c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(new BASE64Decoder().decodeBuffer(currentIV)));
byte[] encValue = c.doFinal(plainVal.getBytes()); encryptedText= new BASE64Encoder().encode(encValue);
}else{
System.out.println("Invalid input passed to encrypt !! keyValue="+encKey+", IV="+currentIV+", valueToEnc="+plainVal);
}
return encryptedText; }
}
I managed to get something to work
<?php
$string = "online1234";
$key = "haskingvista127$";
$iv = base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc')));
$encodedEncryptedData = base64_encode(openssl_encrypt($string, "AES-128-CBC", $key, OPENSSL_RAW_DATA, base64_decode($iv)));
$decryptedData = openssl_decrypt(base64_decode($encodedEncryptedData), "AES-128-CBC", $key, OPENSSL_RAW_DATA, base64_decode($iv));
?>
Hope this might help someone else
I ran the Trible DES Encryption in Java, with null IV (I have run cipher.getIV() method and indeed it's IV is null) and the same string ran the Triple DES Encryption in PHP with null IV, but I get a different result. Why is that?
Java Code:
private static final String model = "DESede/ECB/PKCS5Padding";
public static String desEncrypt(String message, String key) throws Exception {
byte[] keyBytes = null;
if(key.length() == 16){
keyBytes = newInstance8Key(ByteUtil.convertHexString(key));
} else if(key.length() == 32){
keyBytes = newInstance16Key(ByteUtil.convertHexString(key));
} else if(key.length() == 48){
keyBytes = newInstance24Key(ByteUtil.convertHexString(key));
}
SecretKey deskey = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance(model);
cipher.init(1, deskey);
return ByteUtil.toHexString(cipher.doFinal(message.getBytes("UTF-8")));
}
PHP Code:
// composer require phpseclib/phpseclib
use phpseclib\Crypt\TripleDES;
function desEncrypt($str,$key){
$cipher = new TripleDES();
$cipher->setKey(hex2bin($key));
$cryptText = $cipher->encrypt($str);
return unpack("H*",$cryptText)[1];
}
I want to modify my PHP code to fit the Java Encryption Process,how should I do? where is the proplem?
Java Encrypt Result:
before: 622700300000
key: 0123456789ABCDEFFEDCBA98765432100123456789ABCDEF
after: c9aa8ebfcc12ce13e22a33b05d4c18cf
PHP Encrypt Result:
before: 622700300000
key: 0123456789ABCDEFFEDCBA98765432100123456789ABCDEF
after: a6e7a000d4ce79ac8b3db9f6acf73de3
Fixed PHP Code:
/**
* Triple DES (ECB) Encryption Function
* PKCS5Padding
*
* #param string $message String needed to be encode
* #param string $key Hex encoded key
* #return string Hex Encoded
*/
function desEncrypt($message,$key){
$cipher = new TripleDES(TripleDES::MODE_ECB);
$cipher->setKey(hex2bin($key));
$cryptText = $cipher->encrypt($message);
return bin2hex($cryptText);
}
You forgot to hex decode the key before using it. You're also using CBC mode instead of ECB mode, but as your IV is all zero's, that amounts to the same thing for the first block of data that is encrypted.
I'm trying to code encryption and decryption methods that will encrypt/decrypt a message.
In the encrypt method, it will take in a string. It will read in a public key and be used in a RSA cipher. Then, the message will be encrypted with an AES Cipher that has a AES Key and IV. Then, a HMAC tag will be generated with the ciphertext encrypted AES by using a HMAC key. The AES Key and HMAC key are concatenated together and encrypted by RSA Cipher. The method will return a JSONObject that contains: RSA ciphertext, AES ciphertext, the AES IV, and HMAC tag. They are byte arrays that are converted into hex strings.
In the decrypt method, it will take in the JSON Object, which will be parsed. It will read in a private key that will be used in a RSA cipher. The RSA cipher will be used to decrypt the concatenated keys. Once decrypted the keys will be separated to AES Key and HMAC key. Then, new HMAC tag will be generated on the AES Ciphertext. Compare the tag from the encryption and the new tag. If they are equal, then decrypt the AES ciphertext and get the message.
When I run my code, there are no errors, but it does not decrypt because the 2 tags don't match. I don't know why.
The public and private keys are .der files that were converted from .pem files.
Please help me. Thanks!
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.json.*;
import javax.xml.bind.DatatypeConverter;
public class CryptographicTools
{
/**
* This method encrypts a message
* #param message String message to be encrypted
* #return a JSONObject
*/
public JSONObject encryptMessage(String message)
{
JSONObject output = new JSONObject(); // instantiate JSONObject
try
{
//read in public key
byte[] publicKeyBytes = readKeyFromFile("public.der");//pem convert to der
//turn bytes into public key
X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(publicKeyBytes); //encodes the bytes
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); //make the key a RSA instance
//initialize RSA object and public key
Cipher RSAObject = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); //with OAEP
RSAObject.init(Cipher.ENCRYPT_MODE, keyFactory.generatePublic(publicSpec)); //create RSA encryption cipher with a generated public key
//generate 256-bit AES key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");//generate AES Key
keyGen.init(256); //generate a key with 256 bits
SecretKey AESKey = keyGen.generateKey(); //generate AES key with 256 bits
//Create AES IV
SecureRandom randomByteGenerator = new SecureRandom();//secure generator to generate random byes for IV
byte[] AESKeyIVArray = new byte[16];
randomByteGenerator.nextBytes(AESKeyIVArray);//get random bytes for iv
IvParameterSpec AES_IV = new IvParameterSpec(AESKeyIVArray); //iv object for AES object
//initialize AES object
Cipher AESObject = Cipher.getInstance("AES/CBC/PKCS5Padding");
AESObject.init(Cipher.ENCRYPT_MODE, AESKey, AES_IV); //tell the AES object to encrypt
//encrypt message with AES
byte[] AESciphertext = AESObject.doFinal(message.getBytes());
//generate 256-bit HMAC key
byte[] SHA256KeyArray = new byte[32];//256 bits
randomByteGenerator.nextBytes(SHA256KeyArray);//generate random bits for key
SecretKeySpec HMACKeySpec = new SecretKeySpec (SHA256KeyArray,"HmacSHA256"); //make the key
Mac HMAC = Mac.getInstance("HmacSHA256"); //initialize HMAC
HMAC.init(HMACKeySpec);//put key in cipher
byte [] HMACTag = HMAC.doFinal(AESciphertext);//generate HMAC tag
//concatenate AES and HMAC keys
byte[] AESKeyByte = AESKey.getEncoded();///turn AESKey to byte array
byte[] HMACKeySpecByte = HMACKeySpec.getEncoded();///turn HMAXKey to byte array
byte[] concatenatedKeys = new byte[AESKeyByte.length + HMACKeySpecByte.length];//new array for concatenated keys
//combine keys in new array
System.arraycopy(AESKeyByte, 0, concatenatedKeys, 0, AESKeyByte.length);
System.arraycopy(HMACKeySpecByte, 0, concatenatedKeys, AESKeyByte.length, HMACKeySpecByte.length);
//encrypt keys with RSA object
byte[] RSAciphertext = RSAObject.doFinal(concatenatedKeys);
//put RSA ciphertext, AES ciphertext, AES_IV and HMAC tag in JSon
//save byte[] as Strings in hex
output.put("RSAciphertext", DatatypeConverter.printHexBinary(RSAciphertext));
output.put("AESciphertext", DatatypeConverter.printHexBinary(AESciphertext));
output.put("AES_IV", DatatypeConverter.printHexBinary(AES_IV.getIV()));
output.put("HMACTag", DatatypeConverter.printHexBinary(HMACTag));
}
catch (Exception e)
{
System.out.println("Error: " + e.toString() +e.getMessage()); //error message
}
return output; //return as JSON Object
}
/**
* This method decrypts a message
* #param jsonObjectEncrypted
* #return message as string
*/
public String decrypt (JSONObject jsonObjectEncrypted)
{
String message="";
try
{
//recover RSA ciphertext from JSON
String RSACiphertextString=jsonObjectEncrypted.getString("RSAciphertext");
byte[] recoveredRSAciphertext = DatatypeConverter.parseHexBinary(RSACiphertextString); //convert hex string to byte array
//recover AES ciphertext from JSON
String AESCiphertextString=jsonObjectEncrypted.getString("AESciphertext");
byte[] recoveredAESciphertext = DatatypeConverter.parseHexBinary(AESCiphertextString); //convert hex string to byte array
//recover AES IV from JSON
String AES_IVString=jsonObjectEncrypted.get("AES_IV").toString();
byte[] recoveredAES_IV = DatatypeConverter.parseHexBinary(AES_IVString); //convert hex string to byte array
//recover HMACTag from JSON
String HMACTagString=jsonObjectEncrypted.getString("HMACTag");
byte[] recoveredHMACTag = DatatypeConverter.parseHexBinary(HMACTagString); //convert hex string to byte array
//read in private key
byte[] privateKeyBytes = readKeyFromFile("private.der");//pem convert to der
//turn bytes into private key
PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//initialize RSA object and private key
Cipher RSAObject = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); //with OAEP
RSAObject.init(Cipher.DECRYPT_MODE, keyFactory.generatePrivate(privateSpec)); //create RSA encryption cipher with a generated private key
//Decrypt concatenated keys with RSA object
byte[] concatenatedKeys = RSAObject.doFinal(recoveredRSAciphertext);
//split the concatenated keys
byte[] AESKey = new byte[concatenatedKeys.length/2];
byte[] HMACKey = new byte[concatenatedKeys.length/2];
System.arraycopy(concatenatedKeys, 0,AESKey,0,AESKey.length); //Copy half into AESKey
System.arraycopy(concatenatedKeys, AESKey.length,HMACKey,0,HMACKey.length); //Copy Other half into HMACKey
//generate HMACTag
SecretKeySpec HMACKeySpec = new SecretKeySpec (HMACKey,"HmacSHA256"); //make the key
Mac HMAC = Mac.getInstance("HmacSHA256");
HMAC.init(HMACKeySpec);//initialize with HMAC Key
byte [] newHMACTag = HMAC.doFinal(recoveredAESciphertext); //generate HMACTag with AES Ciphertext
if(recoveredHMACTag.equals(newHMACTag)) //encrypt message if tags are equal
{
//initialize AES object
Cipher AESObject = Cipher.getInstance("AES/CBC/PKCS5Padding");
AESObject.init(Cipher.DECRYPT_MODE, new SecretKeySpec (AESKey,"AES"), new IvParameterSpec(recoveredAES_IV)); //tell the AES object to encrypt
message = new String (AESObject.doFinal(recoveredAESciphertext), "US-ASCII");//encrypt AES ciphertext and save as string
}
else
{
System.out.println("Message cannot be decrypted.");
}
}
catch (Exception e)
{
System.out.println("Error: "+e.toString()+": "+e.getMessage()); //error message
}
return message; //return plaintext
}
/**
* This method reads bytes of a key from a file into a byte array
* #param fileName type of key
* #return byte array
* #throws IOException
*/
public byte[] readKeyFromFile(String fileName) throws IOException
{
return Files.readAllBytes(Paths.get(fileName));
}
}
The Java array doesn't implement .equals() the way you'd want it to (info). Try replacing this check:
recoveredHMACTag.equals(newHMACTag)
by this one:
java.util.Arrays.equals(recoveredHMACTag, newHMACTag)
I can't say that's all that could be causing it to go wrong, but it's the first thing I would check.
I'm having an issue trying to encrypt and decrypt a string using BouncyCastle.
I'm following an example at http://www.aviransplace.com/2004/10/12/using-rsa-encryption-with-java/ and my code looks like:
public class Cryptotests {
public static final String ALGORITHM = "RSA";
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
init();
KeyPair kp = generateKey();
byte[] enc = encrypt("The Fat Cat Jumped Over the Bat".getBytes("UTF8"), kp.getPublic());
byte[] dec = decrypt(enc, kp.getPrivate());
} catch (Exception ex) {
Logger.getLogger(Cryptotests.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void init() {
Security.addProvider(new BouncyCastleProvider());
}
public static KeyPair generateKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
return key;
}
/**
* Encrypt a text using public key.
*
* #param text The original unencrypted text
* #param key The public key
* #return Encrypted text
* #throws java.lang.Exception
*/
public static byte[] encrypt(byte[] text, PublicKey key) throws Exception {
byte[] cipherText = null;
// get an RSA cipher object and print the provider
Cipher cipher = Cipher.getInstance(
"RSA / ECB / PKCS1Padding");
System.out.println(
"nProvider is:" + cipher.getProvider().getInfo());
// encrypt the plaintext using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text);
return cipherText;
}
/**
* Decrypt text using private key
*
* #param text The encrypted text
* #param key The private key
* #return The unencrypted text
* #throws java.lang.Exception
*/
public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception {
byte[] dectyptedText = null;
// decrypt the text using the private key
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
return dectyptedText;
}
}
When I Run this code I end up with an error:
May 21, 2013 10:20:31 AM cryptotests.Cryptotests main
SEVERE: null
java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
at javax.crypto.Cipher.init(Cipher.java:1209)
at javax.crypto.Cipher.init(Cipher.java:1153)
at cryptotests.Cryptotests.encrypt(Cryptotests.java:70)
at cryptotests.Cryptotests.main(Cryptotests.java:34)
I'm really new and quite honestly feeling a bit lost when it comes to cryptography. My goal is to figure this out so that I can create and use a RSA key pair using SHA512 and a 4k length. I'm having a lot of trouble finding clear examples of how to do achieve this.
Need to install the Unlimited Java Cryptography Extension (JCE) Unlimited Strength
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
I am trying to learn and test the java 1.6 encryption/decryption API. I want to know what I am doing wrong and what I am missing in terms of knowledge.
In the code that follows below, I create two ciphers: one to encrypt and another to decrypt. When I use these ciphers, I initialize them with different SecretKey's, but I am still able to get the same value back out. Why is this?
String algorithm = "DES";
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
byte[] encBytes = "12345678".getBytes("UTF8");
byte[] decBytes = "56781234".getBytes("UTF8");
DESKeySpec keySpecEncrypt = new DESKeySpec(encBytes);
DESKeySpec keySpecDecrypt = new DESKeySpec(decBytes);
SecretKey keyEncrypt = keyFactory.generateSecret(keySpecEncrypt);
SecretKey keyDecrypt = keyFactory.generateSecret(keySpecDecrypt);
Cipher cipherEncrypt = Cipher.getInstance(algorithm);
Cipher cipherDecrypt = Cipher.getInstance(algorithm);
String input = "john doe";
cipherEncrypt.init(Cipher.ENCRYPT_MODE, keyEncrypt);
byte[] inputBytes = cipherEncrypt.doFinal(input.getBytes());
System.out.println("inputBytes: " + new String(inputBytes));
cipherDecrypt.init(Cipher.DECRYPT_MODE, keyDecrypt);
byte[] outputBytes = cipherDecrypt.doFinal(inputBytes);
System.out.println("outputBytes: " + new String(outputBytes));
Welcome to encryption! As mentioned DES is symmetric and requires the same key for encryption as decryption. That key needs to be the right number of bits for the cipher that you're using. For DES that's 56-bit. Before you go too far with that though, here are a few things you might want to consider:
You should use a stronger encryption standard like AES. It's possible to break DES encryption now.
If you want to use a string as the key, then you should use a strong hash function like SHA-256 against that key string. Then take as many bits from that hash output as you need for the encryption key, 128-bit is plenty sufficient for AES. Your key string should be long like you have.
It'll be best to use a block cipher mode that doesn't generate the same output for the same input each time. See block cipher modes of operation for info and a visualization of why ECB mode is bad.
Here's a working example of using 128-bit AES encryption in CBC mode with PKCS #5 padding:
import java.security.MessageDigest;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptDecrypt {
public static void main(String[] args) throws Exception {
// here are your inputs
String keyString = "averylongtext!#$##$##$#*&(*&}{23432432432dsfsdf";
String input = "john doe";
// setup AES cipher in CBC mode with PKCS #5 padding
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// setup an IV (initialization vector) that should be
// randomly generated for each input that's encrypted
byte[] iv = new byte[cipher.getBlockSize()];
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// hash keyString with SHA-256 and crop the output to 128-bit for key
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(keyString.getBytes());
byte[] key = new byte[16];
System.arraycopy(digest.digest(), 0, key, 0, key.length);
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// encrypt
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
System.out.println("encrypted: " + new String(encrypted));
// include the IV with the encrypted bytes for transport, you'll
// need the same IV when decrypting (it's safe to send unencrypted)
// decrypt
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
}
}
Here's the description from JDK doc:
DESKeySpec
public DESKeySpec(byte[] key)
throws InvalidKeyException
Creates a DESKeySpec object using the first 8 bytes in key as the key material for the DES key.
The bytes that constitute the DES key are those between key[0] and key[7] inclusive.
DESKeySpec uses only the first 8 bytes of byte[] as key. Thus the actual keys in used are identical in your example.
Here's a working example of using 56-bit DES encryption.
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class CipherHelper {
// Algorithm used
private final static String ALGORITHM = "DES";
/**
* Encrypt data
* #param secretKey - a secret key used for encryption
* #param data - data to encrypt
* #return Encrypted data
* #throws Exception
*/
public static String cipher(String secretKey, String data) throws Exception {
// Key has to be of length 8
if (secretKey == null || secretKey.length() != 8)
throw new Exception("Invalid key length - 8 bytes key needed!");
SecretKey key = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
return toHex(cipher.doFinal(data.getBytes()));
}
/**
* Decrypt data
* #param secretKey - a secret key used for decryption
* #param data - data to decrypt
* #return Decrypted data
* #throws Exception
*/
public static String decipher(String secretKey, String data) throws Exception {
// Key has to be of length 8
if (secretKey == null || secretKey.length() != 8)
throw new Exception("Invalid key length - 8 bytes key needed!");
SecretKey key = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(toByte(data)));
}
// Helper methods
private static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] stringBytes) {
StringBuffer result = new StringBuffer(2*stringBytes.length);
for (int i = 0; i < stringBytes.length; i++) {
result.append(HEX.charAt((stringBytes[i]>>4)&0x0f)).append(HEX.charAt(stringBytes[i]&0x0f));
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
// Helper methods - end
/**
* Quick test
* #param args
*/
public static void main(String[] args) {
try {
String secretKey = "01234567";
String data="test";
String encryptedData = cipher(secretKey, data);
System.out.println("encryptedData: " + encryptedData);
String decryptedData = decipher(secretKey, encryptedData);
System.out.println("decryptedData: " + decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
}
}