Пример #1
0
        KeysFromAddress(string address, ulong prefix)
        {
            /* Split into chunks of 11 */
            List <List <char> > chunks = address.ToList().ChunkBy(11);

            List <byte> decoded = new List <byte>();

            foreach (List <char> chunk in chunks)
            {
                List <byte> decodedChunk;

                try
                {
                    /* Convert char list to string, and decode from base58 */
                    decodedChunk = new List <byte>(
                        Base58.Decode(string.Concat(chunk))
                        );
                }
                /* Contains non base58 characters */
                catch (FormatException)
                {
                    return(Either.Left <Error, PublicKeys>(
                               Error.AddressNotBase58()
                               ));
                }

                /* Only take last 8 bytes, any more in a chunk are padding
                 * from the base58 convert. Remember we pad the beginning
                 * of a chunk, so we need to take the last 8 bytes, not the
                 * first 8 bytes. */
                decoded.AddRange(decodedChunk.TakeLast(8));
            }

            byte[] expectedPrefix = PackPrefixAsByteList(prefix).ToArray();

            /* Prefix length + spend key length + view key length
             + checksum length */
            int expectedLength = expectedPrefix.Length + 32 + 32 + 4;

            if (decoded.Count != expectedLength)
            {
                return(Either.Left <Error, PublicKeys>(
                           Error.AddressWrongLength()
                           ));
            }

            byte[] actualPrefix   = new byte[expectedPrefix.Length];
            byte[] spendKeyData   = new byte[32];
            byte[] viewKeyData    = new byte[32];
            byte[] actualChecksum = new byte[4];

            int i = 0;

            for (int j = 0; j < expectedPrefix.Length; j++)
            {
                actualPrefix[j] = decoded[i++];
            }

            for (int j = 0; j < spendKeyData.Length; j++)
            {
                spendKeyData[j] = decoded[i++];
            }

            for (int j = 0; j < viewKeyData.Length; j++)
            {
                viewKeyData[j] = decoded[i++];
            }

            for (int j = 0; j < actualChecksum.Length; j++)
            {
                actualChecksum[j] = decoded[i++];
            }

            /* Sanity checking */
            for (int j = 0; j < expectedPrefix.Length; j++)
            {
                /* We already know the lengths are the same so won't go out
                 * of bounds */
                if (actualPrefix[j] != expectedPrefix[j])
                {
                    return(Either.Left <Error, PublicKeys>(
                               Error.AddressWrongPrefix()
                               ));
                }
            }

            List <byte> addressNoChecksum = new List <byte>();

            addressNoChecksum.AddRange(actualPrefix);
            addressNoChecksum.AddRange(spendKeyData);
            addressNoChecksum.AddRange(viewKeyData);

            byte[] expectedChecksum = GetAddressChecksum(addressNoChecksum);

            for (int j = 0; j < expectedChecksum.Length; j++)
            {
                if (actualChecksum[j] != expectedChecksum[j])
                {
                    return(Either.Left <Error, PublicKeys>(
                               Error.AddressWrongChecksum()
                               ));
                }
            }

            var spendKey = new PublicKey(spendKeyData);
            var viewKey  = new PublicKey(viewKeyData);

            if (!KeyOps.IsValidKey(spendKey) || !KeyOps.IsValidKey(viewKey))
            {
                return(Either.Left <Error, PublicKeys>(
                           Error.InvalidPublicKey()
                           ));
            }

            return(Either.Right <Error, PublicKeys>(
                       new PublicKeys(spendKey, viewKey)
                       ));
        }