Here's my scenario.
* I'm receiving a public RSA key from a C application (using openSSL library)
* I create an RSA key from the bytes I'm getting.
* I use RSA key to encrypt a string (known to the C code), and verify that the encryption works
* I generate a payload(Triple-DES) key, encrypt it using the RSA Key, then send the raw bytes to the C code for use
* C code verifies for itself that it can use the tripleDes key created from my bytes to encrypt/decrypt a string
* If everythings succeeded up to this point, I once again encrypt the 'known' data - this time with the triple DES key
Currently when the C code receives my triple-DES encrypted known data, it's the right length, but when it uses the key it created earlier from my bytes to do the decryption, the known data's not there. I may be missing something basic about the key exchange, but I've yet to catch it. I've tried both instantiating the desEde key as a Key and SecretKey. Am I correct that I can be using just one desEde key for everything? Or at least to encrypt the data? If someone could help me figure out why that key's not encrypting correctly - or why the key of C :) is decrypting incorrectly??
(NOTE: All the stuff that I need to do from java has already been done in a C++ client using Crypto5.1, and I'm getting what I can from that code...)
The C code is expecting a 32-byte array with which to construct the TripleDES(DesEde) Key for use. I havent found the exact C++ client code that encodes the 32 byte array (not for lack of looking).
I went with what seemed the standard procedure, constructing the 32 byte[] the Triple-Des key's first 16 bytes. Here's how I coded it:
public byte[] getDesEdeKeyBytes() {
KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
m_desEdeKey = keyGen.generateKey(); // m_desEdeKey is SecretKey
byte[] tripleDesBytes = m_desEdeKey.getEncoded();
// Grab first 16 bytes of Triple Des key (the last 8 bytes are same as first 8 bytes
byte[] firstTripleDesBytes = new byte[16];
for(int i=0;i<16;i++){
firstTripleDesBytes[i] = tripleDesBytes; }
// Create 32 byte array by taking left/right value from
// the 16 bytes, and creating a byte from each
// e.g. 'E7' becomes 'E' = 14, '7' = 7.
String strFirstTripleDesBytes = printByteArrayAsHex(firstTripleDesBytes);
StringBuffer buffer = new StringBuffer();
byte[] desKeyBytes = new byte[32];
for(int z =0;z<32;z++){
String temp = strFirstTripleDesBytes.substring(z, z + 1);
int myInt = Integer.parseInt(temp, 16 )
desKeyBytes[z] = (byte)myInt;
}
String desKey = buffer.toString();
return desKeyBytes;
}
All desKeyBytes = 7af82094eaf8a2a28345b3a29152d38c7af82094eaf8a2a2
first 16 bytes = 7af82094eaf8a2a28345b3a29152d38c
desKeyBytes = 070a0f08020009040e0a0f080a020a02080304050b030a02090105020d03080c
<<<<<OUTPUT>>>>>>>
Here's how I (try to) encrypt the known data (a String - length=61). The EncodedBuffer class is one thats used for writing/reading bytes, and it works plenty of other places in the code, so I'm reasonably certain it works just fine.
public byte[] desEdeEncrypt(byte[] data) {
MessageFormatter formatter = new MessageFormatter();
int paddedBytes = (DES_EDE_BLOCK_SIZE - (data.length%DES_EDE_BLOCK_SIZE));
// if 0, then pad with 8 bytes TODO:TRC
int encryptedLen = data.length + (paddedBytes == 0?DES_EDE_BLOCK_SIZE: paddedBytes);
EncodedBuffer origBuffer = new EncodedBuffer(data.length);
origBuffer.write(data, data.length);
EncodedBuffer encryptedBuffer = new EncodedBuffer(encryptedLen);
try {
Cipher tripleDes = Cipher.getInstance("DESede/ECB/NoPadding");
tripleDes.init(Cipher.ENCRYPT_MODE, m_desEdeKey); // initialize for encrypt mode
byte[] tempBytes = null;
byte[] encryptedBytes = null;
for(int x=0;x<=(data.length - DES_EDE_BLOCK_SIZE);x+=DES_EDE_BLOCK_SIZE){
tempBytes = origBuffer.readByteArrayAtOffset(x, DES_EDE_BLOCK_SIZE);
encryptedBytes = tripleDes.doFinal(tempBytes);
encryptedBuffer.write(encryptedBytes, DES_EDE_BLOCK_SIZE);
}
// now we write the last block..
// possibly some data...
tempBytes = origBuffer.readByteArray(DES_EDE_BLOCK_SIZE - paddedBytes);
EncodedBuffer paddingBuffer = new EncodedBuffer(DES_EDE_BLOCK_SIZE);
paddingBuffer.write(tempBytes, tempBytes.length);
// plus any padding needed; the last byte will always contain the number of padded bytes
// if data divides evenly by 8(DES_EDE_BLOCK_SIZE), a block of 8 bytes of value '8' will be added
byte padChar = (byte)(paddedBytes & 0x0f);
for(int y=0;y<paddedBytes;y++){
paddingBuffer.write(padChar);
}
encryptedBytes = tripleDes.doFinal(paddingBuffer.getBufferBytes());
encryptedBuffer.write(encryptedBytes, DES_EDE_BLOCK_SIZE);
} catch (IoBufferException e2) {
e2.printStackTrace();
}
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (NoSuchPaddingException e1) {
e1.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptedBuffer.getBufferBytes();
}
>>>>>OUTPUT<<<<<<< KNOWN DATA NOT SHOWN (XXXX) FOR OBVIOUS REASONS
paddedBytes = 3
encryptedLen = 64
plain text, x 0= XXXXXXXX
plain text, x 8= XXXXXXXX
plain text, x 16=XXXXXXXX
plain text, x 24=XXXXXXXX
plain text, x 32=XXXXXXXX
plain text, x 40=XXXXXXXX
plain text, x 48=XXXXXXXX
encryptedBuffer.getNumberOfBytesInput = 56
paddingBuffer.getNumberOfBytesInput = 5
padChar = 3
padded buffer = XXXXX
paddingBuffer.getNumberOfBytesInput = 8
encryptedBytes.length = 8
<<<<<OUTPUT>>>>>>>