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; }
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; m_pbBuffer = 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); }