c# - 登录 phpseclib 并在 C# 中验证

标签 c# php rsa sign phpseclib

我正在尝试跨 PHP (phpseclib) 和 C# 验证消息的真实性。

但是,C#端的验证似乎存在一些问题。

我尝试过的:

  1. 向 C# 提供公钥,但让 C# 计算哈希值和签名,然后进行验证(输出:True)
  2. 将哈希更改为在 PHP 中计算的哈希,但让 C# 计算签名然后验证(输出:True)
  3. 让 C# 使用 PHP 计算出的哈希值和签名,然后进行验证(输出:False)

PHP 代码:

//Load private key
$rsa = PublicKeyLoader::load("... private key ...", false);

//Set PKCS1 mode
$rsa->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1)->withHash("sha256");

//Generate and Convert the hash from 64 byte hex to 32 byte
$hash = pack("H*", hash("sha256", "test"));

//Sign the hash and encode it
$signed_hash = base64_encode($rsa->sign($hash));

//Encode the hash
$hash = base64_encode($hash);

C# 代码:

static void Main()
{
    //Create a new instance of RSA.
    using (RSA rsa = RSA.Create())
    {
        //Load public key from XML string
        rsa.FromXmlString("... public key ...");

        //Create an RSAPKCS1SignatureDeformatter object and pass it the RSA instance
        //to transfer the key information.
        RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
        RSADeformatter.SetHashAlgorithm("SHA256");

        //decode the hash
        var hash = Convert.FromBase64String("SHA256 Hash As Base64");
        var signedHash = Convert.FromBase64String("SHA256 Hash Signature As Base64");

        //Verify the hash and display the results to the console.
        if (RSADeformatter.VerifySignature(hash, signedHash))
        {
            Console.WriteLine("True");
        }
        else
        {
            Console.WriteLine("False");
        }
    }
}

最佳答案

两个代码都存在问题:

  • 默认情况下,phpseclib 使用 PSS 作为填充(此处和以下 v3 假设)。尽管填充显式设置为 PKCS#1 v1.5,但由于未应用返回值,因此未使用它。为了使填充更改​​生效,必须考虑返回值。
    顺便说一下,这里默认的是 SHA256。并且 RSA::ENCRYPTION_PKCS1 在签名/验证上下文中会被忽略,也可以删除。

  • phpseclib 在签名时隐式对数据进行哈希处理。由于在当前的 phpseclib 代码中,哈希值是另外显式生成的,因此完成了双重哈希值。这种双重哈希不是必需的,可以删除。

  • 末尾的双重 Base64 编码也是不必要的,也可以删除。

    总体:

    ...
    
    //Set PKCS1 mode
    $rsa = $rsa->withPadding(RSA::SIGNATURE_PKCS1)->withHash("sha256");
    
    //Sign the hash and encode it
    $signature = base64_encode($rsa->sign("test"));
    print($signature . PHP_EOL); 
    

    PKCS#1v1.5 是确定性的,即对于相同的输入数据,重复签名会产生相同的签名。


  • 与 PHP 代码不同,C# 代码中不会进行隐式哈希处理,因此必须显式进行。

    然后可以使用 C# 代码进行验证:

    ...
    
    var hash = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes("test"));
    var signature = Convert.FromBase64String("<Base64 encoded signature from PHP code>");
    Console.WriteLine(RSADeformatter.VerifySignature(hash, signature)); // True
    

关于c# - 登录 phpseclib 并在 C# 中验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70041715/

相关文章:

c# - 将 Webbrowser 与 Control.invoke 结合使用

encryption - 更改私钥中的几个字符是否应该对其进行有意义的更改?

ios - iOS 上的 RSA 加密 (RSA/ECB/PKCS1Padding)

java - 有 Spring PHP 项目吗?

php - 如何获取三级分类(Category,SubCategory,SubCategoryThree)的数据并显示所选分类下的相关数据

Python 密码学导出 key 到 DER

c# - 如何在C#中使用SHA1和MD5?(性能和安全性哪个更好)

c# - 在 DataGrid 中看不到文本框文本

c# - 如何从 Salesforce 获取 consumer Key 和 consumer Secret

php - 设计比赛支架 - 不能很好地组合在一起