Итак, у меня есть этот фрагмент php-кода, который мне не разрешено изменять, в основном потому, что он старый и работает правильно.
Внимание! Очень плохой код в целом. IV не рандомизируется и не сохраняется вместе с выходом. Я не спрашиваю об этом, потому что хочу,
Я спрашиваю, потому что мне нужно. Я также планирую рефакторинг, когда получу эту работу, и дополню свой код C # действительно надежным шифровальным кодом.
function encrypt($string)
{
$output = false;
$encrypt_method = "AES-256-CBC";
$param1 = 'ASasd564D564aAS64ads564dsfg54er8G74s54hjds346gf445gkG7';
$param2 = '654dsfg54er8ASG74sdfg54hjdas346gf34kjdDJF56hfs2345gkFG';
$ky = hash('sha256', $param1); // hash
$iv = substr(hash('sha256', $param2), 0, 16);
$output = openssl_encrypt($string, $encrypt_method, $ky, 0, $iv);
$output = base64_encode($output);
return $output;
}
Я хочу сделать то же самое в C #, потому что я получаю сущность со всеми ее полями, зашифрованными этим кодом.
Я хочу иметь возможность зашифровать эти данные, чтобы я мог запросить свой список сущностей без необходимости расшифровывать все сущности. И я хочу расшифровать некоторые свойства отфильтрованных объектов, чтобы они действительно могли быть полезны.
Теперь, к тому же, я создал CryptoHelper, который будет делать это, кроме случаев, когда это не так.
Я пытаюсь вычислить Ключ и IV в конструкторе:
public readonly byte[] Key;
public readonly byte[] IV;
public CryptoHelper()
{
Key = GetByteArraySha256Hash("ASasd564D564aAS64ads564dsfg54er8G74s54hjds346gf445gkG7", false);
IV = GetByteArraySha256Hash("654dsfg54er8ASG74sdfg54hjdas346gf34kjdDJF56hfs2345gkFG", true);
}
private byte[] GetByteArraySha256Hash(string source, bool salt)
{
byte[] result;
try
{
using (SHA256 sha256Hash = SHA256.Create())
{
result = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(source));
}
}
catch (Exception)
{
throw;
}
if (salt)
{
return result.Take(16).ToArray();
}
return result;
}
А затем используйте методы Encrypt и Decrypt, которые работают довольно хорошо, когда я тестирую их с помощью тестовой строки. Единственная проблема заключается в том, что в конце строки есть некоторый отступ, но это небольшая проблема, учитывая, что любая строка, зашифрованная с помощью метода php, приводит к бреду.
private string Encrypt(string source)
{
try
{
string result = "";
using (var aes = new AesManaged { Key = Key, IV = IV, Mode = CipherMode.CBC, Padding = PaddingMode.Zeros })
{
byte[] sourceByteArray = Encoding.UTF8.GetBytes(source);
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
{
byte[] encriptedSource = encryptor.TransformFinalBlock(sourceByteArray, 0, sourceByteArray.Length);
result = Convert.ToBase64String(encriptedSource);
result = Convert.ToBase64String(Encoding.UTF8.GetBytes(result));
}
}
return result;
}
catch (Exception ex)
{
throw;
}
}
private string Decrypt(string source)
{
try
{
string result = "";
//Double Base64 conversion, as it's done in the php code.
byte[] sourceByte = Convert.FromBase64String(source);
byte[] sourceFreeOfBase64 = Convert.FromBase64String(Encoding.UTF8.GetString(sourceByte));
byte[] resultByte;
int decryptedByteCount = 0;
using (var aes = new AesManaged { Key = Key, IV = IV, Mode = CipherMode.CBC, Padding = PaddingMode.Zeros })
{
using (ICryptoTransform AESDecrypt = aes.CreateDecryptor(aes.Key, aes.IV))
{
using (MemoryStream memoryStream = new MemoryStream(sourceFreeOfBase64))
{
using (CryptoStream cs = new CryptoStream(memoryStream, AESDecrypt, CryptoStreamMode.Read))
{
resultByte = new byte[sourceFreeOfBase64.Length];
decryptedByteCount = cs.Read(resultByte, 0, resultByte.Length);
}
}
}
//This returns the encoded string with a set of "\0" at the end.
result = Encoding.UTF8.GetString(resultByte);
result = result.Replace("\0", "");
}
return result;
}
catch (Exception ex)
{
throw;
}
}
Я почти уверен, что главная проблема здесь заключается в строке php $iv = substr(hash('sha256', $param2), 0, 16);
. Я проверил результаты обеих хеш-функций в php и C # и они абсолютно одинаковы.
Из того, что я читал, php рассматривает строки как байтовые массивы (поправьте меня, если я ошибаюсь), поэтому строки из 16 символов должно быть достаточно для получения массива из 16 байтов и блока 128. Но в C #, когда я получаю 16-байтовый массив и преобразовываю его в строку, я получаю строку из 32 символов, такую же, как если бы я сделал $iv = substr(hash('sha256', $param2), 0, 32);
.
Итак, мой вопрос: как получить тот же результат массива байтов в C #, который я получаю в этой строке $iv = substr(hash('sha256', $param2), 0, 16);
php? Это вообще возможно?