Encrypt a byte array

The name of the pictureThe name of the pictureThe name of the pictureClash 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);







share|improve this question

















  • 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 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










  • 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
















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);







share|improve this question

















  • 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 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










  • 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












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);







share|improve this question













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);









share|improve this question












share|improve this question




share|improve this question








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 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 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










  • 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




    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 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










  • 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










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.






share|improve this answer





















  • 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










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















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






























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.






share|improve this answer





















  • 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














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.






share|improve this answer





















  • 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












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.






share|improve this answer













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.







share|improve this answer













share|improve this answer



share|improve this answer











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
















  • 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












 

draft saved


draft discarded


























 


draft saved


draft discarded














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













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation