Example code PHP / C# AES encryption - random IV - c#

I found an implementation for AES encryption/decryption that's supposed to work in PHP and C#:
https://odan.github.io/2017/08/10/aes-256-encryption-and-decryption-in-php-and-csharp.html
However, in this example, the IV is always 0, which is not good.
So, as the author suggests, I use the openssl_random_pseudo_bytes() function:
$ivlen = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($ivlen);
However, the problem now is, that I have to store the IV somewhere so that the C# app can use it for decryption. My idea was to base64_encode it and prepend it to the encrypted message with ":" separating both, so that I can simply split the string, then base64 decode it in C# and can use the IV. However, this does not work. This is the code:
public string DecryptString(string cipherText, byte[] key, byte[] iv)
{
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
// Will contain decrypted plaintext
string plainText = String.Empty;
try {
// Convert the ciphertext string into a byte array
byte[] cipherBytes = Convert.FromBase64String(cipherText);
// Decrypt the input ciphertext string
cryptoStream.Write(cipherBytes, 0, cipherBytes . Length);
// Complete the decryption process
cryptoStream.FlushFinalBlock();
// Convert the decrypted data from a MemoryStream to a byte array
byte[] plainBytes = memoryStream.ToArray();
// Convert the decrypted byte array to string
plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
} finally {
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
}
// Return the decrypted data as a string
return plainText;
}
And this is how I try to call the function with the IV prepended to the encrypted message:
private void btnDecrypt_Click(object sender, EventArgs e)
{
string encrypted = txtEncrypted.Text;
string password = txtPW.Text;
string[] temp = encrypted.Split(":".ToCharArray());
string iv_str = temp[0];
encrypted = temp[1];
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
iv_str = Encoding.Default.GetString(Convert.FromBase64String(iv_str));
byte[] iv = Encoding.ASCII.GetBytes(iv_str);
txtDecrypted.Text = this.DecryptString(encrypted, key, iv);
}
Doesn't work. It decrypts something, but that's just gibberish and not the message I encrypted in PHP.
I think it has to do with the IV somehow.

#Topaco:
Thank you very much... now I see what my mistake was. It works now with generated IV.
By the way, two more questions on the strength of the encryption:
Is it ok to use the following function to generate an IV (GenerateIV() for some reason won't work):
byte[] iv = new byte[16];
Random rnd = new Random();
rnd.NextBytes(iv);
I added a randomly generated salt to the password of the user, so that the key is a hash from the user password and a salt. I also prepend the salt, together with the now randomly generated IV, to the message. Then for the decryption process I use the prepended salt and the key the user enters. Works so far. But does it weaken the encryption? No, right?
Thank you very much.
// Edit: Code format doesn't work, don't know why.

Related

How to decrypt a Rijndael 128 encrypted text

I'm trying to decrypt a Rijndael-128 encrypted cipher, these are the values:
Cipher: "QfJzZ9V6Jm43jYPiVaXP9mu+f88S/JC24saHbOMxxC8="
Key: "45744855535472525844494538555934",
Mode: CBC
Result should be: "abcd#1234"
This website seems to decrypt the cipher just fine:
https://codebeautify.org/encrypt-decrypt
I'm trying to do the same thing in C# with absolutely no luck, what am I missing here?
class Program
{
static void Main(string[] args)
{
var text = Decrypt("QfJzZ9V6Jm43jYPiVaXP9mu+f88S/JC24saHbOMxxC8=", Convert.FromBase64String("45744855535472525844494538555934"));
}
public static string Decrypt(string Text, byte[] keyBytes)
{
var textBytes = Convert.FromBase64String(Text);
var rijKey = new RijndaelManaged();
rijKey.IV = textBytes.Take(rijKey.BlockSize / 8).ToArray();
rijKey.Padding = PaddingMode.None;
rijKey.Mode = CipherMode.CBC;
var decryptor = rijKey.CreateDecryptor(keyBytes, rijKey.IV);
var memoryStream = new MemoryStream(textBytes);
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
var pTextBytes = new byte[textBytes.Length];
var decryptedByteCount = cryptoStream.Read(pTextBytes, 0, pTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string plainText = Encoding.UTF8.GetString(pTextBytes, 0, decryptedByteCount);
return plainText;
}
}
The problem with your code is this line:
rijKey.GenerateIV();
You need the original IV. You can't just use a random one.
If you go to the site you linked to, each time you press encrypt with the key and text you have given, you get a different encrypted text (because a random IV is used). The web page must be prepending the random IV used to encrypt to the encrypted text (or less likely, the web page is storing it), which is why it can then decrypt the encrypted text.
[Your code also needs using statements.]
Is it possible to NOT use the IV when implementing Rijndael decryption?
How to Use Rijndael ManagedEncryption with C#

How to convert CryptoJS decryption code into C#?

I have this code in CryptoJS, inside browser:
var decrypt = function (cipherText) {
var key = "a_long_key_goes_here";
var iv = "initial_vector_goes_here";
key = CryptoJS.enc.Hex.parse(key);
iv = CryptoJS.enc.Hex.parse(iv);
var decrypted = CryptoJS.TripleDES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(cipherText)
}, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
var clearText = decrypted.toString(CryptoJS.enc.Utf8);
return clearText;
};
This code is not written by me. Also the cipherText come from another server that I have no access to. However, I have access to key and to iv.
I can decrypt that cipherText inside a browser's console. But I want to use these keys to decrypt that cipherText inside C# code. Here's the code I've written:
public void Desrypt()
{
ICryptoTransform decryptor;
UTF8Encoding encoder;
string key = "a_long_key_goes_here";
string iv = "initial_vector_goes_here";
var cipherText = "cipher_text_goes_here";
string clearText = "";
byte[] cipherBytes = FromHexString(cipherText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { });
aes.Key = pdb.GetBytes(32);
aes.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
clearText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return clearText;
}
public static byte[] FromHexString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return bytes;
}
I have some problems though. I don't understand if I'm correctly decoding the given cipherText from hexadecimal or not. Also I can't instantiate Rfc2898DeriveBytes, because I don't know what the second parameter (salt) should be.
Also I don't know where should I use that iv I've gotten from the CryptoJS code.
Could you please help?
So that both codes are compatible, the following changes of the C# code are necessary:
The return type of the Decrypt method must be changed from void to string.
Key and IV have to be decoded hexadecimal like the ciphertext with FromHexString.
Instead of AES, TripleDES must be used.
Rfc2898DeriveBytes implements PBKDF2 and must not be applied (since the JavaScript code does not use PBKDF2 either).
The decrypted data must not be decoded with Encoding.Unicode (which corresponds to UTF16LE in .NET), but with Encoding.UTF8.
The C# code can handle 24 bytes keys (to support 3TDEA) and 16 bytes keys (to support the less secure 2TDEA). The posted CryptoJS code also handles these key sizes plus additionally 8 bytes keys (to support the least secure, DES compatible variant 1TDEA).
The following C# code decrypts a ciphertext generated with CryptoJS and 3TDEA:
public string Decrypt()
{
byte[] key = FromHexString("000102030405060708090a0b0c0d0e0f1011121314151617"); // 24 bytes (3TDEA)
byte[] iv = FromHexString("0001020304050607"); // 8 bytes
byte[] ciphertext = FromHexString("2116057c372e0e95dbe91fbfd148371b8e9974187b71e7c018de89c757280ad342d4191d29472040ee70d19015b025e1");
string plaintext = "";
using (TripleDES tdes = TripleDES.Create())
{
tdes.Key = key;
tdes.IV = iv;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor(tdes.Key, tdes.IV), CryptoStreamMode.Write))
{
cs.Write(ciphertext, 0, ciphertext.Length);
}
plaintext = Encoding.UTF8.GetString(ms.ToArray());
}
}
return plaintext;
}
The decryption is also possible with the posted JavaScript code, which shows the functional equivalence of both codes.
Note: Since AES is more performant than TripleDES, AES should be used if possible.

Are my codes as secure as using AES?

I am currently working on a project assigned by my teacher and I need to ensure the application it has strong encryption. Below is my encrypt method:
private String Encrypt(string text)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
string Password = System.Configuration.ConfigurationManager.AppSettings["Password"];
byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(TextBox1.Text);
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
cryptoStream.Write(PlainText, 0, PlainText.Length);
cryptoStream.FlushFinalBlock();
byte[] CipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string EncryptedData = Convert.ToBase64String(CipherBytes);
return EncryptedData;
}
This is my Decrypt Method
public string Decrypt(string encrypted)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
string Password = System.Configuration.ConfigurationManager.AppSettings["Password"];
string DecryptedData;
try
{
byte[] EncryptedData = Convert.FromBase64String(TextBox2.Text);
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));
MemoryStream memoryStream = new MemoryStream(EncryptedData);
CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
byte[] PlainText = new byte[EncryptedData.Length];
int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);
memoryStream.Close();
cryptoStream.Close();
DecryptedData = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);
}
catch
{
DecryptedData = TextBox3.Text;
}
return DecryptedData;
}
As you can see from my codes, I am using the password from the web config and I do not store any IV and key into the database. So my question is if the encryptions method that I use is as secure as using AES method. If it isn't, is there any other possible solutions that I can refer to? Thanks for replying and sorry for my poor english skills.
This bad in several ways:
It's unauthenticated. Add a MAC on use an existing authenticated algorithm like AES-GCM, AES-SIV.
The salt is derived deterministically from the password, which is equivalent to using no salt at all. Each user needs to use a different salt.
Similar to the salt, the point of an IV is to ensure that encrypting similar or identical plaintexts using a fixed key produces completely different outputs every time. If your key is single-use (e.g. because its derivation involves a single-use salt), a fixes IV would be acceptable.
PasswordDeriveBytes is a mix of PBKDF1 and undocumented Microsoft specific extensions. Don't use it. At minimum use Rfc2898DeriveBytes which is standard compliant PBKDF2-HMAC-SHA1. Using about 100000 iterations, instead of the much too small default.
I recommend using jbtule's answer to Encrypt and decrypt a string in C#

Decrypt string using AES/CBC/NoPadding algorithm

I want to decrypt an Encrypted Sting using AES/CBC/Nopadding in c# Windows Phone 8 application. My string is in file of IsolatedSorage. I pasted the string HERE which is junk.
From this Article I am using AesManaged class to decrypt.
But how to set padding to NoPadding because by default the padding set to PKCS7 from here.
string fileName = "titlepage.xhtml";
if (fileStorage.FileExists(fileName))
{
IsolatedStorageFileStream someStream = fileStorage.OpenFile(fileName, System.IO.FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(someStream))
{
str1 = reader.ReadToEnd();
MessageBox.Show(str1);
try
{
string text = Decrypt(str1, "****************", "****************");
MessageBox.Show(text);
}
catch (CryptographicException cryptEx)
{
MessageBox.Show(cryptEx.Message, "Encryption Error", MessageBoxButton.OK);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "General Error", MessageBoxButton.OK);
}
}
}
public string Decrypt(string dataToDecrypt, string password, string salt)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
try
{
//Generate a Key based on a Password and HMACSHA1 pseudo-random number generator
//Salt must be at least 8 bytes long
//Use an iteration count of at least 1000
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);
//Create AES algorithm
aes = new AesManaged();
//Key derived from byte array with 32 pseudo-random key bytes
aes.Key = rfc2898.GetBytes(32);
//IV derived from byte array with 16 pseudo-random key bytes
aes.IV = rfc2898.GetBytes(16);
//Create Memory and Crypto Streams
memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write);
byte[] data = Convert.FromBase64String(dataToDecrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
//Return Decrypted String
byte[] decryptBytes = memoryStream.ToArray();
//Dispose
if (cryptoStream != null)
cryptoStream.Dispose();
//Retval
return Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
}
finally
{
if (memoryStream != null)
memoryStream.Dispose();
if (aes != null)
aes.Clear();
}
}
Edit 1:
When I am decrypting my Encrypted string in thins line
byte[] data = Convert.FromBase64String(dataToDecrypt);
Moving to Finally block and getting exception of The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters in decrypted string.
It is bit of confuse on this which is supported class to Decrypt in windows phone.
If I am completely wrong suggest me url of article regarding algorithm in Windows Phone
Edit 2:
As Below answer suggested " I am getting cyperText as bytes it is fine in decryption side. But it is giving an exception with the description
[Cryptography_SSD_InvalidDataSize]
Arguments:
Debugging resource strings are unavailable. Often the key and arguments provide
sufficient information to diagnose the problem
I believe that problem is IV[salt key] or setting padding to AesManged.
But I can't change padding property to AesManaged in Windows Phone.
By default padding to AesManged is PKCS7. I want to change to NoPadding. Because my cyperText is encrypted using AES/CBC/NoPadding algorithm "
If I understand the problem, you have data that is already encrypted in AES CBC mode, with no padding. But on the phone where you want to decrypt the data, the only option you have is PKCS#7 padding.
Well, you are in luck! You can decrypt the ciphertext using PKCS#7 padding. All you need to do is add the padding to the ciphertext, on the phone, and then decrypt it.
To add padding after the fact, you will encrypt a small bit of data and append it to the ciphertext. Then, you decrypt the modified ciphertext, and take that small bit of data off, and you have the original plaintext.
Here is how you do it:
Take a ciphertext on the phone. This is a multiple of 16 bytes, even if there is no padding. There is no other possibility -- AES ciphertext is always a multiple of 16 bytes.
Take the LAST 16 bytes of the ciphertext aside, and set that as the IV of your AES ENCRYPT. (Encrypt, not decrypt.) Use the same key as you are going to use to decrypt later.
Now encrypt something smaller than 16 bytes, for example, the character '$'. The phone is going to add PKCS#7 padding to this.
Append the resulting 16-bytes of ciphertext to the original ciphertext from step 1, and you now have a properly PKCS#7-padded ciphertext which includes the original plaintext plus the added '$'.
Use the original IV, and the same key, and now DECRYPT this combined ciphertext. You can now remove the '$' that will appear at the end of your plaintext (or whatever you added in step 3.)
When the small bit is encrypted with the last 16-bytes of the original ciphertext, you are actually extending the ciphertext in true AES CBC mode, and you happen to be doing that with PKCS#7 padding, so you can now decrypt the whole thing and take the small bit off. You will have the original plaintext which had no padding.
I thought this would be interesting to show in code:
var rfc2898 = new Rfc2898DeriveBytes("password", new byte[8]);
using (var aes = new AesManaged())
{
aes.Key = rfc2898.GetBytes(32);
aes.IV = rfc2898.GetBytes(16);
var originalIV = aes.IV; // keep a copy
// Prepare sample plaintext that has no padding
aes.Padding = PaddingMode.None;
var plaintext = Encoding.UTF8.GetBytes("this plaintext has 32 characters");
byte[] ciphertext;
using (var encryptor = aes.CreateEncryptor())
{
ciphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
Console.WriteLine("ciphertext: " + BitConverter.ToString(ciphertext));
}
// From this point on we do everything with PKCS#7 padding
aes.Padding = PaddingMode.PKCS7;
// This won't decrypt -- wrong padding
try
{
using (var decryptor = aes.CreateDecryptor())
{
var oops = decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
}
}
catch (Exception e)
{
Console.WriteLine("caught: " + e.Message);
}
// Last block of ciphertext is used as IV to encrypt a little bit more
var lastBlock = new byte[16];
var modifiedCiphertext = new byte[ciphertext.Length + 16];
Array.Copy(ciphertext, ciphertext.Length - 16, lastBlock, 0, 16);
aes.IV = lastBlock;
using (var encryptor = aes.CreateEncryptor())
{
var dummy = Encoding.UTF8.GetBytes("$");
var padded = encryptor.TransformFinalBlock(dummy, 0, dummy.Length);
// Set modifiedCiphertext = ciphertext + padded
Array.Copy(ciphertext, modifiedCiphertext, ciphertext.Length);
Array.Copy(padded, 0, modifiedCiphertext, ciphertext.Length, padded.Length);
Console.WriteLine("modified ciphertext: " + BitConverter.ToString(modifiedCiphertext));
}
// Put back the original IV, and now we can decrypt...
aes.IV = originalIV;
using (var decryptor = aes.CreateDecryptor())
{
var recovered = decryptor.TransformFinalBlock(modifiedCiphertext, 0, modifiedCiphertext.Length);
var str = Encoding.UTF8.GetString(recovered);
Console.WriteLine(str);
// Now you can remove the '$' from the end
}
}
The string you linked to is not Base-64. It looks as if it is raw encrypted bytes, interpreted as characters. Either work on the encryption side to output a Base-64 string encoding of the raw bytes or else work on the decryption side to read the cyphertext as raw bytes, not as text, and forget about removing the Base-64.
Generally better to work on the encryption side since passing Base-64 text is a lot less error-prone than passing raw bytes.

Length of the data to decrypt is invalid

I'm trying to Decrypt an byte array and I got this error:
Length of the data to decrypt is invalid.
The error occurs at this point:
int decryptedByteCount = cryptoStream
.Read(plainTextBytes, 0, plainTextBytes.Length);
here's the complete code
public static byte[] Decrypt(byte[] encryptedBytes, string key) {
string initVector = "#1B2c3D4e5F6g7H8";
string saltValue = "s#1tValue";
string passPhrase = key;//"s#1tValue";
string hashAlgorithm = "SHA1";
int passwordIterations = 2;
int keySize = 128;
// Convert strings defining encryption key characteristics into byte
// arrays. Let us assume that strings only contain ASCII codes.
// If strings include Unicode characters, use Unicode, UTF7, or UTF8
// encoding.
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
// Convert our ciphertext into a byte array.
byte[] cipherTextBytes = encryptedBytes;
// First, we must create a password, from which the key will be
// derived. This password will be generated from the specified
// passphrase and salt value. The password will be created using
// the specified hash algorithm. Password creation can be done in
// several iterations.
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
// Use the password to generate pseudo-random bytes for the encryption
// key. Specify the size of the key in bytes (instead of bits).
byte[] keyBytes = password.GetBytes(keySize / 8);
// Create uninitialized Rijndael encryption object.
TripleDESCryptoServiceProvider symmetricKey = new TripleDESCryptoServiceProvider();
// It is reasonable to set encryption mode to Cipher Block Chaining
// (CBC). Use default options for other symmetric key parameters.
symmetricKey.Mode = CipherMode.CBC;
// Generate decryptor from the existing key bytes and initialization
// vector. Key size will be defined based on the number of the key
// bytes.
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
// Define memory stream which will be used to hold encrypted data.
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
// Define cryptographic stream (always use Read mode for encryption).
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
// Since at this point we don't know what the size of decrypted data
// will be, allocate the buffer long enough to hold ciphertext;
// plaintext is never longer than ciphertext.
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
// Start decrypting.
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
// Close both streams.
memoryStream.Close();
cryptoStream.Close();
// Convert decrypted data into a string.
// Let us assume that the original plaintext string was UTF8-encoded.
string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
// Return decrypted string.
//return plainText;
return plainTextBytes;
}
the error is here,
MemoryStream fileStreamIn = new MemoryStream(buffer);
ZipInputStream zipInStream = new ZipInputStream(fileStreamIn);
ZipEntry entry = zipInStream.GetNextEntry();
MemoryStream fileStreamOut = new MemoryStream();
int size;
byte[] bufferOut = new byte[buffer.Length];
do {
size = zipInStream.Read(bufferOut, 0, bufferOut.Length);
fileStreamOut.Write(bufferOut, 0, size);
} while (size > 0);
zipInStream.Close();
fileStreamOut.Close();
fileStreamIn.Close();
return bufferOut;
this is the unzip method and the size of the bufferout is bigger than should be

Categories