将代码从 C# 加密到 php(使用 phpseclib)

Posted

技术标签:

【中文标题】将代码从 C# 加密到 php(使用 phpseclib)【英文标题】:Encypting code from C# to php (with phpseclib) 【发布时间】:2017-04-18 08:38:11 【问题描述】:

我有一个加密 C# 代码,我正在尝试在 php 和 phpseclib 中实现它并获得完全相同的结果。是 RSA。但我无法完成它。它给了我编码后的 PHP 中的空字符串。

公钥格式如下:

<?xml version="1.0" encoding="utf-16"?>

<RSAParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Exponent>AQAB</Exponent>
      <Modulus>sMFsHSyxAP5N85yvx/XDs9acJa30qwBjoOdDKvNOHJUYBpspwatkdtErCqM2W6tXH9rbvhIn8/nqW4OqAdLinlgkEJoQ/qnzKjYJhHl4YzKFL6Wp+iFRH6ar6ZWOE87LeNQ0nHwlXKoWkJQKV8NB38XRw6aLvNTj8Po2yaFDbQFztsJ+ILkumRh7Leu77IV+124Swc6JqLRt5z2FnDX869dRi2fqcnFa1EHEBsPEndVd2HSeJUncTQiWJ9SNRU+WLltVVewYiGheqr1ABab++3XM5qrB6fWn/RN9Fcg5nM8fachAFSX2YRrEsg7mcbNALRes6OEdpI0LBdX8Wdw6oQ==</Modulus>
    </RSAParameters>

C#代码是:

public static string Encrypt(string data, string public)
    
        RSAParameters pubKey = public;
        var csp = new RSACryptoServiceProvider();
        csp.ImportParameters(pubKey);

        var bytesPlainTextData = System.Text.Encoding.Unicode.GetBytes(data);
        var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
        return Convert.ToBase64String(bytesCypherText);
    

在 PHP 中我正在这样做,但结果是一个空字符串:

$rsa = new Crypt_RSA();
$modulus = new Math_BigInteger(($modulus), 16);
$exponent = new Math_BigInteger(($exponent), 16);
$rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setPublicKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encryptedPassword = $rsa->encrypt($password);

echo $encryptedPassword;

【问题讨论】:

我不熟悉 php 端使用的 biginteger 类,但也许值得注意的是 rsaparameters 以大端表示形式保存数字......至少使用 c# BigInteger 类你可以遇到一些麻烦,因为它需要小端... 你不只是忘记将结果转换为base 64吗?打印随机二进制字节不是一个好主意。 @MaartenBodewes $encryptedPassword 为空,因此没有进行更改 这是基本的故障排除。您是否从系统中收到任何警告? PHP 有时会在错误结果旁边的日志/控制台上生成警告(很好的错误处理)。你的钥匙有多大? “密码”等有多大?这些都是我们看不到的。 没有错误,结果为NULL。我正在尝试的公钥是我发布的那个。密码长度约为 100 个字符。 【参考方案1】:

phpseclib 多年来一直支持这种格式的密钥。根据https://github.com/phpseclib/phpseclib/releases/tag/0.2.2,自 v0.2.2 以来发布的时间还不到五年前。

无论如何,这对我有用:

<?php
include('Crypt/RSA.php');

$xml = '<RSAParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Exponent>AQAB</Exponent>
      <Modulus>sMFsHSyxAP5N85yvx/XDs9acJa30qwBjoOdDKvNOHJUYBpspwatkdtErCqM2W6tXH9rbvhIn8/nqW4OqAdLinlgkEJoQ/qnzKjYJhHl4YzKFL6Wp+iFRH6ar6ZWOE87LeNQ0nHwlXKoWkJQKV8NB38XRw6aLvNTj8Po2yaFDbQFztsJ+ILkumRh7Leu77IV+124Swc6JqLRt5z2FnDX869dRi2fqcnFa1EHEBsPEndVd2HSeJUncTQiWJ9SNRU+WLltVVewYiGheqr1ABab++3XM5qrB6fWn/RN9Fcg5nM8fachAFSX2YRrEsg7mcbNALRes6OEdpI0LBdX8Wdw6oQ==</Modulus>
    </RSAParameters>';

$rsa = new Crypt_RSA();
$rsa->loadKey($xml);

$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encryptedPassword = $rsa->encrypt('password');

echo base64_encode($encryptedPassword);

我不得不从密钥中删除 &lt;?xml version="1.0" encoding="utf-16"?&gt; 位,但除此之外它起作用了。

【讨论】:

亲爱的 neubert,@neubert 您的脚本可以完美地执行并提供加密字符串。但由于某种原因,无法使用 C# 解密正确解密此密钥,这意味着加密算法中的某些内容与 c# 代码不同。如果有帮助,我在 C# 中发现使用加密算法“RSA-PKCS1-KeyEx”。我们是否需要对您提供的基于 Rsa-pkcs1-keyex 的代码进行任何更改? 假设我使用你的代码——即使结果与 c# 加密不一样——解密字符串的代码是什么?如果需要解密,我有盐、私有、矢量数据。 @Simos - 您发布的 C# 代码用于加密 - 而不是解密。对于 PKCS1 填充,我建议您尝试 define('CRYPT_RSA_PKCS15_COMPAT', true); 您好,感谢您的回复。我已经尝试过了,但是加密的字符串仍然与 C# 不同,换句话说,它不能被 c# 解密。我发布的代码是加密的,还有另一个代码在 c# 中再次解密。我正在尝试将 c# 加密代码模拟为 php,但 c# 解密仍将保留。但是我从您的代码中尝试过的所有编码字符串(包括 define('CRYPT_RSA_PKCS15_COMPAT', true);)稍后都无法从 c# 中正确解密。任何其他想法可能会有所不同? @SimosFasouliotis - 然后发布您最新的 C# 代码。正如我之前观察到的,您的 OP 中的 C# 代码似乎是加密的,而不是解密的。我不是 C# 专家,但我尝试修改代码以解密但没有成功:pastebin.com/z8NTCUGw 这是基于您发布的 C# 代码的前四行,并尝试编译它给我一个 error CS0029: Cannot implicitly convert type 'string' to 'System.Security.Cryptography.RSAParameters' 错误。

以上是关于将代码从 C# 加密到 php(使用 phpseclib)的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 与 PHP 的 AES GCM 加密

在会话中存储密码是不是安全? [复制]

c#怎么给源代码加密,就是就算给别人源代码

无法使用AES / ECB / PKCS5Padding将加密方法从Java复制到PHP

无法将数据从 c# 发送到 php

如何将代码从 C# 转换为 PHP [关闭]