public static string AddressFromKeys(PrivateKey privateSpendKey, PrivateKey privateViewKey) { PublicKey publicSpendKey = KeyOps.PrivateKeyToPublicKey(privateSpendKey); PublicKey publicViewKey = KeyOps.PrivateKeyToPublicKey(privateViewKey); return(AddressFromKeys(publicSpendKey, publicViewKey)); }
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) )); }