Beispiel #1
0
        /// <summary>
        /// Creates a symmetric decryptor object with the current Key property and one-time use state parameter.
        /// </summary>
        /// <param name="key">The secret that will be used during decryption.</param>
        /// <param name="nonce">The one-time use state parameter.</param>
        public override ICryptoTransform CreateDecryptor(byte[] key, byte[] nonce)
        {
            var ivLow  = m_iv;
            var ivHigh = BinaryPrimitives.ReadUInt32LittleEndian(nonce.AsSpan(0, ChaChaTransform.WordLength));

            return(ChaChaTransform.New(Initialize(key, nonce, ivLow), BitwiseHelpers.ConcatBits(ivHigh, ivLow), 20U));
        }
Beispiel #2
0
        private void Compress(ReadOnlySpan <byte> data, uint finalizer)
        {
            var dataAsUInt = MemoryMarshal.Cast <byte, uint>(data);
            var h0         = m_h0;
            var h1         = m_h1;
            var h2         = m_h2;
            var h3         = m_h3;
            var h4         = m_h4;
            var r0         = m_r0;
            var r1         = m_r1;
            var r2         = m_r2;
            var r3         = m_r3;
            var r4         = m_r4;
            var s0         = m_s0;
            var s1         = m_s1;
            var s2         = m_s2;
            var s3         = m_s3;
            var t0         = dataAsUInt[0];
            var t1         = dataAsUInt[1];
            var t2         = dataAsUInt[2];
            var t3         = dataAsUInt[3];

            h0 += (t0 & 0x3FFFFFFU);
            h1 += ((uint)((BitwiseHelpers.ConcatBits(t1, t0) >> 26) & 0x3FFFFFFU));
            h2 += ((uint)((BitwiseHelpers.ConcatBits(t2, t1) >> 20) & 0x3FFFFFFU));
            h3 += ((uint)((BitwiseHelpers.ConcatBits(t3, t2) >> 14) & 0x3FFFFFFU));
            h4 += ((uint)BitwiseHelpers.Add((t3 >> 8), finalizer));

            var d0 = (BitwiseHelpers.Multiply(h0, r0) + BitwiseHelpers.Multiply(h1, s3) + BitwiseHelpers.Multiply(h2, s2) + BitwiseHelpers.Multiply(h3, s1) + BitwiseHelpers.Multiply(h4, s0));
            var d1 = (BitwiseHelpers.Multiply(h0, r1) + BitwiseHelpers.Multiply(h1, r0) + BitwiseHelpers.Multiply(h2, s3) + BitwiseHelpers.Multiply(h3, s2) + BitwiseHelpers.Multiply(h4, s1));
            var d2 = (BitwiseHelpers.Multiply(h0, r2) + BitwiseHelpers.Multiply(h1, r1) + BitwiseHelpers.Multiply(h2, r0) + BitwiseHelpers.Multiply(h3, s3) + BitwiseHelpers.Multiply(h4, s2));
            var d3 = (BitwiseHelpers.Multiply(h0, r3) + BitwiseHelpers.Multiply(h1, r2) + BitwiseHelpers.Multiply(h2, r1) + BitwiseHelpers.Multiply(h3, r0) + BitwiseHelpers.Multiply(h4, s3));
            var d4 = (BitwiseHelpers.Multiply(h0, r4) + BitwiseHelpers.Multiply(h1, r3) + BitwiseHelpers.Multiply(h2, r2) + BitwiseHelpers.Multiply(h3, r1) + BitwiseHelpers.Multiply(h4, r0));
            var c  = (d0 >> 26);

            h0  = ((uint)(d0 & 0x3FFFFFFU));
            d1 += c;
            c   = (d1 >> 26);
            h1  = ((uint)(d1 & 0x3FFFFFFU));
            d2 += c;
            c   = (d2 >> 26);
            h2  = ((uint)(d2 & 0x3FFFFFFU));
            d3 += c;
            c   = (d3 >> 26);
            h3  = ((uint)(d3 & 0x3FFFFFFU));
            d4 += c;
            c   = (d4 >> 26);
            h4  = ((uint)(d4 & 0x3FFFFFFU));
            h0 += ((uint)(c * 5UL));
            c   = (h0 >> 26);
            h0  = (h0 & 0x3FFFFFFU);
            h1 += ((uint)c);

            m_h0 = h0;
            m_h1 = h1;
            m_h2 = h2;
            m_h3 = h3;
            m_h4 = h4;
        }
Beispiel #3
0
        public static void WriteKeyStreamBlock(ReadOnlySpan <uint> state, ulong iv, uint numRounds, Span <byte> destination)
        {
            var destinationAsUInt = MemoryMarshal.Cast <byte, uint>(destination);
            var ivLow             = ((uint)BitwiseHelpers.ExtractLow(iv));
            var ivHigh            = ((uint)BitwiseHelpers.ExtractHigh(iv));
            var t0 = state[0];
            var t1 = state[1];
            var t2 = state[2];
            var t3 = state[3];
            var t4 = state[4];
            var t5 = state[5];
            var t6 = state[6];
            var t7 = state[7];
            var t8 = state[8];
            var t9 = state[9];
            var tA = state[10];
            var tB = state[11];
            var tC = ivLow;
            var tD = ivHigh;
            var tE = state[14];
            var tF = state[15];

            numRounds = (numRounds >> 1);

            for (var i = 0U; (i < numRounds); i++)
            {
                DoubleRound(
                    ref t0, ref t1, ref t2, ref t3,
                    ref t4, ref t5, ref t6, ref t7,
                    ref t8, ref t9, ref tA, ref tB,
                    ref tC, ref tD, ref tE, ref tF
                    );
            }

            destinationAsUInt[0]  = (t0 + state[0]);
            destinationAsUInt[1]  = (t1 + state[1]);
            destinationAsUInt[2]  = (t2 + state[2]);
            destinationAsUInt[3]  = (t3 + state[3]);
            destinationAsUInt[4]  = (t4 + state[4]);
            destinationAsUInt[5]  = (t5 + state[5]);
            destinationAsUInt[6]  = (t6 + state[6]);
            destinationAsUInt[7]  = (t7 + state[7]);
            destinationAsUInt[8]  = (t8 + state[8]);
            destinationAsUInt[9]  = (t9 + state[9]);
            destinationAsUInt[10] = (tA + state[10]);
            destinationAsUInt[11] = (tB + state[11]);
            destinationAsUInt[12] = (tC + ivLow);
            destinationAsUInt[13] = (tD + ivHigh);
            destinationAsUInt[14] = (tE + state[14]);
            destinationAsUInt[15] = (tF + state[15]);
        }
Beispiel #4
0
        public static XChaCha20 New(ReadOnlySpan <byte> key, ReadOnlySpan <byte> nonce, ulong iv)
        {
            if (nonce.Length != 24)
            {
                throw new ArgumentOutOfRangeException(actualValue: nonce.Length, message: NONCE_LENGTH_ERROR, paramName: nameof(nonce));
            }

            var derivedKey   = ComputeHash(key, nonce.Slice(0, 16));
            var derivedNonce = (Span <byte>) stackalloc byte[12];

            BinaryPrimitives.WriteUInt32BigEndian(derivedNonce, ((uint)BitwiseHelpers.ExtractHigh(iv)));
            nonce.Slice(16, 8).CopyTo(derivedNonce.Slice(4, 8));

            return(new XChaCha20(derivedKey, derivedNonce, iv));
        }
Beispiel #5
0
        public static byte[] GenerateOneTimeKey(ReadOnlySpan <byte> key, ReadOnlySpan <byte> nonce, uint numRounds)
        {
            var ivLow      = 0U;
            var ivHigh     = BinaryPrimitives.ReadUInt32LittleEndian(nonce);
            var oneTimeKey = new byte[ChaChaTransform.BlockLength];

            ChaChaTransform.WriteKeyStreamBlock(ChaCha.Initialize(key, nonce, ivLow), BitwiseHelpers.ConcatBits(ivHigh, ivLow), numRounds, oneTimeKey);

            return(oneTimeKey);
        }
Beispiel #6
0
        /// <summary>
        /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
        /// </summary>
        protected override byte[] HashFinal()
        {
            var h0 = m_h0;
            var h1 = m_h1;
            var h2 = m_h2;
            var h3 = m_h3;
            var h4 = m_h4;
            var k0 = m_k0;
            var k1 = m_k1;
            var k2 = m_k2;
            var k3 = m_k3;

            h1 += (h0 >> 26);
            h0 &= 0x3FFFFFFU;
            h2 += (h1 >> 26);
            h1 &= 0x3FFFFFFU;
            h3 += (h2 >> 26);
            h2 &= 0x3FFFFFFU;
            h4 += (h3 >> 26);
            h3 &= 0x3FFFFFFU;
            h0 += ((h4 >> 26) * 5U);
            h4 &= 0x3FFFFFFU;
            h1 += (h0 >> 26);
            h0 &= 0x3FFFFFFU;

            uint g0;
            uint g1;
            uint g2;
            uint g3;
            uint g4;
            uint x;
            uint y;

            g0  = (h0 + 5U);
            x   = (g0 >> 26);
            g0 &= 0x3FFFFFFU;
            g1  = (h1 + x);
            x   = (g1 >> 26);
            g1 &= 0x3FFFFFFU;
            g2  = (h2 + x);
            x   = (g2 >> 26);
            g2 &= 0x3FFFFFFU;
            g3  = (h3 + x);
            x   = (g3 >> 26);
            g3 &= 0x3FFFFFFU;
            g4  = ((h4 + x) - (1 << 26));

            x = ((g4 >> ((sizeof(uint) * 8) - 1)) - 1U);
            y = ~x;

            h0 = ((h0 & y) | (g0 & x));
            h1 = ((h1 & y) | (g1 & x));
            h2 = ((h2 & y) | (g2 & x));
            h3 = ((h3 & y) | (g3 & x));
            h4 = ((h4 & y) | (g4 & x));

            var f0 = BitwiseHelpers.Add(((h0) | (h1 << 26)), k0);
            var f1 = BitwiseHelpers.Add(((h1 >> 6) | (h2 << 20)), k1);
            var f2 = BitwiseHelpers.Add(((h2 >> 12) | (h3 << 14)), k2);
            var f3 = BitwiseHelpers.Add(((h3 >> 18) | (h4 << 8)), k3);

            m_h0 = ((uint)f0);
            f1  += (f0 >> 32);
            m_h1 = ((uint)f1);
            f2  += (f1 >> 32);
            m_h2 = ((uint)f2);
            f3  += (f2 >> 32);
            m_h3 = ((uint)f3);
            m_h4 = 0U;

            var result       = new byte[BlockLength];
            var resultAsUInt = MemoryMarshal.Cast <byte, uint>(result);

            resultAsUInt[0] = m_h0;
            resultAsUInt[1] = m_h1;
            resultAsUInt[2] = m_h2;
            resultAsUInt[3] = m_h3;

            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// Creates a symmetric decryptor object with the current Key property and one-time use state parameter.
        /// </summary>
        /// <param name="key">The secret that will be used during decryption.</param>
        /// <param name="nonce">The one-time use state parameter.</param>
        public override ICryptoTransform CreateDecryptor(byte[] key, byte[] nonce)
        {
            var ivLow = ((uint)BitwiseHelpers.ExtractLow(m_iv));

            return(ChaChaTransform.New(Initialize(key, nonce, ivLow), m_iv, 20U));
        }
Beispiel #8
0
 public static void SingleRound(ref uint x, ref uint y, uint z, int count)
 {
     y = BitwiseHelpers.RotateLeft((y ^ (x += z)), count);
     //((value << count) | (value >> ((-count) & ((sizeof(uint) * 8) - 1))))
 }