Example #1
0
 private void UInt32_To_LE(uint n, PinnedMemory <byte> bs, int off)
 {
     bs[off]     = (byte)(n);
     bs[off + 1] = (byte)(n >> 8);
     bs[off + 2] = (byte)(n >> 16);
     bs[off + 3] = (byte)(n >> 24);
 }
        /**
         * close the digest, producing the final digest value. The doFinal
         * call leaves the digest reset.
         * Key, salt and personal string remain.
         *
         * @param out       the array the digest is to be copied into.
         * @param outOffset the offset into the out array the digest is to start at.
         */
        public virtual void DoFinal(PinnedMemory <byte> output, int outOffset)
        {
            f0  = 0xFFFFFFFFFFFFFFFFUL;
            t0 += (ulong)_bufferPos;
            if (_bufferPos > 0 && t0 == 0)
            {
                t1++;
            }
            Compress(_buffer, 0);
            Array.Clear(_buffer, 0, _buffer.Length);// Holds eventually the key if input is null
            Array.Clear(_internalState, 0, _internalState.Length);

            for (var i = 0; i < _chainValue.Length && (i * 8 < _digestLength); i++)
            {
                var bytes = UInt64_To_LE(_chainValue[i]);

                if (i * 8 < _digestLength - 8)
                {
                    Array.Copy(bytes, 0, output.ToArray(), outOffset + i * 8, 8);
                }
                else
                {
                    Array.Copy(bytes, 0, output.ToArray(), outOffset + i * 8, _digestLength - (i * 8));
                }
            }

            Array.Clear(_chainValue, 0, _chainValue.Length);
            Reset();
        }
Example #3
0
        static void Main(string[] args)
        {
            var iv  = new byte[16];
            var key = new byte[32];

            using var provider = new RNGCryptoServiceProvider();
            provider.GetBytes(iv);
            provider.GetBytes(key);

            using var keyPin = new PinnedMemory <byte>(key, false);
            using var argon2 = new Argon2(keyPin, iv)
                  {
                      Addressing = Argon2.AddressType.DependentAddressing,
                      HashLength = 64,
                      MemoryCost = 65536,
                      Lanes      = 4,
                      Threads    = 2,
                      TimeCost   = 3
                  };

            argon2.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false),
                               0, 11); // caw caw caw in utf8

            using var hash = new PinnedMemory <byte>(new byte[argon2.GetLength()]);
            argon2.DoFinal(hash, 0);

            Console.WriteLine(BitConverter.ToString(hash.ToArray()));
        }
Example #4
0
 private void OutputLength(PinnedMemory <byte> buf, int off, int len, string msg)
 {
     if (off + len > buf.Length)
     {
         throw new Exception(msg);
     }
 }
Example #5
0
        private ulong LE_To_UInt64(PinnedMemory <byte> bs, int off)
        {
            var lo = LE_To_UInt32(bs, off);
            var hi = LE_To_UInt32(bs, off + 4);

            return(((ulong)hi << 32) | (ulong)lo);
        }
Example #6
0
        private PinnedMemory <byte> UInt64_To_LE(ulong n)
        {
            var bs = new PinnedMemory <byte>(new byte[8]);

            UInt64_To_LE(n, bs, 0);
            return(bs);
        }
        private void SetKey(PinnedMemory <byte> key)
        {
            if (key.Length != 32)
            {
                throw new ArgumentException("Poly1305 key must be 256 bits.");
            }

            // Extract r portion of key (and "clamp" the values)
            var t0 = LE_To_UInt32(key, 0);
            var t1 = LE_To_UInt32(key, 4);
            var t2 = LE_To_UInt32(key, 8);
            var t3 = LE_To_UInt32(key, 12);

            // NOTE: The masks perform the key "clamping" implicitly
            r0 = t0 & 0x03FFFFFFU;
            r1 = ((t0 >> 26) | (t1 << 6)) & 0x03FFFF03U;
            r2 = ((t1 >> 20) | (t2 << 12)) & 0x03FFC0FFU;
            r3 = ((t2 >> 14) | (t3 << 18)) & 0x03F03FFFU;
            r4 = (t3 >> 8) & 0x000FFFFFU;

            // Precompute multipliers
            s1 = r1 * 5;
            s2 = r2 * 5;
            s3 = r3 * 5;
            s4 = r4 * 5;

            k0 = LE_To_UInt32(key, BlockSize + 0);
            k1 = LE_To_UInt32(key, BlockSize + 4);
            k2 = LE_To_UInt32(key, BlockSize + 8);
            k3 = LE_To_UInt32(key, BlockSize + 12);
        }
Example #8
0
 private uint LE_To_UInt32(PinnedMemory <byte> bs, int off)
 {
     return((uint)bs[off]
            | (uint)bs[off + 1] << 8
            | (uint)bs[off + 2] << 16
            | (uint)bs[off + 3] << 24);
 }
Example #9
0
 internal static uint LE_To_UInt32(PinnedMemory <byte> bs, int off)
 {
     return(bs[off]
            | ((uint)bs[off + 1] << 8)
            | ((uint)bs[off + 2] << 16)
            | ((uint)bs[off + 3] << 24));
 }
Example #10
0
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         Value.Dispose();
         PinnedMemory.Dispose();
     }
 }
Example #11
0
 internal static void LE_To_UInt32(PinnedMemory <byte> bs, int bOff, uint[] ns, int nOff, int count)
 {
     for (var i = 0; i < count; ++i)
     {
         ns[nOff + i] = LE_To_UInt32(bs, bOff);
         bOff        += 4;
     }
 }
        /// <summary>
        /// Constructs a Poly1305 MAC.
        /// </summary>
        public Poly1305(PinnedMemory <byte> key)
        {
            _singleBytePin   = new PinnedMemory <byte>(_singleByte);
            _currentBlockPin = new PinnedMemory <byte>(_currentBlock);

            SetKey(key);
            Reset();
        }
Example #13
0
        private void SetKey(PinnedMemory <byte> key, byte[] nonce)
        {
            if (key.Length != 32)
            {
                throw new ArgumentException("Poly1305 key must be 256 bits.");
            }

            if (_dance && (nonce == null || nonce.Length != BlockSize))
            {
                throw new ArgumentException("Poly1305 requires a 128 bit IV.");
            }

            // Extract r portion of key (and "clamp" the values)
            var t0 = LE_To_UInt32(key, 0);
            var t1 = LE_To_UInt32(key, 4);
            var t2 = LE_To_UInt32(key, 8);
            var t3 = LE_To_UInt32(key, 12);

            // NOTE: The masks perform the key "clamping" implicitly
            r0 = t0 & 0x03FFFFFFU;
            r1 = ((t0 >> 26) | (t1 << 6)) & 0x03FFFF03U;
            r2 = ((t1 >> 20) | (t2 << 12)) & 0x03FFC0FFU;
            r3 = ((t2 >> 14) | (t3 << 18)) & 0x03F03FFFU;
            r4 = (t3 >> 8) & 0x000FFFFFU;

            // Precompute multipliers
            s1 = r1 * 5;
            s2 = r2 * 5;
            s3 = r3 * 5;
            s4 = r4 * 5;

            PinnedMemory <byte> kBytes;
            int kOff;

            if (!_dance)
            {
                kBytes = key.Clone();
                kOff   = BlockSize;
            }
            else
            {
                // Compute encrypted nonce with chacha20
                kBytes = key.Clone();
                kOff   = 0;

                using var cipher = new ChaCha20.NetCore.ChaCha20(kBytes, nonce);
                cipher.UpdateBlock(nonce, 0, BlockSize);
                cipher.DoFinal(kBytes, 0);
                cipher.Reset();
            }

            k0 = LE_To_UInt32(kBytes, kOff + 0);
            k1 = LE_To_UInt32(kBytes, kOff + 4);
            k2 = LE_To_UInt32(kBytes, kOff + 8);
            k3 = LE_To_UInt32(kBytes, kOff + 12);

            kBytes.Dispose();
        }
Example #14
0
        private readonly uint[] _x = new uint[StateSize]; // internal buffer

        /// <summary>
        ///     Creates a Salsa20 engine with a specific number of rounds.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        public ChaCha20(PinnedMemory <byte> key, byte[] iv, int rounds = 20)
        {
            _keyStreamPin   = new PinnedMemory <byte>(_keyStream);
            _engineStatePin = new PinnedMemory <uint>(_engineState);
            _xPin           = new PinnedMemory <uint>(_x);

            Rounds = rounds;
            SetKey(key, iv);
        }
Example #15
0
        public GlfwMouseState()
        {
            var buttonsLength = (int)(MouseButton.Last + 1);

            _mb = MemoryBlockPool.Get(sizeof(KeyEvent) * buttonsLength * 2);

            _buttons         = _mb.AllocPinnedMemory <KeyEvent>(buttonsLength);
            _previousButtons = _mb.AllocPinnedMemory <KeyEvent>(buttonsLength);
        }
Example #16
0
        /// <summary>
        /// Constructs a Poly1305 MAC with ChaCha20 cipher.
        /// </summary>
        public Poly1305ChaCha20(PinnedMemory <byte> key, byte[] salt)
        {
            _singleBytePin   = new PinnedMemory <byte>(_singleByte);
            _currentBlockPin = new PinnedMemory <byte>(_currentBlock);

            _dance = true;
            SetKey(key, salt);
            Reset();
        }
Example #17
0
        static void Main(string[] args)
        {
            // WARNING: It's unsafe to output pinned memory as a string, even using bitconverter however for the sake of learning this is done below.
            // DO NOT DO THIS IN YOUR APPLICATION, you should store your pinned data in it's native form so it will remain locked, and pinned in place
            // strings can't be pinned due to there nature, however, for example an array of char[] can be provided it's not converted back to string

            // This example shows how even if you have supplied bytes, they will be zero'd at creation. This is often the biggest mistake people make with this library.
            using (var pinZero = new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }))
            {
                Console.WriteLine(BitConverter.ToString(pinZero.ToArray()));
            }

            // This example shows how you can populate pinned memory on creation without those bytes being zero'd. They will still be zero'd on free!
            using var pin = new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false);
            Console.WriteLine(BitConverter.ToString(pin.ToArray()));
            pin.Dispose();

            // This second write should be all zero's as the memory has been freed
            Console.WriteLine(BitConverter.ToString(pin.ToArray()));

            // This example shows how even if you have supplied bytes, they will be zero'd at creation. This is often the biggest mistake people make with this library.
            PinnedMemory <byte> pinPopulated;

            using (pinPopulated = new PinnedMemory <byte>(new byte[11]))
            {
                pinPopulated[0] = 65;
                //pinPopulated.Write(0, 63);
                pinPopulated[1] = 61;
                //pinPopulated.Write(1, 61);
                pinPopulated[2] = 77;
                //pinPopulated.Write(2, 77);
                pinPopulated[3] = 20;
                //pinPopulated.Write(3, 20);
                pinPopulated[4] = 63;
                //pinPopulated.Write(4, 63);
                pinPopulated[5] = 61;
                //pinPopulated.Write(5, 61);
                pinPopulated[6] = 77;
                //pinPopulated.Write(6, 77);
                pinPopulated[7] = 20;
                //pinPopulated.Write(7, 20);
                pinPopulated[8] = 63;
                //pinPopulated.Write(8, 63);
                pinPopulated[9] = 61;
                //pinPopulated.Write(9, 61);
                pinPopulated[10] = 77;
                //pinPopulated.Write(10, 77);

                Console.WriteLine(BitConverter.ToString(pinPopulated.ToArray()));
            }

            // This is an example of using a char array.
            using var cawPin = new PinnedMemory <char>(new [] { 'c', 'a', 'w', ' ', 'c', 'a', 'w', ' ', 'c', 'a', 'w' }, false);

            // This pin will be freed when the program exits.
            Console.WriteLine(cawPin.ToArray());
        }
Example #18
0
        public void UpdateBlock(PinnedMemory <byte> value, int offset, int length)
        {
            DataLength(value, offset, length, "input buffer too short");

            var block = new byte[length];

            Array.Copy(value.ToArray(), offset, block, 0, length);
            _buffer = _buffer == null ? block : Append(_buffer, block);
        }
Example #19
0
        internal GlfwKeyboardState()
        {
            var keyEventsLength = ((int)Key.LastKey + 1);
            var size            = sizeof(KeyEvent) * keyEventsLength * 2;

            _mb = MemoryBlockPool.Get(size);

            _keyEvents         = _mb.AllocPinnedMemory <KeyEvent>(keyEventsLength);
            _previousKeyEvents = _mb.AllocPinnedMemory <KeyEvent>(keyEventsLength);
        }
Example #20
0
        public static void Poly()
        {
            using var poly = new Poly1305(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false));
            using var hash = new PinnedMemory <byte>(new byte[poly.GetLength()]);

            // digest.UpdateBlock(new byte[] {63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77}, 0, 11); // This may be exposed without being pinned.
            poly.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false), 0, 11);
            poly.DoFinal(hash, 0);

            Console.WriteLine(BitConverter.ToString(hash.ToArray()));
        }
Example #21
0
        private ulong f0 = 0UL; // finalization flag, for last block: ~0L

        // For Tree Hashing Mode, not used here:
        // private long f1 = 0L; // finalization flag, for last node: ~0L

        /**
         * Basic sized constructor - size in bits.
         *
         * @param digestSize size of the digest in bits
         */
        public Blake2b(int digestSize = 512)
        {
            if (digestSize != 160 && digestSize != 256 && digestSize != 384 && digestSize != 512)
            {
                throw new ArgumentException("Blake2b digest restricted to one of [160, 256, 384, 512]");
            }

            _buffer       = new byte[BlockLengthBytes];
            _bufferPin    = new PinnedMemory <byte>(_buffer);
            _digestLength = digestSize / 8;
            Init();
        }
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                Value.Dispose();
                PinnedMemory.Dispose();
            }
            _disposed = true;
        }
        private static void Mac()
        {
            // This is an example of hashing byte[] using PinnedMemory. This is the best method as it protects bytes during creation of the mac
            // and not just the output. It will also zero bytes after there written. However, raw byte[] is also accepted as shown in the commented version.
            var digest = new Blake2bMac(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false));

            using var exampleHash = new PinnedMemory <byte>(new byte[digest.GetLength()]);

            // digest.UpdateBlock(new byte[] {63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77}, 0, 11); // This may be exposed without being pinned.
            digest.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false),
                               0, 11);
            digest.DoFinal(exampleHash, 0);

            Console.WriteLine(BitConverter.ToString(exampleHash.ToArray()));
        }
Example #24
0
        public void DoFinal(PinnedMemory <byte> output, int outOff)
        {
            DataLength(output, outOff, BlockSize, "Output buffer is too short.");

            if (_currentBlockOffset > 0)
            {
                // Process padded block
                ProcessBlock();
            }

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

            var g0 = h0 + 5;
            var b  = g0 >> 26; g0 &= 0x3ffffff;
            var g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
            var g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
            var g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
            var g4 = h4 + b - (1 << 26);

            b = (g4 >> 31) - 1;
            var nb = ~b;

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

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

            UInt32_To_LE((uint)f0, output, outOff);
            f1 += (f0 >> 32);
            UInt32_To_LE((uint)f1, output, outOff + 4);
            f2 += (f1 >> 32);
            UInt32_To_LE((uint)f2, output, outOff + 8);
            f3 += (f2 >> 32);
            UInt32_To_LE((uint)f3, output, outOff + 12);

            Reset();
        }
Example #25
0
        public static void Mac()
        {
            var digest = new Blake2bMac(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false));

            // This is a common, but could be unsafe example of dealing with strings from a form using text encoding.
            using var exampleHash = new PinnedMemory <byte>(new byte[digest.GetLength()]);
            var unsafeCaw = "caw caw caw";                                                     // this is unsafe because string's can't be pinned and are subject to garbage collection, and being written to disk (pagefile).
            var caw       = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(unsafeCaw), false); // this is now safe but ONLY the variable caw, unsafeCaw is STILL exposed.

            unsafeCaw = string.Empty;                                                          // unsafeCaw COULD STILL exposed even tho we set it to empty because this depends on garbage collection getting around to clearing it.
            digest.UpdateBlock(caw, 0, caw.Length);
            digest.DoFinal(exampleHash, 0);

            Console.WriteLine(BitConverter.ToString(exampleHash.ToArray()));

            // This is a more uncommon but should be safer example of how to use strings with SecureString for input.
            using var exampleHash2 = new PinnedMemory <byte>(new byte[digest.GetLength()]);

            var secureCaw = new SecureString();

            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.AppendChar(' ');
            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.AppendChar(' ');
            secureCaw.AppendChar('c');
            secureCaw.AppendChar('a');
            secureCaw.AppendChar('w');
            secureCaw.MakeReadOnly();

            using var pinnedCaw = new PinnedMemory <char>(new char[secureCaw.Length]);
            var cawPointer = Marshal.SecureStringToBSTR(secureCaw);

            for (var i = 0; i <= secureCaw.Length - 1; i++)
            {
                var c = (char)Marshal.ReadByte(cawPointer, i * 2);
                pinnedCaw[i] = c;
            }

            using var pinnedCawBytes = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(pinnedCaw.ToArray()), false);
            digest.UpdateBlock(pinnedCawBytes, 0, secureCaw.Length);
            digest.DoFinal(exampleHash2, 0);
            Console.WriteLine(BitConverter.ToString(exampleHash2.ToArray()));
        }
Example #26
0
        static void Main(string[] args)
        {
            var iv  = new byte[16];
            var key = new byte[32];

            using var provider = new RNGCryptoServiceProvider();
            provider.GetBytes(iv);
            provider.GetBytes(key);

            using var keyPin = new PinnedMemory <byte>(key, false);
            using var cipher = new Poly1305ChaCha20(keyPin, iv);
            cipher.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false), 0, 11); // caw caw caw in utf8

            using var output = new PinnedMemory <byte>(new byte[cipher.GetLength()]);
            cipher.DoFinal(output, 0);

            Console.WriteLine(BitConverter.ToString(output.ToArray()));
        }
        private ulong f0 = 0UL; // finalization flag, for last block: ~0L

        // For Tree Hashing Mode, not used here:
        // private long f1 = 0L; // finalization flag, for last node: ~0L

        /**
         * Blake2b for authentication ("Prefix-MAC mode").
         * After calling the doFinal() method, the key will
         * remain to be used for further computations of
         * this instance.
         * The key can be overwritten using the clearKey() method.
         *
         * @param key A key up to 64 bytes or null
         */
        public Blake2bMac(PinnedMemory <byte> key)
        {
            _buffer    = new byte[BlockLengthBytes];
            _bufferPin = new PinnedMemory <byte>(_buffer);
            if (key != null)
            {
                _key = key;
                if (_key.Length > 64)
                {
                    throw new ArgumentException("Keys > 64 are not supported");
                }

                _keyLength = _key.Length;
                Array.Copy(_key.ToArray(), 0, _buffer, 0, _keyLength);
                _bufferPos = BlockLengthBytes; // zero padding
            }
            _digestLength = 64;
            Init();
        }
Example #28
0
        private void SetKey(PinnedMemory <byte> keyBytes, byte[] ivBytes)
        {
            if (keyBytes != null)
            {
                if (keyBytes.Length != 16 && keyBytes.Length != 32)
                {
                    throw new ArgumentException("ChaCha20 requires 128 bit or 256 bit key");
                }

                PackTauOrSigma(keyBytes.Length, _engineState, 0);

                // Key
                LE_To_UInt32(keyBytes, 0, _engineState, 4, 4);
                LE_To_UInt32(keyBytes, keyBytes.Length - 16, _engineState, 8, 4);
            }

            // IV
            LE_To_UInt32(ivBytes, 0, _engineState, 14, 2);
        }
Example #29
0
        /// <summary>
        /// Secure random number generator using Blake2b
        /// </summary>
        /// <param name="rounds">Number of rounds imposed on seeds (Default: 10)</param>
        /// <param name="seed">Auto seed by nano time, and digest size</param>
        public SecureRandom(int rounds = 10, bool seed = true)
        {
            _rounds = rounds;
            _digest = new Blake2b();

            _seed        = new PinnedMemory <byte>(new byte[_digest.GetLength()]);
            _seedCounter = 0;

            _state        = new PinnedMemory <byte>(new byte[_digest.GetLength()]);
            _stateCounter = 1;

            if (!seed)
            {
                return;
            }

            _seedCounter = 2;
            AddSeedMaterial(NextCounterValue());
            AddSeedMaterial(NextBytes(_digest.GetLength()));
        }
Example #30
0
        public void DoFinal(PinnedMemory <byte> output, int offset)
        {
            OutputLength(output, offset, _buffer.Length, "output buffer too short");

            if (LimitExceeded((uint)_buffer.Length))
            {
                throw new Exception("2^70 byte limit per IV would be exceeded; Change IV");
            }

            for (var i = 0; i < _buffer.Length; i++)
            {
                if (_index == 0)
                {
                    GenerateKeyStream(_keyStream);
                    AdvanceCounter();
                }

                output[i + offset] = (byte)(_keyStream[_index] ^ _buffer[i]);
                _index             = (_index + 1) & 63;
            }
        }