Encrypt a byte array
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
This code is a Frankenstein. I found ten examples done in ten different ways and my requirements were slightly different so even if they were reliable they weren't a copy and paste solution.
Encrypt takes in a byte
and password and returns the byte
encrypted with the password. It has to tack on the length of the original byte
and the initialization vector used by the encryption algorithm.
Decrypt knows how to read the encrypted byte
and will return the original message.
Note: One thing about naming conventions - Since a lot of this is copy and paste from different sources I tended to keep the original authors' conventions so that the code would match up. That's why some variables start with caps and some don't. Not looking to have this post turn into a tangent about that low hanging fruit though. But since it's obvious I thought I should point it out.
Encrypt
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/eab7d698-2340-4ba0-a91c-da6fae06963c/aes-encryption-encrypting-byte-array?forum=csharpgeneral
// https://crypto.stackexchange.com/questions/2280/why-is-the-iv-passed-in-the-clear-when-it-can-be-easily-encrypted
public static byte Encrypt(byte bytesToEncrypt, string password)
byte ivSeed = Guid.NewGuid().ToByteArray();
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte encrypted;
using (MemoryStream mstream = new MemoryStream())
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
using (CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
cryptoStream.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
encrypted = mstream.ToArray();
var messageLengthAs32Bits = Convert.ToInt32(bytesToEncrypt.Length);
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
encrypted = encrypted.Prepend(ivSeed);
encrypted = encrypted.Prepend(messageLength);
return encrypted;
Decrypt
public static byte Decrypt(byte bytesToDecrypt, string password)
(byte messageLengthAs32Bits, byte bytesWithIv) = bytesToDecrypt.Shift(4); // get the message length
(byte ivSeed, byte encrypted) = bytesWithIv.Shift(16); // get the initialization vector
var length = BitConverter.ToInt32(messageLengthAs32Bits, 0);
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte decrypted;
using (MemoryStream mStream = new MemoryStream(encrypted))
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
aesProvider.Padding = PaddingMode.None;
using (CryptoStream cryptoStream = new CryptoStream(mStream,aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
cryptoStream.Read(encrypted, 0, length);
decrypted = mStream.ToArray().Take(length).ToArray();
return decrypted;
Relevant Extension Methods (i'm more worried about security than these)
public static byte Prepend(this byte bytes, byte bytesToPrepend)
var tmp = new byte[bytes.Length + bytesToPrepend.Length];
bytesToPrepend.CopyTo(tmp, 0);
bytes.CopyTo(tmp, bytesToPrepend.Length);
return tmp;
public static (byte left, byte right) Shift(this byte bytes, int size)
var left = new byte[size];
var right = new byte[bytes.Length - size];
Array.Copy(bytes, 0, left, 0, left.Length);
Array.Copy(bytes, left.Length, right, 0, right.Length);
return (left, right);
c# array security
add a comment |Â
up vote
5
down vote
favorite
This code is a Frankenstein. I found ten examples done in ten different ways and my requirements were slightly different so even if they were reliable they weren't a copy and paste solution.
Encrypt takes in a byte
and password and returns the byte
encrypted with the password. It has to tack on the length of the original byte
and the initialization vector used by the encryption algorithm.
Decrypt knows how to read the encrypted byte
and will return the original message.
Note: One thing about naming conventions - Since a lot of this is copy and paste from different sources I tended to keep the original authors' conventions so that the code would match up. That's why some variables start with caps and some don't. Not looking to have this post turn into a tangent about that low hanging fruit though. But since it's obvious I thought I should point it out.
Encrypt
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/eab7d698-2340-4ba0-a91c-da6fae06963c/aes-encryption-encrypting-byte-array?forum=csharpgeneral
// https://crypto.stackexchange.com/questions/2280/why-is-the-iv-passed-in-the-clear-when-it-can-be-easily-encrypted
public static byte Encrypt(byte bytesToEncrypt, string password)
byte ivSeed = Guid.NewGuid().ToByteArray();
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte encrypted;
using (MemoryStream mstream = new MemoryStream())
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
using (CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
cryptoStream.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
encrypted = mstream.ToArray();
var messageLengthAs32Bits = Convert.ToInt32(bytesToEncrypt.Length);
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
encrypted = encrypted.Prepend(ivSeed);
encrypted = encrypted.Prepend(messageLength);
return encrypted;
Decrypt
public static byte Decrypt(byte bytesToDecrypt, string password)
(byte messageLengthAs32Bits, byte bytesWithIv) = bytesToDecrypt.Shift(4); // get the message length
(byte ivSeed, byte encrypted) = bytesWithIv.Shift(16); // get the initialization vector
var length = BitConverter.ToInt32(messageLengthAs32Bits, 0);
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte decrypted;
using (MemoryStream mStream = new MemoryStream(encrypted))
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
aesProvider.Padding = PaddingMode.None;
using (CryptoStream cryptoStream = new CryptoStream(mStream,aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
cryptoStream.Read(encrypted, 0, length);
decrypted = mStream.ToArray().Take(length).ToArray();
return decrypted;
Relevant Extension Methods (i'm more worried about security than these)
public static byte Prepend(this byte bytes, byte bytesToPrepend)
var tmp = new byte[bytes.Length + bytesToPrepend.Length];
bytesToPrepend.CopyTo(tmp, 0);
bytes.CopyTo(tmp, bytesToPrepend.Length);
return tmp;
public static (byte left, byte right) Shift(this byte bytes, int size)
var left = new byte[size];
var right = new byte[bytes.Length - size];
Array.Copy(bytes, 0, left, 0, left.Length);
Array.Copy(bytes, left.Length, right, 0, right.Length);
return (left, right);
c# array security
3
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such asRNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspx
â Nikita B
Jun 8 at 6:50
1
Rfc2898DeriveBytes
is anIDisposable
-implementing class, so you should wrap its lifetime in ausing
statement as you have the others.
â Jesse C. Slicer
Jun 8 at 14:37
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
This code is a Frankenstein. I found ten examples done in ten different ways and my requirements were slightly different so even if they were reliable they weren't a copy and paste solution.
Encrypt takes in a byte
and password and returns the byte
encrypted with the password. It has to tack on the length of the original byte
and the initialization vector used by the encryption algorithm.
Decrypt knows how to read the encrypted byte
and will return the original message.
Note: One thing about naming conventions - Since a lot of this is copy and paste from different sources I tended to keep the original authors' conventions so that the code would match up. That's why some variables start with caps and some don't. Not looking to have this post turn into a tangent about that low hanging fruit though. But since it's obvious I thought I should point it out.
Encrypt
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/eab7d698-2340-4ba0-a91c-da6fae06963c/aes-encryption-encrypting-byte-array?forum=csharpgeneral
// https://crypto.stackexchange.com/questions/2280/why-is-the-iv-passed-in-the-clear-when-it-can-be-easily-encrypted
public static byte Encrypt(byte bytesToEncrypt, string password)
byte ivSeed = Guid.NewGuid().ToByteArray();
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte encrypted;
using (MemoryStream mstream = new MemoryStream())
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
using (CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
cryptoStream.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
encrypted = mstream.ToArray();
var messageLengthAs32Bits = Convert.ToInt32(bytesToEncrypt.Length);
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
encrypted = encrypted.Prepend(ivSeed);
encrypted = encrypted.Prepend(messageLength);
return encrypted;
Decrypt
public static byte Decrypt(byte bytesToDecrypt, string password)
(byte messageLengthAs32Bits, byte bytesWithIv) = bytesToDecrypt.Shift(4); // get the message length
(byte ivSeed, byte encrypted) = bytesWithIv.Shift(16); // get the initialization vector
var length = BitConverter.ToInt32(messageLengthAs32Bits, 0);
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte decrypted;
using (MemoryStream mStream = new MemoryStream(encrypted))
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
aesProvider.Padding = PaddingMode.None;
using (CryptoStream cryptoStream = new CryptoStream(mStream,aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
cryptoStream.Read(encrypted, 0, length);
decrypted = mStream.ToArray().Take(length).ToArray();
return decrypted;
Relevant Extension Methods (i'm more worried about security than these)
public static byte Prepend(this byte bytes, byte bytesToPrepend)
var tmp = new byte[bytes.Length + bytesToPrepend.Length];
bytesToPrepend.CopyTo(tmp, 0);
bytes.CopyTo(tmp, bytesToPrepend.Length);
return tmp;
public static (byte left, byte right) Shift(this byte bytes, int size)
var left = new byte[size];
var right = new byte[bytes.Length - size];
Array.Copy(bytes, 0, left, 0, left.Length);
Array.Copy(bytes, left.Length, right, 0, right.Length);
return (left, right);
c# array security
This code is a Frankenstein. I found ten examples done in ten different ways and my requirements were slightly different so even if they were reliable they weren't a copy and paste solution.
Encrypt takes in a byte
and password and returns the byte
encrypted with the password. It has to tack on the length of the original byte
and the initialization vector used by the encryption algorithm.
Decrypt knows how to read the encrypted byte
and will return the original message.
Note: One thing about naming conventions - Since a lot of this is copy and paste from different sources I tended to keep the original authors' conventions so that the code would match up. That's why some variables start with caps and some don't. Not looking to have this post turn into a tangent about that low hanging fruit though. But since it's obvious I thought I should point it out.
Encrypt
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/eab7d698-2340-4ba0-a91c-da6fae06963c/aes-encryption-encrypting-byte-array?forum=csharpgeneral
// https://crypto.stackexchange.com/questions/2280/why-is-the-iv-passed-in-the-clear-when-it-can-be-easily-encrypted
public static byte Encrypt(byte bytesToEncrypt, string password)
byte ivSeed = Guid.NewGuid().ToByteArray();
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte encrypted;
using (MemoryStream mstream = new MemoryStream())
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
using (CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
cryptoStream.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
encrypted = mstream.ToArray();
var messageLengthAs32Bits = Convert.ToInt32(bytesToEncrypt.Length);
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
encrypted = encrypted.Prepend(ivSeed);
encrypted = encrypted.Prepend(messageLength);
return encrypted;
Decrypt
public static byte Decrypt(byte bytesToDecrypt, string password)
(byte messageLengthAs32Bits, byte bytesWithIv) = bytesToDecrypt.Shift(4); // get the message length
(byte ivSeed, byte encrypted) = bytesWithIv.Shift(16); // get the initialization vector
var length = BitConverter.ToInt32(messageLengthAs32Bits, 0);
var rfc = new Rfc2898DeriveBytes(password, ivSeed);
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
byte decrypted;
using (MemoryStream mStream = new MemoryStream(encrypted))
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
aesProvider.Padding = PaddingMode.None;
using (CryptoStream cryptoStream = new CryptoStream(mStream,aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
cryptoStream.Read(encrypted, 0, length);
decrypted = mStream.ToArray().Take(length).ToArray();
return decrypted;
Relevant Extension Methods (i'm more worried about security than these)
public static byte Prepend(this byte bytes, byte bytesToPrepend)
var tmp = new byte[bytes.Length + bytesToPrepend.Length];
bytesToPrepend.CopyTo(tmp, 0);
bytes.CopyTo(tmp, bytesToPrepend.Length);
return tmp;
public static (byte left, byte right) Shift(this byte bytes, int size)
var left = new byte[size];
var right = new byte[bytes.Length - size];
Array.Copy(bytes, 0, left, 0, left.Length);
Array.Copy(bytes, left.Length, right, 0, right.Length);
return (left, right);
c# array security
edited Jun 9 at 6:54
t3chb0t
31.9k54195
31.9k54195
asked Jun 8 at 4:52
user875234
1779
1779
3
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such asRNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspx
â Nikita B
Jun 8 at 6:50
1
Rfc2898DeriveBytes
is anIDisposable
-implementing class, so you should wrap its lifetime in ausing
statement as you have the others.
â Jesse C. Slicer
Jun 8 at 14:37
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55
add a comment |Â
3
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such asRNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspx
â Nikita B
Jun 8 at 6:50
1
Rfc2898DeriveBytes
is anIDisposable
-implementing class, so you should wrap its lifetime in ausing
statement as you have the others.
â Jesse C. Slicer
Jun 8 at 14:37
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55
3
3
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such as
RNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspxâ Nikita B
Jun 8 at 6:50
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such as
RNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspxâ Nikita B
Jun 8 at 6:50
1
1
Rfc2898DeriveBytes
is an IDisposable
-implementing class, so you should wrap its lifetime in a using
statement as you have the others.â Jesse C. Slicer
Jun 8 at 14:37
Rfc2898DeriveBytes
is an IDisposable
-implementing class, so you should wrap its lifetime in a using
statement as you have the others.â Jesse C. Slicer
Jun 8 at 14:37
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
5
down vote
Standard disclaimer: in a production setting it is overwhelmingly better to use somebody else's crypto.
I don't have the expertise to certify "Yes, this is secure" (and as I'm some randomer online, you should assume that even if I was actually a world expert!) There are, however, a few things that strike me as red flags.
byte ivSeed = Guid.NewGuid().ToByteArray();
In crypto, if you need a random number, you basically always need a cryptographically secure random number. NewGuid()
is not cryptographically secure.
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
Block ciphers like AES do not claim to obscure the approximate message length, so this is not strictly a vulnerability. Nevertheless if you are vulnerable to any attacks based on the length, then passing the precise length in plaintext makes those attacks a whole bunch quicker and easier to execute.
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
The derivation of your key should not be tied to the derivation of your IV.
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
Standard disclaimer: in a production setting it is overwhelmingly better to use somebody else's crypto.
I don't have the expertise to certify "Yes, this is secure" (and as I'm some randomer online, you should assume that even if I was actually a world expert!) There are, however, a few things that strike me as red flags.
byte ivSeed = Guid.NewGuid().ToByteArray();
In crypto, if you need a random number, you basically always need a cryptographically secure random number. NewGuid()
is not cryptographically secure.
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
Block ciphers like AES do not claim to obscure the approximate message length, so this is not strictly a vulnerability. Nevertheless if you are vulnerable to any attacks based on the length, then passing the precise length in plaintext makes those attacks a whole bunch quicker and easier to execute.
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
The derivation of your key should not be tied to the derivation of your IV.
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
add a comment |Â
up vote
5
down vote
Standard disclaimer: in a production setting it is overwhelmingly better to use somebody else's crypto.
I don't have the expertise to certify "Yes, this is secure" (and as I'm some randomer online, you should assume that even if I was actually a world expert!) There are, however, a few things that strike me as red flags.
byte ivSeed = Guid.NewGuid().ToByteArray();
In crypto, if you need a random number, you basically always need a cryptographically secure random number. NewGuid()
is not cryptographically secure.
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
Block ciphers like AES do not claim to obscure the approximate message length, so this is not strictly a vulnerability. Nevertheless if you are vulnerable to any attacks based on the length, then passing the precise length in plaintext makes those attacks a whole bunch quicker and easier to execute.
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
The derivation of your key should not be tied to the derivation of your IV.
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
add a comment |Â
up vote
5
down vote
up vote
5
down vote
Standard disclaimer: in a production setting it is overwhelmingly better to use somebody else's crypto.
I don't have the expertise to certify "Yes, this is secure" (and as I'm some randomer online, you should assume that even if I was actually a world expert!) There are, however, a few things that strike me as red flags.
byte ivSeed = Guid.NewGuid().ToByteArray();
In crypto, if you need a random number, you basically always need a cryptographically secure random number. NewGuid()
is not cryptographically secure.
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
Block ciphers like AES do not claim to obscure the approximate message length, so this is not strictly a vulnerability. Nevertheless if you are vulnerable to any attacks based on the length, then passing the precise length in plaintext makes those attacks a whole bunch quicker and easier to execute.
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
The derivation of your key should not be tied to the derivation of your IV.
Standard disclaimer: in a production setting it is overwhelmingly better to use somebody else's crypto.
I don't have the expertise to certify "Yes, this is secure" (and as I'm some randomer online, you should assume that even if I was actually a world expert!) There are, however, a few things that strike me as red flags.
byte ivSeed = Guid.NewGuid().ToByteArray();
In crypto, if you need a random number, you basically always need a cryptographically secure random number. NewGuid()
is not cryptographically secure.
var messageLength = BitConverter.GetBytes(messageLengthAs32Bits);
Block ciphers like AES do not claim to obscure the approximate message length, so this is not strictly a vulnerability. Nevertheless if you are vulnerable to any attacks based on the length, then passing the precise length in plaintext makes those attacks a whole bunch quicker and easier to execute.
byte Key = rfc.GetBytes(16);
byte IV = rfc.GetBytes(16);
The derivation of your key should not be tied to the derivation of your IV.
answered Jun 8 at 7:02
Josiah
3,172326
3,172326
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
add a comment |Â
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
Be careful with your statements about cryptographic randomness. For initialisation vectors and salts, uniqueness is usually sufficient and monotonically increasing counters are often better than pseudorandom generators, especially when little to no entropy is available.
â Rainer P.
Jun 8 at 16:56
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I would stand by my claim as written. If you need a random number, it should be from a cryptographically secure source. Salts I agree can be deterministic. IVs depend on the protocol, e.g. I recall the beast attack on TLS exploited a predictabe (even though unique) IV.
â Josiah
Jun 8 at 17:52
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
I think in a well-designed cryptosystem, the IV's only purpose is to produce distinct cyphertexts even when multiple messages have the same payload. Though I agree that a good random IV can sometimes save the day in a not-so-well-designed cryptosystem, a bad RNG (like the debian bug some years ago) can certainly make it worse compared to a deterministc counter.
â Rainer P.
Jun 8 at 21:17
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
Thanks :) Get random number â Don't include message length (figure it out programatically) â The key and iv one I updated based on @Nikita B's comment.
â user875234
Jun 9 at 0:53
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196088%2fencrypt-a-byte-array%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
3
Guids are designed to be unique, but not necessary random. If you need a random salt, you should use random number generators the were designed for cryptography (such as
RNGCryptoServiceProvider
). Take a look at example on msdn: msdn.microsoft.com/en-us/library/zhe81fz4(v=vs.110).aspxâ Nikita B
Jun 8 at 6:50
1
Rfc2898DeriveBytes
is anIDisposable
-implementing class, so you should wrap its lifetime in ausing
statement as you have the others.â Jesse C. Slicer
Jun 8 at 14:37
Did both. Thanks guys.
â user875234
Jun 9 at 0:54
I have rolled back your last couple of edits. Please see What should I do when someone answers my question?: Do not add an improved version of the code after receiving an answer. Including revised versions of the code makes the question confusing, especially if someone later reviews the newer code.
â t3chb0t
Jun 9 at 6:55