簡體   English   中英

將加密從C ++(crypto ++)匹配到c#

[英]matching encryption from C++ (crypto++) to c#

我正在嘗試使用crypto ++和c#匹配c ++上的加密方案,但似乎都無法獲得相同的結果。 他們倆都自己工作,但彼此之間卻沒有。 任何幫助將是巨大的!

使用Crypto ++的C ++代碼:

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#代碼中復制它,反之亦然,以匹配它們。 不確定是否還有其他我想念的地方...感謝您的幫助!

編輯:

我已經匹配了鍵,現在字符串在兩端都匹配,除了填充差異。 當我嘗試在C#中解密字符串時,它告訴我輸入數據的塊大小不正確? 現在有什么幫助嗎?

再次編輯:

它似乎為每個c#和c ++加密函數生成相同的字節字符串,因此該問題得以解決。 我現在似乎遇到的問題是在c#端,我收到了加密的字符串並使用以下方式轉換字節:text = System.Text.Encoding.Default.GetString(recvBuf); recvBuf是來自c ++的加密字符串,並且缺少該字符串的最后一個字符。 它與減去最后一個字符的c ++字符串匹配? 不知道為什么會這樣。

例如,我的c ++發送此加密的字符串:Ö&qcƒ” yy»Lïv,而我的c#程序將僅接收此:Ö&qcƒ”¹yLY»Lï,這反過來會使解密失敗。 如果有任何區別,則將通過TCP SOCKET發送加密的字符串。

編輯

在兩端將編碼和解碼更改為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;
}

編輯

有用!!! 這只是我的一個忽略,我的套接字正在加密之前檢查數據的大小,然后發送該大小而不是加密的字符串大小。 修復該問題,使其一切正常。 感謝布蘭登的幫助!

我建議您在將明文轉換為字節進行加密以及從字節轉換為顯示字符串以進行“傳輸”時,都對文本編碼產生誤解。

嘗試這個:

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

您需要在C ++代碼中進行相同的 base64更改。 我對您的C ++字符串的編碼不太熟悉。 認為 ,如果您在代碼中使用的是硬編碼的C ++字符串文字,那么它們將是UTF8。 這意味着一旦進行C#更改,在C ++代碼中進行base64更改並將UTF8傳遞給C#加密/解密方法,您的C ++和C#代碼就應該達成共識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM