< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Crypto.Providers.Native.Ciphers.HChaCha20
Assembly: NLightning.Infrastructure
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Crypto/Providers/Native/Ciphers/HChaCha20.cs
Tag: 36_15743069263
Line coverage
97%
Covered lines: 42
Uncovered lines: 1
Coverable lines: 43
Total lines: 90
Line coverage: 97.6%
Branch coverage
87%
Covered branches: 7
Total branches: 8
Branch coverage: 87.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
CreateInitialState(...)50%2290%
PerformRounds(...)100%22100%
CreateSubkey(...)100%11100%
ToUint32LittleEndian(...)100%22100%
FromUint32LittleEndian(...)100%22100%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Crypto/Providers/Native/Ciphers/HChaCha20.cs

#LineLine coverage
 1#if CRYPTO_NATIVE
 2using System.Buffers;
 3using System.Buffers.Binary;
 4using NLightning.Infrastructure.Crypto.Providers.Native.Constants;
 5
 6namespace NLightning.Infrastructure.Crypto.Providers.Native.Ciphers;
 7
 8using Converters;
 9
 10public static class HChaCha20
 11{
 212    private static readonly uint[] s_hChacha20Constant = [0x61707865, 0x3320646E, 0x79622D32, 0x6B206574];
 13
 14    public static void CreateInitialState(ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, Span<uint> state)
 15    {
 416        if (state.Length != XChaCha20Constants.StateSize)
 017            throw new ArgumentException("State must be 16 bytes long", nameof(state));
 18
 19        // set HChaCha20 constant
 420        s_hChacha20Constant.CopyTo(state);
 21
 22        // set key
 423        Span<uint> keyState = stackalloc uint[8];
 424        ToUint32LittleEndian(key, keyState);
 425        keyState.CopyTo(state[4..]);
 26
 27        // set nonce
 428        Span<uint> nonceState = stackalloc uint[4];
 429        ToUint32LittleEndian(nonce, nonceState);
 430        nonceState.CopyTo(state[^4..]);
 431    }
 32
 33    public static void PerformRounds(Span<uint> state)
 34    {
 8835        for (var i = 0; i < 10; i++)
 36        {
 4037            ChaCha20.QuarterRound(ref state[0], ref state[4], ref state[8], ref state[12]);
 4038            ChaCha20.QuarterRound(ref state[1], ref state[5], ref state[9], ref state[13]);
 4039            ChaCha20.QuarterRound(ref state[2], ref state[6], ref state[10], ref state[14]);
 4040            ChaCha20.QuarterRound(ref state[3], ref state[7], ref state[11], ref state[15]);
 4041            ChaCha20.QuarterRound(ref state[0], ref state[5], ref state[10], ref state[15]);
 4042            ChaCha20.QuarterRound(ref state[1], ref state[6], ref state[11], ref state[12]);
 4043            ChaCha20.QuarterRound(ref state[2], ref state[7], ref state[8], ref state[13]);
 4044            ChaCha20.QuarterRound(ref state[3], ref state[4], ref state[9], ref state[14]);
 45        }
 446    }
 47
 48    public static void CreateSubkey(ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, Span<byte> subkey)
 49    {
 450        Span<uint> state = stackalloc uint[XChaCha20Constants.StateSize];
 451        CreateInitialState(key, nonce, state);
 452        PerformRounds(state);
 53
 454        FromUint32LittleEndian([state[0], state[1], state[2], state[3], state[12], state[13], state[14], state[15]],
 455                               subkey);
 456    }
 57
 58    private static void ToUint32LittleEndian(ReadOnlySpan<byte> buffer, Span<uint> output)
 59    {
 860        var temp = ArrayPool<byte>.Shared.Rent(4);
 61        try
 62        {
 863            var pos = 0;
 64
 865            using var ms = new MemoryStream(buffer.ToArray());
 5666            while (pos != output.Length)
 67            {
 4868                ms.ReadExactly(temp, 0, 4);
 4869                output[pos] = EndianBitConverter.ToUInt32LittleEndian(temp[..4]);
 4870                pos += 1;
 71            }
 72        }
 73        finally
 74        {
 875            ArrayPool<byte>.Shared.Return(temp, true);
 876        }
 877    }
 78
 79    private static void FromUint32LittleEndian(ReadOnlySpan<uint> input, Span<byte> output)
 80    {
 7281        for (var i = 0; i < input.Length; i++)
 82        {
 3283            var u = input[i];
 3284            var temp = EndianBitConverter.GetBytesLittleEndian(u);
 3285            BinaryPrimitives.WriteUInt32LittleEndian(temp, u);
 3286            temp.CopyTo(output[(i * 4)..]);
 87        }
 488    }
 89}
 90#endif