Rijndael Encryption/Decryption C# to PHP conversion - c#

I have an encryption decryption class written in C# and i need help writing same algorithm in PHP to obtain same output result, any help finding a reliable solution is highly appreciated, Thank you.
C# Code: (Input: admin, Output: nRy/sK5Z7ENvGsSwfcmLzw==)
static readonly string PasswordHash = "P##Sw0rd";
static readonly string SaltKey = "S#LT&KEY";
static readonly string VIKey = "#1B2c3D4e5F6g7H8";
//for encrypt
public string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash,Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
//to decrypt
public string Decrypt(string encryptedText)
{
byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
var memoryStream = new MemoryStream(cipherTextBytes);
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
}
PHP Code: (Input: admin, Output: LCvAt7BMJcG81a3foyMh8Q==)
$ciphertext_b64 = "";
$plaintext = "admin";
$password = "P##Sw0rd";
$salt = "S#LT&KEY";
$iv = "#1B2c3D4e5F6g7H8";
$iterations = 1000;
$keyLength = 32;
$prepared_key = openssl_pbkdf2($password, $salt, $keyLength, $iterations, "sha256");
$ciphertext_b64 = base64_encode(openssl_encrypt($plaintext,"AES-256-CBC",$prepared_key,OPENSSL_RAW_DATA, $iv));
echo $ciphertext_b64 . "<br/>";
$plaintext = openssl_decrypt(base64_decode($ciphertext_b64),"AES-256-CBC", $prepared_key,OPENSSL_RAW_DATA, $iv);
echo $plaintext . "<br/>";

Related

Encryption method for using AES-256 symmetric algorithm (AES/ECB/PKCS7Padding) in c#

I want to encrypt a string using AES 256-bit encryption algorithm with ECB and PKCS7Padding. I had gone through many sites but none of them were suitable.
Please suggest a solution
public static string Encrypt(string PlainText, string Password,
string Salt = "Kosher", string HashAlgorithm = "SHA1",
int PasswordIterations = 2, string InitialVector = "OFRna73m*aze01xY",
int KeySize = 256)
{
if (string.IsNullOrEmpty(PlainText))
return "";
byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
RijndaelManaged SymmetricKey = new RijndaelManaged();
SymmetricKey.Mode = CipherMode.CBC;
byte[] CipherTextBytes = null;
using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
{
using (MemoryStream MemStream = new MemoryStream())
{
using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
{
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
CryptoStream.FlushFinalBlock();
CipherTextBytes = MemStream.ToArray();
MemStream.Close();
CryptoStream.Close();
}
}
}
SymmetricKey.Clear();
return Convert.ToBase64String(CipherTextBytes);
}
source
Note: you can change the mode by changing SymmetricKey.Mode = CipherMode.CBC;
and you can add SymmetricKey.Padding = PaddingMode.PKCS7; for padding
with bounty castle you should be able to do this :
cipher = CipherUtilities.GetCipher("AES/ECB/PKCS7");
cipher.Init(false, new KeyParameter(key));

Symmetric encryption which returns specific character set and specific length

I use this code below to encrypt and decrypt a string, but it returns a value including special characters and length of returned value is not specific.
I want to use this to generate a serial key, so is it possible to turn result to specific length and specific character set like A-Z,0-9 ?
static readonly string PasswordHash = "P##Sw0rd";
static readonly string SaltKey = "S#LT&KEY";
static readonly string VIKey = "#1B2c3D4e5F6g7H8";
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string encryptedText)
{
byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
var memoryStream = new MemoryStream(cipherTextBytes);
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
}
The two padding modes do not match. Especially PaddingMode.None does not make sense if your data is not block-aligned.
PaddingMode.Zeros also does not make sense because it causes the padding to be not removable.
It seems you have fiddled with settings until it seemed to work. That is very dangerous with cryptography. It is also an unsound development practice in general.

Encrypting using C# AES encryption & decryption from these PHP codes

I am facing some issues in AES encryption using PHP and decode the same using C #. My reference site.
Here is the PHP code:
function encrypt_string($input, $key)
{
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
return preg_replace('/=/', "", base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, hash("sha256", $key, true), $input, MCRYPT_MODE_CBC, $iv)));
}
function decrypt_string($input, $key)
{
$input .= "=";
$data = base64_decode($input);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,hash('sha256', $key, true),substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),MCRYPT_MODE_CBC,$iv),"\0");
}
Here is C# code that I tried:
private static byte[] sha256_data(string input)
{
SHA256 hash = SHA256Managed.Create();
Encoding encode = Encoding.UTF8;
return hash.ComputeHash(encode.GetBytes(input));
}
private string encode_data(string data, string key)
{
byte[] buff;
RijndaelManaged rij = new RijndaelManaged();
rij.BlockSize = 256;
rij.KeySize = 256;
rij.GenerateIV();
rij.Key = sha256_data(key);
rij.Mode = CipherMode.CBC;
ICryptoTransform encoder = rij.CreateEncryptor(rij.Key, rij.IV);
using (MemoryStream mem = new MemoryStream())
{
using (CryptoStream crypt = new CryptoStream(mem, encoder, CryptoStreamMode.Write))
{
byte[] temp = Encoding.UTF8.GetBytes(data);
crypt.Write(temp, 0, temp.Length);
}
buff = mem.ToArray();
}
return Convert.ToBase64String(result);
}
private string decode_data(string input, string key)
{
RijndaelManaged rij = new RijndaelManaged();
rij.KeySize = 256;
rij.BlockSize = 256;
rij.Key = sha256_data(key);
rij.GenerateIV();
rij.Mode = CipherMode.CBC;
rij.Padding = PaddingMode.PKCS7;
ICryptoTransform decrypter = rij.CreateDecryptor();
byte[] buff;
using (MemoryStream mem = new MemoryStream())
{
using (CryptoStream cstream = new CryptoStream(mem, decrypter, CryptoStreamMode.Write))
{
byte[] data = Convert.FromBase64String(input);
cstream.Write(data, 0, data.Length);
}
buff = mem.ToArray();
}
return Encoding.UTF8.GetString(buff);
}
What am i doing wrong?
when you decode you must parse the IV that was used for encoding not generate a new one.

An easy way to encrypt and decrypt with a key [duplicate]

This question already has answers here:
Encrypt and decrypt a string in C#? [closed]
(29 answers)
Closed 9 years ago.
I'm looking for an easy way to encrypt and decrypt some data using a fixed key (which will be stored in my configurations) and store the result as string (base16 or hex).
Something like
string myString = "hello world";
string myKey = "k2k3aij3h";
string enc = new Algorithm().Encrypt(myString, myKey);
string dec = new Alrorithm().Decrypt(enc, myKey);
try this
private const string initVector = "tu89geji340t89u2";
private const int keysize = 256;
public static string Encrypt(string Text, string Key)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(Text);
PasswordDeriveBytes password = new PasswordDeriveBytes(Key, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] Encrypted = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(Encrypted);
}
public static string Decrypt(string EncryptedText, string Key)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] DeEncryptedText = Convert.FromBase64String(EncryptedText);
PasswordDeriveBytes password = new PasswordDeriveBytes(Key, null);
byte[] keyBytes = password.GetBytes(keysize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(DeEncryptedText);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[DeEncryptedText.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
it's from here

How to encrypt/decrypt an XML file?

I am trying to encrypt/decrypt an XML file. I found this sample for encrypting but I do not know how to decrypt? Any idea? Thanks!
// Load this XML file
System.Xml.XmlDocument myDoc = new System.Xml.XmlDocument();
myDoc.Load(#"c:\persons.xml");
// Get a specified element to be encrypted
System.Xml.XmlElement element = myDoc.GetElementsByTagName("Persons")[0] as System.Xml.XmlElement;
// Create a new TripleDES key.
System.Security.Cryptography.TripleDESCryptoServiceProvider tDESkey = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
// Form a Encrypted XML with the Key
System.Security.Cryptography.Xml.EncryptedXml encr = new System.Security.Cryptography.Xml.EncryptedXml();
encr.AddKeyNameMapping("Deskey", tDESkey);
// Encrypt the element data
System.Security.Cryptography.Xml.EncryptedData ed = encr.Encrypt(element, "Deskey");
// Replace the existing data with the encrypted data
System.Security.Cryptography.Xml.EncryptedXml.ReplaceElement(element, ed, false);
// saves the xml file with encrypted data
myDoc.Save(#"c:\encryptedpersons.xml");
But I do not know how I would decrypt that? Any ideas? Thanks!
Something like this:
public static class Encryption
{
private const string InitVector = "T=A4rAzu94ez-dra";
private const int KeySize = 256;
private const int PasswordIterations = 1000; //2;
private const string SaltValue = "d=?ustAF=UstenAr3B#pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE#ras!a+uc#";
public static string Decrypt(string encryptedText, string passPhrase)
{
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
string plainText;
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize / 8);
RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };
try
{
using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
//TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
byte[] plainTextBytes = new byte[encryptedTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
catch (CryptographicException)
{
plainText = string.Empty; // Assume the error is caused by an invalid password
}
return plainText;
}
public static string Encrypt(string plainText, string passPhrase)
{
string encryptedText;
byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize / 8);
RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};
using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
encryptedText = Convert.ToBase64String(cipherTextBytes);
}
}
}
return encryptedText;
}
}
Edit:
Sani Huttunen pointed out that my static implementation above has a severe performance issue if you will be encrypting multiple pieces of data using the same password. You can read more about it here: http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/
Edit: A non-static implementation that is much more efficient if you need to perform multiple encryptions/decryptions using the same password (~32ms original ~1ms new).
public class SimpleEncryption
{
#region Constructor
public SimpleEncryption(string password)
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
_DeriveBytes = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
_InitVectorBytes = Encoding.UTF8.GetBytes(InitVector);
_KeyBytes = _DeriveBytes.GetBytes(32);
}
#endregion
#region Private Fields
private readonly Rfc2898DeriveBytes _DeriveBytes;
private readonly byte[] _InitVectorBytes;
private readonly byte[] _KeyBytes;
#endregion
private const string InitVector = "T=A4rAzu94ez-dra";
private const int PasswordIterations = 1000; //2;
private const string SaltValue = "d=?ustAF=UstenAr3B#pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE#ras!a+uc#";
public string Decrypt(string encryptedText)
{
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
string plainText;
RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };
try
{
using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(_KeyBytes, _InitVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
//TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
byte[] plainTextBytes = new byte[encryptedTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
catch (CryptographicException exception)
{
plainText = string.Empty; // Assume the error is caused by an invalid password
}
return plainText;
}
public string Encrypt(string plainText)
{
string encryptedText;
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};
using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(_KeyBytes, _InitVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
encryptedText = Convert.ToBase64String(cipherTextBytes);
}
}
}
return encryptedText;
}
}
There's a complete example on MSDN, although is uses RSA and not TripleDES.

Categories