我们尝试通过加密的数据通信连接两个平台。当文本大小小于keysize时,我们俩都可以加密和解密数据。当密码大小增长时,C#端可以解密数据,而PHP端则不能。
下面我们用于加密和解密的代码
我们在C#上使用Bouncy Castle Crypto API
C#加密
public static string Encrypt(string text, RSACryptoServiceProvider publicKeyRSAProvider)
{
if (publicKeyRSAProvider == null)
{
throw new Exception("_publicKeyRsaProvider is null");
}
var plaintextData = Encoding.UTF8.GetBytes(text);
//var plaintextData = GZipCompress(Encoding.UTF8.GetBytes(text));
var maxBlockSize = (publicKeyRSAProvider.KeySize / 8) - 11;
if (plaintextData.Length <= maxBlockSize)
{
return Convert.ToBase64String(publicKeyRSAProvider.Encrypt(plaintextData, false));
}
using (var plaiStream = new MemoryStream(plaintextData))
{
using (var crypStream = new MemoryStream())
{
var buffer = new byte[maxBlockSize];
var blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toEncrypt = new byte[blockSize];
Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
var cryptograph = publicKeyRSAProvider.Encrypt(toEncrypt, false);
crypStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
}
return Convert.ToBase64String(crypStream.ToArray());
//return Convert.ToBase64String(GZipCompress(crypStream.ToArray()));
}
}
}
C#Decrpyt
public static string Decrypt(string ciphertext, RSACryptoServiceProvider privateKeyRSAProvider)
{
if (privateKeyRSAProvider == null)
{
throw new Exception("_privateKeyRsaProvider is null");
}
var ciphertextData = Convert.FromBase64String(ciphertext);
//var ciphertextData = GZipUncompress(Convert.FromBase64String(ciphertext));
var maxBlockSize = privateKeyRSAProvider.KeySize / 8;
if (ciphertextData.Length <= maxBlockSize)
return Encoding.UTF8.GetString(privateKeyRSAProvider.Decrypt(ciphertextData, false));
using (var crypStream = new MemoryStream(ciphertextData))
{
using (var plaiStream = new MemoryStream())
{
var buffer = new byte[maxBlockSize];
var blockSize = crypStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
var toDecrypt = new byte[blockSize];
Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
var plaintext = privateKeyRSAProvider.Decrypt(toDecrypt, false);
plaiStream.Write(plaintext, 0, plaintext.Length);
blockSize = crypStream.Read(buffer, 0, maxBlockSize);
}
return Encoding.UTF8.GetString(plaiStream.ToArray());
//return Encoding.UTF8.GetString(GZipUncompress(plaiStream.ToArray()));
}
}
}
PHP解密
function DecryptLargeData($data,$privateKey,$compress=false){
// Get the private Key
//
$data = base64_decode($data);
$pkImport = openssl_pkey_get_private($privateKey);
$a_key = openssl_pkey_get_details($pkImport);
// Decrypt the data in the small chunks
$chunkSize = ceil($a_key['bits'] / 8);
$output = '';
while ($data)
{
$chunk = substr($data, 0, $chunkSize);
$data = substr($data, $chunkSize);
$decrypted = '';
if (!openssl_private_decrypt($chunk, $decrypted, $privateKey))
{
die('Failed to decrypt data');
}
$output .= $decrypted;
}
openssl_free_key($privateKey);
// Uncompress the unencrypted data.
if($compress)
return $data;
else
return gzcompress($data);
}
PHP加密
public function EncryptLargeData($data,$privatekey,$publickey,$compress=false){
// Ref : https://www.virendrachandak.com/techtalk/encryption-using-php-openssl/
$pkImport = openssl_pkey_get_private($privatekey); // import
// Get the public Key of the recipient
$a_key = openssl_pkey_get_details($pkImport);
// Encrypt the data in small chunks and then combine and send it.
$chunkSize = ceil($a_key['bits'] / 8) - 11;
$output = '';
if($compress)
$plaintext = gzcompress($data);
else
$plaintext = $data;
while ($plaintext)
{
$chunk = substr($plaintext, 0, $chunkSize);
$plaintext = substr($plaintext, $chunkSize);
$encrypted = '';
if (!openssl_public_encrypt($chunk, $encrypted, $publickey))
{
die('Failed to encrypt data');
}
$output .= $encrypted;
}
openssl_free_key($publickey);
// This is the final encrypted data to be sent to the recipient
$encrypted = $output;
return base64_encode($encrypted);
}