Code Comments
Programming Forum and web based access to our favorite programming groups.I have code that has been working fine for some time, or so we
thought. We recently discovered that at times the decryption is
failing. I should say that are using Sun JCE1.2.2.
Below is an example of a clear text string that will fail
consistently:
String clearText = "ss=078388601&ts=20040210195639";
Ok, Here is my test class that I run. It executes the CipherTest
class, enclosed further down:
public class JCEDebug {
/**
* Constructor for JCEDebug.
*/
public JCEDebug() {
super();
}
public static void main(String[] args)
{
String clearText = "ss=078388601&ts=20040210195639";
try
{
CipherTest cipher1 = new CipherTest();
System.out.println("Start value = " + clearText);
cipherText = cipher1.encrypt(clearText);
System.out.println("Encrypted value = " + cipherText);
CipherTest cipher2 = new CipherTest();
clearText = cipher2.decrypt(cipherText);
System.out.println("Decrypted value = " + clearText);
}
catch(Exception e)
{
System.out.println("Caught Exception msg = " + e.getMessage());
}
}
}
Here is the source for CipherTest:
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.IOException;
public class CipherTest
{
final private static String CRYPTO_ALGORITHM = "DESede";
final private static String CRYPTO_BLOCK_MODE = "CBC";
final private static String CRYPTO_PADDING = "PKCS5Padding";
private static String keyData1 = "qTqE0Fgy";
private static String keyData2 = "G5h2NERs";
private static String keyData3 = "NiFNj4Vg";
private static String initVector = "h8sNq4lJ";
private static String keyData = null;
private static byte[] desedeKeyData = null;
private static IvParameterSpec ivParamSpec = null;
private static DESedeKeySpec secretKeySpec = null;
private static SecretKeyFactory keyFactory = null;
private static SecretKey secretKey = null;
private boolean initialized=false;
/**
* CipherTest constructor comment.
*/
public CipherTest() {
super();
try{
initData();
}
catch(NoSuchAlgorithmException nsae){
}
catch(InvalidKeyException ike){
}
catch(InvalidKeySpecException ikse){
}
catch(java.io.UnsupportedEncodingException uee){
}
}
/**
* Insert the method's description here.
* Creation date: (1/16/2003 4:29:47 PM)
* @return java.lang.String
* @param passedString java.lang.String
* @param cipherMode int
*/
protected String cipher(String passedString, int cipherMode)
throws InvalidKeyException, NoSuchAlgorithmException,
ExceptionInInitializerError, InvalidKeySpecException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalStateException, IllegalBlockSizeException,
BadPaddingException, NoClassDefFoundError
{
if (!isInitialized()){
throw new java.lang.IllegalStateException();
}
// Create the encryption cipher
Cipher desCipher = null;
desCipher = Cipher.getInstance(CRYPTO_ALGORITHM+"/"+CRYPTO_BLOCK_MODE+"/"+CR
YPTO_PADDING);
// Initialize the cipher for encryption
desCipher.init(cipherMode, secretKey, ivParamSpec);
byte[] passedBytes = passedString.getBytes();
// Cipher the data
byte[] resultBytes = null;
resultBytes = desCipher.doFinal(passedBytes);
if( resultBytes != null )
{
return new String(resultBytes);
}
else
{
return null;
}
}
/**
* Insert the method's description here.
* Creation date: (1/16/2003 4:29:47 PM)
* @return java.lang.String
* @param clearText java.lang.String
*/
public String decrypt(String cipherText)
throws InvalidKeyException, NoSuchAlgorithmException,
ExceptionInInitializerError, InvalidKeySpecException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalStateException, IllegalBlockSizeException,
BadPaddingException, NoClassDefFoundError
{
// Pass the string and the correct mode
return cipher(cipherText, Cipher.DECRYPT_MODE);
}
/**
* Insert the method's description here.
* Creation date: (1/16/2003 4:29:47 PM)
* @return java.lang.String
* @param clearText java.lang.String
*/
public String encrypt(String clearText)
throws InvalidKeyException, NoSuchAlgorithmException,
ExceptionInInitializerError, InvalidKeySpecException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalStateException, IllegalBlockSizeException,
BadPaddingException, NoClassDefFoundError
{
// Pass the string and the correct mode
return cipher(clearText, Cipher.ENCRYPT_MODE);
}
/**
* Insert the method's description here.
* Creation date: (1/16/2003 4:08:42 PM)
*/
public void initData()
throws InvalidKeyException, NoSuchAlgorithmException,
ExceptionInInitializerError,
InvalidKeySpecException, NoClassDefFoundError
{
Security.insertProviderAt( new com.sun.crypto.provider.SunJCE(),
2);
System.setProperty("java.protocol.handler.pkgs",
"sun.net.www.protocol");
keyData = keyData1 + keyData2 + keyData3;
desedeKeyData = keyData.getBytes();
// Create the initialization vector paramater spec
ivParamSpec = new IvParameterSpec(initVector.getBytes());
// Create the key spec
secretKeySpec = new DESedeKeySpec(desedeKeyData);
// Create the key factory
keyFactory = SecretKeyFactory.getInstance(CRYPTO_ALGORITHM);
// Generate the encryption key
secretKey = keyFactory.generateSecret(secretKeySpec);
// Mark it as initialized
initialized = true;
}
/**
* Insert the method's description here.
* Creation date: (5/6/2003 1:53:22 PM)
* @return boolean
*/
public boolean isInitialized() {
return initialized;
}
public void setInitialized(boolean newInitialized) {
initialized = newInitialized;
}
}
What I see for results are:
Start value = ss=078388601&ts=20040210195639
Encrypted value = ¦Í?+s²þy8{d
gƒ?çè‚P½:Õ]/Á?½ö"î
Decrypted value = ¼"™Hu¼^
^#ëvÅt200402?0195639
This type of behavior doesn't occur all of the time, only when certain
results are produced by the encryption. So, that along with other
posts, is why I suspect it may be related to the string to byte[] and
byte[] to string conversions. But, I have attempted to perform these
conversions using string.getBytes("ASCII"), as well as
string.getBytes("UTF-8"). Furthermore, I have attempted to serialize
the string prior to encryption, then deserialize it after encryption
using the ByteArrayOutputStream, all to no avail.
Any help that you all can provide with solving this riddle would be
greatly appreciated. Thank you!
Post Follow-up to this messageDan Anderson wrote:
> // Cipher the data
> byte[] resultBytes = null;
> resultBytes = desCipher.doFinal(passedBytes);
>
> if( resultBytes != null )
> {
> return new String(resultBytes);
> }
> else
> {
> return null;
> }
I'm surprised you're not failing much more frequently.
ciphertext -cannot- be reliably turned into a String. Strings have
internal structure; ciphertext is (or at least it ought to be!) an
apparently-random bitstream. The String(byte[]) constructor is going to
mash your bitstream into String format, and generally mangle it along
the way. Once String has "improved" your ciphertext, it isn't
ciphertext anymore - it's junk.
If you want your ciphertext to be a String, use Base64 to encode it -
that's what Base64 is for. Base64.decode() before decrypting.
> This type of behavior doesn't occur all of the time, only when certain
> results are produced by the encryption. So, that along with other
> posts, is why I suspect it may be related to the string to byte[] and
> byte[] to string conversions. But, I have attempted to perform these
> conversions using string.getBytes("ASCII"), as well as
> string.getBytes("UTF-8").
I don't think these are your problem - but it's a good idea to do this
anyway. If you're moving data from one machine to another, you'll get
bitten when the default encoding is different.
> Furthermore, I have attempted to serialize
> the string prior to encryption, then deserialize it after encryption
> using the ByteArrayOutputStream, all to no avail.
If you've already turned it into a String, it's too late - the damage is
already done.
Grant
--
In theory, there is no difference between Theory and Practice.
In practice, there is no relationship between Theory and Practice.
Post Follow-up to this messageDan Anderson wrote:
> I have code that has been working fine for some time, or so we
> thought. We recently discovered that at times the decryption is
> failing. I should say that are using Sun JCE1.2.2.
> /**
> * Insert the method's description here.
> * Creation date: (1/16/2003 4:29:47 PM)
> * @return java.lang.String
> * @param passedString java.lang.String
> * @param cipherMode int
> */
> protected String cipher(String passedString, int cipherMode)
> throws InvalidKeyException, NoSuchAlgorithmException,
> ExceptionInInitializerError, InvalidKeySpecException,
> NoSuchPaddingException, InvalidAlgorithmParameterException,
> IllegalStateException, IllegalBlockSizeException,
> BadPaddingException, NoClassDefFoundError
> {
> if (!isInitialized()){
> throw new java.lang.IllegalStateException();
> }
>
> // Create the encryption cipher
> Cipher desCipher = null;
> desCipher = Cipher.getInstance(CRYPTO_ALGORITHM+"/"+CRYPTO_BLOCK_MODE+
"/"+CRYPTO_PADDING);
>
> // Initialize the cipher for encryption
> desCipher.init(cipherMode, secretKey, ivParamSpec);
>
> byte[] passedBytes = passedString.getBytes();
Your passedBytes will always be a sequence of bytes that is a valid
character encoding. If the ciphertext is not a sequences of bytes that
is a valid character encoding, there is no String for which getBytes()
will return the ciphertext.
>
> // Cipher the data
> byte[] resultBytes = null;
> resultBytes = desCipher.doFinal(passedBytes);
>
> if( resultBytes != null )
> {
> return new String(resultBytes);
Someone did not read
http://java.sun.com/j2se/1.4.2/docs...ng/String.html, which
says in the description of the String(byte[]) constructor, "The behavior
of this constructor when the given bytes are not valid in the default
charset is unspecified."
Leaving the ciphertext as a byte array is the easiest thing to do. A
byte array is the easiest thing to write to a file or send to a Socket's
output stream.
If you insist on converting the ciphertext to characters, use a
method that works for any sequence of bytes, such as hexadecimal or base 64.
> }
> else
> {
> return null;
> }
> }
--Mike Amling
Post Follow-up to this message
Show a Printable Version
Email This Page to Someone!
Receive updates to this thread
Powered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.