private void GenerateAddresses(Position position, ulong[] pseudoRands)
        {
            var buf          = new ulong[QwordsInBlock * 4];
            var zeroBlock    = new BlockValues(buf, 0);
            var inputBlock   = new BlockValues(buf, 1);
            var addressBlock = new BlockValues(buf, 2);
            var tmpBlock     = new BlockValues(buf, 3);

            inputBlock[0] = (ulong)position.Pass;
            inputBlock[1] = (ulong)position.Lane;
            inputBlock[2] = (ulong)position.Slice;
            inputBlock[3] = (ulong)this.MemoryBlockCount;
            inputBlock[4] = (ulong)this.config.TimeCost;
            inputBlock[5] = (ulong)this.config.Type;
            for (int i = 0; i < this.SegmentLength; ++i)
            {
                if (i % QwordsInBlock == 0)
                {
                    inputBlock[6] += 1;
                    tmpBlock.Init(0);
                    addressBlock.Init(0);
                    FillBlockWithXor(zeroBlock, inputBlock, tmpBlock);
                    FillBlockWithXor(zeroBlock, tmpBlock, addressBlock);
                }

                pseudoRands[i] = addressBlock[i % QwordsInBlock];
            }
        }
 /// <summary>
 /// XOR <paramref name="other"/> with this and store the result into this.
 /// </summary>
 /// <param name="other">
 /// The <see cref="BlockValues"/> to XOR.
 /// </param>
 public void Xor(BlockValues other)
 {
     for (int i = 0; i < Argon2.QwordsInBlock; ++i)
     {
         this[i] ^= other[i];
     }
 }
Example #3
0
        private void FillSegment(Position position)
        {
            bool dataIndependentAddressing = this.config.Type == Argon2Type.DataIndependentAddressing ||
                                             (this.config.Type == Argon2Type.HybridAddressing && position.Pass == 0 &&
                                              position.Slice < SyncPoints / 2);
            var pseudoRands = new ulong[this.SegmentLength];

            if (dataIndependentAddressing)
            {
                this.GenerateAddresses(position, pseudoRands);
            }

            // 2 if already generated the first two blocks
            int startingIndex = position.Pass == 0 && position.Slice == 0 ? 2 : 0;
            int curOffset     = (position.Lane * this.LaneLength) + (position.Slice * this.SegmentLength) + startingIndex;
            int prevOffset    = curOffset % this.LaneLength == 0 ? curOffset + this.LaneLength - 1 : curOffset - 1;

            for (int i = startingIndex; i < this.SegmentLength; ++i, ++curOffset, ++prevOffset)
            {
                if (curOffset % this.LaneLength == 1)
                {
                    prevOffset = curOffset - 1;
                }

                // compute index of reference block taking pseudo-random value from previous block
                ulong pseudoRand = dataIndependentAddressing ? pseudoRands[i] : this.Memory[prevOffset][0];

                // cannot reference other lanes until pass or slice are not zero
                int refLane =
                    (position.Pass == 0 && position.Slice == 0)
                    ? position.Lane
                    : (int)((uint)(pseudoRand >> 32) % (uint)this.config.Lanes);

                // compute possible number of reference blocks in lane
                position.Index = i;
                int refIndex = this.IndexAlpha(position, (uint)pseudoRand, refLane == position.Lane);

                BlockValues refBlock = this.Memory[(this.LaneLength * refLane) + refIndex];
                BlockValues curBlock = this.Memory[curOffset];
                if (this.config.Version == Argon2Version.Sixteen)
                {
                    // version 1.2.1 and earlier: overwrite, not XOR
                    FillBlock(this.Memory[prevOffset], refBlock, curBlock);
                }
                else if (position.Pass == 0)
                {
                    FillBlock(this.Memory[prevOffset], refBlock, curBlock);
                }
                else
                {
                    FillBlockWithXor(this.Memory[prevOffset], refBlock, curBlock);
                }
            }
        }
        private SecureArray <byte> Final()
        {
            using (var blockhashBuffer = BestSecureArray <ulong>(BlockSize / 8))
            {
                var blockhash = new BlockValues(blockhashBuffer.Buffer, 0);
                blockhash.Copy(this.Memory[this.LaneLength - 1]);

                // XOR last blocks
                for (int l = 1; l < this.config.Lanes; ++l)
                {
                    blockhash.Xor(this.Memory[(l * this.LaneLength) + (this.LaneLength - 1)]);
                }

                using (var blockhashBytes = BestSecureArray <byte>(BlockSize))
                {
                    StoreBlock(blockhashBytes.Buffer, blockhash);
                    var ret = BestSecureArray <byte>(this.config.HashLength);
                    Blake2BLong(ret.Buffer, blockhashBytes.Buffer);
                    PrintTag(ret.Buffer);
                    return(ret);
                }
            }
        }
 /// <summary>
 /// Copy <paramref name="other"/> into this.
 /// </summary>
 /// <param name="other">
 /// The <see cref="BlockValues"/> to copy.
 /// </param>
 public void Copy(BlockValues other)
 {
     Array.Copy(other.memory, other.offset, this.memory, this.offset, Argon2.QwordsInBlock);
 }