Skip to Main Content

Java Security

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Problem Encrypting/Decrypting

843811Jun 5 2007 — edited Jun 6 2007
Hi 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.
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 4 2007
Added on Jun 5 2007
3 comments
431 views