Problem Encrypting/Decrypting
843811Jun 5 2007 — edited Jun 6 2007Hi all,
I'm a bit of a newb in java development, and having some trouble getting an implementation of symmetric encryption working. Basically, the design for the program I'm building uses the following encryption paradigm:
1. User enters username/password
2. System checks DB for salt associated with that username (caveat-only 1 user expected per installation)
3. System takes password, hashes it using default Sun SHA-512 message digest to build a decryption key
4. System uses decryption key created in step 3 to decrypt an authentication string stored in the DB using PBEwithMD5andDES.
So, steps 1-3 work. Step 4 is having issues. Right now, I have a test program which takes a default password, hashes it, builds cipher objects using the hash, and then attempts to encrypt then decrypt the string. (This is basically just a proof-of-concept to prove that I can reliably decrypt data.) The problem is that when I decrypt the byte array, I don't get the original byte array I encrypted.
For reference, here is my encryption/decryption cipher routines that I'm using. I made a local cipher class which creates two JCE cypher objects, one for encryption and one for decryption, based on the same salt, iteration count, and password. I based this code off of the sample PBE code found here:
http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html#PBEEx
My cipher class:
package zen.client.authentication;
public class Cipher {
byte[] key;
javax.crypto.Cipher Encrypter;
javax.crypto.Cipher Decrypter;
public Cipher(byte[] encryptionKey, byte[] salt)
{
// Declare encryption structures
javax.crypto.spec.PBEKeySpec pbeKeySpec;
javax.crypto.spec.PBEParameterSpec pbeParamSpec;
javax.crypto.SecretKeyFactory keyFac;
int iterationCount = 55;
// use the hashed encryption key as our "password"
key = encryptionKey;
// Initialize the ciphers for encryption and decryption
try {
Encrypter = javax.crypto.Cipher.getInstance("PBEWithMD5AndDES");
Decrypter = javax.crypto.Cipher.getInstance("PBEWithMD5AndDES");
// Create PBE parameter set
pbeParamSpec = new javax.crypto.spec.PBEParameterSpec(salt, iterationCount);
// Convert key SecretKey object
pbeKeySpec = new javax.crypto.spec.PBEKeySpec(key.toString().toCharArray());
keyFac = javax.crypto.SecretKeyFactory.getInstance("PBEWithMD5AndDES");
javax.crypto.SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Initialize PBE Cipher with key and parameters
Encrypter.init(javax.crypto.Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
Decrypter.init(javax.crypto.Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
}
catch (Exception e){
e.printStackTrace();
}
}
public byte[] encrypt(String text){
byte[] test = null;
byte[] test2 = text.getBytes();
System.out.println("Cleartext Original: " + text);
System.out.println("Cleartext in bytes: " + bytes_to_byte_string(test2));
System.out.println("Cleartext in chars: " + bytes_to_char_string(test2));
// Encrypt using Encrypter
try{
test = Encrypter.doFinal(text.getBytes());
}
catch (Exception e){
e.printStackTrace();
}
System.out.println("Ciphertext in bytes: " + bytes_to_byte_string(test));
System.out.println("Ciphertext in chars: " + bytes_to_char_string(test));
return test;
}
public String decrypt(byte[] data){
byte[] test = null;
System.out.println("Encrypted bytes: " + bytes_to_byte_string(data));
System.out.println("Encrypted chars: " + bytes_to_char_string(data));
// Decrypt using Encrypter
try{
test = Decrypter.doFinal(data);
}
catch (Exception e){
e.printStackTrace();
}
System.out.println("Unencrypted bytes: " + bytes_to_byte_string(test));
System.out.println("Unencrypted chars: " + bytes_to_char_string(test));
return bytes_to_char_string(test);
}
private String bytes_to_byte_string(byte[] input)
{
StringBuffer text = new StringBuffer();
// Iterate through the bytes and append to the string buffer
for (int i = 0; i < input.length; i++)
text.append(input[ i ]);
// Return the resulting string
return text.toString();
}
private String bytes_to_char_string(byte[] input)
{
StringBuffer text = new StringBuffer();
// Iterate through the bytes and append to the string buffer
for (int i = 0; i < input.length; i++)
text.append((char)input[ i ]);
// Return the resulting string
return text.toString();
}
}
Also for reference, here is my test program which uses this class:
package zen.client.authentication;
public class TestClass2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Cipher authCipher;
byte[] random_number = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
String pass1 = "password";
StringBuffer pw1 = new StringBuffer().append(pass1);
byte[] result1 = null;
String encryptionString = "ZoMg It wOrKs9{?^j$Q}]|2";
String authenticationText = "ZoMg It wOrKs";
try{
// Build a MessageDigest (1-way hash) object
java.security.MessageDigest md1 = java.security.MessageDigest.getInstance("SHA-512");
java.security.MessageDigest md2 = java.security.MessageDigest.getInstance("SHA-512");
// Initialize MD object
md1.reset();
// Add the password to the MD object via the update method
md1.update(pw1.toString().getBytes());
// Add the salt as well to further randomize the result
md1.update(random_number);
// Complete the encryption and return the result
result1 = md1.digest();
}
catch (Exception e){
e.printStackTrace();
}
// Create authentication cipher with this key
authCipher = new Cipher(result1, random_number);
// Encrypt Encryption String using authentication cipher
byte[] encryptedData = authCipher.encrypt(encryptionString);
// Decrypt Encryption String using authentication cipher
String decryptedString = authCipher.decrypt(encryptedData);
/*
// Parse the Authentication Text
String authText = decryptedEncryptionString.substring(0, 12);
// Check to see if we've matched the Authentication Text
if (authText.equals(authenticationText))
// User is authenticated.
System.out.println("It works!");
else
System.out.println("It failed!"); */
}
}
Any help anyone could provide for figuring out why the decryption mechanism isn't working would be appreciated. Right now my guesses are:
1. Something is wrong with the "PBEWithMD5AndDES" algorithm I'm using (I tried downloading bouncycastle's implementation, but I can't get it to work)
2. I didn't initialize the decryption cipher correctly (although both ciphers take the exact same parameters)
3. I have to use the same cipher for encryption & decryption, I just have to reinitialize it for encryption/decryption every time I need to use it.
Thanks for any help you can provide.