Example #1
0
        public unsafe void TestAESBSingleRound()
        {
            byte[] expandedKeys1 = HexStringToByteArray(
                "4d54c79ab1e27ae04bfe734df26877d7bab89ecbffe598f87d23bbf5ceddc04d97e893355e4d537c4066085159a5515fcfdc9a3a3fe840b61175a446ea75dfb5d7bc2a7a66a268e5e96607e813b8666b443acaff24742a3bed7feaafd78854e170c10468125e99855850588dada7a7f7baf193b754136d748fca760b20628180ece674cfbd44d22168f105d320909d933336f4ffd5afc27eaf8f02b3b289b4e5c8584b928e0ce9b62871f9feae271d4183237e03b88a53c92c549c62366c141599a9995681d612d1206a26eb1559d61f29998383cffce1178c9d1a2c1ba4e8be22b081a7802960dfa6811fe45cf77741"
                );

            byte[] input1 = HexStringToByteArray(
                "f77f10a5fb1a52a2b466751c3a858dc3"
                );

            /* Test the unsafe version */
            fixed(byte *input = input1, expandedKeys = expandedKeys1)
            {
                AES.AESBSingleRound((uint *)input, (uint *)expandedKeys);

                Assert.AreEqual <string>("d3f15e41a16af6931839a8e818cb9abd", ByteArrayToHexString(input1));
            }

            byte[] expandedKeys2 = HexStringToByteArray(
                "af7a7e743ead40cfbc04e390d359ed70f9bd891c25d72aa78f27dba3d0b2922689550342cc1c5616e234a7478551c31c12716645e5b2d4e6dadd251413f3348a221a71868bfb3f18f79cf62b154374c7d8b1ef504288b360652b8fe8a4ee8017397c38b73121778bafc7e24368dedf0c0048789395d40d1d04595bccac8d48b188e0192f7dcb2eb9a0132d2d7eb748a882b53685414cea08de50d83fdf52eba61c5cbe4b9d03e4b0aa674850b485dec2ca8bb8787f90fa9f254292a11d65825ff30d417a56d898721d507d6b1e6b66aa009cc3082ed1c451215b9e9992abba51d4f6a3655a69e43b4e65b99a415c0a75"
                );

            byte[] input2 = HexStringToByteArray(
                "f6ab72cec832b4070711b7e3b8700d6a"
                );

            fixed(byte *input = input2, expandedKeys = expandedKeys2)
            {
                AES.AESBSingleRound((uint *)input, (uint *)expandedKeys);

                Assert.AreEqual <string>("e59c503c34b319b45b66a344316cd109", ByteArrayToHexString(input2));
            }

            byte[] expandedKeys3 = HexStringToByteArray(
                "6a8fd2a6c65c036133649dab4eb09b54148512fc83f1ea9f61aaa0e260848e6320adb182e16bcae13422161f5ca9e600132aaca1be8873dbe5e641eb18412072d41bcbe74c174b4d557acf6e2aeff71f5ec94249f0e781bfd4f9b0d54172d188a17db5c4e69fa309f53a474ebb9640790296d1006f0bfaa223176e74cf4d51116e476b58e8f801e2ddc458e38abeb46ce49f19a9cb1740be0e021b691d59a221d8cd4ff700a1e301f3c8f3edd94956ff1dbacfc925b57a32ea90575548d2a0d6d8dfb8fcfa2130751f7882b984a0d1fa0e6383d1522f9dba6e84365d3236e9564f088cb6fe7b16236fbe65ef61b61eeb"
                );

            byte[] input3 = HexStringToByteArray(
                "ac2432e2f84f5f244ef7e5d977c9f19e"
                );

            fixed(byte *input = input3, expandedKeys = expandedKeys3)
            {
                AES.AESBSingleRound((uint *)input, (uint *)expandedKeys);

                Assert.AreEqual <string>("16767345c5adc04004b973481f5682c3", ByteArrayToHexString(input3));
            }
        }
        /* 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 MixScratchpadV0(
            CNState cnState,
            ICryptoNight cnParams,
            byte[] scratchpad)
        {
            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())
            {
                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);

                    /* 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);

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

                    /* Copy a block from c1 to b */
                    CopyBlock(b, c1);
                }
            }
        }
        private static unsafe void MixScratchpadV2(
            CNState cnState,
            ICryptoNight cnParams,
            byte[] scratchpad)
        {
            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(),
                  hashState = cnState.GetState())
            {
                ulong divisionResult;
                ulong sqrtResult;

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

                /* Init */
                {
                    ulong *_b = (ulong *)b;
                    ulong *w  = (ulong *)hashState;

                    _b[2] = w[8] ^ w[10];
                    _b[3] = w[9] ^ w[11];

                    divisionResult = w[12];
                    sqrtResult     = w[13];
                }

                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);

                    VariantTwoShuffleAdd(scratchpadPtr, j, (ulong *)b, (ulong *)a);

                    XORBlocks(p, (ulong *)b);

                    /* 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);

                    VariantTwoIntegerMath(
                        (ulong *)c,
                        (ulong *)c1,
                        ref divisionResult,
                        ref sqrtResult
                        );

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

                    /* Variant 2 */
                    XORBlocks((ulong *)(scratchpadPtr + (j ^ 0x10)), (ulong *)d);
                    XORBlocks((ulong *)d, (ulong *)(scratchpadPtr + (j ^ 0x20)));

                    VariantTwoShuffleAdd(scratchpadPtr, j, (ulong *)b, (ulong *)a);

                    /* 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);

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

                    /* Copy first half of b to second half */
                    CopyBlock(b + AES.BLOCK_SIZE, b);

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