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);
}
}
}
}
}
}
}
}
Related
pretty new to c# and currently having a problem decrypting long passwords with an error of
Specified key is not a valid size for this algorithm
I know this has something to do with the encrypted password bits length not being supported but unsure how to go about suggested ways to allow for these longer passwords.
Here's my encrypt and decrypt
"cipherKey": "0123456789abcdef", "cipherVector":
"somereallycooliv"
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
namespace DataApi
{
public class Encryption
{
private readonly IConfigurationService _configService;
private const string _vector = "cipherVector";
private const string _key = "cipherKey";
public Encryption(IConfigurationService configService)
{
_configService = configService;
}
public string EncryptString(string text)
{
if(string.IsNullOrEmpty(text))
{
return "";
}
try
{
var key = Encoding.UTF8.GetBytes(_configService.Get(_key));
byte[] IV = Encoding.ASCII.GetBytes(_configService.Get(_vector));
using (var aesAlg = Aes.Create())
{
using (var encryptor = aesAlg.CreateEncryptor(key, IV))
{
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var decryptedContent = msEncrypt.ToArray();
var result = new byte[IV.Length + decryptedContent.Length];
Buffer.BlockCopy(IV, 0, result, 0, IV.Length);
Buffer.BlockCopy(decryptedContent, 0, result, IV.Length, decryptedContent.Length);
return Convert.ToBase64String(result);
}
}
}
}
catch(Exception e) {
Loggifer.Error("Unable to encrypt string: "+text , e );
throw e;
}
}
public string DecryptString(string cipherText)
{
if(string.IsNullOrEmpty(cipherText))
{
return "";
}
try
{
var fullCipher = Convert.FromBase64String(cipherText);
byte[] IV = Encoding.ASCII.GetBytes(_configService.Get(_vector));
var cipher = new byte[16];
Buffer.BlockCopy(fullCipher, 0, IV, 0, IV.Length);
Buffer.BlockCopy(fullCipher, IV.Length, cipher, 0, IV.Length);
var key = Encoding.UTF8.GetBytes(_configService.Get(_key));
using (var aesAlg = Aes.Create())
{
using (var decryptor = aesAlg.CreateDecryptor(key, IV))
{
string result;
using (var msDecrypt = new MemoryStream(cipher))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
result = srDecrypt.ReadToEnd();
}
}
}
return result;
}
}
}
catch (Exception e)
{
Loggifer.Error("Unable to decrypt string: "+cipherText , e );
throw e;
}
}
}
}
Two changes are required in the function public string DecryptString(string cipherText)
var cipher = new byte[fullCipher.Length - IV.Length];
and
Buffer.BlockCopy(fullCipher, IV.Length, cipher, 0, fullCipher.Length - IV.Length);
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);
}
}
}
I have cryptographic code in Go but I can't hard find similar code in CSharp.
I am debating to make my own implementation of XorKeyStream but I am told that there is legal issue if I write my own cryptographic code. I am sure there must be similar code in CSharp.
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
)
func main() {
k1 := []byte("0123456789abcdef")
r1 := []byte("1234567890abcdef")
data := []byte("0123456789")
fmt.Printf("original %x %s\n", data, string(data))
{
block, _ := aes.NewCipher(k1)
stream := cipher.NewCFBEncrypter(block, r1)
stream.XORKeyStream(data, data)
fmt.Printf("crypted %x\n", data)
}
{
block, _ := aes.NewCipher(k1)
stream := cipher.NewCFBDecrypter(block, r1)
stream.XORKeyStream(data, data)
fmt.Printf("decrypted %x %s\n", data, string(data))
}
}
http://play.golang.org/p/EnJ56dYX_-
output
original 30313233343536373839 0123456789
crypted 762b6dcea9c2a7460db7
decrypted 30313233343536373839 0123456789
PS
Some people marked that question as possible duplicate of question: "C# AES: Encrypt a file causes “Length of the data to encrypt is invalid.” error"
I look for identical code in CSharp for existing code in Go. That question is about padding. This algorithm needs "Key stream" that will xor text.
It is different questions.
Here is your code
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
class AES_CFB_XorKeyStream
{
static void Main(string[] args)
{
byte[] data = Encoding.UTF8.GetBytes("0123456789");
byte [] k1 = Encoding.UTF8.GetBytes("0123456789abcdef");
byte [] r1 = Encoding.UTF8.GetBytes("1234567890abcdef");
Console.WriteLine("original " + BitConverter.ToString(data));
using (RijndaelManaged Aes128 = new RijndaelManaged())
{
Aes128.BlockSize = 128;
Aes128.KeySize = 128;
Aes128.Mode = CipherMode.CFB;
Aes128.FeedbackSize = 128;
Aes128.Padding = PaddingMode.None;
Aes128.Key = k1;
Aes128.IV = r1;
using (var encryptor = Aes128.CreateEncryptor())
using (var msEncrypt = new MemoryStream())
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var bw = new BinaryWriter(csEncrypt, Encoding.UTF8))
{
bw.Write(data);
bw.Close();
data = msEncrypt.ToArray();
Console.WriteLine("crypted " + BitConverter.ToString(data));
}
}
using (RijndaelManaged Aes128 = new RijndaelManaged())
{
Aes128.BlockSize = 128;
Aes128.KeySize = 128;
Aes128.Mode = CipherMode.CFB;
Aes128.FeedbackSize = 128;
Aes128.Padding = PaddingMode.None;
Aes128.Key = k1;
Aes128.IV = r1;
using (var decryptor = Aes128.CreateDecryptor())
using (var msEncrypt = new MemoryStream())
using (var csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Write))
using (var bw = new BinaryWriter(csEncrypt, Encoding.UTF8))
{
bw.Write(data);
bw.Close();
data = msEncrypt.ToArray();
Console.WriteLine("decrypted " + BitConverter.ToString(data));
}
}
}
}
output
original 30-31-32-33-34-35-36-37-38-39
crypted 76-2B-6D-CE-A9-C2-A7-46-0D-B7
decrypted 30-31-32-33-34-35-36-37-38-39
I had this exact same issue with only the first byte of each decrypted block being correct, but I did not have the luxury of being able to change source on the Go program.
I ended up implementing my own padding. Just pad the encrypted bytes with 0 bytes to make it divisible by the block size of 128, then after running through the decryption routine, chop that number of bytes off the end.
Example code:
using System;
using System.Text;
using System.Security.Cryptography;
using System.Linq;
public static class Program
{
static RijndaelManaged aes = new RijndaelManaged(){
Mode = CipherMode.CFB,
BlockSize = 128,
KeySize = 128,
FeedbackSize = 128,
Padding = PaddingMode.None
};
public static void Main(){
byte[] key = Encoding.UTF8.GetBytes("0123456789abcdef");
byte[] iv = Encoding.UTF8.GetBytes("1234567890abcdef");
byte[] encryptedBytes = new byte[]{0x76, 0x2b, 0x6d, 0xce, 0xa9, 0xc2, 0xa7, 0x46, 0x0d, 0xb7};
// Custom pad the bytes
int padded;
encryptedBytes = PadBytes(encryptedBytes, aes.BlockSize, out padded);
// Decrypt bytes
byte[] decryptedBytes = DecryptBytesAES(encryptedBytes, key, iv, encryptedBytes.Length);
// Check for successful decrypt
if(decryptedBytes != null){
// Unpad
decryptedBytes = UnpadBytes(decryptedBytes, padded);
Console.Write("Decrypted: " + Encoding.UTF8.GetString(decryptedBytes));
}
}
// Just an elegant way of initializing an array with bytes
public static byte[] Initialize(this byte[] array, byte value, int length)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = value;
}
return array;
}
// Custom padding to get around the issue of how Go uses CFB mode without padding differently than C#
public static byte[] PadBytes(byte[] encryptedBytes, int blockSize, out int numPadded)
{
numPadded = 0;
// Check modulus of block size
int mod = encryptedBytes.Length % blockSize;
if (mod != 0)
{
// Calculate number to pad
numPadded = blockSize - mod;
// Build array
return encryptedBytes.Concat(new byte[numPadded].Initialize(0, numPadded)).ToArray();
}
else {
// No padding needed
return encryptedBytes;
}
}
public static byte[] UnpadBytes(byte[] decryptedBytes, int numPadded)
{
if(numPadded != 0)
{
byte[] unpaddedBytes = new byte[decryptedBytes.Length - numPadded];
Array.Copy(decryptedBytes, unpaddedBytes, unpaddedBytes.Length);
return unpaddedBytes;
}
else
{
return decryptedBytes;
}
}
public static byte[] DecryptBytesAES(byte[] cipherText, byte[] Key, byte[] IV, int size)
{
byte[] array = new byte[size];
try{
aes.Key = Key;
aes.IV = IV;
ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV);
using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(cipherText))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read))
{
cryptoStream.Read(array, 0, size);
}
}
}
catch(Exception e){
return null;
}
return array;
}
}
.NET Fiddle: https://dotnetfiddle.net/NPHKN3
Hello everyone I am developing a chat application for school. Its in C#, a language I have never worked with before. Now I have a winform that needs to encrypt some data, I have the encryption code in is own class but for some reason I can't use any of the functions in the cipher class.
Here is a very simplified version of the code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data;
using System.Security.Cryptography;
namespace WindowsFormsApplication2
{
public class SimpleAES
{
// Change these keys
private byte[] Key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
private byte[] Vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 252, 112, 79, 32, 114, 156 };
private ICryptoTransform EncryptorTransform, DecryptorTransform;
private System.Text.UTF8Encoding UTFEncoder;
public SimpleAES()
{
//This is our encryption method
RijndaelManaged rm = new RijndaelManaged();
//Create an encryptor and a decryptor using our encryption method, key, and vector.
EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);
//Used to translate bytes to text and vice versa
UTFEncoder = new System.Text.UTF8Encoding();
}
/// -------------- Two Utility Methods (not used but may be useful) -----------
/// Generates an encryption key.
public byte[] Encrypt(string TextValue)
{
//Translates our text value into a byte array.
Byte[] bytes = UTFEncoder.GetBytes(TextValue);
//Used to stream the data in and out of the CryptoStream.
MemoryStream memoryStream = new MemoryStream();
/*
* We will have to write the unencrypted bytes to the stream,
* then read the encrypted result back from the stream.
*/
#region Write the decrypted value to the encryption stream
CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write);
cs.Write(bytes, 0, bytes.Length);
cs.FlushFinalBlock();
#endregion
#region Read encrypted value back out of the stream
memoryStream.Position = 0;
byte[] encrypted = new byte[memoryStream.Length];
memoryStream.Read(encrypted, 0, encrypted.Length);
#endregion
//Clean up.
cs.Close();
memoryStream.Close();
return encrypted;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
byte[] result = Encrypt(textBox1.Text);
}
}
}
When I throw this into visual studio the function call to Encrypt() is highlighted in red and the description it gives is the Encrypt does not exist in the current context.
I am much more experienced with C++ and I figured something like what I have would work, but I guess thats incorrect.
Any help would be most appreciated.
SimpleAES is not a static class, so you'll need to create an instance of it before you can call methods on it:
private void button1_Click(object sender, EventArgs e)
{
SimpleAES simpleAes = new SimpleAES();
byte[] result = simpleAes.Encrypt(textBox1.Text);
}
Make instance of SimpleAES like answer in #PoweredByOrange or change to static like #Bob or make extenstion method on a string like mine answer:
private void button1_Click(object sender, EventArgs e)
{
byte[] result = textBox1.Text.Encrypt();
}
public class Extensionmethods
{
public static byte[] Encrypt(this string TextValue)
{
//Your code here
}
}
I need to pass a URL as a parameter into my querystring, since the URLs can be long I need to shorten the URL while passing and then be able to decrypt them on server side.
The URL that I am trying to pass does not contain sensitive information so string encryption techniques are not required, I am just looking to convert a long string to a short string and be able to reconstruct it back to a string.
I have tried AES encryption and it works but the resulting string is sometimes longer than the URL value itself.
Example of what I've tried so far :
private static byte[] key = { 252, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
private static byte[] vector = { 152, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 };
private ICryptoTransform encryptor, decryptor;
private UTF8Encoding encoder;
public SimpleAES()
{
RijndaelManaged rm = new RijndaelManaged();
encryptor = rm.CreateEncryptor(key, vector);
decryptor = rm.CreateDecryptor(key, vector);
encoder = new UTF8Encoding();
}
public string Encrypt(string unencrypted)
{
return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
}
public string Decrypt(string encrypted)
{
return encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
}
public string EncryptToUrl(string unencrypted)
{
return HttpUtility.UrlEncode(Encrypt(unencrypted));
}
public string DecryptFromUrl(string encrypted)
{
return Decrypt(HttpUtility.UrlDecode(encrypted));
}
public byte[] Encrypt(byte[] buffer)
{
return Transform(buffer, encryptor);
}
public byte[] Decrypt(byte[] buffer)
{
return Transform(buffer, decryptor);
}
protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
{
MemoryStream stream = new MemoryStream();
using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}
return stream.ToArray();
}
Example TEST :
string unencrypted = "/exampleurl/this_is_a_long_string_the_length_of_this_url_is_112_charachters_/this_string_needs_to_be-shortened/";
var result = EncryptToUrl(unencrypted);
"MHMyQdwbJpw8ah%2fbhAr2eJwTFa%2fyupemjuOVcBJmxTIdzcR0PZKCNSa5Fvi7kNrY3Kxlk5KWqAAEspWVtJfNjwwPs%2bCDGpC9Fn8CeGezWhXEbLT6CST2v%2fKpvptHVi3fBYSk1w3q1FYMx3C5DdKueQ%3d%3d"
The actual string is 112 charachters long and the result is 165 charahcters long.
The following code is taken verbatim from here. I duplicated this because the question is not a duplicate but the answer solves the problem this question poses. When you call Zip you will need to base64 encode the result to make it friendly for a browser if you plan to include it in a URL or something.
public static void CopyTo(Stream src, Stream dest) {
byte[] bytes = new byte[4096];
int cnt;
while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
dest.Write(bytes, 0, cnt);
}
}
public static byte[] Zip(string str) {
var bytes = Encoding.UTF8.GetBytes(str);
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
//msi.CopyTo(gs);
CopyTo(msi, gs);
}
return mso.ToArray();
}
}
public static string Unzip(byte[] bytes) {
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream()) {
using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
//gs.CopyTo(mso);
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
}
static void Main(string[] args) {
byte[] r1 = Zip("StringStringStringStringStringStringStringStringStringStringStringStringStringString");
string r2 = Unzip(r1);
}
This might sound strange, but can you store the querystring in a database and reference it by some primary key? That might be similar to using some third party URL shortening service.