C# расшифровка данных из Yii2, в частности, сравнение MAC.
Итак, теперь у меня есть рабочая версия функции расшифровки AES, которая берет данные с сервера с yii2 в качестве фреймворка. Yii2 имеет встроенное шифрование по ключу и дешифрование по ключу. У меня есть yii2 для использования AES-192-CBC. Недавно я получил помощь, пытаясь выяснить, как расшифровать данные и выполнил эту задачу с помощью пользователя VSTM.
Если кто-то хочет увидеть первую проблему, посмотрите проблему здесь.
Итак, я уверен, что моя проблема где-то в том, как данные отправляются и принимаются. Я думаю, что мне нужно как-то преобразовать его, чтобы можно было правильно сравнить отправленный код аутентификации сообщений с данными и MAC-адрес, который я вычисляю.
Yii2 и написанная мной форма C# используют sha256 для хеширования данных. Код Yii2 ниже.
$helpers = new Json();
$data = $helpers::encode($array);
Yii::$app->security->cipher = "AES-192-CBC";
$string = Yii::$app->security->encryptByKey($data, $key);
$response = Yii::$app->getResponse();
$response->format = yii\web\Response::FORMAT_RAW;
$response->content = $string;
return $response->send();
Этот блок кода возвращает зашифрованную строку в программу через веб-запрос в формате. [KeySalt][MAC][IV][шифротекста]
Я получаю эти данные в C# со следующим кодом.
try
{
var data = new MemoryStream();
var WR = (HttpWebRequest)WebRequest.Create(url);
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
WR.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
WR.UserAgent = "MultiPoolMiner V" + Application.ProductVersion;
var Response = WR.GetResponse();
var SS = Response.GetResponseStream();
SS.ReadTimeout = 20 * 100;
SS.CopyTo(data);
Response.Close();
byte[] dataByteArray = data.ToArray();
string plainTextData = Utils.AesCipher.DecryptString(dataByteArray, password);
//check if ticks from the db is bigger than 0;
}
catch (Exception e)
{
}
ниже находится функция decryptString
public static string DecryptString(byte[] allBytes, string password)
{
byte[] one = new byte[] { 1 };
string plaintext = null;
// this is all of the bytes
byte[] passwordByteArray = ToByteArray(password);
using (var aes = Aes.Create())
{
aes.KeySize = KeySize;
aes.BlockSize = BlockSize;
aes.Mode = CipherMode.CBC;
// get the key salt
byte[] keySalt = new byte[KeySize / 8];
Array.Copy(allBytes, keySalt, keySalt.Length);
// Yii2 says
//$key = $this->hkdf($this->kdfHash, $secret, $keySalt, $info, $keySize);
//
//Yii2 hkdf says
//$prKey = hash_hmac($algo, $inputKey, $salt, true);
//$hmac = '';
//$outputKey = '';
//for ($i = 1; $i <= $blocks; $i++) {
// $hmac = hash_hmac($algo, $hmac . $info . chr($i), $prKey, true);
// $outputKey .= $hmac;
//}
// chr($i) is the char byte of 1;
// the blocksize is 1
// info here is nothing
// hash first key with keysalt and password
HMACSHA256 hmac = new HMACSHA256(keySalt);
byte[] computedHash = hmac.ComputeHash(passwordByteArray);
// hash primary key with one byte and computed hash
HMACSHA256 hmac2 = new HMACSHA256(computedHash);
byte[] prKeyFull = hmac2.ComputeHash(one);
byte[] key = new byte[KeySize / 8];
Array.Copy(prKeyFull, 0, key, 0, key.Length);
//create the 32 byte array of all 0's for hashing the MAC authKey
byte[] zeroByte = ToByteArray("\0");
byte[] newSalt = new byte[32];
for (int i = 0; i < 32; i++)
{
newSalt[i] = zeroByte[0];
}
//calculate MAC authKey
// Yii2 is again using the hkdf function as above. Except this time info is "AuthorizationKey".
HMACSHA256 hmac3 = new HMACSHA256(newSalt);
byte[] preAuthKey = hmac3.ComputeHash(key);
string authKeyInfo = "AuthorizationKey";
byte[] authkeyInfoByteArray = ToByteArray(authKeyInfo);
// add text authorizationkey and the byte 1 together.
byte[] actualByteArrayInfo = new byte[authkeyInfoByteArray.Length + one.Length];
Array.Copy(authkeyInfoByteArray, actualByteArrayInfo, authkeyInfoByteArray.Length);
Array.Copy(one, 0, actualByteArrayInfo, authkeyInfoByteArray.Length, one.Length);
//second hash of authKey
HMACSHA256 hmac4 = new HMACSHA256(preAuthKey);
byte[] authKeyFull = hmac4.ComputeHash(actualByteArrayInfo);
byte[] authKey = new byte[24];
Array.Copy(authKeyFull, authKey, authKey.Length);
// get the MAC code
byte[] MAC = new byte[MacHashSize / 8];
Array.Copy(allBytes, keySalt.Length, MAC, 0, MAC.Length);
// get our IV
byte[] iv = new byte[BlockSize / 8];
Array.Copy(allBytes, (keySalt.Length + MAC.Length), iv, 0, iv.Length);
// get the data we need to decrypt
byte[] cipherBytes = new byte[allBytes.Length - iv.Length - MAC.Length - keySalt.Length];
Array.Copy(allBytes, (keySalt.Length + MAC.Length + iv.Length), cipherBytes, 0, cipherBytes.Length);
// if we want to verify the mac hash this is where we would do it.
// Yii2 encryption data.
// $encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
//
//$authKey = $this->hkdf($this->kdfHash, $key, null, $this->authKeyInfo, $keySize);
//hashed = $this->hashData($iv . $encrypted, $authKey);
//hashed = [macHash][data]
//so I'm putting together the data to hash.
byte[] dataToHash = new byte[cipherBytes.Length + iv.Length];
// fist is the iv
Array.Copy(iv, dataToHash, iv.Length);
// then the data.
Array.Copy(cipherBytes, 0, dataToHash, iv.Length, cipherBytes.Length);
// hash data to get the MAC
HMACSHA256 hmac5 = new HMACSHA256(dataToHash);
byte[] calculatedMacHash = hmac5.ComputeHash(authKey);
// the calculatedMacHash I come out with is not the same as the MAC that I copied from the
// string response. I have verified all of the keys up to the point of hashing the MAC.
// Create a decrytor to perform the stream transform.
var decryptor = aes.CreateDecryptor(key, iv);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
//Read the decrypted bytes from the decrypting stream
//and place them in a string.
plaintext = srDecrypt.ReadToEnd();
plaintext = plaintext.Remove(0, 32);
}
}
}
}
return plaintext;
}
public static byte[] ToByteArray(string value)
{
byte[] allBytes = new byte[value.Length];
int i = 0;
foreach (byte bite in value)
{
allBytes[i] = Convert.ToByte(bite);
i++;
}
return allBytes;
}
Так что моя проблема в том, что когда я вычисляю хеш-код MAC из моих ключей, которые были проверены как правильные ключи для ключей в yii2, я получаю байтовый массив, отличный от байтового массива, который передается как MAC, Я думаю, у меня проблемы с тем, что MAC не является необработанными данными, такими как зашифрованный текст. В yii2 все ключи возвращаются как необработанные данные. За исключением MAC, которого нет.
пример хэша = [MAC][данные]
ace6008a19b91a8d684c2970d31ab6aa7ac4d928be589dddd54d88146a9a57dc;siQ v H o @ ^ 8 ����躒�%Ō6I�
.4����>*�Q�I!��R�k���eØ* O�>+�M�g�
4Kk K ܇;N垑H P " K Ql t u tE&