diff --git a/.gitignore b/.gitignore
index 87b9870..be25087 100644
--- a/.gitignore
+++ b/.gitignore
@@ -238,3 +238,5 @@ _Doc/*
/Mac/HMAC2*.cs
/.vs/config/applicationhost.config
/Inferno.1.0.0.nuspec
+/COMMITS.md
+*.snk
diff --git a/Cipher/AesCtrCryptoTransform.cs b/Cipher/AesCtrCryptoTransform.cs
index 52db145..6aacbea 100644
--- a/Cipher/AesCtrCryptoTransform.cs
+++ b/Cipher/AesCtrCryptoTransform.cs
@@ -13,15 +13,16 @@ internal static class AesConstants
public class AesCtrCryptoTransform : ICryptoTransform
{
- byte[] counterBuffer = new byte[AesConstants.AES_BLOCK_SIZE];
+ byte[] counterBuffer_KeyStreamBuffer = new byte[AesConstants.AES_BLOCK_SIZE * 2];
+ int keyStreamBytesRemaining;
Aes aes;
readonly ICryptoTransform cryptoTransform;
public bool CanReuseTransform { get { return false; } }
public bool CanTransformMultipleBlocks { get { return true; } }
- public int InputBlockSize { get { return AesConstants.AES_BLOCK_SIZE; } }
- public int OutputBlockSize { get { return AesConstants.AES_BLOCK_SIZE; } }
+ public int InputBlockSize { get { return 1; } }
+ public int OutputBlockSize { get { return 1; } }
/// ctor
public AesCtrCryptoTransform(byte[] key, ArraySegment counterBufferSegment, Func aesFactory = null)
@@ -33,39 +34,61 @@ public AesCtrCryptoTransform(byte[] key, ArraySegment counterBufferSegment
this.aes.Mode = CipherMode.ECB;
this.aes.Padding = PaddingMode.None;
- Utils.BlockCopy(counterBufferSegment.Array, counterBufferSegment.Offset, counterBuffer, 0, AesConstants.AES_BLOCK_SIZE);
+ Utils.BlockCopy(counterBufferSegment.Array, counterBufferSegment.Offset, counterBuffer_KeyStreamBuffer, 0, AesConstants.AES_BLOCK_SIZE);
this.cryptoTransform = aes.CreateEncryptor(rgbKey: key, rgbIV: null);
}// ctor
#region public
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
- int partialBlockSize = inputCount % AesConstants.AES_BLOCK_SIZE;
- int fullBlockSize = inputCount & (-AesConstants.AES_BLOCK_SIZE);//inputCount - partialBlockSize;
- int i, j;
- byte[] counterBuffer = this.counterBuffer; // looks dumb, but local-access is faster than field-access
+ if (inputCount == 0) return 0;
- for (i = outputOffset, /* reusing inputCount as iMax */ inputCount = outputOffset + fullBlockSize; i < inputCount; i += AesConstants.AES_BLOCK_SIZE)
+ int i, j, k, remainingInputCount = inputCount;
+ byte[] counterBuffer_KeyStreamBuffer = this.counterBuffer_KeyStreamBuffer; // looks dumb, but local-access is faster than field-access
+
+ // process any available key stream first
+ if (this.keyStreamBytesRemaining > 0)
{
- Utils.BlockCopy(counterBuffer, 0, outputBuffer, i, AesConstants.AES_BLOCK_SIZE);
- for (j = AesConstants.AES_BLOCK_SIZE - 1; j >= AesConstants.AES_BLOCK_SIZE - AesConstants.COUNTER_SIZE; --j)
- if (++counterBuffer[j] != 0) break;
+ j = inputCount > this.keyStreamBytesRemaining ? this.keyStreamBytesRemaining : inputCount;
+ for (i = 0; i < j; ++i)
+ outputBuffer[outputOffset + i] = (byte)(counterBuffer_KeyStreamBuffer[AesConstants.AES_BLOCK_SIZE * 2 - this.keyStreamBytesRemaining + i] ^ inputBuffer[inputOffset + i]);
+
+ inputOffset += j;
+ outputOffset += j;
+ this.keyStreamBytesRemaining -= j;
+ remainingInputCount -= j;
+
+ if (remainingInputCount == 0) return inputCount;
}
+ int partialBlockSize = remainingInputCount % AesConstants.AES_BLOCK_SIZE;
+ int fullBlockSize = remainingInputCount & (-AesConstants.AES_BLOCK_SIZE); // remainingInputCount - partialBlockSize;
+
+ // process full blocks, if any
if (fullBlockSize > 0)
{
+ for (i = outputOffset, /* reusing k as iMax */ k = outputOffset + fullBlockSize; i < k; i += AesConstants.AES_BLOCK_SIZE)
+ {
+ Utils.BlockCopy(counterBuffer_KeyStreamBuffer, 0, outputBuffer, i, AesConstants.AES_BLOCK_SIZE);
+ for (j = AesConstants.AES_BLOCK_SIZE - 1; j >= AesConstants.AES_BLOCK_SIZE - AesConstants.COUNTER_SIZE; --j) if (++counterBuffer_KeyStreamBuffer[j] != 0) break;
+ }
+
fullBlockSize = this.cryptoTransform.TransformBlock(outputBuffer, outputOffset, fullBlockSize, outputBuffer, outputOffset);
- //for (i = 0; i < fullBlockSize; ++i) outputBuffer[outputOffset + i] ^= inputBuffer[inputOffset + i];
Utils.Xor(outputBuffer, outputOffset, inputBuffer, inputOffset, fullBlockSize);
}
+ // process the remaining partial block, if any
if (partialBlockSize > 0)
{
- outputOffset += fullBlockSize;
inputOffset += fullBlockSize;
- this.cryptoTransform.TransformBlock(counterBuffer, 0, AesConstants.AES_BLOCK_SIZE, counterBuffer, 0);
- for (i = 0; i < partialBlockSize; ++i) outputBuffer[outputOffset + i] = (byte)(counterBuffer[i] ^ inputBuffer[inputOffset + i]);
+ outputOffset += fullBlockSize;
+
+ this.cryptoTransform.TransformBlock(counterBuffer_KeyStreamBuffer, 0, AesConstants.AES_BLOCK_SIZE, counterBuffer_KeyStreamBuffer, AesConstants.AES_BLOCK_SIZE);
+ for (j = AesConstants.AES_BLOCK_SIZE - 1; j >= AesConstants.AES_BLOCK_SIZE - AesConstants.COUNTER_SIZE; --j) if (++counterBuffer_KeyStreamBuffer[j] != 0) break;
+ for (i = 0; i < partialBlockSize; ++i) outputBuffer[outputOffset + i] = (byte)(counterBuffer_KeyStreamBuffer[AesConstants.AES_BLOCK_SIZE + i] ^ inputBuffer[inputOffset + i]);
+ this.keyStreamBytesRemaining = AesConstants.AES_BLOCK_SIZE - partialBlockSize;
}
+
return inputCount;
}// TransformBlock()
@@ -88,7 +111,7 @@ public void Dispose()
}
finally
{
- Array.Clear(counterBuffer, 0, AesConstants.AES_BLOCK_SIZE);
+ Array.Clear(this.counterBuffer_KeyStreamBuffer, 0, AesConstants.AES_BLOCK_SIZE * 2);
this.aes = null;
}
}
diff --git a/CryptoRandom.cs b/CryptoRandom.cs
index 92ed93d..9a0b037 100644
--- a/CryptoRandom.cs
+++ b/CryptoRandom.cs
@@ -74,7 +74,7 @@ public long NextLong()
public long NextLong(long maxValue)
{
if (maxValue < 0)
- throw new ArgumentOutOfRangeException("maxValue");
+ throw new ArgumentOutOfRangeException(nameof(maxValue));
return NextLong(0, maxValue);
}//NextLong()
@@ -96,7 +96,7 @@ public long NextLong(long minValue, long maxValue)
return minValue;
if (minValue > maxValue)
- throw new ArgumentOutOfRangeException("minValue");
+ throw new ArgumentOutOfRangeException(nameof(minValue));
ulong diff = decimal.ToUInt64((decimal)maxValue - minValue);
ulong upperBound = ulong.MaxValue / diff * diff;
@@ -136,7 +136,7 @@ public override int Next()
public override int Next(int maxValue)
{
if (maxValue < 0)
- throw new ArgumentOutOfRangeException("maxValue");
+ throw new ArgumentOutOfRangeException(nameof(maxValue));
return Next(0, maxValue);
}//Next()
@@ -158,7 +158,7 @@ public override int Next(int minValue, int maxValue)
return minValue;
if (minValue > maxValue)
- throw new ArgumentOutOfRangeException("minValue");
+ throw new ArgumentOutOfRangeException(nameof(minValue));
long diff = (long)maxValue - minValue;
long upperBound = uint.MaxValue / diff * diff;
@@ -180,8 +180,8 @@ public override int Next(int minValue, int maxValue)
///
public override double NextDouble()
{
- const double max = 1.0 + uint.MaxValue;
- return GetRandomUInt() / max;
+ const double max = 1L << 53; // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+ return (GetRandomULong() >> 11) / max;
}//NextDouble()
///
@@ -220,7 +220,7 @@ public void NextBytes(byte[] buffer, int offset, int count)
var checkedBufferSegment = new ArraySegment(buffer, offset, count); // bounds-validation happens here
if (count == 0) return;
NextBytesInternal(checkedBufferSegment);
- }
+ }//NextBytes()
void NextBytesInternal(ArraySegment bufferSegment)
{
@@ -236,36 +236,25 @@ void NextBytesInternal(ArraySegment bufferSegment)
throw new CryptographicException((int)status);
}
- while (true)
+ lock (_byteCache)
{
- int currentByteCachePosition = Interlocked.Add(ref _byteCachePosition, count);
- if (currentByteCachePosition <= BYTE_CACHE_SIZE && currentByteCachePosition > 0)
+ if (_byteCachePosition + count <= BYTE_CACHE_SIZE)
{
- Utils.BlockCopy(_byteCache, currentByteCachePosition - count, buffer, 0, count);
+ Utils.BlockCopy(_byteCache, _byteCachePosition, buffer, offset, count);
+ _byteCachePosition += count;
return;
}
- lock (_byteCache)
+ status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
+ if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
{
- currentByteCachePosition = _byteCachePosition; // atomic read
- if (currentByteCachePosition > (BYTE_CACHE_SIZE - count) || currentByteCachePosition <= 0)
- {
- status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
- if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
- {
- _byteCachePosition = count; // atomic write
- Utils.BlockCopy(_byteCache, 0, buffer, 0, count);
- return;
- }
-
- // defensive logic to prevent _byteCachePosition from wrapping into valid range due to BCryptGenRandom failures
- if (currentByteCachePosition > BYTE_CACHE_SIZE || currentByteCachePosition < 0) _byteCachePosition = BYTE_CACHE_SIZE;
-
- throw new CryptographicException((int)status);
- }// if outside the valid range
- }// lock
- }// while(true)
- }//NextBytes()
+ _byteCachePosition = count;
+ Utils.BlockCopy(_byteCache, 0, buffer, offset, count);
+ return;
+ }
+ throw new CryptographicException((int)status);
+ }// lock
+ }//NextBytesInternal()
///
/// Gets one random unsigned 32bit integer in a thread safe manner.
@@ -273,31 +262,24 @@ void NextBytesInternal(ArraySegment bufferSegment)
uint GetRandomUInt()
{
BCrypt.NTSTATUS status;
- while (true)
+
+ lock (_byteCache)
{
- int currentByteCachePosition = Interlocked.Add(ref _byteCachePosition, sizeof(uint));
- if (currentByteCachePosition <= BYTE_CACHE_SIZE && currentByteCachePosition > 0)
- return BitConverter.ToUInt32(_byteCache, currentByteCachePosition - sizeof(uint));
+ if (_byteCachePosition + sizeof(uint) <= BYTE_CACHE_SIZE)
+ {
+ var result = BitConverter.ToUInt32(_byteCache, _byteCachePosition);
+ _byteCachePosition += sizeof(uint);
+ return result;
+ }
- lock (_byteCache)
+ status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
+ if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
{
- currentByteCachePosition = _byteCachePosition; // atomic read
- if (currentByteCachePosition > (BYTE_CACHE_SIZE - sizeof(uint)) || currentByteCachePosition <= 0)
- {
- status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
- if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
- {
- _byteCachePosition = sizeof(uint); // atomic write
- return BitConverter.ToUInt32(_byteCache, 0);
- }
-
- // defensive logic to prevent _byteCachePosition from wrapping into valid range due to BCryptGenRandom failures
- if (currentByteCachePosition > BYTE_CACHE_SIZE || currentByteCachePosition < 0) _byteCachePosition = BYTE_CACHE_SIZE;
-
- throw new CryptographicException((int)status);
- }// if outside the valid range
- }// lock
- }// while(true)
+ _byteCachePosition = sizeof(uint);
+ return BitConverter.ToUInt32(_byteCache, 0);
+ }
+ throw new CryptographicException((int)status);
+ }// lock
}//GetRandomUInt()
///
@@ -306,31 +288,24 @@ uint GetRandomUInt()
ulong GetRandomULong()
{
BCrypt.NTSTATUS status;
- while (true)
+
+ lock (_byteCache)
{
- int currentByteCachePosition = Interlocked.Add(ref _byteCachePosition, sizeof(ulong));
- if (currentByteCachePosition <= BYTE_CACHE_SIZE && currentByteCachePosition > 0)
- return BitConverter.ToUInt64(_byteCache, currentByteCachePosition - sizeof(ulong));
+ if (_byteCachePosition + sizeof(ulong) <= BYTE_CACHE_SIZE)
+ {
+ var result = BitConverter.ToUInt64(_byteCache, _byteCachePosition);
+ _byteCachePosition += sizeof(ulong);
+ return result;
+ }
- lock (_byteCache)
+ status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
+ if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
{
- currentByteCachePosition = _byteCachePosition; // atomic read
- if (currentByteCachePosition > (BYTE_CACHE_SIZE - sizeof(ulong)) || currentByteCachePosition <= 0)
- {
- status = BCrypt.BCryptGenRandom(_byteCache, BYTE_CACHE_SIZE);
- if (status == BCrypt.NTSTATUS.STATUS_SUCCESS)
- {
- _byteCachePosition = sizeof(ulong); // atomic write
- return BitConverter.ToUInt64(_byteCache, 0);
- }
-
- // defensive logic to prevent _byteCachePosition from wrapping into valid range due to BCryptGenRandom failures
- if (currentByteCachePosition > BYTE_CACHE_SIZE || currentByteCachePosition < 0) _byteCachePosition = BYTE_CACHE_SIZE;
-
- throw new CryptographicException((int)status);
- }// if outside the valid range
- }// lock
- }// while(true)
+ _byteCachePosition = sizeof(ulong);
+ return BitConverter.ToUInt64(_byteCache, 0);
+ }
+ throw new CryptographicException((int)status);
+ }// lock
}//GetRandomULong()
}//class CryptoRandom
diff --git a/EtM_CBC.cs b/EtM_CBC.cs
index 3f99b98..c53cbe6 100644
--- a/EtM_CBC.cs
+++ b/EtM_CBC.cs
@@ -52,7 +52,7 @@ public static void Encrypt(byte[] masterKey, ArraySegment plaintext, byte[
int finalBlockLength = plaintext.Count % Cipher.AesConstants.AES_BLOCK_SIZE;
int paddingLength = Cipher.AesConstants.AES_BLOCK_SIZE - finalBlockLength;
int ciphertextLength = CONTEXT_BUFFER_LENGTH + plaintext.Count + paddingLength + MAC_LENGTH;
- if (output.Length - outputOffset < ciphertextLength) throw new ArgumentOutOfRangeException("output", "'output' array segment is not big enough for the ciphertext");
+ if (output.Length - outputOffset < ciphertextLength) throw new ArgumentOutOfRangeException(nameof(output), $"'{nameof(output)}' array segment is not big enough for the ciphertext");
try
{
diff --git a/EtM_CTR.cs b/EtM_CTR.cs
index f7a4335..1b53681 100644
--- a/EtM_CTR.cs
+++ b/EtM_CTR.cs
@@ -35,7 +35,7 @@ static void ClearKeyMaterial()
public static void Encrypt(byte[] masterKey, ArraySegment plaintext, byte[] output, int outputOffset, ArraySegment? salt = null, uint counter = 1)
{
int ciphertextLength = CONTEXT_BUFFER_LENGTH + plaintext.Count + MAC_LENGTH;
- if (output.Length - outputOffset < ciphertextLength) throw new ArgumentOutOfRangeException("output", "'output' array segment is not big enough for the ciphertext");
+ if (output.Length - outputOffset < ciphertextLength) throw new ArgumentOutOfRangeException(nameof(output), $"'{nameof(output)}' array segment is not big enough for the ciphertext");
try
{
_cryptoRandom.NextBytes(_contextBuffer.Value);
diff --git a/EtM_Transforms.cs b/EtM_Transforms.cs
index 575295b..f59fa57 100644
--- a/EtM_Transforms.cs
+++ b/EtM_Transforms.cs
@@ -28,7 +28,7 @@ public class EtM_EncryptTransform : ICryptoTransform
/// ctor
public EtM_EncryptTransform(byte[] key, ArraySegment? salt = null, uint chunkNumber = 1)
{
- if (key == null) throw new ArgumentNullException("key", "key cannot be null.");
+ if (key == null) throw new ArgumentNullException(nameof(key), nameof(key) + " cannot be null.");
this.key = key;
this.salt = salt;
this.currentChunkNumber = chunkNumber;
@@ -53,7 +53,7 @@ public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, b
output: outputBuffer,
outputOffset: outputOffset + j,
salt: this.salt,
- counter: this.currentChunkNumber++);
+ counter: checked(this.currentChunkNumber++));
}
}
return j;
@@ -104,7 +104,7 @@ public class EtM_DecryptTransform : ICryptoTransform
/// ctor
public EtM_DecryptTransform(byte[] key, ArraySegment? salt = null, uint chunkNumber = 1, bool authenticateOnly = false)
{
- if (key == null) throw new ArgumentNullException("key", "key cannot be null.");
+ if (key == null) throw new ArgumentNullException(nameof(key), nameof(key) + " cannot be null.");
this.key = key;
this.salt = salt;
this.currentChunkNumber = chunkNumber;
@@ -152,7 +152,7 @@ public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, b
this.key = null;
throw new CryptographicException("Decryption failed for block " + this.currentChunkNumber.ToString() + ".");
}
- ++this.currentChunkNumber;
+ this.currentChunkNumber = checked(this.currentChunkNumber + 1);
}
}
return j;
diff --git a/Extensions/B64Extensions.cs b/Extensions/B64Extensions.cs
index 3b90fb5..22ca7bd 100644
--- a/Extensions/B64Extensions.cs
+++ b/Extensions/B64Extensions.cs
@@ -84,7 +84,7 @@ public static string ToB64(this ArraySegment inputSegment)
public static byte[] FromB64(this string input)
{
if (input == null)
- throw new ArgumentNullException("input");
+ throw new ArgumentNullException(nameof(input));
int len = input.Length;
if (len < 1)
diff --git a/Extensions/Base16Config.cs b/Extensions/Base16Config.cs
index 810b57b..a86866e 100644
--- a/Extensions/Base16Config.cs
+++ b/Extensions/Base16Config.cs
@@ -21,7 +21,7 @@ public Base16Config(char[] alphabet = null)
}
if (alphabet.Length != BASE)
- throw new ArgumentOutOfRangeException("alphabet", "'alphabet' array must have exactly " + BASE + " characters.");
+ throw new ArgumentOutOfRangeException(nameof(alphabet), $"'{nameof(alphabet)}' array must have exactly {BASE.ToString()} characters.");
this.Base16table = alphabet;
diff --git a/Extensions/Base16Extensions.cs b/Extensions/Base16Extensions.cs
index a3ff765..e377e1a 100644
--- a/Extensions/Base16Extensions.cs
+++ b/Extensions/Base16Extensions.cs
@@ -4,6 +4,9 @@ namespace SecurityDriven.Inferno.Extensions
{
public static class Base16Extensions
{
+ ///
+ /// Converts a byte array into equivalent Base16-encoded string.
+ ///
public static string ToBase16(this byte[] binary, Base16Config config = null)
{
if (config == null)
@@ -20,6 +23,9 @@ public static string ToBase16(this byte[] binary, Base16Config config = null)
return new string(chars);
}//ToBase16()
+ ///
+ /// Converts a byte array into equivalent Base16-encoded string.
+ ///
public static string ToBase16(this ArraySegment binarySegment, Base16Config config = null)
{
if (config == null)
@@ -40,6 +46,9 @@ public static string ToBase16(this ArraySegment binarySegment, Base16Confi
return new string(chars);
}//ToBase16()
+ ///
+ /// Converts a Base16-encoded string into equivalent byte array. Does not validate Base16 encoding correctness.
+ ///
public static byte[] FromBase16(this string str16, Base16Config config = null)
{
if (config == null)
diff --git a/Extensions/Base32Config.cs b/Extensions/Base32Config.cs
index c63aeed..49dd488 100644
--- a/Extensions/Base32Config.cs
+++ b/Extensions/Base32Config.cs
@@ -21,7 +21,7 @@ public Base32Config(char[] alphabet = null)
}
if (alphabet.Length != BASE)
- throw new ArgumentOutOfRangeException("alphabet", "'alphabet' array must have exactly " + BASE + " characters.");
+ throw new ArgumentOutOfRangeException(nameof(alphabet), $"'{nameof(alphabet)}' array must have exactly {BASE.ToString()} characters.");
this.Base32table = alphabet;
diff --git a/Extensions/Base32Extensions.cs b/Extensions/Base32Extensions.cs
index 43ce823..6d5f2c5 100644
--- a/Extensions/Base32Extensions.cs
+++ b/Extensions/Base32Extensions.cs
@@ -4,13 +4,17 @@ namespace SecurityDriven.Inferno.Extensions
{
public static class Base32Extensions
{
+ ///
+ /// Converts a byte array into equivalent Base32-encoded string.
+ ///
+ /// Binary array length must be a multiple of 5.
public static string ToBase32(this byte[] binary, Base32Config config = null)
{
int length = binary.Length;
- int bitLength = length * 8;
+ int bitLength = checked(length * 8);
int base32Length = bitLength / 5;
if (base32Length * 5 != bitLength)
- throw new ArgumentOutOfRangeException("binary", "'binary' array length must be a multiple of 5.");
+ throw new ArgumentOutOfRangeException(nameof(binary), $"'{nameof(binary)}' array length must be a multiple of 5.");
if (config == null)
config = Base32Config.Default;
@@ -49,16 +53,20 @@ public static string ToBase32(this byte[] binary, Base32Config config = null)
return new string(chArray);
}//ToBase32()
+ ///
+ /// Converts a byte array segment into equivalent Base32-encoded string.
+ ///
+ /// Binary segment length must be a multiple of 5.
public static string ToBase32(this ArraySegment binarySegment, Base32Config config = null)
{
byte[] binaryArray = binarySegment.Array;
int binaryLength = binarySegment.Count;
int binaryOffset = binarySegment.Offset;
- int bitLength = binaryLength * 8;
+ int bitLength = checked(binaryLength * 8);
int base32Length = bitLength / 5;
if (base32Length * 5 != bitLength)
- throw new ArgumentOutOfRangeException("binary", "'binary' array length must be a multiple of 5.");
+ throw new ArgumentOutOfRangeException(nameof(binarySegment), $"'{nameof(binarySegment)}' length must be a multiple of 5.");
if (config == null)
config = Base32Config.Default;
@@ -97,12 +105,15 @@ public static string ToBase32(this ArraySegment binarySegment, Base32Confi
return new string(chArray);
}//ToBase32()
+ ///
+ /// Converts a Base32-encoded string into equivalent byte array. Does not validate Base32 encoding correctness.
+ ///
public static byte[] FromBase32(this string str32, Base32Config config = null)
{
int length = str32.Length;
int bit5length = length / 8;
if (bit5length * 8 != length)
- throw new ArgumentOutOfRangeException("str32", "'str32' string length must be a multiple of 8.");
+ throw new ArgumentOutOfRangeException(nameof(str32), $"'{nameof(str32)}' string length must be a multiple of 8.");
if (config == null)
config = Base32Config.Default;
diff --git a/Extensions/SerializationExtensions.cs b/Extensions/SerializationExtensions.cs
index 4f0e36b..ac5b913 100644
--- a/Extensions/SerializationExtensions.cs
+++ b/Extensions/SerializationExtensions.cs
@@ -22,7 +22,7 @@ public static string FromBytes(this byte[] bytes)
{
int byteCount = bytes.Length;
if (byteCount % 2 != 0)
- throw new ArgumentException("bytes", "'bytes' array must have even number of bytes");
+ throw new ArgumentException($"'{nameof(bytes)}' array must have even number of bytes", nameof(bytes));
char[] chars = new char[byteCount / 2];
for (int i = 0; i < chars.Length; ++i)
@@ -39,7 +39,7 @@ public static string FromBytes(this ArraySegment bytesSegment)
int bytesOffset = bytesSegment.Offset;
if (bytesLength % 2 != 0)
- throw new ArgumentException("bytesSegment", "'bytesSegment' must have even number of bytes");
+ throw new ArgumentException($"'{nameof(bytesSegment)}' must have even number of bytes", nameof(bytesSegment));
char[] chars = new char[bytesLength / 2];
for (int i = 0; i < chars.Length; ++i)
diff --git a/Kdf/PBKDF2.cs b/Kdf/PBKDF2.cs
index 9b4dcab..552ba34 100644
--- a/Kdf/PBKDF2.cs
+++ b/Kdf/PBKDF2.cs
@@ -90,7 +90,7 @@ public PBKDF2(Func hmacFactory, byte[] password, byte[] salt, int iteratio
static byte[] GenerateSalt(int saltSize)
{
if (saltSize < 0)
- throw new ArgumentOutOfRangeException("saltSize");
+ throw new ArgumentOutOfRangeException(nameof(saltSize));
byte[] data = new byte[saltSize];
rng.NextBytes(data);
@@ -160,7 +160,7 @@ public int IterationCount
{
if (value <= 0)
{
- throw new ArgumentOutOfRangeException("value");
+ throw new ArgumentOutOfRangeException(nameof(value));
}
this.iterations = (uint)value;
this.Initialize();
@@ -180,7 +180,7 @@ public byte[] Salt
{
if (value == null)
{
- throw new ArgumentNullException("value");
+ throw new ArgumentNullException(nameof(value));
}
if (value.Length < 8)
{
@@ -201,7 +201,7 @@ public override byte[] GetBytes(int cb)
{
if (cb <= 0)
{
- throw new ArgumentOutOfRangeException("cb", "Positive number required.");
+ throw new ArgumentOutOfRangeException(nameof(cb), "Positive number required.");
}
byte[] dst = new byte[cb];
int dstOffsetBytes = 0;
diff --git a/Kdf/SP800_108_Ctr.cs b/Kdf/SP800_108_Ctr.cs
index be2ecae..f2a0047 100644
--- a/Kdf/SP800_108_Ctr.cs
+++ b/Kdf/SP800_108_Ctr.cs
@@ -7,18 +7,18 @@ namespace SecurityDriven.Inferno.Kdf
///
/// Concepts from:
- /// http://csrc.nist.gov/publications/nistpubs/800-108/sp800-108.pdf
+ /// http://dx.doi.org/10.6028/NIST.SP.800-108
/// http://referencesource.microsoft.com/#System.Web/Security/Cryptography/SP800_108.cs
///
public static class SP800_108_Ctr
{
- const int COUNTER_LENGTH = sizeof(uint), KEY_LENGTH = sizeof(uint);
+ const int COUNTER_LENGTH = sizeof(uint), DERIVED_KEY_LENGTH_LENGTH = sizeof(uint);
internal static byte[] CreateBuffer(ArraySegment? label, ArraySegment? context, uint keyLengthInBits)
{
int labelLength = (label != null) ? label.GetValueOrDefault().Count : 0;
int contextLength = (context != null) ? context.GetValueOrDefault().Count : 0;
- int bufferLength = (COUNTER_LENGTH /* counter */) + (labelLength + 1 /* label + 0x00 */) + (contextLength /* context */) + (KEY_LENGTH /* [L]_2 */);
+ int bufferLength = (COUNTER_LENGTH /* counter */) + (labelLength + 1 /* label + 0x00 */) + (contextLength /* context */) + (DERIVED_KEY_LENGTH_LENGTH /* [L]_2 */);
var buffer = new byte[bufferLength];
// store label, if any
@@ -30,7 +30,7 @@ internal static byte[] CreateBuffer(ArraySegment? label, ArraySegment timeFactory)
{
var time = timeFactory();
- if (time.Kind == DateTimeKind.Local) throw new ArgumentException("DateTime cannot of 'Local' kind.", "timeFactory");
+ if (time.Kind == DateTimeKind.Local) throw new ArgumentException("DateTime cannot of 'Local' kind.", nameof(timeFactory));
var deltaTicks = (time - _unixEpoch).Ticks;
var timeStepNumber = deltaTicks / _timeStepTicks;
//Console.WriteLine(string.Format("Remaining ticks: {0}", TimeSpan.FromTicks(_timeStepTicks - deltaTicks % _timeStepTicks)));
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 1013dd7..a66b68e 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -32,6 +32,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.3.0.0")]
-[assembly: AssemblyFileVersion("1.3.0.0")]
+[assembly: AssemblyVersion("1.4.0.0")]
+[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: InternalsVisibleTo("SecurityDriven.Inferno.Tests")]
\ No newline at end of file
diff --git a/SecurityDriven.Inferno.csproj b/SecurityDriven.Inferno.csproj
index e36ce7a..486eb48 100644
--- a/SecurityDriven.Inferno.csproj
+++ b/SecurityDriven.Inferno.csproj
@@ -39,6 +39,13 @@
false
bin\Release\SecurityDriven.Inferno.XML
+
+ false
+
+
+
+
+
diff --git a/Utils.cs b/Utils.cs
index 20d260f..68a92b7 100644
--- a/Utils.cs
+++ b/Utils.cs
@@ -55,9 +55,9 @@ public static bool ConstantTimeEqual(byte[] x, int xOffset, byte[] y, int yOffse
throw new ArgumentOutOfRangeException("yOffset", "yOffset < 0");
if (length < 0)
throw new ArgumentOutOfRangeException("length", "length < 0");
- if (xOffset + length > x.Length)
+ if (checked(xOffset + length) > x.Length)
throw new ArgumentException("xOffset + length > x.Length");
- if (yOffset + length > y.Length)
+ if (checked(yOffset + length) > y.Length)
throw new ArgumentException("yOffset + length > y.Length");
int differentbits = 0;
@@ -98,9 +98,9 @@ static bool ConstantTimeEqual(string x, int xOffset, string y, int yOffset, int
throw new ArgumentOutOfRangeException("yOffset", "yOffset < 0");
if (length < 0)
throw new ArgumentOutOfRangeException("length", "length < 0");
- if (xOffset + length > x.Length)
+ if (checked(xOffset + length) > x.Length)
throw new ArgumentException("xOffset + length > x.Length");
- if (yOffset + length > y.Length)
+ if (checked(yOffset + length) > y.Length)
throw new ArgumentException("yOffset + length > y.Length");
int differentbits = 0;