Beispiel #1
0
        private static double GetSolveAttemptsPerSecond(byte[] payload, EstimationAccuracy accuracy)
        {
            CashPack pack = Packer.Pack(payload, (ushort)(payload.Length * 8));

            Stopwatch watch = new Stopwatch();

            int decrypts = 0;

            watch.Start();

            byte[] currentKey = new byte[pack.Key.Length];
            Array.Copy(pack.Key, 0, currentKey, 0, pack.Key.Length);

            byte[] solveWorkspace = new byte[pack.Payload.Length];

            while (watch.ElapsedMilliseconds < ((uint)accuracy * 1000))
            {
                for (int i = 0; i < pack.Payload.Length; i++)
                {
                    solveWorkspace[i] = (byte)(pack.Payload[i] ^ currentKey[i]);
                }

                // IMPORTANT: Use HMAC instead of Checksum
                // This prevents you to do attacks where you can correlate known payloads
                // And a CashPack without ever solving it.
                using (HMACSHA512 sha = new HMACSHA512(currentKey))
                {
                    byte[] hash = sha.ComputeHash(solveWorkspace);

                    for (int i = 0; i < pack.Hash.Length; i++)
                    {
                        if (pack.Hash[i] != hash[i])
                        {
                            break;
                        }
                    }
                }

                // Increment key
                ulong keyAsNumber = BitHelper.KeyToNumber(currentKey, pack.BitDifficulty);
                BitHelper.SetLastBitNumberBytes(currentKey, keyAsNumber + 1, pack.BitDifficulty);

                decrypts++;
            }

            watch.Stop();

            return(decrypts / (watch.ElapsedMilliseconds / 1000d));
        }
Beispiel #2
0
        /// <summary>
        /// Gets the number of bits difficulty required to get an average solve time for a specific payload on the current hardware.
        /// </summary>
        /// <param name="payload">The payload to attempt on.</param>
        /// <param name="span">The average solve time.</param>
        /// <param name="accuracy">The accuracy to use to estimate the processor speed.</param>
        /// <param name="solveThreads">The amount of simultaneous solvers to account for.</param>
        /// <returns>The amount of bits required to be omitted.</returns>
        public static ushort GetBitsForPayloadDecodeTime(byte[] payload, TimeSpan span, EstimationAccuracy accuracy = EstimationAccuracy.Normal, uint solveThreads = 1)
        {
            double decryptsPerSecond = GetSolveAttemptsPerSecond(payload, accuracy) * solveThreads;

            double iterationsRequired = (decryptsPerSecond * span.TotalSeconds);

            ulong currentClosestDifference = ulong.MaxValue;

            for (ushort i = 0; i < ushort.MaxValue; i++)
            {
                ulong howManyIterationsWeAreOff = ((ulong)Math.Round(iterationsRequired) - (ulong)Math.Pow(2, i));

                if (howManyIterationsWeAreOff < currentClosestDifference)
                {
                    currentClosestDifference = howManyIterationsWeAreOff;
                }
                else
                {
                    // DONT use (i - 1) here, because we want to actually have one binary bit more, which doubles the complexity. Since the average solve time is in the middle.
                    return(i);
                }
            }

            return(ushort.MaxValue);
        }