Esempio n. 1
0
        /* CryptoNight Step 2:  Iteratively encrypt the results from Keccak
         * to fill the large scratchpad
         */
        private static byte[] FillScratchpad(CNState cnState,
                                             ICryptoNight cnParams)
        {
            /* Expand our initial key into many for each round of pseudo aes */
            byte[] expandedKeys = AES.AES.ExpandKey(cnState.GetAESKey());

            /* Our large scratchpad, 2MB in default CN */
            byte[] scratchpad = new byte[cnParams.Memory()];

            byte[] text = cnState.GetText();

            /* Fill the scratchpad with AES encryption of text */
            for (int i = 0; i < cnParams.Memory() / Constants.InitSizeByte; i++)
            {
                for (int j = 0; j < Constants.InitSizeBlock; j++)
                {
                    /* Need to pass the array with an offset because we manip
                     * it in place */
                    AES.AES.AESBPseudoRound(expandedKeys, text,
                                            j * AES.Constants.BlockSize);
                }

                /* Write text to the scratchpad, at the offset
                 * i * InitSizeByte */
                Buffer.BlockCopy(text, 0, scratchpad,
                                 i * Constants.InitSizeByte, text.Length);
            }

            return(scratchpad);
        }
Esempio n. 2
0
        /* CryptoNight Step 4: Sequentially pass through the mixing buffer
         * and use 10 rounds of AES encryption to mix the random data back
         * into the 'text' buffer.
         */
        private static void EncryptScratchpadToText(CNState cnState,
                                                    ICryptoNight cnParams,
                                                    byte[] scratchpad)
        {
            /* Reinitialize text from state */
            byte[] text = cnState.GetText();

            /* Expand our initial key into many for each round of pseudo aes */
            byte[] expandedKeys = AES.AES.ExpandKey(cnState.GetAESKey2());

            for (int i = 0; i < cnParams.Memory() / Constants.InitSizeByte; i++)
            {
                for (int j = 0; j < Constants.InitSizeBlock; j++)
                {
                    int offsetA = j * AES.Constants.BlockSize;
                    int offsetB = (i * Constants.InitSizeByte) + offsetA;

                    XORBlocks(text, scratchpad, offsetA, offsetB);

                    /* Need to pass the array with an offset because we manip
                     * it in place */
                    AES.AES.AESBPseudoRound(expandedKeys, text, offsetA);
                }
            }

            cnState.SetText(text);
        }
Esempio n. 3
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 void MixScratchpadV0(CNState cnState,
                                            ICryptoNight cnParams,
                                            byte[] scratchpad)
        {
            MixScratchpadState mixingState = new MixScratchpadState(cnState);

            for (int i = 0; i < cnParams.Iterations() / 2; i++)
            {
                for (int iteration = 1; iteration < 3; iteration++)
                {
                    /* Get our 'memory' address we're using for this round */
                    int j = E2I(mixingState.a, cnParams.Memory());

                    /* Load c from the scratchpad */
                    CopyBlockFromScratchpad(scratchpad, mixingState.c, j);

                    /* Perform the mixing function */
                    if (iteration == 1)
                    {
                        MixScratchpadIterationOne(mixingState);
                    }
                    else
                    {
                        MixScratchpadIterationTwo(mixingState);
                    }

                    /* Write c back to the scratchpad */
                    CopyBlockToScratchpad(scratchpad, mixingState.c, j);

                    SwapBlocks(ref mixingState.a, ref mixingState.b);
                }
            }
        }
Esempio n. 4
0
        private static byte[] VariantOneInit(CNState state, byte[] input)
        {
            byte[] tweak = state.GetTweak();

            XOR64(tweak, input, 0, 35);

            return(tweak);
        }
Esempio n. 5
0
        public MixScratchpadState(CNState cnState)
        {
            k = cnState.GetK();

            for (int i = 0; i < AES.Constants.BlockSize; i++)
            {
                a[i] = (byte)(k[i] ^ k[i + 32]);
                b[i] = (byte)(k[i + 16] ^ k[i + 48]);
            }
        }
Esempio n. 6
0
        private static byte[] CryptoNightV0(byte[] input, ICryptoNight cnParams)
        {
            /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state'
             * buffer, encapsulated in cnState
             */
            CNState cnState = new CNState(Keccak.Keccak.keccak1600(input));

            byte[] scratchpad = FillScratchpad(cnState, cnParams);

            MixScratchpadV0(cnState, cnParams, scratchpad);

            EncryptScratchpadToText(cnState, cnParams, scratchpad);

            return(HashFinalState(cnState));
        }
Esempio n. 7
0
        /* CryptoNight Step 5: Apply Keccak to the state again, and then
         * use the resulting data to select which of four finalizer
         * hash functions to apply to the data (Blake, Groestl, JH,
         * or Skein). Use this hash to squeeze the state array down
         * to the final 32 byte hash output.
         */
        private static byte[] HashFinalState(CNState cnState)
        {
            /* Get the state buffer as an array of ulongs rather than bytes */
            ulong[] hashState = cnState.GetHashState();

            Keccak.Keccak.keccakf(hashState, 24);

            /* Set the state buffer from the coerced hash state */
            cnState.SetHashState(hashState);

            /* Get the actual state buffer finally */
            byte[] state = cnState.GetState();

            IHashProvider p;

            /* Choose the final hashing function to use based on the value of
             * state[0] */
            switch (state[0] % 4)
            {
            case 0:
            {
                p = new Blake.Blake();
                return(p.Hash(state));
            }

            case 1:
            {
                p = new Groestl.Groestl();
                return(p.Hash(state));
            }

            case 2:
            {
                p = new JH.JH();
                return(p.Hash(state));
            }

            default:
            {
                p = new Skein.Skein();
                return(p.Hash(state));
            }
            }
        }
Esempio n. 8
0
        private static byte[] CryptoNightV1(byte[] input, ICryptoNight cnParams)
        {
            if (input.Length < 43)
            {
                throw new ArgumentException(
                          "Input to CryptoNightV1 must be at least 43 bytes!"
                          );
            }

            /* CryptoNight Step 1: Use Keccak1600 to initialize the 'state'
             * buffer, encapsulated in cnState
             */
            CNState cnState = new CNState(Keccak.Keccak.keccak1600(input));

            byte[] scratchpad = FillScratchpad(cnState, cnParams);

            byte[] tweak = VariantOneInit(cnState, input);

            MixScratchpadV1(cnState, cnParams, scratchpad, tweak);

            EncryptScratchpadToText(cnState, cnParams, scratchpad);

            return(HashFinalState(cnState));
        }