Sto tentando di crittografare alcuni dati (cookie) in C# e quindi decrittografarli in PHP. Ho scelto di usare la crittografia Rijndael. Ho quasi funzionato, tranne che solo una parte del testo è stata decifrata! Ho iniziato a lavorare da questo esempio: Decrypt PHP encrypted string in C#C# Crittografia in PHP Decryption
Ecco il testo (JSON) che io sono la crittografia (informazioni sensibili rimossa):
{"DisplayName":"xxx", "Username": "yyy", "EmailAddress":"zzz"}
Così faccio il login al C# app che crea/codifica il cookie di memorizzata Chiave e IV e poi reindirizza all'app PHP che dovrebbe decodificare/leggere il cookie. Quando ho decifrare il biscotto, esce in questo modo:
{"DisplayName":"xxx","F�A ;��HP=D�������4��z����ť���k�#E���R�j�5�\�t. t�D��"
UPDATE: ho ottenuto un po 'più avanti e questo è ora il risultato
string(96) "{"DisplayName":"xxx","Username":"yyy","EmailAddress"�)ق��-�J��k/VV-v� �9�B`7^"
Come si può vedere , inizia a decrittografarlo, ma poi viene incasinato ...
Quando decrittografa la stringa risulta corretta (con padding, che ho una funzione di remov e padding), ma se cambio la stringa di prova di un carattere ricevo ancora spazzatura:
B�nHL�Ek �¿?�UΣlO����OЏ�M��NO/�f.M���Lƾ�CC�Y>F��~�qd�+
Ecco il codice C# che uso per generare il caso chiave e IV:
UPDATE: sto solo usando la chiave statica/IV per ora, qui sono:
Key: lkirwf897+22#bbtrm8814z5qq=498j5
IV: 741952hheeyy66#[email protected]
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
symmetricKey.Padding = PaddingMode.Zeros;
symmetricKey.Mode = CipherMode.CBC;
string key = Convert.ToBase64String(symmetricKey.Key);
string IV = Convert.ToBase64String(symmetricKey.IV);
Ho quindi salvato la chiave e IV in un database da recuperare in seguito per la codifica/decodifica.
Questa è la classe crittografia completa:
public static class Encryption
{
public static string Encrypt(string prm_text_to_encrypt, string prm_key, string prm_iv)
{
var sToEncrypt = prm_text_to_encrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Encoding.ASCII.GetBytes(prm_key);
var IV = Encoding.ASCII.GetBytes(prm_iv);
//var key = Convert.FromBase64String(prm_key);
//var IV = Convert.FromBase64String(prm_iv);
var encryptor = rj.CreateEncryptor(key, IV);
var msEncrypt = new MemoryStream();
var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
var toEncrypt = Encoding.ASCII.GetBytes(sToEncrypt);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
var encrypted = msEncrypt.ToArray();
return (Convert.ToBase64String(encrypted));
}
public static string Decrypt(string prm_text_to_decrypt, string prm_key, string prm_iv)
{
var sEncryptedString = prm_text_to_decrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Encoding.ASCII.GetBytes(prm_key);
var IV = Encoding.ASCII.GetBytes(prm_iv);
//var key = Convert.FromBase64String(prm_key);
//var IV = Convert.FromBase64String(prm_iv);
var decryptor = rj.CreateDecryptor(key, IV);
var sEncrypted = Convert.FromBase64String(sEncryptedString);
var fromEncrypt = new byte[sEncrypted.Length];
var msDecrypt = new MemoryStream(sEncrypted);
var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return (Encoding.ASCII.GetString(fromEncrypt));
}
public static void GenerateKeyIV(out string key, out string IV)
{
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
rj.GenerateKey();
rj.GenerateIV();
key = Convert.ToBase64String(rj.Key);
IV = Convert.ToBase64String(rj.IV);
}
}
Ecco il codice PHP che sto usando per decodificare i dati:
function decryptRJ256($key,$iv,$string_to_decrypt)
{
$string_to_decrypt = base64_decode($string_to_decrypt);
$rtn = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string_to_decrypt, MCRYPT_MODE_CBC, $iv);
//$rtn = rtrim($rtn, "\0\4");
$rtn = unpad($rtn);
return($rtn);
}
function unpad($value)
{
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
//apply pkcs7 padding removal
$packing = ord($value[strlen($value) - 1]);
if($packing && $packing < $blockSize){
for($P = strlen($value) - 1; $P >= strlen($value) - $packing; $P--){
if(ord($value{$P}) != $packing){
$packing = 0;
}//end if
}//end for
}//end if
return substr($value, 0, strlen($value) - $packing);
}
$ky = 'lkirwf897+22#bbtrm8814z5qq=498j5'; // 32 * 8 = 256 bit key
$iv = '741952hheeyy66#[email protected]'; // 32 * 8 = 256 bit iv
$enc = $_COOKIE["MyCookie"];
$dtext = decryptRJ256($ky, $iv, $enc);
var_dump($dtext);
Io sono un po 'incerto su questa parte, perché tutti il codice di esempio che ho visto passa semplicemente nella stringa codificata in base 64 direttamente al decryptor, ma nel mio esempio, devo basarlo 64_decode prima di passarlo altrimenti ricevo l'errore che la chiave e IV non sono la lunghezza corretta.
UPDATE: Sto utilizzando le chiavi ASCII nel formato richiesto da PHP. Se genero chiavi dalla classe RijndaelManaged, non funzionano sul lato PHP, ma posso usare le chiavi che sono conosciute per funzionare su PHP e usarle nel lato RijndaelManaged C#.
Per favore fatemi sapere se ho omesso qualsiasi informazione pertinente. TIA!
Mi sembra di ricordare che si può ottenere questo se il IV fornite per decifrare è sbagliato – pm100
Funziona senza la IV? –
Non funziona se non includo la flebo. – solidau