Newbie mistake
843810Mar 30 2004 — edited Apr 1 2004Hello,
I am new to the cryptography stuff, so please excuse me if I have made any stupid mistakes. I have this simple program that does encryption and decryption. It is supposed to print out the encrypted string as well as the key used. These values will then go into the XML configuration file. When the other application reads this config file, it is supposed to decrypt the stuff. I have a few problems actually.
1. If I run this program, it works sometimes and sometimes it gives me an exception. The strange part is that the input is the same. I run the program 2 times within 3 mins and I get this unexpected behavior.
2. When it does work, the decrypted value displayed is not the same as the input.
Please can someone help and tell me what my stupid mistake is.
You can run it as
java -cp .;<PATH_TO_BASE64_ENCODER>.jar SecurityService <VALUE_TO_ENCRYPT_AND_DECRYPT>
Here is my complete program
import java.io.UnsupportedEncodingException;
import java.security.*;
import javax.crypto.spec.*;
import javax.crypto.*;
import com.Ostermiller.util.Base64;
public class SecurityService {
protected final String DEFAULT_ALGORITHM = "DESede";
protected final String DEFAULT_MODE = "NONE";
protected final String DEFAULT_PADDING = "NoPadding";
public SecurityService() {
}
/**
* This method will encrypt the value passed to it using the algorithm provided by the user.
* The default algorightm is DESede with no mode or padding. Only if the encoding algorithm is
* specified will the mode and padding be read. Since these two values make most sense with a
* particular algorithm only, there is no reason to read these values if no algorithm is specified.
* @param anEncodingAlgorithm The algorithm to use to encrypt the value. eg. DES, DESede, RSA
* @param aMode The mode to use along with the encryption algorithm. eg. CBC, CFB
* @param aPadding The type of padding to use.
* @param aValueToEncode The value to encode.
* @return The encrypted value and the key separated using ...
*/
public String encrypt(String anEncodingAlgorithm,
String aMode,
String aPadding,
String aValueToEncode)
throws NoSuchAlgorithmException, Exception
{
String currentAlgorithm = this.DEFAULT_ALGORITHM;
try
{
StringBuffer transformationBuffer = new StringBuffer();
if ((null != anEncodingAlgorithm) && (0 != anEncodingAlgorithm.trim().length()))
{
transformationBuffer.append(anEncodingAlgorithm);
currentAlgorithm = anEncodingAlgorithm;
if ((null != aMode) && (0 != aMode.trim().length()))
{
transformationBuffer.append("/" + aMode);
}
else
{
transformationBuffer.append("/" + DEFAULT_MODE);
}
if ((null != aPadding) && (0 != aPadding.trim().length()))
{
transformationBuffer.append("/" + aPadding);
}
else
{
transformationBuffer.append("/" + DEFAULT_PADDING);
}
}
else
{
transformationBuffer.append(DEFAULT_ALGORITHM);
}
System.out.println("The transformation to use is : " + transformationBuffer.toString());
//STEP 1: Create the Cipher object that will be used to encrypt the value
Cipher cipherObject = Cipher.getInstance(transformationBuffer.toString());
//STEP 2: Obtain an instance of the KeyGenerator to generate a Key.
KeyGenerator keyGenerator = KeyGenerator.getInstance(currentAlgorithm);
keyGenerator.init(112);
//STEP 3: Generate the secret key
SecretKey keyToUse = keyGenerator.generateKey();
System.out.println("During encryption, the encoded secret key is : " + keyToUse.getEncoded());
System.out.println("During encryption, the secret key format is : " + keyToUse.getFormat());
//STEP 4: Initialize the Cipher object so that it is in the Encryption mode.
cipherObject.init(Cipher.ENCRYPT_MODE, keyToUse);
//STEP 5: Encrypt the value
byte[] encryptedData = cipherObject.doFinal(aValueToEncode.getBytes());
//STEP 6: The encrypted data is in the form of bytes and has no structure. In order to
//convert it to a String, it must be base64 encoded first.
String base64EncryptedString = new String(Base64.encode(encryptedData));
System.out.println("During encryption, the base64 encrypted value is : " + base64EncryptedString);
//STEP 7: Create the buffer to hold the delimited encrypted value and key
StringBuffer resultBuffer = new StringBuffer(base64EncryptedString);
resultBuffer.append("...");
//STEP 8: Convert the SecretKey to a DESede key
SecretKeyFactory desEdeFactory = SecretKeyFactory.getInstance("DESede");
DESedeKeySpec desEdeSpec = (DESedeKeySpec)desEdeFactory.getKeySpec(keyToUse, javax.crypto.spec.DESedeKeySpec.class);
byte[] rawDesEdeKey = desEdeSpec.getKey();
/*
byte[] rawDesEdeKey = keyToUse.getEncoded();
*/
String keyInBase64Format = new String(Base64.encode(rawDesEdeKey));
resultBuffer.append(keyInBase64Format);
System.out.println("During encryption, the secret key is : " + keyInBase64Format);
return resultBuffer.toString();
}
catch(NoSuchAlgorithmException noSuchAlgorithm)
{
throw noSuchAlgorithm;
}
catch(NoSuchPaddingException noSuchPadding)
{
throw noSuchPadding;
}
catch(Exception e)
{
throw e;
}
}
public String decrypt(String aDecodingAlgorithm,
String aMode,
String aPadding,
String akeyToUseToDecode,
String aValueToDecode)
throws NoSuchAlgorithmException, Exception
{
String currentAlgorithm = this.DEFAULT_ALGORITHM;
try
{
StringBuffer transformationBuffer = new StringBuffer();
if ((null != aDecodingAlgorithm) && (0 != aDecodingAlgorithm.trim().length()))
{
transformationBuffer.append(aDecodingAlgorithm);
currentAlgorithm = aDecodingAlgorithm;
if ((null != aMode) && (0 != aMode.trim().length()))
{
transformationBuffer.append("/" + aMode);
}
else
{
transformationBuffer.append("/" + DEFAULT_MODE);
}
if ((null != aPadding) && (0 != aPadding.trim().length()))
{
transformationBuffer.append("/" + aPadding);
}
else
{
transformationBuffer.append("/" + DEFAULT_PADDING);
}
}
else
{
transformationBuffer.append(DEFAULT_ALGORITHM);
}
System.out.println("Decrypting : The transformation to use is : " + transformationBuffer.toString());
System.out.println("Decrypting : The algorithm to use is : " + currentAlgorithm);
//STEP 1: Create an instance of the Cipher object using the transformation.
Cipher cipherObject = Cipher.getInstance(transformationBuffer.toString());
//STEP 2: Convert the DESede key to a secret key
SecretKeyFactory desEdeFactory = SecretKeyFactory.getInstance("DESede");
//Decode the base64 encoded key to it's raw format first
byte[] rawKey = Base64.decodeToBytes(akeyToUseToDecode);
DESedeKeySpec keyspec = new DESedeKeySpec(rawKey);
// SecretKeySpec keyspec = new SecretKeySpec(rawKey, currentAlgorithm);
System.out.println("Decrypting : Key Spec created...");
SecretKey keyToUse = desEdeFactory.generateSecret(keyspec);
cipherObject.init(Cipher.DECRYPT_MODE, keyToUse);
byte[] decryptedData = cipherObject.doFinal(Base64.decodeToBytes(aValueToDecode));
StringBuffer resultBuffer = new StringBuffer(Base64.encode(decryptedData).toString());
System.out.println("Decrypting: The decrypted value is : " + Base64.decode(resultBuffer.toString()));
resultBuffer.append("...");
// resultBuffer.append(Base64.encode(keyspec.getEncoded()).toString());
resultBuffer.append(Base64.encode(keyspec.getKey()).toString());
return resultBuffer.toString();
}
catch(NoSuchAlgorithmException noSuchAlgorithm)
{
throw noSuchAlgorithm;
}
catch(NoSuchPaddingException noSuchPadding)
{
throw noSuchPadding;
}
catch(Exception e)
{
throw e;
}
}
public static void main(String args[])
{
SecurityService testSecurityService = new SecurityService();
if (args.length <= 0 )
{
args[0] = "Amitabh";
}
/*
if (args.length <= 0 )
{
System.out.println("USAGE: java com.petris.security.SecurityService valueToEncrypt");
System.exit(1);
}
*/
try
{
String encryptedValueAndKey = testSecurityService.encrypt(null, null, null,
args[0]);
int indexOfDelimiter = encryptedValueAndKey.indexOf("...");
String encryptedValue = encryptedValueAndKey.substring(0, indexOfDelimiter);
String key = encryptedValueAndKey.substring(indexOfDelimiter + 3);
System.out.println("The value to encrypt is : " + args[0]);
System.out.println("The encrypted value is : " + encryptedValue);
System.out.println("The key used is : " + key);
String decryptedValueAndKey = testSecurityService.decrypt(null, null, null,
key, encryptedValue);
indexOfDelimiter = decryptedValueAndKey.indexOf("...");
String decryptedValue = decryptedValueAndKey.substring(0, indexOfDelimiter);
key = decryptedValueAndKey.substring(indexOfDelimiter + 3);
System.out.println("The complete decrypted string is : " + decryptedValueAndKey);
System.out.println("The decrypted value is : " + Base64.decode(decryptedValue));
System.out.println("The key used is : " + key);
}
catch(Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}