0

我知道有很多这样的问题有答案,但我花了几个小时在谷歌上搜索并尝试了我发现的所有建议。

我对密码学知之甚少,但我需要对字符串进行非常简单的加密/解密。好吧,它适用于某些字符串的长度,但不适用于其他字符串,抛出“填充无效......”。我正在使用加密/解密来存储密码。因此,一些密码很好,但其他密码在解密时会失败。密钥和向量是硬编码的,并且始终相同。

以下是功能:

String^ EncryptString(String^ stringtoencrypt,String^ EnKey,String^ EnVector)
{
    String^ myreturn="";
    array<Byte>^ mykey= UnicodeEncoding::Unicode->GetBytes(EnKey);
    array<Byte>^ myvector= UnicodeEncoding::Unicode->GetBytes(EnVector);
    array<Byte>^ inBlock = UnicodeEncoding::Unicode->GetBytes(stringtoencrypt);

    System::Security::Cryptography::AesManaged^ myaes= gcnew AesManaged();
    myaes->Padding=PaddingMode::PKCS7;

    ICryptoTransform^ myaest= myaes->CreateEncryptor(mykey,myvector);
    array<Byte>^ outBlock = myaest->TransformFinalBlock(inBlock, 0, inBlock->Length);
    myreturn = UnicodeEncoding::Unicode->GetString(outBlock);
    return myreturn;
}


String^ DecryptString(String^ stringtodeencrypt,String^ EnKey,String^ EnVector)
{
    String^ myreturn="";
    array<Byte>^ mykey= UnicodeEncoding::Unicode->GetBytes(EnKey);
    array<Byte>^ myvector= UnicodeEncoding::Unicode->GetBytes(EnVector);
    array<Byte>^ inBlock = UnicodeEncoding::Unicode->GetBytes(stringtodeencrypt);//UnicodeEncoding::Unicode->GetBytes(stringtodeencrypt);
    System::Security::Cryptography::AesManaged^ myaes= gcnew AesManaged();
    myaes->Padding=PaddingMode::PKCS7;
    myaes->KeySize=128;

        MemoryStream^ encryptedStream = gcnew MemoryStream();
    ICryptoTransform^ myaest= myaes->CreateDecryptor(mykey,myvector);

    CryptoStream^ decryptStream = gcnew CryptoStream(encryptedStream, myaest, CryptoStreamMode::Write);
    decryptStream->Write(inBlock, 0, inBlock->Length);
    decryptStream->FlushFinalBlock();

    array<Byte>^ outBlock = encryptedStream->ToArray();
        encryptedStream->Close();
    decryptStream->Close();

    //originally it was like this
    //array<Byte>^ outBlock = myaest->TransformFinalBlock(inBlock, 0, inBlock->Length);
    myreturn = UnicodeEncoding::Unicode->GetString(outBlock);
    return myreturn;
}

一个工作和一个不工作之间的唯一区别是字符串的长度。我尝试对字节数组使用不同的编码,使用 TransformFinalBlock,使用 Streams,刷新它们,使用不同的键,......

为什么它会根据字符串的长度而失败?

4

1 回答 1

2
   myreturn = UnicodeEncoding::Unicode->GetString(outBlock);

字符串不能存储任意二进制数据,不是每个字节值都与 Unicode 代码点匹配,并且当字符串被规范化时数据可能会损坏。当二进制数据恰好与 utf-16 代理匹配时,崩溃的可能性也很大。

您必须对其进行编码,这样就不会发生这种情况,base64 编码是常见的选择:

   myreturn = Convert::ToBase64String(outBlock);

并在解密时使用 Convert::FromBase64String()array<Byte>^从字符串中恢复。

于 2013-10-17T17:42:12.067 回答