当我try 使用openssl\u encrypt PHP进行加密时,我在解密数据的末尾得到了正方形空间,如附图所示

我的API响应失败,因为在由执行解密期间获得了额外字符.网侧..

如何解决此问题请帮助

C#

public static string Decrypt(String encryptedText, String VendorKey, String Token)
{
    var encryptedBytes = Convert.FromBase64String(encryptedText);
    return Encoding.UTF8.GetString(Decrypt(encryptedBytes, GetRijndaelManaged(VendorKey,Token)));
}

private static byte[] Decrypt(byte[] encryptedData, RijndaelManaged rijndaelManaged)
{
    return rijndaelManaged.CreateDecryptor()
                .TransformFinalBlock(encryptedData, 0, encryptedData.Length);
}

public static RijndaelManaged GetRijndaelManaged(String VendorKey, String Token)
{
    var keyBytes = new byte[32];
    var ivBytes = new byte[16];
            
    var secretKeyBytes = Encoding.UTF8.GetBytes(VendorKey + Token);
    Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));

    var ivKeyBytes = Encoding.UTF8.GetBytes(VendorKey);
    Array.Copy(ivKeyBytes, ivBytes, Math.Min(ivBytes.Length, ivKeyBytes.Length));

    return new RijndaelManaged
    {
       Mode = CipherMode.CBC,
       Padding = PaddingMode.Zeros,
       KeySize = 256, 
       BlockSize = 128, 
       Key = keyBytes,
       IV = ivKeyBytes
    };
}

public static string Encrypt(String plainText, String VendorKey, String Token)
{
    var plainBytes = Encoding.UTF8.GetBytes(plainText);
    return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(VendorKey, Token)));
}

private static byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
    return rijndaelManaged.CreateEncryptor()
                .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}

public static RijndaelManaged GetRijndaelManaged(String VendorKey, String Token)
{
    var keyBytes = new byte[32];
    var ivBytes = new byte[16];
            
    var secretKeyBytes = Encoding.UTF8.GetBytes(VendorKey + Token);
    Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));

    var ivKeyBytes = Encoding.UTF8.GetBytes(VendorKey);
    Array.Copy(ivKeyBytes, ivBytes, Math.Min(ivBytes.Length, ivKeyBytes.Length));

    return new RijndaelManaged
    {
       Mode = CipherMode.CBC,
       Padding = PaddingMode.Zeros,
       KeySize = 256, 
       BlockSize = 128, 
       Key = keyBytes,
       IV = ivKeyBytes
    };
}

所以可以帮我解决这个问题

enter image description here

推荐答案

使用您提供的示例数据时,请使用加密.网络代码:

string vendorKey = "0123456789012345";
string token = "012345";
string pt = @"{""prospectNo"":""SL1000000"",""paymentRequestDateFrom"":""2020-05-28"",""paymentRequestDateTo"":""2020-06-02"",""merchantTransactionId"":""7"",""callerReferenceNo"":""3""}";
string ct = Encrypt(pt, vendorKey, token);
Console.WriteLine(ct);

返回以下密文:

g163a7jXmZKjH1J3RjC7xkPn5+PJWY6wTX9BgxiTY8hkYjsqImlCuvXOtZgUrrfLnwLy1QGUk6iylc/sInV/XJ9sypJ93tCvjRoj4s4RWGKTqUk3bY31JTM6QuYVclw4zNvyq2WUBCc+EMGGYtn5dBAvqiYdTqrJJTae67EZfgc4Fw5ormmf0rCYXQ2mn7mc1Jdg8v2r3LK9FYiwLEbhOA==

PHP代码如下:

<?php
$cipher = "AES-256-CBC"; 

$array =  json_encode(array(
    "prospectNo"=> "SL1000000",
    "paymentRequestDateFrom"=>"2020-05-28",
    "paymentRequestDateTo"=>"2020-06-02",
    "merchantTransactionId"=> "7",
    "callerReferenceNo"=>"3"
    )
);

$token = "012345";
$vendorKey = "0123456789012345";
$key = substr(str_pad($vendorKey . $token, 32, "\0"), 0, 32);
$iv = substr(str_pad($vendorKey, 16, "\0"), 0, 16);

$encrypted_data = openssl_encrypt(zeroPad($array, 16), $cipher, $key, OPENSSL_ZERO_PADDING, $iv); 
print($encrypted_data . "\n");

function zeroPad($text, $bs) { 
    $pad = ($bs - strlen($text) % $bs) % $bs; 
    return ($pad > 0) ? $text . str_repeat("\0", $pad) : $text; 
}
?>

提供相同的密文,因此是您正在寻找的PHP对应项,即在API可以处理由加密的数据的前提下.NET代码,它还必须处理由PHP代码加密的数据.


正如所料,该密文由解密程序解密为正确的明文.NET代码.十六进制编码的明文还揭示了.NET code not删除了填充字节(注意末尾的8 0x00字节):

string vendorKey = "0123456789012345";
string token = "012345";
string ct = "g163a7jXmZKjH1J3RjC7xkPn5+PJWY6wTX9BgxiTY8hkYjsqImlCuvXOtZgUrrfLnwLy1QGUk6iylc/sInV/XJ9sypJ93tCvjRoj4s4RWGKTqUk3bY31JTM6QuYVclw4zNvyq2WUBCc+EMGGYtn5dBAvqiYdTqrJJTae67EZfgc4Fw5ormmf0rCYXQ2mn7mc1Jdg8v2r3LK9FYiwLEbhOA==";
string dt = Decrypt(ct, vendorKey, token);
Console.WriteLine("Plaintext:      " + dt);
Console.WriteLine("Plaintext, hex: " + Convert.ToHexString(Encoding.UTF8.GetBytes(dt)));

输出:

Plaintext:      {"prospectNo":"SL1000000","paymentRequestDateFrom":"2020-05-28","paymentRequestDateTo":"2020-06-02","merchantTransactionId":"7","callerReferenceNo":"3"}
Plaintext, hex: 7B2270726F73706563744E6F223A22534C31303030303030222C227061796D656E74526571756573744461746546726F6D223A22323032302D30352D3238222C227061796D656E745265717565737444617465546F223A22323032302D30362D3032222C226D65726368616E745472616E73616374696F6E4964223A2237222C2263616C6C65725265666572656E63654E6F223A2233227D0000000000000000

这个答案中发布的PHP代码与您的原始PHP代码本质上只在更一般的$key$iv派生(但这对这里使用的vendorKey没有什么区别)和填充上有所不同.原始PHP代码应用openssl_encrypt()使用的默认PKCS#7填充,而当前PHP代码应用零填充.

具体来说,对于当前明文,这意味着原始PHP代码填充0x080808080808,而当前PHP代码填充0x0000000000.自从.NET代码不会删除填充,即使使用当前PHP代码(只是具有不同的值),填充字节仍然存在.

Csharp相关问答推荐

如何使嵌套for-loop更高效?

如何将字节数组转换为字符串并返回?

一种安全的方式来存储SSH凭证(MAUI/C#应用程序)

如何循环遍历XML文档 node 以使用XSLT存储值

`Task`只有在C#中等待时才会运行吗?

在FilePath中搜索一个词,并根据First Match从左到右提取文件路径

使用Audit.EntityFramework,我如何将外键的值设置为相关实体上的属性?

Blazor服务器端的身份验证角色

如何在实体框架中添加包含列表?

当前代码Cosmos DB 3.37.1:PartitionKey key key mismatch exception

有没有更好的方法来在CosmosDB上插入非id?

是否可以将Collectionview中的数组与ObservableCollection绑定?

Postgres ENUM类型在第一次运行时对Dapper不可见

如何从Entity Framework Core中填充ListIInterface

C#静态抽象属性不能被子接口覆盖

删除MudRadio时,MudRadioGroup未 Select 正确的MudRadio

SharpZipLib在文件名前加上目录名,生成tar.gz

在C#中通过Matheval使用自定义公式

为什么Visual Studio 2022建议IDE0251将我的方法设置为只读?

Unity 3D-意外轴捕捉和未知力对脉冲react 行为的影响