Hello all,
I'm trying to do the most trivial 3DES encryption/decryption. I'm
trying to 3DES encrypt using ECB, no padding in VB, and decrypt the
ciphertext in Java using the same key. I can encrypt fine, but
decryption always yields garbage.
I encrypt in VB using one of several free libraries (one is based on
the MS Crypto API, which I switched away from when I found out it was
doing CBC/PKCS5Padding), then Base64 encode the resulting ciphertext
and send it across the network to the java program which Base64
decodes the string and attempts to decode the resulting string. I've
verified that the java program is receiving the *same exact* string
(at least it *looks* the same) of Base64 encoded data that was sent
from VB. I *know* I'm using the same key, ECB mode, and padding.
What other things do I need to take into account to make this work?
Unicode strings on VB? Here's my Java decrypting code, if you'd care
to comment on it:
SecretKey desKey =
myKeyChain.getKey(Integer.parseInt(strKeyNumber));
javax.crypto.Cipher myDecryptCipher;
try
{
myDecryptCipher =
javax.crypto.Cipher.getInstance(
"DESede/ECB/NoPadding");
try
{
myDecryptCipher.init(
myDecryptCipher.DECRYPT_MODE,
desKey);
//base64 decode the remaining data
BASE64Decoder b64Decoder = new BASE64Decoder();
//decode it with the given secret
try
{
byte[] raw = b64Decoder.decodeBuffer(tempStr);
byte[] stringBytes = myDecryptCipher.doFinal(raw);
sResult = new String(stringBytes, "ASCII");
_theLog.debug("Raw decoded string is: " + sResult);
System.out.println("Decoded SSN is: " + sResult);
Here's a sample program that illustrates the problem succintly:
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* @author bschuhma
*
* To change this generated comment edit the template variable
"typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
public class B643DesTest
{
public static void main(String[] args)
{
byte[] baKey;
SecretKey desKey;
try
{
//key
baKey = "bcslpPiPp/2dOCPBf6g3O4xrZKieejRw".getBytes();
DESedeKeySpec dks;
dks = new DESedeKeySpec(baKey);
try
{
SecretKeyFactory d3Factory;
d3Factory = SecretKeyFactory.getInstance("DESede");
try
{
desKey = d3Factory.generateSecret(dks);
// javax.crypto.KeyGenerator keygen =
// javax.crypto.KeyGenerator.getInstance("DESede");
//keygen.init(56,new SecureRandom());
//keygen.init(168); //new SecureRandom());
// keygen.init(168);
//
// SecretKey desKey = keygen.generateKey();
// System.out.println("keygenerator is " + keygen.toString());
//javax.crypto.SecretKey desKey = keygen.generateKey();
System.out.println("DES Key is " + desKey);
System.out.println(
"DES Key bytes are " + desKey.toString().getBytes());
//java.security.KeyFactory myKey =
java.security.KeyFactory.getInstance("DESede");
//myKey.
Cipher myEncryptCipher =
javax.crypto.Cipher.getInstance("DESede/ECB/NoPadding");
///ECB/PKCS5Padding");
javax.crypto.Cipher myDecryptCipher =
javax.crypto.Cipher.getInstance("DESede/ECB/NoPadding");
///ECB/PKCS5Padding");
try
{
myEncryptCipher.init(
myEncryptCipher.ENCRYPT_MODE,
desKey);
myDecryptCipher.init(
myDecryptCipher.DECRYPT_MODE,
desKey);
}
catch (java.security.InvalidKeyException eInvalidKey)
{
System.out.println(
"Exception caught: InvalidKeyException");
}
try
{
//bogus cleartext license key
java.lang.String clearText = "1234567890000000";
byte[] encryptedData =
myEncryptCipher.doFinal(clearText.getBytes());
System.out.println("ClearText is " + clearText);
System.out.println(
"Encrypted license is "
+ new String(encryptedData));
//B64 encode the encrypted text now
BASE64Encoder myBase64Encoder = new BASE64Encoder();
BASE64Decoder myBase64Decoder = new
BASE64Decoder();
System.out.println(
"B64 encoded 3DES encrypted SSN is: "
+ myBase64Encoder.encode(encryptedData));
String B64EncodedEncryptedData = new
String(myBase64Encoder.encode(encryptedData));
//System.out.println("Encrypted license (in Hex) is " +
myHexEncoder.encode(encryptedData));
long endTime = 0;
long beginTime = System.currentTimeMillis();
myDecryptCipher.doFinal(encryptedData);
/*
try
{
java.lang.Thread.sleep(10);
}
catch (InterruptedException e)
{
}
*/
endTime = System.currentTimeMillis();
System.out.println(
"decryption took "
+ (endTime - beginTime)
+ " milliseconds");
System.out.println(
"Decrypted data is "
+ new String(
myDecryptCipher.doFinal(encryptedData)));
try
{
System.out.println(
"Decrypted B64 Data is "
+ new String(
myDecryptCipher.doFinal(myBase64Decoder.decodeBuffer(B64EncodedEncryptedData))));
}
catch (IOException e)
{
e.printStackTrace();
}
//an number from VB encrypted w/this key and
b64'd, taken from the output of the VB pgm
String B64TextFromVB = new
String("MrHDeSSijBRykvJsrTZjecG3Nqs9btY8");
try
{
System.out.println(
"Decrypted B64 VB Data is "
+ new String(
myDecryptCipher.doFinal(myBase64Decoder.decodeBuffer(B64TextFromVB)),"ASCII"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (
javax
.crypto
.IllegalBlockSizeException eIllegalBlocksize)
{
System.out.println(
"Exception caught: IllegalBlockSizeException");
}
catch (javax.crypto.BadPaddingException eBadPad)
{
System.out.println(
"Exception caught: BadPaddingException");
eBadPad.printStackTrace();
}
}
catch (NoSuchPaddingException nspe)
{
System.out.println(
"Exception caught: NoSuchPaddingException");
}
catch (java.security.NoSuchAlgorithmException e2)
{
System.out.println(
"Exception caught: NoSuchAlgorithmException");
}
catch (ExceptionInInitializerError eInit)
{
System.out.println("Exception was " + eInit.getException());
eInit.printStackTrace();
}
}
catch (InvalidKeySpecException e)
{
e.printStackTrace();
}
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (InvalidKeyException e)
{
e.printStackTrace();
}
}
}
Here's the output of the program:
DES Key is com.sun.crypto.provider.DESedeKey@b069ebca
DES Key bytes are [B@1ac2f9c
ClearText is 1234567890000000
Encrypted license is ³ñS»ýJÌ çð?-ý'!
B64 encoded 3DES encrypted SSN is: s/FTu/0FSsyg5/CQLf2SIQ==
decryption took 0 milliseconds
Decrypted data is 1234567890000000
Decrypted B64 Data is 1234567890000000
Decrypted B64 VB Data is ?1???????J%???????
For the VB data, I took an encrypted string from my VB program and
hardcoded it. It should decode into a string of numbers.
I'm obviously missing something going between VB and Java, but I
*cannot* put my finger on it! ANY help you can provide would be most
gratefully accepted! :-)
FWIW, all this is running on a WinXP machine for the moment. However,
the Java pgm will be on Solaris when everything works. Do I need to
worry about byte order or anything?
Thanks for your comments! :-)
Bret
Michael Amling - 23 May 2004 06:11 GMT
> System.out.println(
> "DES Key bytes are " + desKey.toString().getBytes());
You realize, of course, that this does not print anything useful. In
particular, what gets printed does not depend in any way on the contents
of the ...getByte() array, and the contents of that array is not the key
you're encrypting with anyway.
> Here's the output of the program:
> DES Key is com.sun.crypto.provider.DESedeKey@b069ebca
> DES Key bytes are [B@1ac2f9c
"[B" denotes a type, an array of bytes. "@" is irrelevant, and
"1ac2f9c" is probably the array Object's hashCode.
A better idea would be to print out the key that's being used for
encryption, in hexadecimal.
> ClearText is 1234567890000000
> Encrypted license is ³ñS»ýJÌ çð?-ý'!
[quoted text clipped - 3 lines]
> Decrypted B64 Data is 1234567890000000
> Decrypted B64 VB Data is ?1????????J%???????
I would suggest starting with something simple. The triple DES ede
encryption of a block of 64 zero bits, using all zeros for all three
keys is hex 15C59830944C6244. Once your software can duplicate this
result, try something just a little more complicated.
--Mike Amling
asfonseca - 01 Jun 2004 15:31 GMT
When i tried to send a key from java to asp, the key always got there in a
bad format, in asp it was needed to reverse the byte order of the key,
read the following, some clues there
http://www.jensign.com/JavaScience/dotnet/RSAEncrypt/