C ++ эквивалент Java-шифрования - PullRequest
1 голос
/ 17 апреля 2019

У меня есть следующий фрагмент кода Java, который используется для шифрования

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;
        }
    }
}

Что является эквивалентом шифрования Java в C ++?

Это связано с шифрованием Java. Но не уверен, что эквивалентно. по сути, я хотел бы получить тот же вывод, что генерирует код Java. Я пытался использовать Openssl для шифрования и дешифрования, однако это не работает, я видел кучу примеров Openssl, я до сих пор не знал, что не так Я уже сделал, код пытался сделать шифрование DES / CBC / PKCS5padding

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;
}

последствия Java-кода, которым DES / cbc / pkcs5padding был

08yw6mx6giw/tzhQk3ivwQ==

в то время как последствия кода C ++ были

e4CsOw==

Есть идеи?

1 Ответ

1 голос
/ 18 апреля 2019

В encryptdate -методе есть некоторые ошибки:

  • sizeof -оператор возвращает размер объекта или типа (см. здесь ).Этот оператор часто неправильно используется в коде, например, в следующем фрагменте кода:

    const char* incstyle = plaindatas.c_str();              // 1)
    unsigned char in[sizeof(incstyle)];                     // 2)               
    std::copy(incstyle, incstyle + sizeof(incstyle), in);   // 3)
    

    Здесь вы пытаетесь скопировать содержимое plaindatas (которое содержит открытый текст) в массив in1) incstyle указатель (char*) и, следовательно, имеет размер 4 байта или 8 байтов (в зависимости от того, 32-битная или 64-битная ОС).sizeof(incstyle) возвращает этот размер, а не длину строки.Следовательно, в 2) определяется массив, который обычно слишком мал, и, таким образом, в 3) в этот массив копируется только часть содержимого plaindatas.

    Массив inправильно заполнен, например, следующим кодом:

    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);
    
  • При вызове EVP_EncryptUpdate длина простого текста также определена неправильно с оператором sizeof (так как длина массиваin ранее уже был определен неверно):

    EVP_EncryptUpdate(ctx, &outbuf[written], &temp, in, sizeof(in)) 
    

    Скорее, оно должно быть следующим:

    EVP_EncryptUpdate(ctx, outbuf, &temp, in, in_len)
    
  • В вызове есть другие ошибкииз VP_EncryptFinal_ex

    if (!EVP_EncryptFinal_ex(ctx, outbuf, &written)) {...}
    

    , который на самом деле должен быть следующим:

    if (!EVP_EncryptFinal_ex(ctx, outbuf + temp, &temp)){...}
    written += temp;
    delete in;
    

    Здесь вы должны обратить внимание на обновление длины зашифрованного текста (written) в конце,Кроме того, выделенная память для in может быть освобождена таким образом, чтобы не происходила утечка памяти.

  • Для кодирования-Base64 длина зашифрованного текста снова определяется неправильно с помощью sizeof -оператор:

    encryptedatas = base64_encode(outbuf, sizeof(outbuf));
    

    Вместо этого оно должно быть:

    encryptedatas = base64_encode(outbuf, written); 
    delete outbuf;
    

    Здесь выделенная память для outbuf может быть освобождена, чтобы не происходила утечка памяти.

  • С этими изменениями следующий простой текст:

    The quick brown fox jumps over the lazy dog 
    

    предоставляет следующий зашифрованный текст:

    lXrmm21mt/5nd+bFm13mmXs+Kca4/wH1ZkbHXNe5/dPkIil7Vr7VuwQ8SeaLvMEh
    

    в соответствии с кодом Java,если используются один и тот же ключ и IV.Кстати, для тестирования я использовал кодировку Base64 из фрагмента декодирования base64 в c ++ .

. Я лишь ненадолго просмотрел метод decryptdate.Также здесь оператор sizeof используется неправильно.Дополнительные ошибки не исключены.

Помимо упомянутых ошибок, код также неоправданно сложен и должен быть пересмотрен, если это возможно.Существует подробный OpenSSL-C / C ++ - пример здесь для AES-256 в режиме CBC, который можно использовать в качестве схемы (где EVP_aes_256_cbc() должен быть заменен на EVP_des_cbc(), и, конечно,IV и ключ).Кстати, DES небезопасен и устарел (см., Например, здесь ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...