示例#1
0
        public unsafe byte[] Compress22(Span <byte> data)
        {
            fixed(byte *dPt = data)
            fixed(uint *rip_blkPt = &rip.block[0], rip_hPt = &rip.hashState[0], sh_wPt = &sha.w[0])
            {
                // Step 1: compute SHA256 of data then copy result of hash (HashState) into RIPEMD160 block
                // so we just pass RIPEMD160 block as HashState of SHA256
                sha.Init(rip_blkPt);

                sh_wPt[0]  = (uint)((dPt[0] << 24) | (dPt[1] << 16) | (dPt[2] << 8) | dPt[3]);
                sh_wPt[1]  = (uint)((dPt[4] << 24) | (dPt[5] << 16) | (dPt[6] << 8) | dPt[7]);
                sh_wPt[2]  = (uint)((dPt[8] << 24) | (dPt[9] << 16) | (dPt[10] << 8) | dPt[11]);
                sh_wPt[3]  = (uint)((dPt[12] << 24) | (dPt[13] << 16) | (dPt[14] << 8) | dPt[15]);
                sh_wPt[4]  = (uint)((dPt[16] << 24) | (dPt[17] << 16) | (dPt[18] << 8) | dPt[19]);
                sh_wPt[5]  = (uint)((dPt[20] << 24) | (dPt[21] << 16) | 0b00000000_00000000_10000000_00000000U);
                sh_wPt[6]  = 0;
                sh_wPt[7]  = 0;
                sh_wPt[8]  = 0;
                sh_wPt[9]  = 0;
                sh_wPt[10] = 0;
                sh_wPt[11] = 0;
                sh_wPt[12] = 0;
                sh_wPt[13] = 0;

                sh_wPt[14] = 0;
                sh_wPt[15] = 176; // 22*8

                sha.Compress22(rip_blkPt, sh_wPt);

                // SHA256 compression is over and the result is already inside RIPEMD160 Block
                // But SHA256 endianness is reverse of RIPEMD160, so we have to do an endian swap

                // 32 byte or 8 uint items coming from SHA256
                for (int i = 0; i < 8; i++)
                {
                    // RIPEMD160 uses little-endian while SHA256 uses big-endian
                    rip_blkPt[i] =
                        (rip_blkPt[i] >> 24) | (rip_blkPt[i] << 24) |                       // Swap byte 1 and 4
                        ((rip_blkPt[i] >> 8) & 0xff00) | ((rip_blkPt[i] << 8) & 0xff0000);  // Swap byte 2 and 3
                }
                rip_blkPt[8]  = 0b00000000_00000000_00000000_10000000U;
                rip_blkPt[14] = 256;
                // rip_blkPt[15] = 0;
                // There is no need to set other items in block (like 13, 12,...)
                // because they are not changed and they are always zero

                rip.Init(rip_hPt);
                rip.CompressBlock(rip_blkPt, rip_hPt);

                return(rip.GetBytes(rip_hPt));
            }
        }
        public unsafe void Compress22Test()
        {
            int dataLen = 22;

            byte[] data     = GetRandomBytes(dataLen);
            byte[] expected = ComputeSingleSha(data);

            using Sha256Fo sha = new Sha256Fo();
            fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0])
            {
                int dIndex = 0;

                for (int i = 0; i < 5; i++, dIndex += 4)
                {
                    wPt[i] = (uint)((data[dIndex] << 24) | (data[dIndex + 1] << 16) | (data[dIndex + 2] << 8) | data[dIndex + 3]);
                }
                wPt[5] = (uint)((data[20] << 24) | (data[21] << 16) | 0b00000000_00000000_10000000_00000000U);

                wPt[15] = (uint)dataLen * 8;
                sha.Init(hPt);
                sha.Compress22(hPt, wPt);
                byte[] actual = sha.GetBytes(hPt);

                Assert.Equal(expected, actual);
            }
        }
示例#3
0
        private static unsafe bool Loop23Hash(Sha256Fo sha, uint *wPt, uint *hPt, byte *tmp, ICompareService comparer)
        {
            // The added value below is the fixed first char('S')=0x53 shifted left 24 places
            wPt[0] = 0b01010011_00000000_00000000_00000000U | (uint)tmp[1] << 16 | (uint)tmp[2] << 8 | tmp[3];
            wPt[1] = (uint)tmp[4] << 24 | (uint)tmp[5] << 16 | (uint)tmp[6] << 8 | tmp[7];
            wPt[2] = (uint)tmp[8] << 24 | (uint)tmp[9] << 16 | (uint)tmp[10] << 8 | tmp[11];
            wPt[3] = (uint)tmp[12] << 24 | (uint)tmp[13] << 16 | (uint)tmp[14] << 8 | tmp[15];
            wPt[4] = (uint)tmp[16] << 24 | (uint)tmp[17] << 16 | (uint)tmp[18] << 8 | tmp[19];
            // The added value below is the SHA padding and the last added ? char equal to 0x3f shifted right 8 places
            wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | 0b00000000_00000000_00111111_10000000U;
            // from 6 to 14 = 0
            wPt[15] = 184; // 23 *8 = 184

            sha.Init(hPt);
            sha.Compress23(hPt, wPt);

            if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0)
            {
                // The actual key is SHA256 of 22 char key (without '?')
                // SHA working vector is already set, only the last 2 bytes ('?' and pad) and the length have to change
                wPt[5] ^= 0b00000000_00000000_10111111_10000000U;
                // from 6 to 14 (remain) = 0
                wPt[15] = 176; // 22 *8 = 176

                sha.Init(hPt);
                sha.Compress22(hPt, wPt);

                return(comparer.Compare(hPt));
            }
示例#4
0
        public static unsafe byte[] Compress22(Span <byte> data)
        {
            uint *pt = stackalloc uint[Sha256Fo.UBufferSize];

            fixed(byte *dPt = data)
            {
                // Step 1: compute SHA256 of data then copy result of hash (HashState) into RIPEMD160 block
                Sha256Fo.Init(pt);

                pt[8]  = (uint)((dPt[0] << 24) | (dPt[1] << 16) | (dPt[2] << 8) | dPt[3]);
                pt[9]  = (uint)((dPt[4] << 24) | (dPt[5] << 16) | (dPt[6] << 8) | dPt[7]);
                pt[10] = (uint)((dPt[8] << 24) | (dPt[9] << 16) | (dPt[10] << 8) | dPt[11]);
                pt[11] = (uint)((dPt[12] << 24) | (dPt[13] << 16) | (dPt[14] << 8) | dPt[15]);
                pt[12] = (uint)((dPt[16] << 24) | (dPt[17] << 16) | (dPt[18] << 8) | dPt[19]);
                pt[13] = (uint)((dPt[20] << 24) | (dPt[21] << 16) | 0b00000000_00000000_10000000_00000000U);
                pt[23] = 176; // 22*8

                Sha256Fo.Compress22(pt);

                // First 8 items (32 byte) of pt is SHA256 hashState now and has to be converted to RIPEMD160 block
                // SHA256 and RIPEMD160 use different endianness
                // RIPMED160 hashState is 20 bytes (or 5 items) and block starts from 6th item (index 5)
                // Set in reverse since each item is going to change
                pt[12] = (pt[7] >> 24) | (pt[7] << 24) | ((pt[7] >> 8) & 0xff00) | ((pt[7] << 8) & 0xff0000);
                pt[11] = (pt[6] >> 24) | (pt[6] << 24) | ((pt[6] >> 8) & 0xff00) | ((pt[6] << 8) & 0xff0000);
                pt[10] = (pt[5] >> 24) | (pt[5] << 24) | ((pt[5] >> 8) & 0xff00) | ((pt[5] << 8) & 0xff0000);
                pt[9]  = (pt[4] >> 24) | (pt[4] << 24) | ((pt[4] >> 8) & 0xff00) | ((pt[4] << 8) & 0xff0000);
                pt[8]  = (pt[3] >> 24) | (pt[3] << 24) | ((pt[3] >> 8) & 0xff00) | ((pt[3] << 8) & 0xff0000);
                pt[7]  = (pt[2] >> 24) | (pt[2] << 24) | ((pt[2] >> 8) & 0xff00) | ((pt[2] << 8) & 0xff0000);
                pt[6]  = (pt[1] >> 24) | (pt[1] << 24) | ((pt[1] >> 8) & 0xff00) | ((pt[1] << 8) & 0xff0000);
                pt[5]  = (pt[0] >> 24) | (pt[0] << 24) |                      // Swap byte 1 and 4
                         ((pt[0] >> 8) & 0xff00) | ((pt[0] << 8) & 0xff0000); // Swap byte 2 and 3
                pt[13] = 0b00000000_00000000_00000000_10000000U;
                pt[19] = 256;

                Ripemd160Fo.Init(pt);
                Ripemd160Fo.CompressBlock(pt);

                return(Ripemd160Fo.GetBytes(pt));
            }
        }
示例#5
0
        /// <summary>
        /// Returns HASH160(OP_0 | Push(HASH160(33_bytes)))
        /// </summary>
        public static unsafe byte[] Compress33_P2sh(Span <byte> data)
        {
            uint *pt = stackalloc uint[Sha256Fo.UBufferSize];

            fixed(byte *dPt = data)
            {
                pt[8]  = (uint)((dPt[0] << 24) | (dPt[1] << 16) | (dPt[2] << 8) | dPt[3]);
                pt[9]  = (uint)((dPt[4] << 24) | (dPt[5] << 16) | (dPt[6] << 8) | dPt[7]);
                pt[10] = (uint)((dPt[8] << 24) | (dPt[9] << 16) | (dPt[10] << 8) | dPt[11]);
                pt[11] = (uint)((dPt[12] << 24) | (dPt[13] << 16) | (dPt[14] << 8) | dPt[15]);
                pt[12] = (uint)((dPt[16] << 24) | (dPt[17] << 16) | (dPt[18] << 8) | dPt[19]);
                pt[13] = (uint)((dPt[20] << 24) | (dPt[21] << 16) | (dPt[22] << 8) | dPt[23]);
                pt[14] = (uint)((dPt[24] << 24) | (dPt[25] << 16) | (dPt[26] << 8) | dPt[27]);
                pt[15] = (uint)((dPt[28] << 24) | (dPt[29] << 16) | (dPt[30] << 8) | dPt[31]);
                pt[16] = (uint)((dPt[32] << 24) | 0b00000000_10000000_00000000_00000000U);
                pt[23] = 264;

                Sha256Fo.Init(pt);
                Sha256Fo.Compress33(pt);

                pt[12] = (pt[7] >> 24) | (pt[7] << 24) | ((pt[7] >> 8) & 0xff00) | ((pt[7] << 8) & 0xff0000);
                pt[11] = (pt[6] >> 24) | (pt[6] << 24) | ((pt[6] >> 8) & 0xff00) | ((pt[6] << 8) & 0xff0000);
                pt[10] = (pt[5] >> 24) | (pt[5] << 24) | ((pt[5] >> 8) & 0xff00) | ((pt[5] << 8) & 0xff0000);
                pt[9]  = (pt[4] >> 24) | (pt[4] << 24) | ((pt[4] >> 8) & 0xff00) | ((pt[4] << 8) & 0xff0000);
                pt[8]  = (pt[3] >> 24) | (pt[3] << 24) | ((pt[3] >> 8) & 0xff00) | ((pt[3] << 8) & 0xff0000);
                pt[7]  = (pt[2] >> 24) | (pt[2] << 24) | ((pt[2] >> 8) & 0xff00) | ((pt[2] << 8) & 0xff0000);
                pt[6]  = (pt[1] >> 24) | (pt[1] << 24) | ((pt[1] >> 8) & 0xff00) | ((pt[1] << 8) & 0xff0000);
                pt[5]  = (pt[0] >> 24) | (pt[0] << 24) |                      // Swap byte 1 and 4
                         ((pt[0] >> 8) & 0xff00) | ((pt[0] << 8) & 0xff0000); // Swap byte 2 and 3
                pt[13] = 0b00000000_00000000_00000000_10000000U;
                pt[14] = 0;
                pt[15] = 0;
                pt[16] = 0;
                pt[19] = 256;

                Ripemd160Fo.Init(pt);
                Ripemd160Fo.CompressBlock(pt);

                // Compute second HASH160
                pt[8] = 0x00140000U | ((pt[0] << 8) & 0xff00) | ((pt[0] >> 8) & 0xff);
                pt[9] = ((pt[0] << 8) & 0xff000000) | ((pt[0] >> 8) & 0x00ff0000) |
                        ((pt[1] << 8) & 0x0000ff00) | ((pt[1] >> 8) & 0x000000ff);
                pt[10] = ((pt[1] << 8) & 0xff000000) | ((pt[1] >> 8) & 0x00ff0000) |
                         ((pt[2] << 8) & 0x0000ff00) | ((pt[2] >> 8) & 0x000000ff);
                pt[11] = ((pt[2] << 8) & 0xff000000) | ((pt[2] >> 8) & 0x00ff0000) |
                         ((pt[3] << 8) & 0x0000ff00) | ((pt[3] >> 8) & 0x000000ff);
                pt[12] = ((pt[3] << 8) & 0xff000000) | ((pt[3] >> 8) & 0x00ff0000) |
                         ((pt[4] << 8) & 0x0000ff00) | ((pt[4] >> 8) & 0x000000ff);
                pt[13] = ((pt[4] << 8) & 0xff000000) | ((pt[4] >> 8) & 0x00ff0000) |
                         0b00000000_00000000_10000000_00000000U;
                pt[19] = 0;
                pt[23] = 176; // 22*8

                Sha256Fo.Init(pt);
                Sha256Fo.Compress22(pt);

                pt[12] = (pt[7] >> 24) | (pt[7] << 24) | ((pt[7] >> 8) & 0xff00) | ((pt[7] << 8) & 0xff0000);
                pt[11] = (pt[6] >> 24) | (pt[6] << 24) | ((pt[6] >> 8) & 0xff00) | ((pt[6] << 8) & 0xff0000);
                pt[10] = (pt[5] >> 24) | (pt[5] << 24) | ((pt[5] >> 8) & 0xff00) | ((pt[5] << 8) & 0xff0000);
                pt[9]  = (pt[4] >> 24) | (pt[4] << 24) | ((pt[4] >> 8) & 0xff00) | ((pt[4] << 8) & 0xff0000);
                pt[8]  = (pt[3] >> 24) | (pt[3] << 24) | ((pt[3] >> 8) & 0xff00) | ((pt[3] << 8) & 0xff0000);
                pt[7]  = (pt[2] >> 24) | (pt[2] << 24) | ((pt[2] >> 8) & 0xff00) | ((pt[2] << 8) & 0xff0000);
                pt[6]  = (pt[1] >> 24) | (pt[1] << 24) | ((pt[1] >> 8) & 0xff00) | ((pt[1] << 8) & 0xff0000);
                pt[5]  = (pt[0] >> 24) | (pt[0] << 24) |                      // Swap byte 1 and 4
                         ((pt[0] >> 8) & 0xff00) | ((pt[0] << 8) & 0xff0000); // Swap byte 2 and 3
                pt[13] = 0b00000000_00000000_00000000_10000000U;
                pt[14] = 0;
                pt[15] = 0;
                pt[16] = 0;
                pt[19] = 256;

                Ripemd160Fo.Init(pt);
                Ripemd160Fo.CompressBlock(pt);

                return(Ripemd160Fo.GetBytes(pt));
            }
        }
示例#6
0
        private unsafe bool Loop23()
        {
            // The actual data that is changing is 22 bytes (22 char long mini key) with a fixed starting character ('S')
            // plus an additional byte added to the end (char('?')=0x3f) during checking loop.
            // Checksum is replaced by checking if first byte of hash result is zero.
            // The actual key itself is the hash of the same 22 bytes (without '?') using a single SHA256
            // Note characters are decoded using UTF-8

            var cartesian = CartesianProduct.Create(Enumerable.Repeat(Encoding.UTF8.GetBytes(ConstantsFO.Base58Chars), missCount));

            using Sha256Fo sha = new Sha256Fo();
            bool success = false;

            byte[] temp = new byte[precomputed.Length];
            fixed(uint *hPt = &sha.hashState[0], wPt = &sha.w[0])
            fixed(byte *pre = &precomputed[0], tmp = &temp[0])
            fixed(int *mi   = &missingIndexes[0])
            {
                foreach (var item in cartesian)
                {
                    Buffer.MemoryCopy(pre, tmp, 22, 22);
                    int mis = 0;
                    foreach (var keyItem in item)
                    {
                        tmp[mi[mis]] = keyItem;
                        mis++;
                    }

                    // The added value below is the fixed first char(S)=0x53 shifted left 24 places
                    wPt[0] = 0b01010011_00000000_00000000_00000000U | (uint)tmp[1] << 16 | (uint)tmp[2] << 8 | tmp[3];
                    wPt[1] = (uint)tmp[4] << 24 | (uint)tmp[5] << 16 | (uint)tmp[6] << 8 | tmp[7];
                    wPt[2] = (uint)tmp[8] << 24 | (uint)tmp[9] << 16 | (uint)tmp[10] << 8 | tmp[11];
                    wPt[3] = (uint)tmp[12] << 24 | (uint)tmp[13] << 16 | (uint)tmp[14] << 8 | tmp[15];
                    wPt[4] = (uint)tmp[16] << 24 | (uint)tmp[17] << 16 | (uint)tmp[18] << 8 | tmp[19];
                    // The added value below is the SHA padding and the last added ? char equal to 0x3f shifted right 8 places
                    wPt[5] = (uint)tmp[20] << 24 | (uint)tmp[21] << 16 | 0b00000000_00000000_00111111_10000000U;
                    // from 6 to 14 = 0
                    wPt[15] = 184; // 23 *8 = 184

                    sha.Init(hPt);
                    sha.Compress23(hPt, wPt);

                    if ((hPt[0] & 0b11111111_00000000_00000000_00000000U) == 0)
                    {
                        // The actual key is SHA256 of 22 char key (without '?')
                        // SHA working vector is already set, only the last 2 bytes ('?' and pad) and the length have to change
                        wPt[5] ^= 0b00000000_00000000_10111111_10000000U;
                        // from 6 to 14 (remain) = 0
                        wPt[15] = 176; // 22 *8 = 176

                        sha.Init(hPt);
                        sha.Compress22(hPt, wPt);

                        if (comparer.Compare(sha.GetBytes(hPt)))
                        {
                            SetResult(item);
                            success = true;
                            break;
                        }
                    }
                }
            }

            return(success);
        }