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;