private byte[] ComputeHeaderHmac(byte[] pbHeader, byte[] pbKey) { byte[] pbHeaderHmac; byte[] pbBlockKey = HmacBlockStream.GetHmacKey64( pbKey, ulong.MaxValue); using(HMACSHA256 h = new HMACSHA256(pbBlockKey)) { pbHeaderHmac = h.ComputeHash(pbHeader); } MemUtil.ZeroByteArray(pbBlockKey); return pbHeaderHmac; }
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); }
/// <summary> /// Create a cryptographic key of length <paramref name="cbOut" /> /// (in bytes) from <paramref name="pbIn" />. /// </summary> public static byte[] ResizeKey(byte[] pbIn, int iInOffset, int cbIn, int cbOut) { if (pbIn == null) { throw new ArgumentNullException("pbIn"); } if (cbOut < 0) { throw new ArgumentOutOfRangeException("cbOut"); } if (cbOut == 0) { return(MemUtil.EmptyByteArray); } byte[] pbHash; if (cbOut <= 32) { pbHash = HashSha256(pbIn, iInOffset, cbIn); } else { using (SHA512Managed h = new SHA512Managed()) { pbHash = h.ComputeHash(pbIn, iInOffset, cbIn); } } if (cbOut == pbHash.Length) { return(pbHash); } byte[] pbRet = new byte[cbOut]; if (cbOut < pbHash.Length) { Array.Copy(pbHash, pbRet, cbOut); } else { int iPos = 0; ulong r = 0; while (iPos < cbOut) { Debug.Assert(pbHash.Length == 64); using (HMACSHA256 h = new HMACSHA256(pbHash)) { byte[] pbR = MemUtil.UInt64ToBytes(r); byte[] pbPart = h.ComputeHash(pbR); int cbCopy = Math.Min(cbOut - iPos, pbPart.Length); Debug.Assert(cbCopy > 0); Array.Copy(pbPart, 0, pbRet, iPos, cbCopy); iPos += cbCopy; ++r; MemUtil.ZeroByteArray(pbPart); } } Debug.Assert(iPos == cbOut); } #if DEBUG byte[] pbZero = new byte[pbHash.Length]; Debug.Assert(!MemUtil.ArraysEqual(pbHash, pbZero)); #endif MemUtil.ZeroByteArray(pbHash); return(pbRet); }