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"); } } }
/// <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 }
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); }
/// <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); }
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); } } }
/// <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); } } }
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"); }
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); }
/// <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)); } }
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); } }
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 } }
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); } } }
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); }
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()); } }
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()); }
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); }
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 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()); }
/// <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); }
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); } } }
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); } } }
/// <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); } } }
// 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); }
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)); }
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); }
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); }