/**
         * 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();
        }
Exemple #2
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());
        }
Exemple #3
0
 private void AddSeedMaterial(byte[] inSeed)
 {
     lock (_lockObject)
     {
         _digest.UpdateBlock(inSeed, 0, inSeed.Length);
         _digest.UpdateBlock(_seed.ToArray(), 0, _seed.Length);
         _digest.DoFinal(_seed, 0);
     }
 }
Exemple #4
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()));
        }
        /**
         * Reset the digest back to it's initial state.
         * The key, the salt and the personal string will
         * remain for further computations.
         */
        public virtual void Reset()
        {
            _bufferPos  = 0;
            f0          = 0L;
            t0          = 0L;
            t1          = 0L;
            _chainValue = null;
            Array.Clear(_buffer, 0, _buffer.Length);

            if (_key != null)
            {
                Array.Copy(_key.ToArray(), 0, _buffer, 0, _key.Length);
                _bufferPos = BlockLengthBytes; // zero padding
            }
            Init();
        }
Exemple #6
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);
        }
Exemple #7
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()));
        }
Exemple #8
0
        private void GenerateState()
        {
            AddCounter(_stateCounter++);
            _digest.UpdateBlock(_state.ToArray(), 0, _state.Length);
            _digest.UpdateBlock(_seed.ToArray(), 0, _seed.Length);
            _digest.DoFinal(_state, 0);

            if ((_stateCounter % _rounds) == 0)
            {
                CycleSeed();
            }
        }
        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()));
        }
Exemple #10
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()));
        }
Exemple #11
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();
        }
 public virtual void UpdateBlock(PinnedMemory <byte> message, int offset, int len)
 {
     UpdateBlock(message.ToArray(), offset, len);
     message.Dispose();
 }
Exemple #14
0
 public void UpdateBlock(PinnedMemory <byte> value, int offset, int length)
 {
     UpdateBlock(value.ToArray(), offset, length);
     value.Dispose();
 }
 public void UpdateBlock(PinnedMemory <byte> input, int inOff, int len)
 {
     UpdateBlock(input.ToArray(), inOff, len);
     input.Dispose();
 }