Ejemplo n.º 1
0
        /* CryptoNight Step 3: Bounce randomly 1,048,576 times (1<<20)
         * through the mixing scratchpad, using 524,288 iterations of the
         * following mixing function.  Each execution performs two reads
         * and writes from the mixing scratchpad.
         */
        private unsafe static void MixScratchpadV1(
            CNState cnState,
            ICryptoNight cnParams,
            byte[] scratchpad, byte[] tweak)
        {
            byte[] aArray = new byte[AES.BLOCK_SIZE];
            byte[] bArray = new byte[AES.BLOCK_SIZE * 2];
            byte[] cArray = new byte[AES.BLOCK_SIZE];

            fixed(byte *scratchpadPtr = scratchpad,
                  aByte     = aArray,
                  bByte     = bArray,
                  cByte     = cArray,
                  k         = cnState.GetK(),
                  tweakByte = tweak)
            {
                ulong lo;
                ulong hi;

                ulong *loPtr = &lo;
                ulong *p;

                ulong *a        = (ulong *)aByte;
                ulong *b        = (ulong *)bByte;
                ulong *c        = (ulong *)cByte;
                ulong *tweak1_2 = (ulong *)tweakByte;

                CryptoNight.InitMixingState(a, b, (ulong *)k);

                Vector128 <byte> _a;
                Vector128 <byte> _b = Sse2.LoadVector128(bByte);
                Vector128 <byte> _c;

                int j;

                for (int i = 0; i < cnParams.AesRounds; i++)
                {
                    /* Get our 'memory' address we're using for this round */
                    j = CryptoNight.StateIndex(*a, cnParams.ScratchModulus);

                    /* Load C from the memory address in the scratchpad */
                    _c = Sse2.LoadVector128(scratchpadPtr + j);

                    /* Reload A from the buffer */
                    _a = Sse2.LoadVector128(aByte);

                    /* Use AES to mix scratchpad into c */
                    _c = Aes.Encrypt(_c, _a);

                    /* Store C back in it's original spot */
                    Sse2.Store(cByte, _c);

                    /* XOR b and C, and store back at the 'memory' address
                     * in the scratchpad */
                    Sse2.Store(scratchpadPtr + j, Sse2.Xor(_b, _c));

                    CryptoNight.VariantOneStepOne(scratchpadPtr + j);

                    /* Get the new 'memory' address we're using for this round */
                    j = CryptoNight.StateIndex(*c, cnParams.ScratchModulus);

                    /* Grab a pointer to the spot of memory we're interested */
                    p = (ulong *)(scratchpadPtr + j);

                    /* Load b from the memory address in the scratchpad */
                    b[0] = p[0];
                    b[1] = p[1];

                    /* 64 bit multiply the low parts of C and B */
                    hi = Bmi2.X64.MultiplyNoFlags(c[0], b[0], loPtr);

                    /* Sum the result halves of the multiplication with each half of A */
                    a[0] += hi;
                    a[1] += lo;

                    /* Write the modified A back to the scratchpad */
                    p[0] = a[0];
                    p[1] = a[1];

                    /* Xor the two 64 bit halves of A and B */
                    a[0] ^= b[0];
                    a[1] ^= b[1];

                    CryptoNight.VariantOneStepTwo(p + 1, tweak1_2);

                    /* Store C in B */
                    _b = _c;
                }
            }
        }
Ejemplo n.º 2
0
        /* CryptoNight Step 3: Bounce randomly 1,048,576 times (1<<20)
         * through the mixing scratchpad, using 524,288 iterations of the
         * following mixing function.  Each execution performs two reads
         * and writes from the mixing scratchpad.
         */
        private static unsafe void MixScratchpadV1(
            CNState cnState,
            ICryptoNight cnParams,
            byte[] scratchpad,
            byte[] tweak)
        {
            byte[] aArray  = new byte[AES.BLOCK_SIZE];
            byte[] bArray  = new byte[AES.BLOCK_SIZE * 2];
            byte[] cArray  = new byte[AES.BLOCK_SIZE];
            byte[] c1Array = new byte[AES.BLOCK_SIZE];
            byte[] dArray  = new byte[AES.BLOCK_SIZE];

            fixed(byte *scratchpadPtr = scratchpad,
                  a         = aArray,
                  b         = bArray,
                  c         = cArray,
                  c1        = c1Array,
                  d         = dArray,
                  k         = cnState.GetK(),
                  tweakByte = tweak)
            {
                CryptoNight.InitMixingState((ulong *)a, (ulong *)b, (ulong *)k);

                for (int i = 0; i < cnParams.AesRounds; i++)
                {
                    /* ITERATION ONE */

                    /* Get the memory address */
                    int j = CryptoNight.StateIndex(*(ulong *)a, cnParams.ScratchModulus);

                    /* Get a pointer to the memory address in the scratchpad */
                    ulong *p = (ulong *)(scratchpadPtr + j);

                    /* Perform AES round from/to scratchpad, with A as the
                     * expanded key */
                    AES.AESBSingleRound((uint *)p, (uint *)a);

                    /* Copy a block from p to c1 */
                    CopyBlock(c1, p);

                    XORBlocks(p, (ulong *)b);

                    CryptoNight.VariantOneStepOne((byte *)p);

                    /* ITERATION TWO */

                    /* Get new memory address */
                    j = CryptoNight.StateIndex(*(ulong *)c1, cnParams.ScratchModulus);

                    /* Update pointer to scratchpad */
                    p = (ulong *)(scratchpadPtr + j);

                    /* Copy a block from p to c */
                    CopyBlock(c, p);

                    Multiply64((ulong *)c1, (ulong *)c, (ulong *)d);

                    /* Sum half blocks */
                    ((ulong *)a)[0] += ((ulong *)d)[0];
                    ((ulong *)a)[1] += ((ulong *)d)[1];

                    SwapBlocks((ulong *)a, (ulong *)c);

                    XORBlocks((ulong *)a, (ulong *)c);

                    CryptoNight.VariantOneStepTwo((ulong *)(c + 8), (ulong *)tweakByte);

                    /* Copy a block from c to p */
                    CopyBlock(p, c);

                    /* Copy a block from c1 to b */
                    CopyBlock(b, c1);
                }
            }
        }