在 c# 和 php 中使用 Bouncy Castle 进行加密和解密
Encrypt and Decrypt using Bouncy Castle in c# and php
我在c#中使用bouncy castle和以下代码在c#中加密和解密数据
public static string BCEncrypt(string input)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = new byte[16];
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
//PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
return Convert.ToBase64String(outputBytes);
}
public static string BCDecrypt(string input)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = new byte[16];
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
//Decrypt
byte[] outputBytes = Convert.FromBase64String(input);
cipher.Init(false, keyParamWithIV);
byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length); //Do the final block
return System.Text.Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length);
}
这是代码 php 我正在使用的代码:
<?
function encrypt($input, $key) {
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$input = Security::pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
function pkcs5_pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function decrypt($sStr, $sKey) {
$decrypted= mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$sKey,
base64_decode($sStr),
MCRYPT_MODE_ECB
);
$dec_s = strlen($decrypted);
$padding = ord($decrypted[$dec_s-1]);
$decrypted = substr($decrypted, 0, -$padding);
return $decrypted;
}
echo "Input: " . $_REQUEST["inp"] . "<br>Decrypt: ". decrypt($_REQUEST["inp"], 'mysecretkey12345')."<br>";
?>
当我尝试使用 c# 加密短字符串时,例如 "greatscott" 我得到以下结果:dSk7z0F4JYsc0zhl95+yMw==
然后使用php代码解密就可以了。
然而,当我尝试使用 "this is a very long string" 等 C# 代码加密更长的字符串时,我得到以下结果:xcL4arrFD8Fie73evfHjvUjNEmZrA9h6SmO0ZRE82Hw=
而且这个不解密。如果我尝试通过 php 加密函数加密相同的字符串 "this is a very long string" 我得到 xcL4arrFD8Fie73evfHjva6yJyeUOrB8IudISDhQk24=
所以加密字符串的前半部分相同,后半部分不同。这让我觉得我的填充不正确或什么的。
如有任何建议,我们将不胜感激。
谢谢
感谢 Luke 和 James 的建议。
我现在在 PHP 中使用 openssl 进行加密和解密,我正在生成一个随机 IV 并在系统之间来回传递它以进行解密。
这是我现在使用的代码:
c#
public static string BCEncrypt(string input, out string iv_base64)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.NextBytes(iv);
iv_base64 = Convert.ToBase64String(iv);
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
return Convert.ToBase64String(outputBytes);
}
public static string BCDecrypt(string input, string iv_base64)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = Convert.FromBase64String(iv_base64);
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
//Decrypt
byte[] outputBytes = Convert.FromBase64String(input);
cipher.Init(false, keyParamWithIV);
byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length); //Do the final block
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length);
}
PHP 的一面是这样的:
$iv = base64_decode($iv_base64);
$method = "aes-128-cbc";
$password = "mysecretkey12345";
$decrypted = openssl_decrypt($data, $method, $password,0, $iv);
并生成 iv 并在 PHP 中加密字符串我正在使用:
$iv = openssl_random_pseudo_bytes(16)
$encrypted = openssl_encrypt("something interesting", $method, $password,0,$iv);
所以我现在可以在 C# 或 PHP 中加密并在 C# 或 PHP 中解密。
我正在使用 https 在两个系统之间传递 base 64 编码的 iv 和加密的字符串。
对此解决方案有何评论? (安全还是其他?)
我在c#中使用bouncy castle和以下代码在c#中加密和解密数据
public static string BCEncrypt(string input)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = new byte[16];
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
//PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
return Convert.ToBase64String(outputBytes);
}
public static string BCDecrypt(string input)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = new byte[16];
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
//Decrypt
byte[] outputBytes = Convert.FromBase64String(input);
cipher.Init(false, keyParamWithIV);
byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length); //Do the final block
return System.Text.Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length);
}
这是代码 php 我正在使用的代码:
<?
function encrypt($input, $key) {
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$input = Security::pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
function pkcs5_pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function decrypt($sStr, $sKey) {
$decrypted= mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$sKey,
base64_decode($sStr),
MCRYPT_MODE_ECB
);
$dec_s = strlen($decrypted);
$padding = ord($decrypted[$dec_s-1]);
$decrypted = substr($decrypted, 0, -$padding);
return $decrypted;
}
echo "Input: " . $_REQUEST["inp"] . "<br>Decrypt: ". decrypt($_REQUEST["inp"], 'mysecretkey12345')."<br>";
?>
当我尝试使用 c# 加密短字符串时,例如 "greatscott" 我得到以下结果:dSk7z0F4JYsc0zhl95+yMw==
然后使用php代码解密就可以了。
然而,当我尝试使用 "this is a very long string" 等 C# 代码加密更长的字符串时,我得到以下结果:xcL4arrFD8Fie73evfHjvUjNEmZrA9h6SmO0ZRE82Hw=
而且这个不解密。如果我尝试通过 php 加密函数加密相同的字符串 "this is a very long string" 我得到 xcL4arrFD8Fie73evfHjva6yJyeUOrB8IudISDhQk24=
所以加密字符串的前半部分相同,后半部分不同。这让我觉得我的填充不正确或什么的。
如有任何建议,我们将不胜感激。
谢谢
感谢 Luke 和 James 的建议。
我现在在 PHP 中使用 openssl 进行加密和解密,我正在生成一个随机 IV 并在系统之间来回传递它以进行解密。
这是我现在使用的代码:
c#
public static string BCEncrypt(string input, out string iv_base64)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.NextBytes(iv);
iv_base64 = Convert.ToBase64String(iv);
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
return Convert.ToBase64String(outputBytes);
}
public static string BCDecrypt(string input, string iv_base64)
{
string keyString = "mysecretkey12345";
string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString));
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = Convert.FromBase64String(iv_base64);
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
//Decrypt
byte[] outputBytes = Convert.FromBase64String(input);
cipher.Init(false, keyParamWithIV);
byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length); //Do the final block
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length);
}
PHP 的一面是这样的:
$iv = base64_decode($iv_base64);
$method = "aes-128-cbc";
$password = "mysecretkey12345";
$decrypted = openssl_decrypt($data, $method, $password,0, $iv);
并生成 iv 并在 PHP 中加密字符串我正在使用:
$iv = openssl_random_pseudo_bytes(16)
$encrypted = openssl_encrypt("something interesting", $method, $password,0,$iv);
所以我现在可以在 C# 或 PHP 中加密并在 C# 或 PHP 中解密。
我正在使用 https 在两个系统之间传递 base 64 编码的 iv 和加密的字符串。
对此解决方案有何评论? (安全还是其他?)