While playing with some AES C# wrappers found on SO and msdn (most notable here and here and here) I wrote the following code and I made the mistake of writing the IV to the CryptoStream.
What I noticed is that the output byte array contains the same values when the IV is written to the CryptoStream. If I comment out the line cryptoStream.Write(aes.IV, 0, aes.IV.Length);, it's fine, the output will be different.
My question is why in this case the output is the same? I realize that writing the IV to the CryptoStream is not what I am supposed to do but I find it odd especially given that the IV is different every time the function executes.
TestEncryption.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
public class TestEncryption
{
public static readonly int KeyBitSize = 256;
private static readonly int BlockBitSize = 128;
public static readonly byte[] _salt = new byte[] { 23, 13, 23, 213, 15, 193, 134, 147, 223, 151 };
const int Iterations = 10000;
public static string Encrypt(byte[] inputBytes, string password)
{
using (var aes = new AesManaged
{
KeySize = KeyBitSize,
BlockSize = BlockBitSize,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
})
{
var cryptKey = CreateKey(password);
aes.GenerateIV();
Console.WriteLine("IV={0}", string.Join(", ", aes.IV.Select(b => b.ToString())));
using (var encrypter = aes.CreateEncryptor(cryptKey, aes.IV))
using (var output = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(output, encrypter, CryptoStreamMode.Write))
{
cryptoStream.Write(aes.IV, 0, aes.IV.Length);
cryptoStream.Write(inputBytes, 0, inputBytes.Length);
cryptoStream.FlushFinalBlock();
}
Console.WriteLine("Output={0}", string.Join(", ", output.ToArray().Select(b => b.ToString())));
return Convert.ToBase64String(output.ToArray());
}
}
}
public static string Encrypt(string input, string password)
{
return Encrypt(Encoding.UTF8.GetBytes(input), password);
}
public static byte[] CreateKey(string password)
{
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, _salt, Iterations))
return rfc2898DeriveBytes.GetBytes(32);
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static void Main(string[] args)
{
//Test1();
Test2();
Console.ReadLine();
}
private static void Test2()
{
string text = "some longer text";
string pwd = "test2";
String encrypt1 = TestEncryption.Encrypt(text, pwd);
String encrypt2 = TestEncryption.Encrypt(text, pwd);
Console.WriteLine(encrypt1 == encrypt2);
}
}
}
Related
Throws exception: Org.BouncyCastle.Crypto.InvalidCipherTextException: "mac check in GCM failed"
I am taring to decode metamask vault an sure that everithing with it must be OK
I can't find what's wrong
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using System.Text;
using Jose;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
namespace net6metachecker
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void startbtn_Click(object sender, EventArgs e)
{
Decrypt1();
}
public void Decrypt1()
{
byte[] salt = Convert.FromBase64String("RXoBv+8Yu/nQhmj+nXMp8Rf57VLT8aYu5rvP5LEcq7Y=");
byte[] data = Convert.FromBase64String("cVZeRBJI7yzsN6lM9LS6tNSVYTU7IFy+UMAVsZjHa+/nGvXirE99pILb4+VdYANkEg05kbeoYgLwacqUNfZc+9llePvcLkVmzFtye4pYbVSkHtaGCKfFMb0gQxJb2xJz7Br4MHNzGEY7aZAkrWpx1KhIghA3uZBE5sjZ+vjw/aFg3w51xGBMgzwLdMcr8+Fru5Kyb5p1dVXSsMt7AFIQFg1BsOcbEiDNf/jkigxuJpILVYUY3qrUJmYh500frohZnxoh8fSPSWcyLbl08TKGE4DQuBeJ7cMcmmHnpvJ166BK1roOni4CMRIn84BBUr5DEW36+22i52vfPCvzgNUierIBoh3wUTZI/trHozXSLYg8t86XwLIzwNq4H08Ctss/Daivta/7mgE5KC7gesRoda6OLJ5XldxeibdtOprq1v+teeNVaZRRYTKs+cCUkrwxZVrjqzmnVMBxDegR3/gjchZRszm4hOWDfVR8JRhjpCKQmrLkOno=");
byte[] iv = Convert.FromBase64String("beg6WtZTF82na0IKb5Juhw==");
byte[] password = Encoding.UTF8.GetBytes("11111111");
byte[] key = PBKDF2.DeriveKey(password, salt, 10000, 256, HMAC.Create("HMACSHA256"));
GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesFastEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, iv, null);
gcmBlockCipher.Init(false, parameters);
byte[] plainBytes = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
int retLen = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plainBytes, 0);
byte[] cc = gcmBlockCipher.GetMac();
int xx = gcmBlockCipher.DoFinal(plainBytes, retLen); // Exception is here
string x = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n\0".ToCharArray());
MessageBox.Show(x);
}
}
}
I used this link to test decrypting AES CBC.
Here my parameters:
This work. Then I implement with C#. My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace HHT.Module.eWallet.Helper
{
public class AESHelper
{
private AesCryptoServiceProvider _aes;
private ICryptoTransform _crypto;
public AESHelper(string key, string IV)
{
_aes = new AesCryptoServiceProvider();
_aes.BlockSize = 128;
_aes.KeySize = 256;
_aes.Key = ASCIIEncoding.ASCII.GetBytes(key);
if (!string.IsNullOrEmpty(IV)) {
_aes.IV = ASCIIEncoding.ASCII.GetBytes(IV);
}
_aes.Padding = PaddingMode.PKCS7;
_aes.Mode = CipherMode.CBC;
}
public string encrypt(string message)
{
_crypto = _aes.CreateEncryptor(_aes.Key, _aes.IV);
byte[] encrypted = _crypto.TransformFinalBlock(
ASCIIEncoding.ASCII.GetBytes(message), 0, ASCIIEncoding.ASCII.GetBytes(message).Length);
_crypto.Dispose();
return System.Convert.ToBase64String(encrypted);
}
public string decrypt(string message)
{
_crypto = _aes.CreateDecryptor(_aes.Key, _aes.IV);
byte[] decrypted = _crypto.TransformFinalBlock(
System.Convert.FromBase64String(message), 0, System.Convert.FromBase64String(message).Length);
_crypto.Dispose();
return ASCIIEncoding.ASCII.GetString(decrypted);
}
}
}
The function decrypt not work, it return wrong string. I think some parameters is not same as the picture.
Base64-encoded encrypted data:
5qG6aB4UZ6bnbbPgFhnC+qp/FJ7ZuZ+fg1cYm+OUM1uP/6PyWfLg0w5bJstmBf2W
Key:
745d88b1e8f75d320c2bd9198c08485d
You need to initialize the IV to all zeroes because otherwise it starts with a random value:
if (!string.IsNullOrEmpty(IV))
{
_aes.IV = ASCIIEncoding.ASCII.GetBytes(IV);
}
else
{
_aes.IV = new byte[_aes.BlockSize / 8];
}
With this fix in place, it gets the same result as the online site you used.
Also note that your question says ECB but your code and screenshot use CBC (and it's AES, not ACS).
I'm porting the Following C# Encryption logic to php, i tried using OPENSSL to port the encryption but its giving me a weird error, i have no idea what im doing wrong maybe OPENSSL fault, padding? not sure
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.IO;
namespace Rextester
{
public class Program
{
public static ICryptoTransform DES;
public static DESCryptoServiceProvider Crypto = new DESCryptoServiceProvider();
public static MemoryStream memStream = new MemoryStream();
public static string encyrptedMessage;
public static void Main(string[] args)
{
Crypto.BlockSize = 64;
Crypto.FeedbackSize = 8;
Crypto.Mode = CipherMode.ECB;
Crypto.Padding = PaddingMode.PKCS7;
//Your code goes here
DES = Crypto.CreateEncryptor(Encoding.ASCII.GetBytes("L)#!&8#*"), Encoding.UTF8.GetBytes("CodeFast"));
CryptoStreamMode mode = CryptoStreamMode.Write;
// Set up streams and encrypt
byte[] messageBytes = Encoding.ASCII.GetBytes("yes");
CryptoStream cryptoStream = new CryptoStream(memStream, DES, mode);
cryptoStream.Write(messageBytes, 0, messageBytes.Length);
cryptoStream.FlushFinalBlock();
// Read the encrypted message from the memory stream
byte[] encryptedMessageBytes = new byte[memStream.Length];
memStream.Position = 0;
memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length);
// Encode the encrypted message as base64 string
string encryptedMessage = Convert.ToBase64String(encryptedMessageBytes);
Console.WriteLine(encryptedMessage);
}
}
}
<?php
namespace encryption;
class DESCrypto{
private $key;
private $iv;
public function __construct(string $key, ?string $iv){
$this->key = $key;
$this->iv = utf8_encode($iv);
}
public function encrypt(string $text): string {
return openssl_encrypt($text,"DES-ECB",$this->key,OPENSSL_RAW_DATA,$this->iv);
}
public function decrypt(string $text): string {
return openssl_decrypt($text,"DES-ECB",$this->key,OPENSSL_RAW_DATA,$this->iv);
}
}
the C# Code is working fine meanwhile the php one returning the following error
Warning: openssl_decrypt(): IV passed is 4 bytes long which is longer than the 0 expected by selected cipher
Warning: openssl_encrypt(): IV passed is 4 bytes long which is longer than the 0 expected by selected cipher
I have this class 'IdentityConfig.cs and Helper.cs', On IdentityConfig i am calling Helper class to access Decrypt method with its argument list. Somehow i dont seem to get this and i am getting an error called Decrypt does not exist or am i missing some directive. How do i fix this issue and calling the correct package. Please help me mates to resolve this issue.
// IdentityConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using System.Net.Mail;
using eNtsaTrainingRegistration.Models;
using System.Web.Configuration;
using System.Net;
namespace eNtsaTrainingRegistration.App_Start
{
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
var mailMessage = new MailMessage();
mailMessage.To.Add(new MailAddress(message.Destination));
mailMessage.From = new MailAddress("Gcobani Mkontwana <ggcobani#gmail.com>");
mailMessage.Subject = message.Subject;
mailMessage.IsBodyHtml = true;
mailMessage.Body = message.Body;
using(var smtp = new SmtpClient())
{
var credential = new NetworkCredential
{
UserName = WebConfigurationManager.AppSettings["UserName"],
Password = Helper.Decrypt(WebConfigurationManager.AppSettings["UserPasswd"])
};
smtp.Credentials = credential;
smtp.Host = WebConfigurationManager.AppSettings["SMTPName"];
smtp.Port = int.Parse(WebConfigurationManager.AppSettings["SMTPPort"]);
smtp.EnableSsl = true;
smtp.Send(mailMessage);
}
return Task.FromResult(0);
}
}
}
// Helper class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace eNtsaTrainingRegistration.Helper
{
public class Helper
{
private const string PassPhrase = "3pAc0j$_56K?_S7c9gS!";
//Encrypt password.
public static string Encrypt(string strValue)
{
byte[] results;
UTF8Encoding uTF8 = new UTF8Encoding();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] deskey = md5.ComputeHash(uTF8.GetBytes(PassPhrase));
TripleDESCryptoServiceProvider desalg = new TripleDESCryptoServiceProvider();
desalg.Key = deskey;
desalg.Mode = CipherMode.ECB;
desalg.Padding = PaddingMode.PKCS7;
byte[] encrypt_data = uTF8.GetBytes(strValue);
try
{
ICryptoTransform encrytor = desalg.CreateEncryptor();
results = encrytor.TransformFinalBlock(encrypt_data, 0, encrypt_data.Length);
}
finally
{
desalg.Clear();
md5.Clear();
}
return Convert.ToBase64String(results);
}
//Decrypt password.
public static string Decrypt(string strValue)
{
byte[] results;
UTF8Encoding uTF8 = new UTF8Encoding();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] deskey = md5.ComputeHash(uTF8.GetBytes(PassPhrase));
TripleDESCryptoServiceProvider desalg = new TripleDESCryptoServiceProvider();
desalg.Key = deskey;
desalg.Mode = CipherMode.ECB;
desalg.Padding = PaddingMode.PKCS7;
byte[] decrypt_data = Convert.FromBase64String(strValue);
try
{
ICryptoTransform decryptor = desalg.CreateDecryptor();
results = decryptor.TransformFinalBlock(decrypt_data, 0, decrypt_data.Length);
}
finally
{
desalg.Clear();
md5.Clear();
}
return uTF8.GetString(results);
}
// In between space
public static string GetBetween(string strSource, string strStart, string strEnd)
{
int Start, End;
if(strSource.Contains(strStart) && strSource.Contains(strEnd))
{
Start = strSource.IndexOf(strStart, 0) + strStart.Length;
End = strSource.IndexOf(strEnd, Start);
return strSource.Substring(Start, End - Start);
}else
{
return "";
}
}
public static string BytesToString(long byteCount)
{
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
if (byteCount == 0)
return string.Format("{0} {1}", 0, suf[0]);
long bytes = Math.Abs(byteCount);
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return string.Format("{0} {1}", (Math.Sign(byteCount) * num).ToString(), suf[place]);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace eNtsaTrainingRegistration
{
public class Helper_b
{
private const string PassPhrase = "3pAc0j$_56K?_S7c9gS!";
//Encrypt password.
public static string Encrypt(string strValue)
{
byte[] results;
UTF8Encoding uTF8 = new UTF8Encoding();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] deskey = md5.ComputeHash(uTF8.GetBytes(PassPhrase));
TripleDESCryptoServiceProvider desalg = new TripleDESCryptoServiceProvider();
desalg.Key = deskey;
desalg.Mode = CipherMode.ECB;
desalg.Padding = PaddingMode.PKCS7;
byte[] encrypt_data = uTF8.GetBytes(strValue);
try
{
ICryptoTransform encrytor = desalg.CreateEncryptor();
results = encrytor.TransformFinalBlock(encrypt_data, 0, encrypt_data.Length);
}
finally
{
desalg.Clear();
md5.Clear();
}
return Convert.ToBase64String(results);
}
//Decrypt password.
public static string Decrypt(string strValue)
{
byte[] results;
UTF8Encoding uTF8 = new UTF8Encoding();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] deskey = md5.ComputeHash(uTF8.GetBytes(PassPhrase));
TripleDESCryptoServiceProvider desalg = new TripleDESCryptoServiceProvider();
desalg.Key = deskey;
desalg.Mode = CipherMode.ECB;
desalg.Padding = PaddingMode.PKCS7;
byte[] decrypt_data = Convert.FromBase64String(strValue);
try
{
ICryptoTransform decryptor = desalg.CreateDecryptor();
results = decryptor.TransformFinalBlock(decrypt_data, 0, decrypt_data.Length);
}
finally
{
desalg.Clear();
md5.Clear();
}
return uTF8.GetString(results);
}
// In between space
public static string GetBetween(string strSource, string strStart, string strEnd)
{
int Start, End;
if(strSource.Contains(strStart) && strSource.Contains(strEnd))
{
Start = strSource.IndexOf(strStart, 0) + strStart.Length;
End = strSource.IndexOf(strEnd, Start);
return strSource.Substring(Start, End - Start);
}else
{
return "";
}
}
public static string BytesToString(long byteCount)
{
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
if (byteCount == 0)
return string.Format("{0} {1}", 0, suf[0]);
long bytes = Math.Abs(byteCount);
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
return string.Format("{0} {1}", (Math.Sign(byteCount) * num).ToString(), suf[place]);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using eNtsaTrainingRegistration.Models;
using System.Net.Mail;
using System.Net;
using System.Web.Configuration;
namespace eNtsaTrainingRegistration
{
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
var mailMessage = new MailMessage();
mailMessage.To.Add(new MailAddress(message.Destination));
mailMessage.From = new MailAddress("Gcobani Mkontwana <ggcobani#gmail.com>");
mailMessage.Subject = message.Subject;
mailMessage.IsBodyHtml = true;
mailMessage.Body = message.Body;
using(var smtp = new SmtpClient())
{
var credential = new NetworkCredential
{
UserName = WebConfigurationManager.AppSettings["UserName"],
Password = Helper_b.Decrypt(WebConfigurationManager.AppSettings["UserPassword"])
};
smtp.Credentials = credential;
smtp.Host = WebConfigurationManager.AppSettings["SMTPName"];
smtp.Port = int.Parse(WebConfigurationManager.AppSettings["SMTPPort"]);
smtp.EnableSsl = true;
smtp.Send(mailMessage);
}
return Task.FromResult(0);
}
}
}
I am using the following code to test the C# AES encryption and the output is 32 bytes instead of 16. I'd like to understand what is the extra 16 bytes. Thank you very much for any help.
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
namespace TestEnc
{
class Program
{
static void Main(string[] args)
{
byte[] key = { 50, 41, 132,234,143,17,
89, 74, 2, 56, 36,87,
54, 87, 88, 28};
byte[] iv = { 45, 241,153,24,14,17,
8, 57,32,5,96,47,
54,87,88,8};
using (Rijndael algorithm = Rijndael.Create())
{
algorithm.Padding = PaddingMode.PKCS7;
using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
{
string fullpath = #"c:\test.txt";
using (Stream FileOutStream = File.Open(fullpath, FileMode.Create))
{
using (Stream encStream = new CryptoStream(FileOutStream, encryptor, CryptoStreamMode.Write))
{
string s = "hello world 1234";
for (int i = 0; i < 1; i++)
{
encStream.Write(Encoding.ASCII.GetBytes(s), 0, (int)s.Length);
}
}
}
}
}
}
}
}