C# RSA 加密 -> Laravel phpseclib decrypt()
C# RSA Encrpytion -> Laravel phpseclib decrypt()
我正在使用由 phpseclib 生成的密钥对,然后我用它在 C# 中加密消息并在 PHP 中解密。
public键是:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvh4OvlS5+7Skk5Nij296
rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjC
mbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo
6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5
ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEU
askvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczni
WQIDAQAB
-----END PUBLIC KEY-----
到 XML 的转换是通过 https://superdry.apphb.com/tools/online-rsa-key-converter
完成的
以下是消息在 C# 中的加密方式:
public void Synch()
{
string messageToSend = "123";
var encryptedData = EncryptString(messageToSend);
var request = new HTTPRequest(new Uri(APIUrl), HTTPMethods.Post, OnRequestFinished);
request.AddField("message", encryptedData);
request.FormUsage = BestHTTP.Forms.HTTPFormUsage.Multipart;
request.Send();
}
public byte[] EncryptBytes(string message)
{
// https://superdry.apphb.com/tools/online-rsa-key-converter
string XML = "<RSAKeyValue><Modulus>vh4OvlS5+7Skk5Nij296rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjCmbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEUaskvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczniWQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
//get the object back from the stream
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(XML);
byte[] bytesMessage = Encoding.UTF8.GetBytes(message);
var bytesCipherText = rsa.Encrypt(bytesMessage, false);
return bytesCipherText;
}
public string EncryptString(string message)
{
string encryptedText = Convert.ToBase64String(EncryptBytes(message));
return encryptedText;
}
C# 向 PHP 发送(加密消息)的内容(每次都更改):
DE9e82l/lP211YQ0gDhvIcwU1dIXaN7re9+VpUYEB62yRYYnmzZfHxv+WeMHtvg5Yq15Lr4rhvQpTiMGyktxkR5wPQRQhDX74gonPIKgYYIfoqF0mswkulaiLReagcroVyd4ZFEfPxKScLXqjo3yIFLaGWVMGoh81ZwRoOUEGLCPkhsRMp1CiHecGZEmZm7VNoiOEeA5xRdO3asl5/jrbnpXeNXcU4OFV4n1hfdw8W04VHyzDU3AmkDnpfO3AHnZluGPOYpl3OYVn9bsmuqL9d02gBr0UP72vp5GxNoDZAy3tzymhdNZArN9sfBXX+QPOlK2eaFwSypGIa/SUn+erg==
在PHP的解密端:
Route::post('/decrypt', function (Request $request) {
$encoded_message = $request->input('message');
if (!empty($encoded_message)) {
$private = RSA::loadFormat('PKCS8', file_get_contents(resource_path() . '/rsa/key.pem'), $password = false);
try {
$message = $private->decrypt(base64_decode($encoded_message));
echo $message;
}
} catch (Exception $e) {
return response()->json([
'message' => 'Failed to process: '.$e->getMessage().$e->getTraceAsString(),
]);
}
输出是这样的:
Response: {"message":"Failed to process: Decryption error#0 C:\www\laravel\vendor\phpseclib\phpseclib\phpseclib\Crypt\RSA\PrivateKey.php(469):
我在这里错过了什么?
在 C# 代码中应用了 PKCS#1 v1.5 填充(Encrypt()
is false
), phpseclib uses OAEPadding by default (here 的第二个参数)。
如果在 PHP 代码中明确指定 PKCS#1 v1.5 填充,则解密有效:
$message = $private->withPadding(RSA::ENCRYPTION_PKCS1)->decrypt(base64_decode($encoded_message));
或者,可以在 C# 代码中使用 OAEPadding。但要小心,如果在 Encrypt()
中第二个参数设置为 true
,.NET 默认情况下对两个摘要使用 SHA-1。但是,phpseclib 默认情况下对两个摘要应用 SHA-256。因此,在 C# 代码中,为了与 PHP 代码兼容,两个摘要都必须 显式 设置为 SHA256(这在 RSACryptoServiceProvider
中是不可能的,但是RSACng
;另外,需要 Encrypt()
的重载,可以显式设置摘要)。
我正在使用由 phpseclib 生成的密钥对,然后我用它在 C# 中加密消息并在 PHP 中解密。
public键是:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvh4OvlS5+7Skk5Nij296
rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjC
mbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo
6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5
ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEU
askvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczni
WQIDAQAB
-----END PUBLIC KEY-----
到 XML 的转换是通过 https://superdry.apphb.com/tools/online-rsa-key-converter
完成的以下是消息在 C# 中的加密方式:
public void Synch()
{
string messageToSend = "123";
var encryptedData = EncryptString(messageToSend);
var request = new HTTPRequest(new Uri(APIUrl), HTTPMethods.Post, OnRequestFinished);
request.AddField("message", encryptedData);
request.FormUsage = BestHTTP.Forms.HTTPFormUsage.Multipart;
request.Send();
}
public byte[] EncryptBytes(string message)
{
// https://superdry.apphb.com/tools/online-rsa-key-converter
string XML = "<RSAKeyValue><Modulus>vh4OvlS5+7Skk5Nij296rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjCmbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEUaskvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczniWQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
//get the object back from the stream
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(XML);
byte[] bytesMessage = Encoding.UTF8.GetBytes(message);
var bytesCipherText = rsa.Encrypt(bytesMessage, false);
return bytesCipherText;
}
public string EncryptString(string message)
{
string encryptedText = Convert.ToBase64String(EncryptBytes(message));
return encryptedText;
}
C# 向 PHP 发送(加密消息)的内容(每次都更改):
DE9e82l/lP211YQ0gDhvIcwU1dIXaN7re9+VpUYEB62yRYYnmzZfHxv+WeMHtvg5Yq15Lr4rhvQpTiMGyktxkR5wPQRQhDX74gonPIKgYYIfoqF0mswkulaiLReagcroVyd4ZFEfPxKScLXqjo3yIFLaGWVMGoh81ZwRoOUEGLCPkhsRMp1CiHecGZEmZm7VNoiOEeA5xRdO3asl5/jrbnpXeNXcU4OFV4n1hfdw8W04VHyzDU3AmkDnpfO3AHnZluGPOYpl3OYVn9bsmuqL9d02gBr0UP72vp5GxNoDZAy3tzymhdNZArN9sfBXX+QPOlK2eaFwSypGIa/SUn+erg==
在PHP的解密端:
Route::post('/decrypt', function (Request $request) {
$encoded_message = $request->input('message');
if (!empty($encoded_message)) {
$private = RSA::loadFormat('PKCS8', file_get_contents(resource_path() . '/rsa/key.pem'), $password = false);
try {
$message = $private->decrypt(base64_decode($encoded_message));
echo $message;
}
} catch (Exception $e) {
return response()->json([
'message' => 'Failed to process: '.$e->getMessage().$e->getTraceAsString(),
]);
}
输出是这样的:
Response: {"message":"Failed to process: Decryption error#0 C:\www\laravel\vendor\phpseclib\phpseclib\phpseclib\Crypt\RSA\PrivateKey.php(469):
我在这里错过了什么?
在 C# 代码中应用了 PKCS#1 v1.5 填充(Encrypt()
is false
), phpseclib uses OAEPadding by default (here 的第二个参数)。
如果在 PHP 代码中明确指定 PKCS#1 v1.5 填充,则解密有效:
$message = $private->withPadding(RSA::ENCRYPTION_PKCS1)->decrypt(base64_decode($encoded_message));
或者,可以在 C# 代码中使用 OAEPadding。但要小心,如果在 Encrypt()
中第二个参数设置为 true
,.NET 默认情况下对两个摘要使用 SHA-1。但是,phpseclib 默认情况下对两个摘要应用 SHA-256。因此,在 C# 代码中,为了与 PHP 代码兼容,两个摘要都必须 显式 设置为 SHA256(这在 RSACryptoServiceProvider
中是不可能的,但是RSACng
;另外,需要 Encrypt()
的重载,可以显式设置摘要)。