I have a working solution for crypt/decrypt data in my code (below) but when I have upgraded the project to DOTNET6, RijndaelManaged becomes obsolete:
Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.'
and
SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'
Now I want to change that to Aes/RandomNumberGenerator as stated but want to keep the output in the same way as is. Unfortunately, I am not familiar with crypt/decrypt.
Can somebody help me to rewrite the current block to work with Aes instead - or at least help me how to change that and keep the public methods works in the same way?
Whole Code I have (it works as is)
using System.Security.Cryptography;
namespace MyApp;
internal static class AES
{
private static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new())
{
using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
return encryptedBytes;
}
private static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new())
{
using RijndaelManaged AES = new(); // This reports Warning SYSLIB0022 'RijndaelManaged' is obsolete: 'The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
return decryptedBytes;
}
public static string EncryptText(string password, string salt = "MySecretSaltWhichIWantToKeepWorking")
{
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(password);
byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string result = Convert.ToBase64String(bytesEncrypted);
return result;
}
public static string DecryptText(string hash, string salt = "MySecretSaltWhichIWantToKeepWorking")
{
try
{
byte[] bytesToBeDecrypted = Convert.FromBase64String(hash);
byte[] passwordBytes = Encoding.UTF8.GetBytes(salt);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string result = Encoding.UTF8.GetString(bytesDecrypted);
return result;
}
catch (Exception e)
{
return e.Message;
}
}
private const int SALT_BYTE_SIZE = 24;
private const int HASH_BYTE_SIZE = 24;
private const int PBKDF2_ITERATIONS = 1000;
private const int ITERATION_INDEX = 0;
private const int SALT_INDEX = 1;
private const int PBKDF2_INDEX = 2;
public static string PBKDF2_CreateHash(string password)
{
RNGCryptoServiceProvider csprng = new(); // This reports SYSLIB0023 'RNGCryptoServiceProvider' is obsolete: 'RNGCryptoServiceProvider is obsolete. To generate a random number, use one of the RandomNumberGenerator static methods instead.'
byte[] salt = new byte[SALT_BYTE_SIZE];
csprng.GetBytes(salt);
byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
return PBKDF2_ITERATIONS + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
}
public static bool PBKDF2_ValidatePassword(string password, string correctHash)
{
char[] delimiter = { ':' };
string[] split = correctHash.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
private static bool SlowEquals(byte[] a, byte[] b)
{
uint diff = (uint)a.Length ^ (uint)b.Length;
for (int i = 0; i < a.Length && i < b.Length; i++)
diff |= (uint)(a[i] ^ b[i]);
return diff == 0;
}
private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
{
Rfc2898DeriveBytes pbkdf2 = new(password, salt)
{
IterationCount = iterations
};
return pbkdf2.GetBytes(outputBytes);
}
}
As far as I can tell, you should be able to replace
using RijndaelManaged AES = new();
with
using var AES = Aes.Create("AesManaged");
note that you might want to change your variable name to avoid naming conflicts or confusion.
The only difference between AES and Rijndael should be that Rijndael allows more blocksizes/keysizes. But you seem to be using 256 bit key and 128 bit blocks, and this should be allowed by AES.
Related
I have an Encrypted string and function to decrypt it. Now I need to edit this string and encrypt it. When I use this function to encrypt and decrypt in result strings are not the same.
Orginal encrypted string:
APpuC6G3f3cUKaAuOFXOGIo9rwz/+fQ0tBCi6Fk40THVnIT+au7JXkOQHdgPcpQ3VUrXw69rIL+QRsHea5+Q6TxOeuAnzkU8c3UClx6Toe+jOIVi3DlkLIGzE8DmyBArtZYpKTOt4rrOSDyLKifdgcM+MgwuJbDXyXVuQyp2C42zZ1ETPUOF2TSIZKhnMSR43FFy8WEbpKBAjkPmgVpqqhrjabu+JHbj7kPIxGGjDHGaCCyCtFwsk3264Lv4GTp049SCjNNYV0NVcN4wV0MaWMEO0iLuNGkseHuu5Snvp3YzZfXxDBWSLOUXc2zeXL2tA6So9WA5P3lZ/ga5i366EQ==
Orginal encrypted string after decrypt:
{"status":"PASS","data":{"map_path":"VOtKu0.yGT","file_extension":"KAmXWV","username":"damianek","timestamp":9999999999},"message":"Logged in successfully. Your license will run out at 2021-12-03 18:41:39"}
Orginal decrypt function:
public static string Decypher(string var1)
{
var1 = var1.Trim();
byte[] array = Convert.FromBase64String(var1);
byte[] array2 = new byte[16];
byte[] array3 = new byte[32];
byte[] array4 = new byte[array.Length - 48];
for (int i = 0; i < 16; i++)
{
array2[i] = array[i];
}
for (int j = 16; j < 48; j++)
{
array3[j - 16] = array[j];
}
for (int k = 48; k < array.Length; k++)
{
array4[k - 48] = array[k];
}
ivv = array2;
Aes aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.Key = GetToken();
aes.IV = array2;
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform transform = aes.CreateDecryptor();
CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write);
string result = string.Empty;
try
{
cryptoStream.Write(array4, 0, array4.Length);
cryptoStream.FlushFinalBlock();
byte[] array5 = memoryStream.ToArray();
result = Encoding.ASCII.GetString(array5, 0, array5.Length);
memoryStream.Close();
cryptoStream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
return result;
}
My encrypt function:
public void EncryptStringToBytes()
{
string plainText = textBox2.Text;
byte[] array = Encoding.UTF8.GetBytes(plainText);
byte[] encrypted;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = GetToken();
aesAlg.IV = new byte[16];
aesAlg.Mode = CipherMode.CBC;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
textBox3.Text = Convert.ToBase64String(encrypted);
}
String after my encrypt & decrypt with orginal function:
?%j>]???r?????":"KAmXWV","username":"damianek","timestamp":1637955589},"message":"Logged in successfully. Your license will run out at 2021-12-03 18:41:39"}
EDIT:
Now encrypt function look:
public void EncryptStringToBytes()
{
string plainText = textBox2.Text.Trim();
byte[] array = Encoding.ASCII.GetBytes(plainText);
byte[] encrypted;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = GetToken();
aesAlg.IV = GetIV();
aesAlg.Mode = CipherMode.CBC;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (var msEncrypt = new MemoryStream())
{
msEncrypt.Write(aesAlg.Key, 0, aesAlg.Key.Length);
msEncrypt.Flush();
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(aesAlg.Key, 0, aesAlg.Key.Length);
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
textBox3.Text = Convert.ToBase64String(encrypted);
}
But string after encrypt & decrypt look:
;???En Dp??g???{"status":"PASS","data":{"map_path":"VOtKu0.yGT","file_extension":"KAmXWV","username":"damianek","timestamp":1637955589},"message":"Logged in successfully. Your license will run out at 2021-12-03 18:41:39"}
My C# AES implementation
from my answer AES Crypto C# compatible Java
The IV is randomized in every Encrypt process to get different output with same text and avoid to intruders/attackers get original text easily.
The default mode is CBC.
The encoding used is UTF-8. UTF-8 is the most widely used encoding on the web.
You can test/run this code on https://replit.com/#JomaCorpFX/AesCbcEncrypt#main.cs
The code
using System;
using System.Security.Cryptography;
using System.Text;
public enum HashAlgorithm
{
MD5,
SHA1,
SHA256,
SHA384,
SHA512
}
public class HashManager
{
public static byte[] ToRawHash(byte[] data, HashAlgorithm algorithm)
{
byte[] hash;
switch (algorithm)
{
case HashAlgorithm.MD5:
MD5 md5 = MD5.Create();
hash = md5.ComputeHash(data, 0, data.Length);
return hash;
case HashAlgorithm.SHA1:
SHA1Managed sha1 = new SHA1Managed();
hash = sha1.ComputeHash(data);
return hash;
case HashAlgorithm.SHA256:
SHA256Managed sha256 = new SHA256Managed();
hash = sha256.ComputeHash(data);
return hash;
case HashAlgorithm.SHA384:
SHA384Managed sha384 = new SHA384Managed();
hash = sha384.ComputeHash(data);
return hash;
case HashAlgorithm.SHA512:
SHA512Managed sha512 = new SHA512Managed();
hash = sha512.ComputeHash(data, 0, data.Length);
return hash;
default:
throw new ArgumentException("Invalid Algorithm");
}
}
}
public class AesManager
{
private const int MAX_IV_LENGTH = 16;
private const int MAX_KEY_LENGTH = 32;
private static byte[] GenerateValidKey(byte[] keyBytes)
{
byte[] ret = new byte[MAX_KEY_LENGTH];
byte[] hash = HashManager.ToRawHash(keyBytes, HashAlgorithm.SHA256);
Array.Copy(hash, ret, MAX_KEY_LENGTH);
return ret;
}
public static byte[] EncryptRaw(byte[] PlainBytes, byte[] Key)
{
AesManaged AesAlgorithm = new AesManaged()
{
Key = GenerateValidKey(Key)
};
AesAlgorithm.GenerateIV();
var Encrypted = AesAlgorithm.CreateEncryptor().TransformFinalBlock(PlainBytes, 0, PlainBytes.Length);
byte[] ret = new byte[Encrypted.Length + MAX_IV_LENGTH];
Array.Copy(Encrypted, ret, Encrypted.Length);
Array.Copy(AesAlgorithm.IV, 0, ret, ret.Length - MAX_IV_LENGTH, MAX_IV_LENGTH);
return ret;
}
public static byte[] DecryptRaw(byte[] CipherBytes, byte[] Key)
{
AesManaged AesAlgorithm = new AesManaged()
{
Key = GenerateValidKey(Key)
};
byte[] IV = new byte[MAX_IV_LENGTH];
Array.Copy(CipherBytes, CipherBytes.Length - MAX_IV_LENGTH, IV, 0, MAX_IV_LENGTH);
AesAlgorithm.IV = IV;
byte[] RealBytes = new byte[CipherBytes.Length - MAX_IV_LENGTH];
Array.Copy(CipherBytes, RealBytes, CipherBytes.Length - MAX_IV_LENGTH);
return AesAlgorithm.CreateDecryptor().TransformFinalBlock(RealBytes, 0, RealBytes.Length); ;
}
public static String EncryptToBase64(String Plaintext, String Key)
{
byte[] PlainBytes = Encoding.UTF8.GetBytes(Plaintext);
return Base64Manager.ToBase64(EncryptRaw(PlainBytes, Encoding.UTF8.GetBytes(Key)), false);
}
public static String DecryptFromBase64(String CipherText, String Key)
{
byte[] CiPherBytes = Base64Manager.Base64ToByteArray(CipherText);
byte[] Encrypted = DecryptRaw(CiPherBytes, Encoding.UTF8.GetBytes(Key));
return Encoding.UTF8.GetString(Encrypted, 0, Encrypted.Length);
}
}
public class Base64Manager
{
public static byte[] Base64ToByteArray(String base64)
{
return Convert.FromBase64String(base64);
}
public static String ToBase64(byte[] data, Boolean insertLineBreaks = default(Boolean))
{
return insertLineBreaks ? Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks) : Convert.ToBase64String(data);
}
}
public class Program
{
public static void Main()
{
Console.Write("Plain text: ");
string plainText = Console.ReadLine();
Console.Write("Password: ");
string password = Console.ReadLine();
string encrypted = AesManager.EncryptToBase64(plainText, password);
Console.WriteLine();
Console.WriteLine($"Password: {password}" );
Console.WriteLine();
Console.WriteLine($"Encrypted: {encrypted}");
Console.WriteLine();
Console.WriteLine($"Decrypted: {AesManager.DecryptFromBase64(encrypted, password)}");
Console.ReadLine();
}
}
Output
I'm trying to decrypt AES-128 CBC strings in C# but with no success (tried every decrypt method I found on internet for this type of encryption).
The only way I got a result was decrypting those strings in PHP using this code:
<?php
$crypto_data = hex2bin($crypto_data_hex);
$real_data = openssl_decrypt($crypto_data,
'AES-128-CBC',
'23d854ce7364b4f7',
OPENSSL_RAW_DATA,
'23d854ce7364b4f7');
?>
So, is there a way to run this PHP code in .NET (using a PHP.dll library or something similar) ? Or is there a real equivalent method for this operation in .NET C# ?
Thank you
The question seems to boil down to writing C# function that is equivalent to PHP function.
Try this code:
public class Program
{
public static byte[] HexToBytes(string hex)
{
int numberChars = hex.Length;
byte[] bytes = new byte[numberChars / 2];
for (int i = 0; i < numberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
static string Decrypt(byte[] cipherText, byte[] key, byte[] iv)
{
string plaintext;
AesManaged aes = new AesManaged
{
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
BlockSize = 128,
Key = key,
IV = iv
};
using (aes)
{
ICryptoTransform decryptor = aes.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cs))
{
plaintext = reader.ReadToEnd();
}
}
}
}
return plaintext;
}
public static void Main()
{
string crypto_data_hex = "00965fa56e761b11d37b887f98e6bcc2"; // paste $crypto_data_hex value here
string sKey = "23d854ce7364b4f7";
string sIv = "23d854ce7364b4f7";
byte[] encrypted = HexToBytes(crypto_data_hex);
byte[] key = Encoding.ASCII.GetBytes(sKey);
byte[] iv = Encoding.ASCII.GetBytes(sIv);
string decrypted = Decrypt(encrypted, key, iv);
Console.WriteLine(decrypted);
}
}
I encrypt password in postgres
and i want to decrypt it in c#, but two ways can not matching
.How can i do that?
private static byte[] TruncateHash(string key, int length)
{
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
// Hash the key.
byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(key);
byte[] hash = sha1.ComputeHash(keyBytes);
// Truncate or pad the hash.
Array.Resize(ref hash, length);
return hash;
}
public static string EncryptString(string plaintext, string Passphrase)
{
TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
// Initialize the crypto provider.
tripleDes.Key = TruncateHash(Passphrase, tripleDes.KeySize / 8);
tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);
// Convert the plaintext string to a byte array.
byte[] plaintextBytes = System.Text.Encoding.Unicode.GetBytes(plaintext);
// Create the stream.
System.IO.MemoryStream ms = new System.IO.MemoryStream();
// Create the encoder to write to the stream.
CryptoStream encStream = new CryptoStream(ms, tripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
// Use the crypto stream to write the byte array to the stream.
encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
encStream.FlushFinalBlock();
// Convert the encrypted stream to a printable string.
return Convert.ToBase64String(ms.ToArray());
}
public static string DecryptString(string encryptedtext, string Passphrase)
{
TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
// Initialize the crypto provider.
tripleDes.Key = TruncateHash(Passphrase, tripleDes.KeySize / 8);
tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);
// Convert the encrypted text string to a byte array.
byte[] encryptedBytes = Convert.FromBase64String(encryptedtext);
// Create the stream.
System.IO.MemoryStream ms = new System.IO.MemoryStream();
// Create the decoder to write to the stream.
CryptoStream decStream = new CryptoStream(ms, tripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);
// Use the crypto stream to write the byte array to the stream.
decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
decStream.FlushFinalBlock();
// Convert the plaintext stream to a string.
return System.Text.Encoding.Unicode.GetString(ms.ToArray());
}
I found a way to encrypt in postgres using pgcrypto.
And below is encrypt and decrypt in postgres.
SELECT encode(encrypt_iv('ABCDE121212','Key123', '','3des'), 'base64');
select decrypt_iv(decode('jEI4V5q6h5/p12NRJm666g==','base64'),'Key123','','3des')
What's wrong in my code, c# and postgres can't not matching.
I want to keep c# code and change postgres code to matching
Source Url
Encrypt function:
public static String AES_encrypt(String input, string key, string Iv, int keyLength)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = keyLength;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = mkey(key,keyLength);
aes.IV = mkey(Iv,128);
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
{
byte[] xXml = Encoding.UTF8.GetBytes(input);
cs.Write(xXml, 0, xXml.Length);
cs.FlushFinalBlock();
}
xBuff = ms.ToArray();
}
return Convert.ToBase64String(xBuff,Base64FormattingOptions.None);
}
Decrypt function:
public static String AES_decrypt(String Input, string key, string Iv, int keyLength)
{
try
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = keyLength;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = mkey(key,keyLength);
aes.IV = mkey(Iv,128);
var decrypt = aes.CreateDecryptor();
byte[] encryptedStr = Convert.FromBase64String(Input);
string Plain_Text;
using (var ms = new MemoryStream(encryptedStr))
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cs))
{
Plain_Text = reader.ReadToEnd();
}
}
}
return Plain_Text;
}
catch (Exception ex)
{
return null;
}
}
Helper function:
private static byte[] mkey(string skey, int keyLength)
{
int length = keyLength / 8;
byte[] key = Encoding.UTF8.GetBytes(skey);
byte[] k = GenerateEmptyArray(length);
for (int i = 0; i < key.Length; i++)
{
//k[i % 16] = (byte)(k[i % 16] ^ key[i]);
k[i] = key[i];
if(i == length-1)
break;
}
return k;
}
Variables:
input = "Hello World"
key = "NBJ42RKQ2vQoYFZO"
Iv = "j1C83921vHExVhVp"
keyLength = 128
Info about variables:
input - string that is not encrypted or encrypted. If it's encrypted it will be in Base64 format
key - Any Unicode character that will match the AES key size(in this example it's 128). I have written a function that will extract the specific length of characters and add them to a byte array
Code:
public static string PasswordFixer(string skey,int keyLength)
{
int length = keyLength / 8;
byte[] key = Encoding.UTF8.GetBytes(skey);
byte[] k = GenerateEmptyArray(length);
for (int i = 0; i < key.Length; i++)
{
k[i] = key[i];
if(i == length-1)
break;
}
return Encoding.UTF8.GetString(k);
}
Iv - it's always 128bit long meaning 16bytes. you can ignore Iv if you want, in PostgreSQL if you planing to use `encrypt` function then you can ignore the Iv by hard coding like this `aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };`
keylength-
This is the AES key length in this example we use 128bit meaning 16 bytes. whatever the characters that you use as the Key need to match the length of 16 bytes.
PostgreSQL
The equivalent SQL statement for the encryption and decryption is this
encrypt_iv,decrypt_iv
select convert_from(decrypt_iv(decode(tbl1.encrypted,'base64')::bytea ,'NBJ42RKQ2vQoYFZO','j1C83921vHExVhVp', 'aes-cbc/pad:pkcs'), 'UTF-8') as decrypted,tbl1.encrypted from (select encode(encrypt_iv('Hello World', 'NBJ42RKQ2vQoYFZO','j1C83921vHExVhVp', 'aes-cbc/pad:pkcs'), 'base64') as encrypted) as tbl1
encrypt,decrypt
select convert_from(decrypt(decode(tbl1.encrypted,'base64')::bytea ,'NBJ42RKQ2vQoYFZO', 'aes-cbc/pad:pkcs'), 'UTF-8') as decrypted,tbl1.encrypted from (select encode(encrypt('Hello World', 'NBJ42RKQ2vQoYFZO', 'aes-cbc/pad:pkcs'), 'base64') as encrypted) as tbl1
So I've made a desktop application (before the website) were i've made a login and a register system in it and an encryption ofcourse. And now I've had an idea to make a website with the register and login system because i thought it would be easier but the problem is i've made the website after the desktop application which means i've made a C# encryption/decryption before website and I want to convert the C# encryption to the PHP (if it is even possible) to match my database users information (password, username, mail etc.). This is my C# encryption and decryption code:
Encryption:
private static byte[] AesEncrypt(byte[] bytesToBeEncrypted, byte[]
passwordBytes)
{
byte[] encryptedBytes;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // min 8
using (var ms = new MemoryStream())
{
using (var aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
Decryption:
private static byte[] AesDecrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // min 8
using (var ms = new MemoryStream())
{
using (var aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
Method which I use to encrypt data:
public static string Encrypt(string clearText, string password, byte[] salt = null)
{
var baPwd = Encoding.UTF8.GetBytes(password);
var baPwdHash = SHA256.Create().ComputeHash(baPwd);
var baText = Encoding.UTF8.GetBytes(clearText);
byte[] baSalt;
baSalt = salt;
var baEncrypted = new byte[baSalt.Length + baText.Length];
for (var i = 0; i < baSalt.Length; i++)
baEncrypted[i] = baSalt[i];
EncryptionSalt = baSalt.ToString();
for (var i = 0; i < baText.Length; i++)
baEncrypted[i + baSalt.Length] = baText[i];
baEncrypted = AesEncrypt(baEncrypted, baPwdHash);
var result = Convert.ToBase64String(baEncrypted);
EncryptionSalt = baSalt.ToString();
return result;
}
}
Method which I use to decrypt data:
public static string Decrypt(string cipherText, string password)
{
var baPwd = Encoding.UTF8.GetBytes(password);
var baPwdHash = SHA256.Create().ComputeHash(baPwd);
var baText = Convert.FromBase64String(cipherText);
var baDecrypted = AesDecrypt(baText, baPwdHash);
const int saltLength = 12;
var baResult = new byte[baDecrypted.Length - saltLength];
for (var i = 0; i < baResult.Length; i++)
baResult[i] = baDecrypted[i + saltLength];
var result = Encoding.UTF8.GetString(baResult);
return result;
}
An example of using C# encryption in my C# code:
Encryption.Encrypt(password, Encryption.RandomBytes().ToString(), salt));
And the RandomBytes method:
public static byte[] RandomBytes()
{
const int saltLength = 12;
var ba = new byte[saltLength];
RandomNumberGenerator.Create().GetBytes(ba);
return ba;
}
Firstly I need to know if it's possible, secondly if anyone wants to you could give me an example of this encryption in PHP or give me the code.
Encryption/Decryption won't work in cross platform.
I have used this link to encrypt/decrypt text using bouncy castle AES cipher within codename one.
AES Encryption/Decryption with Bouncycastle Example in J2ME
While from server side (.net) , i am using this link to implement same method.
http://zenu.wordpress.com/2011/09/21/aes-128bit-cross-platform-java-and-c-encryption-compatibility/
now i am not getting any error but encrypted from codename one will not getting fully decrypted on server side and vice a versa.
any one please help me out on this.
Code from Codename one:
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;
public class Test
{
private static PaddedBufferedBlockCipher cipher = null;
public static void main(String[] args)
{
try
{
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = new byte[16];
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
new CBCBlockCipher(
new AESEngine()) );
//Encryption
String plainText = "Hello How are you !2#&*()% 123456#";
byte[] plainData = plainText.getBytes("UTF-8");
KeyParameter keyParam = new KeyParameter(key);
CipherParameters ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(true, ivAndKey);
byte[] ciptherBytes = cipherData(plainData); //48
String cipherText = new String(Base64.encode(ciptherBytes), "UTF-8");//FileUtil.getStringFromByteArray(Base64.encode(ciptherBytes));
System.out.println("encrypted >> "+cipherText);
//Decryption
byte[] cipherData = Base64.decode(cipherText);
ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(false, ivAndKey);
plainText = new String(cipherData(cipherData), "UTF-8");//FileUtil.getStringFromByteArray(cipherData(cipherData));
System.out.println("decrypted >> "+plainText);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static byte[] cipherData(byte[] data)
throws CryptoException
{
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
Code from .net:
public static RijndaelManaged GetRijndaelManaged(String secretKey)
{
var keyBytes = new byte[16];
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
return new RijndaelManaged
{
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
KeySize = 128,
BlockSize = 128,
Key = keyBytes,
IV = keyBytes
};
}
public static byte[] EncryptCBC(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateEncryptor()
.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}
public static byte[] DecryptCBC(byte[] encryptedData, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateDecryptor()
.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
}
public static String EncryptCBCStr(String plainText, String key)
{
var plainBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(EncryptCBC(plainBytes, GetRijndaelManaged(key)));
}
public static String DecryptCBCStr(String encryptedText, String key)
{
var encryptedBytes = Convert.FromBase64String(encryptedText);
return Encoding.UTF8.GetString(DecryptCBC(encryptedBytes, GetRijndaelManaged(key)));
}
// call
var PlainText = "Hello How are you !2#&*()% 123456#";
var EncryptionKey = "MAKV2SPBNI992122";
var cypherCBC = EncryptCBCStr(PlainText, EncryptionKey);
var decryptCBC = DecryptCBCStr(cypherCBC, EncryptionKey);
Thanks in adv.
This issue has been fixed...it is just key/IV bytes issue.as in .net there is same key and IV when in java i have used different IV.
correction in java code:
instead of this
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = new byte[16];
use this.
byte key[] = "MAKV2SPBNI992122".getBytes("UTF-8");
byte[] iv = "MAKV2SPBNI992122".getBytes("UTF-8");