Reputation: 11
I have this following snippet from Java code that is used for encryption
public class DESUtil {
private final static String ALGORITHM = "DES";
private static final byte[] EncryptionIV = "12344321".getBytes();
private static String key="1234%^&*";
public static String encrypt(String text) {
try {
IvParameterSpec spec = new IvParameterSpec(EncryptionIV);
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, securekey, spec);
byte[] data = c.doFinal(text.getBytes("UTF-8"));
return new String(Base64.encode(data));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String decrypt(String text) throws Exception{
try {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
Key secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(EncryptionIV);
AlgorithmParameterSpec paramSpec = iv;
cipher.init(Cipher.DECRYPT_MODE, secretKey,paramSpec);
byte[] data = cipher.doFinal(Base64.decode(text.getBytes()));
return new String(data,"utf-8");
} catch (Exception e){
e.printStackTrace();
return null;
}
}
}
what s the equivalent of the Java encryption in C++?
This is related to Java encryption. But not sure what is the equivalent. essentially i would like the same output as Java code generates.the I tried to use Openssl to encrypt and decrypt,however it doesn't work,I'm have seen a bunch of examples of Openssl,I still didn't know what wrong I have done yet, the code was trying to do a DES/CBC/PKCS5padding encryption
int encryptdate(string plaindatas, string & encryptedatas)
{
string EncryptionIVstr = "12344321";
string keystr = "1234%^&*";
const char* ivcstyle = EncryptionIVstr.c_str();
unsigned char iv[sizeof(ivcstyle)];
std::copy(ivcstyle, ivcstyle + sizeof(ivcstyle), iv);
const char * keycstyle = keystr.c_str();
unsigned char key[sizeof(keycstyle)];
std::copy(keycstyle, keycstyle + sizeof(keycstyle), key);
const char * incstyle = plaindatas.c_str();
unsigned char in[sizeof(incstyle)];
std::copy(incstyle, incstyle + sizeof(incstyle), in);
int written = 0, temp;
unsigned char * outbuf = new unsigned char[1024 + EVP_MAX_BLOCK_LENGTH];
EVP_CIPHER_CTX * ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv);
EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);
if (!EVP_EncryptUpdate(ctx, &outbuf[written], &temp, in, sizeof(in)))
{
EVP_CIPHER_CTX_cleanup(ctx);
return -1;
}
written += temp;
if (!EVP_EncryptFinal_ex(ctx, outbuf, &written))
{
EVP_CIPHER_CTX_cleanup(ctx);
return -1;
}
EVP_CIPHER_CTX_cleanup(ctx);
encryptedatas = base64_encode(outbuf, sizeof(outbuf));
return 0;
}
int decryptdate(string encryptdatas, string & decryptdatas)
{
string EncryptionIVstr = "12344321";
string keystr = "1234%^&*";
const char* ivcstyle = EncryptionIVstr.c_str();
unsigned char iv[sizeof(ivcstyle)];
std::copy(ivcstyle, ivcstyle + sizeof(ivcstyle), iv);
const char * keycstyle = keystr.c_str();
unsigned char key[sizeof(keycstyle)];
std::copy(keycstyle, keycstyle + sizeof(keycstyle), key);
EVP_CIPHER_CTX * ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv);
std::string decodestr = base64_decode(encryptdatas);
const char * ciphertextcstyle = decodestr.c_str();
unsigned char ciphertext[sizeof(ciphertextcstyle)];
std::copy(ciphertextcstyle, ciphertextcstyle + sizeof(ciphertextcstyle), ciphertext);
int len;
int plaintext_len;
unsigned char * plaintext = new unsigned char[1024 + EVP_MAX_BLOCK_LENGTH];
EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);
if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, sizeof(ciphertext)))
{
EVP_CIPHER_CTX_cleanup(ctx);
return -1;
}
plaintext_len = len;
if (!EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
{
EVP_CIPHER_CTX_cleanup(ctx);
return -1;
}
EVP_CIPHER_CTX_cleanup(ctx);
decryptdatas = reinterpret_cast<char*>(plaintext);
return 0;
}
the consequences of Java code which DES/cbc/pkcs5padding was
08yw6mx6giw/tzhQk3ivwQ==
while the consequences of C++ code was
e4CsOw==
any idea?
Upvotes: 1
Views: 1010
Reputation: 49390
There are some errors in the encryptdate
-method:
The sizeof
-operator returns the size of an object or type (see here). This operator is often used incorrectly in the code, e.g. in the following code-snippet:
const char* incstyle = plaindatas.c_str(); // 1)
unsigned char in[sizeof(incstyle)]; // 2)
std::copy(incstyle, incstyle + sizeof(incstyle), in); // 3)
Here you try to copy the content of plaindatas
(which contains the plaintext) into the array in
. In 1)
incstyle
is a pointer (char*
) and therefore has a size of 4 bytes or 8 bytes (depending on whether 32-bit- or 64-bit-OS). sizeof(incstyle)
returns this size and not the length of the string. Therefore, in 2)
an array is defined which is generally too small and thus, in 3)
only a part of the content of plaindatas
is copied into this array.
The array in
is correctly filled with e.g. the following code:
const char* incstyle = plaindatas.c_str();
int in_len = plaindatas.length(); // Number of characters (without terminating 0)
unsigned char *in = new unsigned char[in_len + 1];
std::copy(incstyle, incstyle + in_len + 1, in);
When calling EVP_EncryptUpdate
the plain text length is also determined wrong with the sizeof
-operator (because the length of the array in
has already been determined incorrectly before):
EVP_EncryptUpdate(ctx, &outbuf[written], &temp, in, sizeof(in))
Rather, it should be as follows:
EVP_EncryptUpdate(ctx, outbuf, &temp, in, in_len)
There are further errors in the call of VP_EncryptFinal_ex
if (!EVP_EncryptFinal_ex(ctx, outbuf, &written)) {...}
which must actually be as follows:
if (!EVP_EncryptFinal_ex(ctx, outbuf + temp, &temp)){...}
written += temp;
delete in;
Here you have to pay attention to the update of the ciphertext length (written
) at the end. In addition, the allocated memory for in
can be released here so that no memory leak occurs.
For the-Base64 encoding the length of the ciphertext is determined incorrectly again with the sizeof
-operator:
encryptedatas = base64_encode(outbuf, sizeof(outbuf));
Instead, it has to be:
encryptedatas = base64_encode(outbuf, written);
delete outbuf;
Here, the allocated memory for outbuf
can be released so that no memory leak occurs.
With these changes, the following plain text:
The quick brown fox jumps over the lazy dog
provides the following ciphertext:
lXrmm21mt/5nd+bFm13mmXs+Kca4/wH1ZkbHXNe5/dPkIil7Vr7VuwQ8SeaLvMEh
in accordance with the Java code, if the same key and IV are used. Btw for the testing I used the Base64-encoding from base64 decode snippet in c++.
I only briefly skimmed over the decryptdate
-method. Also here the sizeof
-operator is used incorrectly. Further errors not excluded.
Besides the mentioned bugs the code is also unnecessarily complicated and should be revised if possible. There is a detailed OpenSSL-C/C++-example here for AES-256 in CBC-mode that can be used as a blueprint (where EVP_aes_256_cbc()
has to be replaced by EVP_des_cbc()
, and of course IV and key). Btw DES is insecure and outdated (see e.g. here).
Upvotes: 1