【问题标题】:AesManaged throwing “Padding is invalid and cannot be removed" depending on length of string to decodeAesManaged 根据要解码的字符串长度抛出“填充无效且无法删除”
【发布时间】:2013-10-18 02:36:53
【问题描述】:

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

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

函数如下:

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,刷新它们,使用不同的键,...

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

【问题讨论】:

    标签: .net encryption


    【解决方案1】:
       myreturn = UnicodeEncoding::Unicode->GetString(outBlock);
    

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

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

       myreturn = Convert::ToBase64String(outBlock);
    

    并在解密时使用 Convert::FromBase64String() 从字符串中恢复 array&lt;Byte&gt;^

    【讨论】:

    • 谢谢!我已将您建议的更改应用于编码函数,该函数将密码存储到文件中。然后解码函数使用'array^ inBlock = Convert::FromBase64String(stringtodeencrypt);'恢复加密文本时。现在,作为紧急情况,直到我完成此操作,有没有办法存储密码以便当前函数可以解密它们?我的意思是那些存储为 Unicode...
    • 看来我对文本编码也知之甚少!:)
    • 您好,非常感谢您的提示。我自己好多年都找不到它了。很抱歉用这个来追你,但我相信你有这个答案:有没有办法我可以重新存储密码,以便旧函数(将字符串读取为 'UnicodeEncoding::Unicode->GetBytes(stringtodeencrypt)' ) 可以解密它们吗?在我可以部署新功能之前,这只是一个临时解决方案......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2021-03-15
    • 1970-01-01
    相关资源
    最近更新 更多