сопоставление шифрования от C ++ (crypto ++) до c # - PullRequest
0 голосов
/ 22 января 2019

Я пытаюсь сопоставить схемы шифрования на c ++ с использованием crypto ++ и c # и не могу получить одинаковые результаты на обоих. Они оба работают над собой, но не от одного к другому. Любая помощь будет отличной!

C ++ код с использованием Crypto ++:

std::string key = "01286567891233460123456789123456";
std::string iv = "0123456789123456";

std::string encrypt(const std::string& str_in)
{
    std::string str_out;

    CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());

    StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
    stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);
    stfEncryptor.MessageEnd();

    return str_out;
}
std::string decrypt(const std::string& cipher_text)
{
    std::string str_out;
    CryptoPP::AES::Decryption aesDecryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, (byte*)iv.c_str());

    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(str_out));
    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(cipher_text.c_str()), cipher_text.size());
    stfDecryptor.MessageEnd();

    return str_out;
}

Код Ран:

 std::string str = encrypt("123456789012345");
 str = decrypt(str);

Этот вывод:

 Encrypted: Ö&qcƒ“¹yLY»Lïv¹w“¼LLŠÀ¶ó¢,óð9·
 Length: 32
 Decrypted: 123456789012345
 Length: 16

Теперь в C # у меня есть следующий код:

 public string Encrypt(string clearText)
 {
       byte[] clearBytes = Encoding.Default.GetBytes(clearText);

       using (Aes encryptor = Aes.Create("AES"))
       {
           // encryptor.BlockSize = 128;
            encryptor.Padding = PaddingMode.Zeros;
            encryptor.KeySize = 128;
            encryptor.Mode = CipherMode.CBC;
            encryptor.Key = Encoding.Default.GetBytes("01234567891234560123456789123456");
            encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                byte[] bt = ms.ToArray();
                clearText = Encoding.Default.GetString(bt);// Convert.ToBase64String(bt);
            }
        }
        return clearText; //Return the encrypted command
  }

 public string Decrypt(string cipherText)
 {
       byte[] clearBytes = Encoding.Default.GetBytes(cipherText);

        using (Aes decryptor = Aes.Create("AES"))
        {
              // decryptor.BlockSize = 128;
                decryptor.Padding = PaddingMode.Zeros;
                decryptor.KeySize = 128;
                decryptor.Mode = CipherMode.CBC;
                decryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
                decryptor.IV = Encoding.Default.GetBytes("0123456789123456");
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    byte[] bt = ms.ToArray();
                    cipherText = Encoding.Default.GetString(bt);// Convert.ToBase64String(bt);
                }
         }

         return cipherText; //Return the decrypted text
     }
}

Код работал:

string orig = "123456789012345";
string cipher = Encrypt(orig);
string dedata = Decrypt(cipher);

Результаты:

Orig: 123456789012345
Encrypted: êßyoº0¦ëì›X˜Ü
Length: 16
Decrypted: 123456789012345 
Length: 16

Как видите, зашифрованные строки оказываются разными. Поэтому, когда я беру зашифрованную строку в c ++, она не может расшифровать ее в c #, как показано здесь:

bytes[] encryptedText = ENCRYPTED TEXT FROM C++
text = System.Text.Encoding.Default.GetString(encryptedText);
text = Decrypt(text);

C ++ возвращает 32 байта для своей зашифрованной строки, которую я считаю добавляемым дополнением. Не уверен, как повторить это в коде c # или наоборот, чтобы все соответствовало. Не уверен, что здесь что-то еще мне не хватает ... Спасибо за любую помощь!

EDIT:

Я сопоставил ключи, и теперь строка совпадает на обоих концах, за исключением разницы заполнения. Когда я пытаюсь расшифровать строку в C #, он говорит мне, что входные данные имеют неправильный размер блока? Любая помощь с этим сейчас?

ИЗМЕНИТЬ СНОВА:

Кажется, что она генерирует одну и ту же байтовую строку для каждой функции шифрования c # и c ++, поэтому проблема решена. Мне кажется, что проблема на стороне c # - я получаю зашифрованную строку и преобразую байты с помощью: text = System.Text.Encoding.Default.GetString (recvBuf); recvBuf - это зашифрованная строка из c ++, в которой отсутствует последний символ строки. Это совпадает со строкой c ++ минус последний символ ?? Не уверен, почему это происходит.

Например, мой c ++ отправляет по этой зашифрованной строке: Ö & qcƒ «LYyLY» Liv, а моя программа на c # получит только следующее: Ö & qcƒ «¹yLY» Lï, что, в свою очередь, приведет к сбою при расшифровке. Зашифрованная строка отправляется через сокет TCP, если это имеет какое-либо значение.

EDIT

Все еще отсутствуют байты после изменения кодирования и декодирования на base64 на обоих концах.

C++ 1iZxY4OTHrl5TFm7Gkzvdrl3k7xMTIrAtvOiLPPwObc=
C# 1iZxY4OTHrl5TFm7Gkzvdg==
C# RECEIVED 1iZxY4OTHrl5TFm

Новый код C #:

    public string Encrypt(string clearText)
    {
        byte[] clearBytes = Encoding.Default.GetBytes(clearText);

        using (Aes encryptor = Aes.Create("AES"))
        {
           // encryptor.BlockSize = 128;
            encryptor.Padding = PaddingMode.Zeros;
            encryptor.KeySize = 128;
            encryptor.Mode = CipherMode.CBC;
            encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
            encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }
                byte[] bt = ms.ToArray();
                clearText =  Convert.ToBase64String(bt);
            }
        }
        return clearText; //Return the encrypted command
    }

и код C ++:

std::string encrypt(const std::string& str_in)
{
    std::string str_out;
    std::string str_out2;

    CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());

    StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
    stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);
    stfEncryptor.MessageEnd();

    str_out2 = base64_encode(reinterpret_cast<const unsigned char*>(str_out.c_str()), strlen(str_out.c_str()));

    return str_out2;
}

РЕДАКТИРОВАТЬ

ЭТО РАБОТАЕТ !!! Это было просто упущением с моей стороны, мой сокет проверял размер данных перед шифрованием и отправлял этот размер вместо размера зашифрованной строки. Исправить это и все это работает идеально. Спасибо Брэндон за помощь!

1 Ответ

0 голосов
/ 23 января 2019

Я предлагаю вам запутаться в кодировке текста как при преобразовании открытого текста в байты для шифрования, так и при преобразовании из байтов в отображаемую строку для «передачи».

Попробуйте это:

C # код

public string Encrypt(string clearText, Encoding encoding)
{
  // use supplied encoding to convert clear text to bytes
  byte[] clearBytes = encoding.GetBytes(clearText);

  byte[] bt = // insert your encrypt code here...
  // bt bytes are *not* ascii or utf8 or anything else.  If you just
  // use an encoding to convert to text, you won't have good results
  // lets use base64 encoding to get a nice display string representation
  // of the bytes
  return Convert.ToBase64String(bt);
}

public string Decrypt(string base64EncryptedString, Encoding encoding)
{
  // decode the base64
  byte[] bt = Convert.FromBase64String(base64EncryptedString);

  byte[] decrypted = // insert your decrypt code here

  // now we have the original bytes.  Convert back to string using the same
  // encoding we used when encrypting
  return encoding.GetString(decrypted);
}


// Usage:
var clearText = "Hello World";
var asciiEncrypted = Encrypt(clearText, Encoding.ASCII);
var decrypted = Decrypt(clearText, Encoding.ASCII); // MUST USE SAME ENCODING

var utf8Encrypted = Encrypt(clearText, Encoding.UTF8);
var utf8Decrypted = Decrypt(clearText, Encoding.UTF8);

Вам необходимо внести такие же base64 изменения в ваш код C ++.Я менее знаком с кодировкой ваших строк C ++.Я думаю , что если вы используете строковые литералы C ++, жестко запрограммированные в коде, то они будут UTF8.Это означает, что ваш код C ++ и C # должен согласовываться после внесения изменений в C #, внесения изменений base64 в ваш код C ++ и передачи UTF8 в ваши методы C # Encrypt / Decrypt.

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