internal byte[] Initialize(byte[] password)
        {
            // initialize the lanes
            var blake2     = new HMACBlake2B(512);
            var dataStream = new LittleEndianActiveStream();

            dataStream.Expose(DegreeOfParallelism);
            dataStream.Expose(_tagLine);
            dataStream.Expose(MemorySize);
            dataStream.Expose(Iterations);
            dataStream.Expose((uint)0x13);
            dataStream.Expose((uint)Type);
            dataStream.Expose(password.Length);
            dataStream.Expose(password);
            dataStream.Expose(Salt?.Length ?? 0);
            dataStream.Expose(Salt);
            dataStream.Expose(Secret?.Length ?? 0);
            dataStream.Expose(Secret);
            dataStream.Expose(AssociatedData?.Length ?? 0);
            dataStream.Expose(AssociatedData);

            blake2.Initialize();
            var blockhash = blake2.ComputeHash(dataStream);

            dataStream.ClearBuffer();
            return(blockhash);
        }
Beispiel #2
0
        internal async Task <Argon2Lane[]> InitializeLanes(byte[] password)
        {
            var blockHash = Initialize(password);

            var lanes = new Argon2Lane[DegreeOfParallelism];

            // adjust memory size if needed so that each segment has
            // an even size
            var segmentLength = MemorySize / (lanes.Length * 4);

            MemorySize = segmentLength * 4 * lanes.Length;
            var blocksPerLane = MemorySize / lanes.Length;

            if (blocksPerLane < 4)
            {
                throw new InvalidOperationException($"Memory should be enough to provide at least 4 blocks per {nameof(DegreeOfParallelism)}");
            }

            Task[] init = new Task[lanes.Length * 2];
            for (var i = 0; i < lanes.Length; ++i)
            {
                lanes[i] = new Argon2Lane(blocksPerLane);

                int taskIndex = i * 2;
                int iClosure  = i;
                init[taskIndex] = Task.Run(() =>
                {
                    var stream = new LittleEndianActiveStream();
                    stream.Expose(blockHash);
                    stream.Expose(0);
                    stream.Expose(iClosure);

                    ModifiedBlake2.Blake2Prime(lanes[iClosure][0], stream);
                });

                init[taskIndex + 1] = Task.Run(() =>
                {
                    var stream = new LittleEndianActiveStream();
                    stream.Expose(blockHash);
                    stream.Expose(1);
                    stream.Expose(iClosure);

                    ModifiedBlake2.Blake2Prime(lanes[iClosure][1], stream);
                });
            }

            await Task.WhenAll(init).ConfigureAwait(false);

            Array.Clear(blockHash, 0, blockHash.Length);
            return(lanes);
        }
Beispiel #3
0
        private byte[] Finalize(Argon2Lane[] lanes)
        {
            XorLanes(lanes);

            var ds = new LittleEndianActiveStream();

            ds.Expose(lanes[0][lanes[0].BlockCount - 1]);

            ModifiedBlake2.Blake2Prime(lanes[0][1], ds, _tagLine);
            var result = new byte[_tagLine];
            var tmp    = MemoryMarshal.Cast <ulong, byte>(lanes[0][1].Span).Slice(0, result.Length);

            tmp.CopyTo(result);
            return(result);
        }
        private byte[] Finalize(Argon2Lane[] lanes)
        {
            XorLanes(lanes);

            var ds = new LittleEndianActiveStream();

            ds.Expose(lanes[0][lanes[0].BlockCount - 1]);

            ModifiedBlake2.Blake2Prime(lanes[0][1], ds, _tagLine);
            var result = new byte[_tagLine];

            var stream = new Argon2Memory.Stream(lanes[0][1]);

            stream.Read(result, 0, _tagLine);

            return(result);
        }
        public static void Blake2Prime(Memory <ulong> memory, LittleEndianActiveStream dataStream, int size = -1)
        {
            var hashStream = new LittleEndianActiveStream();

            if (size < 0 || size > (memory.Length * 8))
            {
                size = memory.Length * 8;
            }

            hashStream.Expose(size);
            hashStream.Expose(dataStream);


            if (size <= 64)
            {
                var blake2 = new HMACBlake2B(8 * size);
                blake2.Initialize();
                memory.Span.Blit(blake2.ComputeHash(hashStream).AsSpan().Slice(0, size), 0);
            }
            else
            {
                var blake2 = new HMACBlake2B(512);
                blake2.Initialize();

                int offset = 0;
                var chunk  = blake2.ComputeHash(hashStream);

                memory.Span.Blit(chunk.AsSpan().Slice(0, 32), offset); // copy half of the chunk
                offset += 4;
                size   -= 32;

                while (size > 64)
                {
                    blake2.Initialize();
                    chunk = blake2.ComputeHash(chunk);
                    memory.Span.Blit(chunk.AsSpan().Slice(0, 32), offset); // half again

                    offset += 4;
                    size   -= 32;
                }

                blake2 = new HMACBlake2B(size * 8);
                blake2.Initialize();
                memory.Span.Blit(blake2.ComputeHash(chunk).AsSpan().Slice(0, size), offset); // copy the rest
            }
        }