< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Crypto.Functions.Hkdf
Assembly: NLightning.Infrastructure
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Crypto/Functions/Hkdf.cs
Tag: 30_15166811759
Line coverage
75%
Covered lines: 30
Uncovered lines: 10
Coverable lines: 40
Total lines: 112
Line coverage: 75%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor()100%11100%
ExtractAndExpand2(...)100%11100%
ExtractAndExpand3(...)100%210%
HmacHash(...)100%22100%
Dispose()50%2.03280%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Crypto/Functions/Hkdf.cs

#LineLine coverage
 1using System.Diagnostics;
 2
 3namespace NLightning.Infrastructure.Crypto.Functions;
 4
 5using Domain.Crypto.Constants;
 6using Hashes;
 7using Primitives;
 8
 9/// <summary>
 10/// HMAC-based Extract-and-Expand Key Derivation Function, defined in
 11/// <see href="https://tools.ietf.org/html/rfc5869">RFC 5869</see>.
 12/// </summary>
 13internal sealed class Hkdf : IDisposable
 14{
 815    private static readonly byte[] s_one = [1];
 816    private static readonly byte[] s_two = [2];
 817    private static readonly byte[] s_three = [3];
 18
 28819    private readonly Sha256 _sha256 = new();
 20
 21    private bool _disposed;
 22
 23    /// <summary>
 24    /// Takes a chainingKey byte sequence of length HashLen,
 25    /// and an inputKeyMaterial byte sequence with length
 26    /// either zero bytes, 32 bytes, or DhLen bytes. Writes a
 27    /// byte sequences of length 2 * HashLen into output parameter.
 28    /// </summary>
 29    public void ExtractAndExpand2(SecureMemory chainingKey, ReadOnlySpan<byte> inputKeyMaterial, Span<byte> output)
 30    {
 31        // ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Hkdf));
 32
 33        Debug.Assert(chainingKey.Length == CryptoConstants.SHA256_HASH_LEN);
 34        Debug.Assert(output.Length == 2 * CryptoConstants.SHA256_HASH_LEN);
 35
 23236        Span<byte> tempKey = stackalloc byte[CryptoConstants.SHA256_HASH_LEN];
 23237        HmacHash(chainingKey, tempKey, inputKeyMaterial);
 38
 23239        var output1 = output[..CryptoConstants.SHA256_HASH_LEN];
 23240        HmacHash(tempKey, output1, s_one);
 41
 23242        var output2 = output.Slice(CryptoConstants.SHA256_HASH_LEN, CryptoConstants.SHA256_HASH_LEN);
 23243        HmacHash(tempKey, output2, output1, s_two);
 23244    }
 45
 46    /// <summary>
 47    /// Takes a chainingKey byte sequence of length HashLen,
 48    /// and an inputKeyMaterial byte sequence with length
 49    /// either zero bytes, 32 bytes, or DhLen bytes. Writes a
 50    /// byte sequences of length 3 * HashLen into output parameter.
 51    /// </summary>
 52    public void ExtractAndExpand3(SecureMemory chainingKey, ReadOnlySpan<byte> inputKeyMaterial, Span<byte> output)
 53    {
 54        // ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Hkdf));
 55
 56        Debug.Assert(chainingKey.Length == CryptoConstants.SHA256_HASH_LEN);
 57        Debug.Assert(output.Length == 3 * CryptoConstants.SHA256_HASH_LEN);
 58
 059        Span<byte> tempKey = stackalloc byte[CryptoConstants.SHA256_HASH_LEN];
 060        HmacHash(chainingKey, tempKey, inputKeyMaterial);
 61
 062        var output1 = output[..CryptoConstants.SHA256_HASH_LEN];
 063        HmacHash(tempKey, output1, s_one);
 64
 065        var output2 = output.Slice(CryptoConstants.SHA256_HASH_LEN, CryptoConstants.SHA256_HASH_LEN);
 066        HmacHash(tempKey, output2, output1, s_two);
 67
 068        var output3 = output.Slice(2 * CryptoConstants.SHA256_HASH_LEN, CryptoConstants.SHA256_HASH_LEN);
 069        HmacHash(tempKey, output3, output2, s_three);
 070    }
 71
 72    private void HmacHash(ReadOnlySpan<byte> key, Span<byte> hmac, ReadOnlySpan<byte> data1 = default, ReadOnlySpan<byte
 73    {
 74        // ExceptionUtils.ThrowIfDisposed(_disposed, nameof(Hkdf));
 75
 76        Debug.Assert(key.Length == CryptoConstants.SHA256_HASH_LEN);
 77        Debug.Assert(hmac.Length == CryptoConstants.SHA256_HASH_LEN);
 78
 69679        Span<byte> ipad = stackalloc byte[CryptoConstants.SHA256_BLOCK_LEN];
 69680        Span<byte> opad = stackalloc byte[CryptoConstants.SHA256_BLOCK_LEN];
 81
 69682        key.CopyTo(ipad);
 69683        key.CopyTo(opad);
 84
 9048085        for (var i = 0; i < CryptoConstants.SHA256_BLOCK_LEN; ++i)
 86        {
 4454487            ipad[i] ^= 0x36;
 4454488            opad[i] ^= 0x5C;
 89        }
 90
 69691        _sha256.AppendData(ipad);
 69692        _sha256.AppendData(data1);
 69693        _sha256.AppendData(data2);
 69694        _sha256.GetHashAndReset(hmac);
 95
 69696        _sha256.AppendData(opad);
 69697        _sha256.AppendData(hmac);
 69698        _sha256.GetHashAndReset(hmac);
 69699    }
 100
 101    public void Dispose()
 102    {
 240103        if (_disposed)
 104        {
 0105            return;
 106        }
 107
 240108        _sha256.Dispose();
 109
 240110        _disposed = true;
 240111    }
 112}