Beispiel #1
0
        private static void HmacEval(byte[] pbKey, byte[] pbMsg,
                                     byte[] pbExpc, string strID)
        {
            using (HMACSHA256 h = new HMACSHA256(pbKey))
            {
                h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
                h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);

                byte[] pbHash = h.Hash;
                if (!MemUtil.ArraysEqual(pbHash, pbExpc))
                {
                    throw new SecurityException("HMAC-SHA-256-" + strID);
                }

                // Reuse the object
                h.Initialize();
                h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
                h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);

                pbHash = h.Hash;
                if (!MemUtil.ArraysEqual(pbHash, pbExpc))
                {
                    throw new SecurityException("HMAC-SHA-256-" + strID + "-R");
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Compute PBKDF2 using HMAC-SHA256 as the PRF, and write the output to derivedKey.
        /// </summary>
        private static void PBKDF2_SHA256(HMACSHA256 mac, byte[] password, byte[] salt, int saltLength, long iterationCount, byte[] derivedKey, int derivedKeyLength)
        {
            if (derivedKeyLength > (Math.Pow(2, 32) - 1) * 32)
            {
                throw new ArgumentException("Requested key length too long");
            }

            var U          = new byte[32];
            var T          = new byte[32];
            var saltBuffer = new byte[saltLength + 4];

            var blockCount = (int)Math.Ceiling((double)derivedKeyLength / 32);
            var r          = derivedKeyLength - (blockCount - 1) * 32;

            Buffer.BlockCopy(salt, 0, saltBuffer, 0, saltLength);

#if COREFX
            using (var incrementalHasher = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, mac.Key))
            {
#endif
            for (int i = 1; i <= blockCount; i++)
            {
                saltBuffer[saltLength + 0] = (byte)(i >> 24);
                saltBuffer[saltLength + 1] = (byte)(i >> 16);
                saltBuffer[saltLength + 2] = (byte)(i >> 8);
                saltBuffer[saltLength + 3] = (byte)(i);

                mac.Initialize();
#if COREFX
                incrementalHasher.AppendData(saltBuffer, 0, saltBuffer.Length);
                Buffer.BlockCopy(incrementalHasher.GetHashAndReset(), 0, U, 0, U.Length);
#else
                mac.TransformFinalBlock(saltBuffer, 0, saltBuffer.Length);
                Buffer.BlockCopy(mac.Hash, 0, U, 0, U.Length);
#endif
                Buffer.BlockCopy(U, 0, T, 0, 32);

                for (long j = 1; j < iterationCount; j++)
                {
#if COREFX
                    incrementalHasher.AppendData(U, 0, U.Length);
                    Buffer.BlockCopy(incrementalHasher.GetHashAndReset(), 0, U, 0, U.Length);
#else
                    mac.TransformFinalBlock(U, 0, U.Length);
                    Buffer.BlockCopy(mac.Hash, 0, U, 0, U.Length);
#endif
                    for (int k = 0; k < 32; k++)
                    {
                        T[k] ^= U[k];
                    }
                }

                Buffer.BlockCopy(T, 0, derivedKey, (i - 1) * 32, (i == blockCount ? r : 32));
            }
#if COREFX
        }
#endif
        }
Beispiel #3
0
        public static void InitRC4Encryption(byte[] secretKey, byte[] pubKeyIn, byte[] pubKeyOut, RC4_KEY rc4keyIn,
                                             RC4_KEY rc4keyOut)
        {
            var sha256 = new HMACSHA256(secretKey);
            var digest = sha256.TransformFinalBlock(pubKeyIn, 0, pubKeyIn.Length);

            Prepare_key(rc4keyOut, digest, 16);
            digest = sha256.TransformFinalBlock(pubKeyOut, 0, pubKeyOut.Length);
            Prepare_key(rc4keyIn, digest, 16);
        }
Beispiel #4
0
        /// <summary>
        /// Prepares an authentication tag.
        /// Authentication Tag = HMAC_SHA-2-256(mac_key, versionbyte + cell_iv + cell_ciphertext + versionbyte_length)
        /// </summary>
        private byte[] PrepareAuthenticationTag(byte[] iv, byte[] cipherText, int offset, int length)
        {
            Debug.Assert(cipherText != null);

            byte[] computedHash;
            byte[] authenticationTag = new byte[KeySizeInBytes];

            // Raw Tag Length:
            //              1 for the version byte
            //              1 block for IV (16 bytes)
            //              cipherText.Length
            //              1 byte for version byte length
            using (HMACSHA256 hmac = new HMACSHA256(this.dataEncryptionKey.MACKey))
            {
                int retVal = 0;
                retVal = hmac.TransformBlock(version, 0, version.Length, version, 0);
                Debug.Assert(retVal == version.Length);
                retVal = hmac.TransformBlock(iv, 0, iv.Length, iv, 0);
                Debug.Assert(retVal == iv.Length);
                retVal = hmac.TransformBlock(cipherText, offset, length, cipherText, offset);
                Debug.Assert(retVal == length);
                hmac.TransformFinalBlock(versionSize, 0, versionSize.Length);
                computedHash = hmac.Hash;
            }

            Debug.Assert(computedHash.Length >= authenticationTag.Length);
            Buffer.BlockCopy(computedHash, 0, authenticationTag, 0, authenticationTag.Length);
            return(authenticationTag);
        }
Beispiel #5
0
        private async Task <byte[]> ComputeRequestBodySha256HashAsyncNew(
            HttpRequest request,
            byte[] secret,
            byte[] prefix,
            byte[] suffix)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (secret == null)
            {
                throw new ArgumentNullException(nameof(secret));
            }

            if (secret.Length == 0)
            {
                throw new ArgumentException();
            }

            await PrepareRequestBody(request);

            byte[] hash;
            using (var hasher = new HMACSHA256(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length != 0)
                    {
                        hasher.TransformBlock(prefix, 0, prefix.Length, (byte[])null, 0);
                    }
                    var buffer      = new byte[4096];
                    var inputStream = request.Body;
                    while (true)
                    {
                        int bytesRead;
                        if ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                        {
                            hasher.TransformBlock(buffer, 0, bytesRead, (byte[])null, 0);
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (suffix != null && suffix.Length != 0)
                    {
                        hasher.TransformBlock(suffix, 0, suffix.Length, (byte[])null, 0);
                    }
                    hasher.TransformFinalBlock(Array.Empty <byte>(), 0, 0);
                    hash = hasher.Hash;
                }
                finally
                {
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
            return(hash);
        }
        public static async Task <byte[]> ComputeRequestBodySha256HashAsync(
            HttpRequest request,
            string secret)
        {
            await PrepareRequestBody(request);

            var secretBytes = Encoding.UTF8.GetBytes(secret);

            using (HMACSHA256 hasher = new HMACSHA256(secretBytes))
            {
                try
                {
                    Stream inputStream = request.Body;

                    int    bytesRead;
                    byte[] buffer = new byte[4096];

                    while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        hasher.TransformBlock(buffer, inputOffset: 0, inputCount: bytesRead,
                                              outputBuffer: null, outputOffset: 0);
                    }

                    hasher.TransformFinalBlock(Array.Empty <byte>(), inputOffset: 0, inputCount: 0);

                    return(hasher.Hash);
                }
                finally
                {
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Hashes or gets hmac of the given byte array
        /// </summary>
        /// <param name="pbBuf1">first byte array to hash</param>
        /// <param name="pbBuf2">second byte array to hash</param>
        /// <param name="pbBuf3">third byte array to hash</param>
        /// <param name="pbSecret">key for hmac generation, can be null</param>
        /// <returns>hash or hmac in bytes</returns>
        private static byte[] HashData(byte[] pbBuf1, byte[] pbBuf2, byte[] pbBuf3, byte[] pbSecret)
        {
            if (pbSecret == null)
            {
                using (SHA256 sha256 = SHA256.Create())
                {
                    sha256.TransformBlock(pbBuf1, 0, pbBuf1.Length, null, 0);
                    sha256.TransformBlock(pbBuf2, 0, pbBuf2.Length, null, 0);
                    sha256.TransformBlock(pbBuf3, 0, pbBuf3.Length, null, 0);
                    sha256.TransformFinalBlock(new byte[0], 0, 0);

                    return(sha256.Hash);
                }
            }
            else
            {
                using (HMACSHA256 hmac = new HMACSHA256(pbSecret))
                {
                    hmac.TransformBlock(pbBuf1, 0, pbBuf1.Length, null, 0);
                    hmac.TransformBlock(pbBuf2, 0, pbBuf2.Length, null, 0);
                    hmac.TransformBlock(pbBuf3, 0, pbBuf3.Length, null, 0);
                    hmac.TransformFinalBlock(new byte[0], 0, 0);

                    return(hmac.Hash);
                }
            }
        }
Beispiel #8
0
 public void CheckD(string testName, byte[] key, byte[] data, byte[] result)
 {
     algo     = new HMACSHA256();
     algo.Key = key;
     // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
     algo.TransformFinalBlock(data, 0, data.Length);
     Assert.AreEqual(result, algo.Hash, testName + "d");
 }
Beispiel #9
0
        private static void HmacEval(byte[] pbKey, byte[] pbMsg,
                                     byte[] pbExpc)
        {
            using var h = new HMACSHA256(pbKey);
            h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
            h.TransformFinalBlock(new byte[0], 0, 0);

            var pbHash = h.Hash;

            Assert.That(MemUtil.ArraysEqual(pbHash, pbExpc), Is.True);

            // Reuse the object
            h.Initialize();
            h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
            h.TransformFinalBlock(new byte[0], 0, 0);

            pbHash = h.Hash;
            Assert.That(MemUtil.ArraysEqual(pbHash, pbExpc), Is.True);
        }
Beispiel #10
0
        /// <summary>
        /// Compute PBKDF2 using HMAC-SHA256 as the PRF, and write the output to derivedKey.
        /// </summary>
        private static void PBKDF2_SHA256(HMACSHA256 mac, byte[] password, byte[] salt, int saltLength, long iterationCount, byte[] derivedKey, int derivedKeyLength)
        {
            if (derivedKeyLength > (Math.Pow(2, 32) - 1) * 32)
            {
                throw new ArgumentException("Requested key length too long");
            }

            var U          = new byte[32];
            var T          = new byte[32];
            var saltBuffer = new byte[saltLength + 4];

            var blockCount = (int)Math.Ceiling((double)derivedKeyLength / 32);
            var r          = derivedKeyLength - (blockCount - 1) * 32;

            Buffer.BlockCopy(salt, 0, saltBuffer, 0, saltLength);

            for (int i = 1; i <= blockCount; i++)
            {
                saltBuffer[saltLength + 0] = (byte)(i >> 24);
                saltBuffer[saltLength + 1] = (byte)(i >> 16);
                saltBuffer[saltLength + 2] = (byte)(i >> 8);
                saltBuffer[saltLength + 3] = (byte)(i);

                mac.Initialize();
                mac.TransformFinalBlock(saltBuffer, 0, saltBuffer.Length);
                Buffer.BlockCopy(mac.Hash, 0, U, 0, U.Length);
                Buffer.BlockCopy(U, 0, T, 0, 32);

                for (long j = 1; j < iterationCount; j++)
                {
                    mac.TransformFinalBlock(U, 0, U.Length);
                    Buffer.BlockCopy(mac.Hash, 0, U, 0, U.Length);

                    for (int k = 0; k < 32; k++)
                    {
                        T[k] ^= U[k];
                    }
                }

                Buffer.BlockCopy(T, 0, derivedKey, (i - 1) * 32, (i == blockCount ? r : 32));
            }
        }
Beispiel #11
0
 public string sign(List <string> list)
 {
     hmac.Initialize();
     foreach (string item in list)
     {
         byte [] sourcebytes = Encoding.UTF8.GetBytes(item);
         hmac.TransformBlock(sourcebytes, 0, sourcebytes.Length, null, 0);
     }
     hmac.TransformFinalBlock(new byte [0], 0, 0);
     return(BitConverter.ToString(hmac.Hash).Replace("-", "").ToLower());
 }
 /// <summary>
 /// Computes the MAC of ciphertext; used for authentication.
 /// </summary>
 private byte[] SignFile(string path, byte[] key, int beg = 0, int end = 0)
 {
     using (HMACSHA256 hmac = new HMACSHA256(key))
     {
         foreach (Object[] chunk in this.FileChunks(path, beg, end))
         {
             byte[] data = (byte[])chunk[0];
             hmac.TransformBlock(data, 0, data.Length, null, 0);
         }
         hmac.TransformFinalBlock(new byte[0], 0, 0);
         return(hmac.Hash);
     }
 }
Beispiel #13
0
 public void CheckE(string testName, byte[] key, byte[] data, byte[] result)
 {
     algo     = new HMACSHA256();
     algo.Key = key;
     byte[] copy = new byte [data.Length];
     // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
     for (int i = 0; i < data.Length - 1; i++)
     {
         algo.TransformBlock(data, i, 1, copy, i);
     }
     algo.TransformFinalBlock(data, data.Length - 1, 1);
     Assert.AreEqual(result, algo.Hash, testName + "e");
 }
        /// <summary>
        ///     Reads the hmac, and compares with the calculated value.
        /// </summary>
        private void ReadHmac()
        {
            var hmacBytes = new byte[32];

            ReadBytes(hmacBytes, "HMAC");

            _hmac.TransformFinalBlock(new byte[0], 0, 0);
            var actualHmac = _hmac.Hash;

            if (!BufferCompare(actualHmac, hmacBytes))
            {
                //throw new InOut.InvalidDataException("Error in HMAC - possible file corruption");
                // ALPHONS TODO
            }
        }
Beispiel #15
0
        private static (byte, byte[]) EncryptData(Stream inStream, Stream outStream, byte[] internalKey, byte[] iv, int bufferSize)
        {
            var lastDataReadSize = 0; // File size modulo 16 in least significant byte positions

            using (var cipher = CreateAes(internalKey, iv))
                using (var ms = new MemoryStream())
                    using (var cryptoStream = new CryptoStream(ms, cipher.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        int bytesRead;
                        var buffer = new byte[bufferSize];
                        while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            cryptoStream.Write(buffer, 0, bytesRead);
                            if (bytesRead < bufferSize)
                            {
                                lastDataReadSize = bytesRead % AesBlockSize;
                                if (lastDataReadSize != 0)
                                {
                                    var padLen  = 16 - bytesRead % AesBlockSize;
                                    var padding = new byte[padLen];
                                    padding.Fill((byte)padLen);
                                    cryptoStream.Write(padding, 0, padding.Length);
                                }
                            }
                        }

                        cryptoStream.FlushFinalBlock();
                        ms.Position = 0;

                        using (var hmac0 = new HMACSHA256(internalKey))
                        {
                            hmac0.Initialize();

                            while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                outStream.Write(buffer, 0, bytesRead);
                                hmac0.TransformBlock(buffer, 0, bytesRead, null, 0);
                            }

                            hmac0.TransformFinalBlock(Array.Empty <byte>(), 0, 0);

                            return((byte)lastDataReadSize, hmac0.Hash);
                        }
                    }
        }
Beispiel #16
0
        protected void EncodeInternal(byte[] buffer, int offset, ushort count)
        {
            byte[] header  = new byte[PREFIX_SIZE];
            byte[] size    = BitConverter.GetBytes(count);
            byte[] counter = BitConverter.GetBytes(_outCounter++);

            _encryptor.TransformBlock(size, 0, size.Length, header, HMAC_SIZE);
            _encryptor.TransformBlock(buffer, offset, count, buffer, offset);

            _signer.TransformBlock(counter, 0, counter.Length, null, 0);
            _signer.TransformBlock(header, HMAC_SIZE, size.Length, null, 0);
            _signer.TransformFinalBlock(buffer, offset, count);

            Buffer.BlockCopy(_signer.Hash, 0, header, 0, HMAC_SIZE);
            _signer.Initialize();

            OnDataEncoded(buffer, offset, count, header);
        }
Beispiel #17
0
        internal string sign(string[] list)
        {
            if (connectionInformation.key == "")
            {
                return("");
            }
            else
            {
                hmac.Initialize();
                foreach (var s in list)
                {
                    transformPart(s);
                }

                hmac.TransformFinalBlock(new byte[] { }, 0, 0);
                return(BitConverter.ToString(hmac.Hash).Replace("-", "").ToLower());
            }
        }
Beispiel #18
0
        private void OnBufferReady(byte[] buffer)
        {
            if (!_secure)
            {
                ProcessFrame(buffer, _offset, _bytesToBuffer);
                return;
            }

            if (_bytesToBuffer == PREFIX_SIZE)
            {
                byte[] size = new byte[2];

                _decryptor.TransformBlock(_buffer, _offset + HMAC_SIZE, 2, size, 0);
                _bytesToBuffer += BitConverter.ToUInt16(size, 0);
            }
            else
            {
                byte[] counter = BitConverter.GetBytes(_inCounter++);

                _verifier.TransformBlock(counter, 0, counter.Length, null, 0);
                _verifier.TransformFinalBlock(_buffer, _offset + HMAC_SIZE, _bytesToBuffer - HMAC_SIZE);

                if (!CompareBytes(_verifier.Hash, 0, _buffer, _offset, HMAC_SIZE))
                {
                    OnExceptionThrown(new InvalidDataException("Invalid record signature."));
                    return;
                }

                _verifier.Initialize();
                _decryptor.TransformBlock(_buffer, _offset + PREFIX_SIZE, _bytesToBuffer - PREFIX_SIZE, _buffer, _offset + PREFIX_SIZE);

                if (_state == FrameState.Established)
                {
                    OnDataDecoded(buffer, _offset + PREFIX_SIZE, _bytesToBuffer - PREFIX_SIZE);

                    _bufferPosition = 0;
                    _bytesToBuffer  = PREFIX_SIZE;
                }
                else
                {
                    ProcessFrame(buffer, _offset + PREFIX_SIZE, _bytesToBuffer - PREFIX_SIZE);
                }
            }
        }
        private static string CalculateSha256Hash(string key, string msg1, string msg2)
        {
            byte[] encodedKey  = Encoding.UTF8.GetBytes(key);
            byte[] encodedMsg1 = Encoding.UTF8.GetBytes(msg1);
            byte[] encodedMsg2 = Encoding.UTF8.GetBytes(msg2);

            HMACSHA256 hmac = new HMACSHA256(encodedKey);

            hmac.TransformBlock(encodedMsg1, 0, encodedMsg1.Length, null, 0);
            hmac.TransformFinalBlock(encodedMsg2, 0, encodedMsg2.Length);

            StringBuilder sb = new StringBuilder();

            foreach (byte b in hmac.Hash)
            {
                sb.Append(b.ToString("x2"));
            }
            return(sb.ToString());
        }
Beispiel #20
0
        public static byte[] ComputeHMACSHA256HashFromFile(string filePath, byte[] authKey, long startPosition, long endPosition)
        {
            byte[] hash = null;

            using (var fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                fStream.Position = startPosition;
                byte[] buffer = new byte[(1024 * 4)];
                long   amount = (endPosition - startPosition);

                using (var hmacSha256 = new HMACSHA256(authKey))
                {
                    while (amount > 0)
                    {
                        int bytesRead = fStream.Read(buffer, 0, (int)Math.Min(buffer.Length, amount));

                        if (bytesRead > 0)
                        {
                            amount -= bytesRead;

                            if (amount > 0)
                            {
                                hmacSha256.TransformBlock(buffer, 0, bytesRead, buffer, 0);
                            }
                            else
                            {
                                hmacSha256.TransformFinalBlock(buffer, 0, bytesRead);
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                    }

                    hash = hmacSha256.Hash;
                }
            }

            return(hash);
        }
Beispiel #21
0
        private void WriteSafeBlock()
        {
            byte[] pbBlockIndex = MemUtil.UInt64ToBytes(m_uBlockIndex);

            int cbBlockSize = m_iBufferPos;

            byte[] pbBlockSize = MemUtil.Int32ToBytes(cbBlockSize);

            byte[] pbBlockHmac;
            byte[] pbBlockKey = GetHmacKey64(m_pbKey, m_uBlockIndex);
            using (HMACSHA256 h = new HMACSHA256(pbBlockKey))
            {
                h.TransformBlock(pbBlockIndex, 0, pbBlockIndex.Length,
                                 pbBlockIndex, 0);
                h.TransformBlock(pbBlockSize, 0, pbBlockSize.Length,
                                 pbBlockSize, 0);

                if (cbBlockSize != 0)
                {
                    h.TransformBlock(m_pbBuffer, 0, cbBlockSize, m_pbBuffer, 0);
                }

                h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);

                pbBlockHmac = h.Hash;
            }
            MemUtil.ZeroByteArray(pbBlockKey);

            MemUtil.Write(m_sBase, pbBlockHmac);
            // MemUtil.Write(m_sBase, pbBlockIndex); // Implicit
            MemUtil.Write(m_sBase, pbBlockSize);
            if (cbBlockSize != 0)
            {
                m_sBase.Write(m_pbBuffer, 0, cbBlockSize);
            }

            ++m_uBlockIndex;
            m_iBufferPos = 0;
        }
Beispiel #22
0
        private string Sign <T>(string key, Message <T> ioPubMessage, List <string> messages, NetMQSocket iopub)
        {
            var encoder = new UTF8Encoding();
            var hMAC    = new HMACSHA256(encoder.GetBytes(key));

            hMAC.Initialize();

            // https://jupyter-client.readthedocs.io/en/stable/messaging.html#the-wire-protocol

            messages.Add(JsonConvert.SerializeObject(ioPubMessage.Header));
            messages.Add(JsonConvert.SerializeObject(ioPubMessage.ParentHeader));
            messages.Add(JsonConvert.SerializeObject(ioPubMessage.Metadata));
            messages.Add(JsonConvert.SerializeObject(ioPubMessage.Content));

            // signature
            foreach (string item in messages)
            {
                var sourceBytes = encoder.GetBytes(item);
                hMAC.TransformBlock(sourceBytes, 0, sourceBytes.Length, null, 0);
            }

            hMAC.TransformFinalBlock(new byte[0], 0, 0);
            return(BitConverter.ToString(hMAC.Hash).Replace("-", "").ToLower());
        }
Beispiel #23
0
        /// <summary>
        /// Encryption Algorithm
        /// cell_iv = HMAC_SHA-2-256(iv_key, cell_data) truncated to 128 bits
        /// cell_ciphertext = AES-CBC-256(enc_key, cell_iv, cell_data) with PKCS7 padding.
        /// (optional) cell_tag = HMAC_SHA-2-256(mac_key, versionbyte + cell_iv + cell_ciphertext + versionbyte_length)
        /// cell_blob = versionbyte + [cell_tag] + cell_iv + cell_ciphertext
        /// </summary>
        /// <param name="plainText">Plaintext data to be encrypted</param>
        /// <param name="hasAuthenticationTag">Does the algorithm require authentication tag.</param>
        /// <returns>Returns the ciphertext corresponding to the plaintext.</returns>
        protected byte[] EncryptData(byte[] plainText, bool hasAuthenticationTag)
        {
            // Empty values get encrypted and decrypted properly for both Deterministic and Randomized encryptions.
            Debug.Assert(plainText != null);

            byte[] iv = new byte[BlockSizeInBytes];

            // Prepare IV
            // Should be 1 single block (16 bytes)
            if (this.isDeterministic)
            {
                SecurityUtility.GetHMACWithSHA256(plainText, this.dataEncryptionKey.IVKey, iv);
            }
            else
            {
                SecurityUtility.GenerateRandomBytes(iv);
            }

            int numBlocks = (plainText.Length / BlockSizeInBytes) + 1;

            // Final blob we return = version + HMAC + iv + cipherText
            const int hmacStartIndex       = 1;
            int       authenticationTagLen = hasAuthenticationTag ? KeySizeInBytes : 0;
            int       ivStartIndex         = hmacStartIndex + authenticationTagLen;
            int       cipherStartIndex     = ivStartIndex + BlockSizeInBytes; // this is where hmac starts.

            // Output buffer size = size of VersionByte + Authentication Tag + IV + cipher Text blocks.
            int outputBufSize = sizeof(byte) + authenticationTagLen + iv.Length + (numBlocks * BlockSizeInBytes);

            byte[] outBuffer = new byte[outputBufSize];

            // Store the version and IV rightaway
            outBuffer[0] = this.algorithmVersion;
            Buffer.BlockCopy(iv, 0, outBuffer, ivStartIndex, iv.Length);

            AesCryptoServiceProvider aesAlg;

            // Try to get a provider from the pool.
            // If no provider is available, create a new one.
            if (!this.cryptoProviderPool.TryDequeue(out aesAlg))
            {
                aesAlg = new AesCryptoServiceProvider();

                try
                {
                    // Set various algorithm properties
                    aesAlg.Key     = this.dataEncryptionKey.EncryptionKey;
                    aesAlg.Mode    = cipherMode;
                    aesAlg.Padding = paddingMode;
                }
                catch (Exception)
                {
                    if (aesAlg != null)
                    {
                        aesAlg.Dispose();
                    }

                    throw;
                }
            }

            try
            {
                // Always set the IV since it changes from cell to cell.
                aesAlg.IV = iv;

                // Compute CipherText and authentication tag in a single pass
                using (ICryptoTransform encryptor = aesAlg.CreateEncryptor())
                {
                    Debug.Assert(encryptor.CanTransformMultipleBlocks, "AES Encryptor can transform multiple blocks");
                    int count       = 0;
                    int cipherIndex = cipherStartIndex; // this is where cipherText starts
                    if (numBlocks > 1)
                    {
                        count        = (numBlocks - 1) * BlockSizeInBytes;
                        cipherIndex += encryptor.TransformBlock(plainText, 0, count, outBuffer, cipherIndex);
                    }

                    byte[] buffTmp = encryptor.TransformFinalBlock(plainText, count, plainText.Length - count); // done encrypting
                    Buffer.BlockCopy(buffTmp, 0, outBuffer, cipherIndex, buffTmp.Length);
                    cipherIndex += buffTmp.Length;
                }

                if (hasAuthenticationTag)
                {
                    using (HMACSHA256 hmac = new HMACSHA256(this.dataEncryptionKey.MACKey))
                    {
                        Debug.Assert(hmac.CanTransformMultipleBlocks, "HMAC can't transform multiple blocks");
                        hmac.TransformBlock(version, 0, version.Length, version, 0);
                        hmac.TransformBlock(iv, 0, iv.Length, iv, 0);

                        // Compute HMAC on final block
                        hmac.TransformBlock(outBuffer, cipherStartIndex, numBlocks * BlockSizeInBytes, outBuffer, cipherStartIndex);
                        hmac.TransformFinalBlock(versionSize, 0, versionSize.Length);
                        byte[] hash = hmac.Hash;
                        Debug.Assert(hash.Length >= authenticationTagLen, "Unexpected hash size");
                        Buffer.BlockCopy(hash, 0, outBuffer, hmacStartIndex, authenticationTagLen);
                    }
                }
            }
            finally
            {
                // Return the provider to the pool.
                this.cryptoProviderPool.Enqueue(aesAlg);
            }

            return(outBuffer);
        }
Beispiel #24
0
        public void Save(Stream stream, byte[] passphraseBuffer)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream), "Stream cannot be null.");
            }
            if (passphraseBuffer == null)
            {
                throw new ArgumentNullException(nameof(passphraseBuffer), "Passphrase cannot be null.");
            }

            if (!this.IsReadOnly && this.TrackModify)
            {
                this.Headers[HeaderType.TimestampOfLastSave].Time = DateTime.UtcNow;

                var assemblyName = Assembly.GetExecutingAssembly().GetName();
                this.Headers[HeaderType.WhatPerformedLastSave].Text = string.Format(CultureInfo.InvariantCulture, "{0} V{1}.{2:00}", assemblyName.Name, assemblyName.Version.Major, assemblyName.Version.Minor);

                this.Headers[HeaderType.LastSavedByUser].Text = Environment.UserName;
                this.Headers[HeaderType.LastSavedOnHost].Text = Environment.MachineName;
            }

            byte[] stretchedKey = null;
            byte[] keyK         = null;
            byte[] keyL         = null;
            //byte[] data = null;
            try {
                stream.Write(BitConverter.GetBytes(Tag), 0, 4);

                var salt = new byte[32];
                Rnd.GetBytes(salt);
                stream.Write(salt, 0, salt.Length);

                this.Iterations = this.Iterations; //to force minimum iteration count
                var iter = (uint)this.Iterations;
                stream.Write(BitConverter.GetBytes(iter), 0, 4);

                stretchedKey = GetStretchedKey(passphraseBuffer, salt, iter);
                stream.Write(GetSha256Hash(stretchedKey), 0, 32);

                keyK = new byte[32];
                Rnd.GetBytes(keyK);
                stream.Write(EncryptKey(stretchedKey, keyK, 0), 0, 32);

                keyL = new byte[32];
                Rnd.GetBytes(keyL);
                stream.Write(EncryptKey(stretchedKey, keyL, 0), 0, 32);

                var iv = new byte[16];
                Rnd.GetBytes(iv);
                stream.Write(iv, 0, iv.Length);

                using (var dataHash = new HMACSHA256(keyL))
                    using (var twofish = new TwofishManaged()) {
                        twofish.Mode    = CipherMode.CBC;
                        twofish.Padding = PaddingMode.None;
                        twofish.KeySize = 256;
                        twofish.Key     = keyK;
                        twofish.IV      = iv;
                        using (var dataEncryptor = twofish.CreateEncryptor()) {
                            foreach (var field in this.Headers)
                            {
                                WriteBlock(stream, dataHash, dataEncryptor, (byte)field.HeaderType, field.RawData);
                            }
                            WriteBlock(stream, dataHash, dataEncryptor, (byte)HeaderType.EndOfEntry, new byte[] { });

                            foreach (var entry in this.Entries)
                            {
                                foreach (var field in entry.Records)
                                {
                                    WriteBlock(stream, dataHash, dataEncryptor, (byte)field.RecordType, field.RawData);
                                }
                                WriteBlock(stream, dataHash, dataEncryptor, (byte)RecordType.EndOfEntry, new byte[] { });
                            }
                        }

                        dataHash.TransformFinalBlock(new byte[] { }, 0, 0);

                        stream.Write(BitConverter.GetBytes(Tag), 0, 4);
                        stream.Write(BitConverter.GetBytes(TagEof), 0, 4);
                        stream.Write(BitConverter.GetBytes(Tag), 0, 4);
                        stream.Write(BitConverter.GetBytes(TagEof), 0, 4);

                        stream.Write(dataHash.Hash, 0, dataHash.Hash.Length);
                        this.HasChanged = false;
                    }
            } finally {
                if (stretchedKey != null)
                {
                    Array.Clear(stretchedKey, 0, stretchedKey.Length);
                }
                if (keyK != null)
                {
                    Array.Clear(keyK, 0, keyK.Length);
                }
                if (keyL != null)
                {
                    Array.Clear(keyL, 0, keyL.Length);
                }
                //if (data != null) { Array.Clear(data, 0, data.Length); }
            }
        }
Beispiel #25
0
        public static Document Load(Stream stream, byte[] passphraseBuffer)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream), "Stream cannot be null.");
            }
            if (passphraseBuffer == null)
            {
                throw new ArgumentNullException(nameof(passphraseBuffer), "Passphrase cannot be null.");
            }

            var buffer = new byte[16384];

            using (var ms = new MemoryStream()) {
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                buffer = ms.ToArray();
            }

            if ((buffer.Length < 200) ||
                (BitConverter.ToInt32(buffer, 0) != Tag) ||
                (BitConverter.ToInt32(buffer, buffer.Length - 32 - 16) != Tag) ||
                (BitConverter.ToInt32(buffer, buffer.Length - 32 - 12) != TagEof) ||
                (BitConverter.ToInt32(buffer, buffer.Length - 32 - 8) != Tag) ||
                (BitConverter.ToInt32(buffer, buffer.Length - 32 - 4) != TagEof))
            {
                throw new FormatException("Unrecognized file format.");
            }

            var salt = new byte[32];

            Buffer.BlockCopy(buffer, 4, salt, 0, salt.Length);

            var iter = BitConverter.ToUInt32(buffer, 36);

            byte[] stretchedKey = null, keyK = null, keyL = null, data = null;
            try {
                stretchedKey = GetStretchedKey(passphraseBuffer, salt, iter);
                if (!AreBytesTheSame(GetSha256Hash(stretchedKey), buffer, 40))
                {
                    throw new CryptographicException("Password mismatch.");
                }

                keyK = DecryptKey(stretchedKey, buffer, 72);
                keyL = DecryptKey(stretchedKey, buffer, 104);

                var iv = new byte[16];
                Buffer.BlockCopy(buffer, 136, iv, 0, iv.Length);

                data = DecryptData(keyK, iv, buffer, 152, buffer.Length - 200);

                using (var dataHash = new HMACSHA256(keyL)) {
                    var dataOffset = 0;

                    var headerFields = new List <Header>();
                    while (dataOffset < data.Length)
                    {
                        var fieldLength     = BitConverter.ToInt32(data, dataOffset + 0);
                        var fieldLengthFull = ((fieldLength + 5 - 1) / 16 + 1) * 16;
                        var fieldType       = (HeaderType)data[dataOffset + 4];
                        var fieldData       = new byte[fieldLength];
                        try {
                            Buffer.BlockCopy(data, dataOffset + 5, fieldData, 0, fieldLength);
                            dataOffset += fieldLengthFull;                                    //there is ALWAYS some random bytes added, thus extra block if 16 bytes

                            dataHash.TransformBlock(fieldData, 0, fieldData.Length, null, 0); //not hashing length nor type - wtf?
                            if (fieldType == HeaderType.EndOfEntry)
                            {
                                break;
                            }

                            headerFields.Add(new Header(fieldType, fieldData));
                        } finally {
                            Array.Clear(fieldData, 0, fieldData.Length);
                        }
                    }

                    if ((headerFields.Count == 0) || (headerFields[0].Version < 0x0300))
                    {
                        throw new FormatException("Unrecognized file format version.");
                    }

                    var           recordFields = new List <List <Record> >();
                    List <Record> records      = null;
                    while (dataOffset < data.Length)
                    {
                        var fieldLength     = BitConverter.ToInt32(data, dataOffset + 0);
                        var fieldLengthFull = ((fieldLength + 5 - 1) / 16 + 1) * 16;
                        var fieldType       = (RecordType)data[dataOffset + 4];
                        var fieldData       = new byte[fieldLength];
                        try {
                            Buffer.BlockCopy(data, dataOffset + 5, fieldData, 0, fieldLength);
                            dataOffset += fieldLengthFull;                                    //there is ALWAYS some random bytes added, thus extra block if 16 bytes

                            dataHash.TransformBlock(fieldData, 0, fieldData.Length, null, 0); //not hashing length nor type - wtf?
                            if (fieldType == RecordType.EndOfEntry)
                            {
                                records = null; continue;
                            }

                            if (records == null)
                            {
                                records = new List <Record>();
                                recordFields.Add(records);
                            }
                            records.Add(new Record(fieldType, fieldData));
                        } finally {
                            Array.Clear(fieldData, 0, fieldData.Length);
                        }
                    }

                    dataHash.TransformFinalBlock(new byte[] { }, 0, 0);

                    if (!AreBytesTheSame(dataHash.Hash, buffer, buffer.Length - 32))
                    {
                        throw new CryptographicException("Authentication mismatch.");
                    }

                    var document = new Document(headerFields, recordFields.ToArray())
                    {
                        _iterations = (int)iter,       //to avoid rounding up if iteration count is less than 2048
                        Passphrase  = passphraseBuffer //to avoid keeping password in memory for save - at least we don't need to deal with string's immutability.
                    };
                    return(document);
                }
            } catch (CryptographicException ex) {
                throw new FormatException(ex.Message, ex);
            } finally { //best effort to sanitize memory
                if (stretchedKey != null)
                {
                    Array.Clear(stretchedKey, 0, stretchedKey.Length);
                }
                if (keyK != null)
                {
                    Array.Clear(keyK, 0, keyK.Length);
                }
                if (keyL != null)
                {
                    Array.Clear(keyL, 0, keyL.Length);
                }
                if (data != null)
                {
                    Array.Clear(data, 0, data.Length);
                }
            }
        }
Beispiel #26
0
        /// <summary>
        /// Returns the SHA256 HMAC of the given <paramref name="prefix"/>, the given <paramref name="request"/>'s
        /// body, and the given <paramref name="suffix"/> (in that order).
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA256"/>.</param>
        /// <param name="prefix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// before the <paramref name="request"/>'s body.
        /// </param>
        /// <param name="suffix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// after the <paramref name="request"/>'s body.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA256 HMAC of
        /// the <paramref name="prefix"/>, the <paramref name="request"/>'s body, and the <paramref name="suffix"/>
        /// (in that order).
        /// </returns>
        protected virtual async Task <byte[]> ComputeRequestBodySha256HashAsync(
            HttpRequest request,
            byte[] secret,
            byte[] prefix,
            byte[] suffix)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (secret == null)
            {
                throw new ArgumentNullException(nameof(secret));
            }
            if (secret.Length == 0)
            {
                throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty);
            }

            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA256(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length > 0)
                    {
                        hasher.TransformBlock(
                            inputBuffer: prefix,
                            inputOffset: 0,
                            inputCount: prefix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    // Split body into 4K chunks.
                    var buffer      = new byte[4096];
                    var inputStream = request.Body;
                    int bytesRead;
                    while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        hasher.TransformBlock(
                            buffer,
                            inputOffset: 0,
                            inputCount: bytesRead,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    if (suffix != null && suffix.Length > 0)
                    {
                        hasher.TransformBlock(
                            suffix,
                            inputOffset: 0,
                            inputCount: suffix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    hasher.TransformFinalBlock(Array.Empty <byte>(), inputOffset: 0, inputCount: 0);

                    return(hasher.Hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
Beispiel #27
0
        // Token is base64 url encoded
        public static byte[] Decrypt(byte[] key, string token, out DateTime timestamp, int?ttl = null)
        {
            if (key == null)
            {
                throw new FernetException($"{nameof(key)} is null.");
            }

            if (key.Length != 32)
            {
                throw new FernetException($"Length of {nameof(key)} should be 32.");
            }

            if (token == null)
            {
                throw new FernetException($"{nameof(key)} is null.");
            }

            var token2 = token.UrlSafe64Decode();

            if (token2.Length < 57)
            {
                throw new FernetException($"Length of {nameof(key)} should be greater or equal 57.");
            }

            var version = token2[0];

            if (version != 0x80)
            {
                throw new FernetException("Invalid version.");
            }

            var signingKey = new byte[16];

            Buffer.BlockCopy(key, 0, signingKey, 0, 16);

            using (var hmac = new HMACSHA256(signingKey))
            {
                hmac.TransformFinalBlock(token2, 0, token2.Length - 32);
                var hash2 = hmac.Hash;

                var hash = token2.Skip(token2.Length - 32).Take(32);

                if (!hash.SequenceEqual(hash2))
                {
                    throw new FernetException("Wrong HMAC!");
                }
            }

            // BigEndian to LittleEndian
            var timestamp2 = BitConverter.ToInt64(token2, 1);

            timestamp2 = IPAddress.NetworkToHostOrder(timestamp2);
            var datetimeOffset = DateTimeOffset.FromUnixTimeSeconds(timestamp2);

            timestamp = datetimeOffset.UtcDateTime;

            // calculate TTL
            if (ttl.HasValue)
            {
                var calculatedTimeSeconds = datetimeOffset.ToUnixTimeSeconds() + ttl.Value;
                var currentTimeSeconds    = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
                if (calculatedTimeSeconds < currentTimeSeconds)
                {
                    throw new FernetException("Token is expired.");
                }
            }

            byte[] decrypted;

            using (var aes = new AesManaged())
            {
                aes.Mode    = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;

                var encryptionKey = new byte[16];
                Buffer.BlockCopy(key, 16, encryptionKey, 0, 16);
                aes.Key = encryptionKey;

                var iv = new byte[16];
                Buffer.BlockCopy(token2, 9, iv, 0, 16);
                aes.IV = iv;

                using (var decryptor = aes.CreateDecryptor())
                {
                    const int startCipherText  = 25;
                    var       cipherTextLength = token2.Length - 32 - 25;
                    decrypted = decryptor.TransformFinalBlock(token2, startCipherText, cipherTextLength);
                }
            }

            return(decrypted);
        }
Beispiel #28
0
        public static string Encrypt(byte[] key, byte[] data, DateTime?timestamp = null, byte[] iv = null,
                                     bool trimEnd = false)
        {
            if (key == null)
            {
                throw new FernetException($"{nameof(key)} is null.");
            }

            if (key.Length != 32)
            {
                throw new FernetException($"Length of {nameof(key)} should be 32.");
            }

            if (data == null)
            {
                throw new FernetException($"{nameof(data)} is null.");
            }

            if (iv != null && iv.Length != 16)
            {
                throw new FernetException($"Length of {nameof(iv)} should be 16.");
            }

            if (timestamp == null)
            {
                timestamp = DateTime.UtcNow;
            }

            var result = new byte[57 + (data.Length + 16) / 16 * 16];

            result[0] = 0x80;

            // BigEndian to LittleEndian
            var timestamp2 = new DateTimeOffset(timestamp.Value).ToUnixTimeSeconds();

            timestamp2 = IPAddress.NetworkToHostOrder(timestamp2);
            var timestamp3 = BitConverter.GetBytes(timestamp2);

            Buffer.BlockCopy(timestamp3, 0, result, 1, timestamp3.Length);

            using (var aes = new AesManaged())
            {
                aes.Mode = CipherMode.CBC;

                var encryptionKey = new byte[16];
                Buffer.BlockCopy(key, 16, encryptionKey, 0, 16);

                aes.Key = encryptionKey;

                if (iv != null)
                {
                    aes.IV = iv;
                }
                else
                {
                    aes.GenerateIV();
                }

                Buffer.BlockCopy(aes.IV, 0, result, 9, 16);

                aes.Padding = PaddingMode.PKCS7;

                using (var encryptor = aes.CreateEncryptor())
                {
                    var encrypted = encryptor.TransformFinalBlock(data, 0, data.Length);
                    Buffer.BlockCopy(encrypted, 0, result, 25, encrypted.Length);
                }
            }

            var signingKey = new byte[16];

            Buffer.BlockCopy(key, 0, signingKey, 0, 16);

            using (var hmac = new HMACSHA256(signingKey))
            {
                hmac.TransformFinalBlock(result, 0, result.Length - 32);
                Buffer.BlockCopy(hmac.Hash, 0, result, result.Length - 32, 32);
            }

            return(result.UrlSafe64Encode(trimEnd));
        }
Beispiel #29
0
        private static byte[] DecryptFernet(byte[] key, string token, out DateTime timestamp)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (key.Length != 32)
            {
                throw new ArgumentException(nameof(key));
            }

            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            byte[] token2 = Base64UrlDecode(token);

            if (token2.Length < 57)
            {
                throw new ArgumentException(nameof(token));
            }

            byte version = token2[0];

            if (version != 0x80)
            {
                throw new Exception("version");
            }

            // Check the hmac
            {
                byte[] signingKey = new byte[16];
                Buffer.BlockCopy(key, 0, signingKey, 0, 16);

                using (var hmac = new HMACSHA256(signingKey))
                {
                    hmac.TransformFinalBlock(token2, 0, token2.Length - 32);
                    //byte[] hash2 = hmac.Hash;

                    //IEnumerable<byte> hash = token2.Skip(token2.Length - 32).Take(32);

                    //if (!hash.SequenceEqual(hash2))
                    //{
                    //    throw new Exception("Wrong HMAC!");
                    //}
                }
            }

            {
                // BigEndian to LittleEndian
                long timestamp2 = BitConverter.ToInt64(token2, 1);
                timestamp2 = IPAddress.NetworkToHostOrder(timestamp2);

                timestamp = DateTimeOffset.FromUnixTimeSeconds(timestamp2).UtcDateTime;
            }

            byte[] decrypted;

            using (var aes = new AesManaged())
            {
                aes.Mode    = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;

                byte[] encryptionKey = new byte[16];
                Buffer.BlockCopy(key, 16, encryptionKey, 0, 16);
                aes.Key = encryptionKey;

                byte[] iv = new byte[16];
                Buffer.BlockCopy(token2, 9, iv, 0, 16);
                aes.IV = iv;

                using (var decryptor = aes.CreateDecryptor())
                {
                    const int startCipherText  = 25;
                    int       cipherTextLength = token2.Length - 32 - 25;
                    decrypted = decryptor.TransformFinalBlock(token2, startCipherText, cipherTextLength);
                }
            }

            return(decrypted);
        }
Beispiel #30
0
        private bool ReadSafeBlock()
        {
            if (m_bEos)
            {
                return(false);                   // End of stream reached already
            }
            byte[] pbStoredHmac = MemUtil.Read(m_sBase, 32);
            if ((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
            {
                throw new EndOfStreamException(KLRes.FileCorrupted + " " +
                                               KLRes.FileIncomplete);
            }

            // Block index is implicit: it's used in the HMAC computation,
            // but does not need to be stored
            // byte[] pbBlockIndex = MemUtil.Read(m_sBase, 8);
            // if((pbBlockIndex == null) || (pbBlockIndex.Length != 8))
            //	throw new EndOfStreamException();
            // ulong uBlockIndex = MemUtil.BytesToUInt64(pbBlockIndex);
            // if((uBlockIndex != m_uBlockIndex) && m_bVerify)
            //	throw new InvalidDataException();
            byte[] pbBlockIndex = MemUtil.UInt64ToBytes(m_uBlockIndex);

            byte[] pbBlockSize = MemUtil.Read(m_sBase, 4);
            if ((pbBlockSize == null) || (pbBlockSize.Length != 4))
            {
                throw new EndOfStreamException(KLRes.FileCorrupted + " " +
                                               KLRes.FileIncomplete);
            }
            int nBlockSize = MemUtil.BytesToInt32(pbBlockSize);

            if (nBlockSize < 0)
            {
                throw new InvalidDataException(KLRes.FileCorrupted);
            }

            m_iBufferPos = 0;

            SetBuffer(MemUtil.Read(m_sBase, nBlockSize));
            if ((m_pbBuffer == null) || ((m_pbBuffer.Length != nBlockSize) && m_bVerify))
            {
                throw new EndOfStreamException(KLRes.FileCorrupted + " " +
                                               KLRes.FileIncompleteExpc);
            }

            if (m_bVerify)
            {
                byte[] pbCmpHmac;
                byte[] pbBlockKey = GetHmacKey64(m_pbKey, m_uBlockIndex);
                using (HMACSHA256 h = new HMACSHA256(pbBlockKey))
                {
                    h.TransformBlock(pbBlockIndex, 0, pbBlockIndex.Length,
                                     pbBlockIndex, 0);
                    h.TransformBlock(pbBlockSize, 0, pbBlockSize.Length,
                                     pbBlockSize, 0);

                    if (m_pbBuffer.Length != 0)
                    {
                        h.TransformBlock(m_pbBuffer, 0, m_pbBuffer.Length,
                                         m_pbBuffer, 0);
                    }

                    h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);

                    pbCmpHmac = h.Hash;
                }
                MemUtil.ZeroByteArray(pbBlockKey);

                if (!MemUtil.ArraysEqual(pbCmpHmac, pbStoredHmac))
                {
                    throw new InvalidDataException(KLRes.FileCorrupted);
                }
            }

            ++m_uBlockIndex;

            if (nBlockSize == 0)
            {
                m_bEos = true;
                return(false);                // No further data available
            }
            return(true);
        }