< 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: 30_15166811759
Line coverage
0%
Covered lines: 0
Uncovered lines: 43
Coverable lines: 43
Total lines: 90
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
CreateInitialState(...)0%620%
PerformRounds(...)0%620%
CreateSubkey(...)100%210%
ToUint32LittleEndian(...)0%620%
FromUint32LittleEndian(...)0%620%

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{
 012    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    {
 016        if (state.Length != XChaCha20Constants.STATE_SIZE)
 017            throw new ArgumentException("State must be 16 bytes long", nameof(state));
 18
 19        // set HChaCha20 constant
 020        s_hChacha20Constant.CopyTo(state);
 21
 22        // set key
 023        Span<uint> keyState = stackalloc uint[8];
 024        ToUint32LittleEndian(key, keyState);
 025        keyState.CopyTo(state[4..]);
 26
 27        // set nonce
 028        Span<uint> nonceState = stackalloc uint[4];
 029        ToUint32LittleEndian(nonce, nonceState);
 030        nonceState.CopyTo(state[^4..]);
 031    }
 32
 33    public static void PerformRounds(Span<uint> state)
 34    {
 035        for (var i = 0; i < 10; i++)
 36        {
 037            ChaCha20.QuarterRound(ref state[0], ref state[4], ref state[8], ref state[12]);
 038            ChaCha20.QuarterRound(ref state[1], ref state[5], ref state[9], ref state[13]);
 039            ChaCha20.QuarterRound(ref state[2], ref state[6], ref state[10], ref state[14]);
 040            ChaCha20.QuarterRound(ref state[3], ref state[7], ref state[11], ref state[15]);
 041            ChaCha20.QuarterRound(ref state[0], ref state[5], ref state[10], ref state[15]);
 042            ChaCha20.QuarterRound(ref state[1], ref state[6], ref state[11], ref state[12]);
 043            ChaCha20.QuarterRound(ref state[2], ref state[7], ref state[8], ref state[13]);
 044            ChaCha20.QuarterRound(ref state[3], ref state[4], ref state[9], ref state[14]);
 45        }
 046    }
 47
 48    public static void CreateSubkey(ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, Span<byte> subkey)
 49    {
 050        Span<uint> state = stackalloc uint[XChaCha20Constants.STATE_SIZE];
 051        CreateInitialState(key, nonce, state);
 052        PerformRounds(state);
 53
 054        FromUint32LittleEndian([state[0], state[1], state[2], state[3], state[12], state[13], state[14], state[15]],
 055                               subkey);
 056    }
 57
 58    private static void ToUint32LittleEndian(ReadOnlySpan<byte> buffer, Span<uint> output)
 59    {
 060        var temp = ArrayPool<byte>.Shared.Rent(4);
 61        try
 62        {
 063            var pos = 0;
 64
 065            using var ms = new MemoryStream(buffer.ToArray());
 066            while (pos != output.Length)
 67            {
 068                ms.ReadExactly(temp, 0, 4);
 069                output[pos] = EndianBitConverter.ToUInt32LittleEndian(temp[..4]);
 070                pos += 1;
 71            }
 72        }
 73        finally
 74        {
 075            ArrayPool<byte>.Shared.Return(temp);
 076        }
 077    }
 78
 79    private static void FromUint32LittleEndian(ReadOnlySpan<uint> input, Span<byte> output)
 80    {
 081        for (var i = 0; i < input.Length; i++)
 82        {
 083            var u = input[i];
 084            var temp = EndianBitConverter.GetBytesLittleEndian(u);
 085            BinaryPrimitives.WriteUInt32LittleEndian(temp, u);
 086            temp.CopyTo(output[(i * 4)..]);
 87        }
 088    }
 89}
 90#endif