Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Text;
- using BitCoin.Extensions;
- using BitCoin.Scripting;
- namespace BitCoin
- {
- public static class BTC
- {
- static string _symbols = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
- static IntPtr _bn58;
- static IntPtr _bn0;
- static IntPtr _ecKey;
- static IntPtr _ecGroup;
- static byte _testnetAddrPrefix = 0x6f;
- static byte _mainnetAddrPrefix = 0x00;
- static byte _testnetWIFPrefix = 0xef;
- static byte _mainnetWIFPrefix = 0x80;
- public static bool Testnet { get; set; }
- static BTC()
- {
- _bn58 = OpenSSL.BN_bin2bn(new byte[] { 58 }, 1, IntPtr.Zero);
- _bn0 = OpenSSL.BN_new();
- OpenSSL.BN_set_word(_bn0, 0);
- _ecKey = OpenSSL.EC_KEY_new_by_curve_name(714);
- _ecGroup = OpenSSL.EC_KEY_get0_group(_ecKey);
- Testnet = false;
- }
- public static string Base58Encode(byte[] data)
- {
- var bn = OpenSSL.BN_bin2bn(data, data.Length, IntPtr.Zero);
- var dv = OpenSSL.BN_new();
- var rem = OpenSSL.BN_new();
- List<char> result = new List<char>(34);
- while (OpenSSL.BN_cmp(bn, _bn0) != 0)
- {
- OpenSSL.BN_div(dv, rem, bn, _bn58, OpenSSL.BN_CTX);
- result.Add(_symbols[(int)OpenSSL.BN_get_word(rem)]);
- OpenSSL.BN_free(bn);
- bn = dv;
- dv = OpenSSL.BN_new();
- }
- OpenSSL.BN_free(bn);
- OpenSSL.BN_free(dv);
- OpenSSL.BN_free(rem);
- result.Reverse();
- return new string(result.ToArray());
- }
- public static byte[] Base58Decode(string str)
- {
- var bn = OpenSSL.BN_new();
- OpenSSL.BN_set_word(bn, 0);
- var mulResult = OpenSSL.BN_new();
- var symbol = OpenSSL.BN_new();
- for (int i = 0; i < str.Length; i++)
- {
- OpenSSL.BN_mul(mulResult, bn, _bn58, OpenSSL.BN_CTX);
- OpenSSL.BN_set_word(symbol, _symbols.IndexOf(str[i]));
- OpenSSL.BN_add(bn, mulResult, symbol);
- }
- var data = new byte[OpenSSL.BN_num_bytes(bn)];
- OpenSSL.BN_bn2bin(bn, data);
- OpenSSL.BN_free(bn);
- OpenSSL.BN_free(mulResult);
- OpenSSL.BN_free(symbol);
- return data;
- }
- public static string PrivateKeyToWIF(byte[] data)
- {
- if (data.Length != 32)
- throw new ArgumentException("data");
- var array = new byte[37];
- array[0] = Testnet ? _testnetWIFPrefix : _mainnetWIFPrefix;
- Array.Copy(data, 0, array, 1, data.Length);
- var hash = new byte[32];
- var sha256ctx = new OpenSSL.SHA256_CTX();
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, array, 33);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- Array.Copy(hash, 0, array, 33, 4);
- return Base58Encode(array);
- }
- public static byte[] WIFToPrivateKey(string wif)
- {
- byte[] bytes = Base58Decode(wif);
- // TODO: check not working for testnet
- /*if (bytes.Length != 37)
- throw new InvalidOperationException();*/
- if (bytes[0] != (Testnet ? _testnetWIFPrefix : _mainnetWIFPrefix))
- throw new InvalidOperationException();
- // TODO: check hash
- byte[] data = new byte[32];
- Array.Copy(bytes, 1, data, 0, 32);
- return data;
- }
- public static byte[] FromHex(string str)
- {
- if (str.Length % 2 == 1)
- throw new ArgumentException("str");
- byte[] data = new byte[str.Length / 2];
- for (int i = 0; i < data.Length; i++)
- data[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
- return data;
- }
- public static string ToHex(byte[] data)
- {
- var sb = new StringBuilder(data.Length * 2);
- for (int i = 0; i < data.Length; i++)
- sb.Append(data[i].ToString("x2"));
- return sb.ToString();
- }
- public static bool ArraysEqual(byte[] a1, byte[] a2)
- {
- if (a1.Length != a2.Length)
- return false;
- int len = a1.Length;
- for (int i = 0; i < len; i++)
- if (a1[i] != a2[i])
- return false;
- return true;
- }
- public static DateTime FromUnixTime(uint time)
- {
- return new DateTime(1970, 1, 1).AddSeconds(time);
- }
- public static uint ToUnixTime(DateTime time)
- {
- return (uint)(time - new DateTime(1970, 1, 1)).TotalSeconds;
- }
- public static byte[] PublicKeyToHash160(byte[] data)
- {
- if (data.Length != 65 && data.Length != 33)
- throw new ArgumentException("data");
- var sha2hash = new byte[32];
- var ripemdhash = new byte[20];
- var sha256ctx = new OpenSSL.SHA256_CTX();
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
- OpenSSL.SHA256_Final(sha2hash, ref sha256ctx);
- var ripemd160ctx = new OpenSSL.RIPEMD160_CTX();
- OpenSSL.RIPEMD160_Init(ref ripemd160ctx);
- OpenSSL.RIPEMD160_Update(ref ripemd160ctx, sha2hash, 32);
- OpenSSL.RIPEMD160_Final(ripemdhash, ref ripemd160ctx);
- return ripemdhash;
- }
- public static string PublicKeyToAddress(byte[] data)
- {
- byte[] hash = PublicKeyToHash160(data);
- var array = new byte[25];
- array[0] = Testnet ? _testnetAddrPrefix : _mainnetAddrPrefix;
- Array.Copy(hash, 0, array, 1, 20);
- var sha256ctx = new OpenSSL.SHA256_CTX();
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, array, 21);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- Array.Copy(hash, 0, array, 21, 4);
- int index = 0;
- string prefix = "";
- while (array[index++] == 0)
- prefix += "1";
- return prefix + Base58Encode(array);
- }
- public static byte[] AddressToHash160(string address)
- {
- var bytes = Base58Decode(address);
- var hash = new byte[20];
- if (Testnet)
- Array.Copy(bytes, 1, hash, 0, 20);
- else
- Array.Copy(bytes, 0, hash, 24 - bytes.Length, bytes.Length - 4);
- return hash;
- }
- public static string PrivateKeyToAddressUncompressed(byte[] data)
- {
- return PublicKeyToAddress(PrivateKeyToPublicKeyUncompressed(data));
- }
- public static byte[] PrivateKeyToPublicKeyUncompressed(byte[] data)
- {
- if (data.Length != 32)
- throw new ArgumentException("data");
- var ecPoint = OpenSSL.EC_POINT_new(_ecGroup);
- var privKeyBN = OpenSSL.BN_bin2bn(data, 32, IntPtr.Zero);
- OpenSSL.EC_POINT_mul(_ecGroup, ecPoint, privKeyBN, IntPtr.Zero, IntPtr.Zero, OpenSSL.BN_CTX);
- var bn = OpenSSL.EC_POINT_point2bn(_ecGroup, ecPoint,
- OpenSSL.point_conversion_form_t.POINT_CONVERSION_UNCOMPRESSED,
- OpenSSL.BN_new(), OpenSSL.BN_CTX);
- var publicKey = new byte[65];
- OpenSSL.BN_bn2bin(bn, publicKey);
- OpenSSL.EC_POINT_free(ecPoint);
- OpenSSL.BN_free(privKeyBN);
- OpenSSL.BN_free(bn);
- return publicKey;
- }
- public static string PrivateKeyToAddressCompressed(byte[] data)
- {
- return PublicKeyToAddress(PrivateKeyToPublicKeyCompressed(data));
- }
- public static byte[] PrivateKeyToPublicKeyCompressed(byte[] data)
- {
- if (data.Length != 32)
- throw new ArgumentException("data");
- var ecPoint = OpenSSL.EC_POINT_new(_ecGroup);
- var privKeyBN = OpenSSL.BN_bin2bn(data, 32, IntPtr.Zero);
- OpenSSL.EC_POINT_mul(_ecGroup, ecPoint, privKeyBN, IntPtr.Zero, IntPtr.Zero, OpenSSL.BN_CTX);
- var bn = OpenSSL.EC_POINT_point2bn(_ecGroup, ecPoint,
- OpenSSL.point_conversion_form_t.POINT_CONVERSION_COMPRESSED,
- OpenSSL.BN_new(), OpenSSL.BN_CTX);
- var publicKey = new byte[33];
- OpenSSL.BN_bn2bin(bn, publicKey);
- OpenSSL.EC_POINT_free(ecPoint);
- OpenSSL.BN_free(privKeyBN);
- OpenSSL.BN_free(bn);
- return publicKey;
- }
- public static byte[] CompressedKeyToUncompressed(byte[] data)
- {
- if (data.Length != 33)
- throw new ArgumentException("data");
- if (data[0] != 2 && data[0] != 3)
- throw new ArgumentException("data");
- GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
- IntPtr pointer = pinnedArray.AddrOfPinnedObject();
- IntPtr ecKey = OpenSSL.EC_KEY_new_by_curve_name(714);
- OpenSSL.o2i_ECPublicKey(ref ecKey, ref pointer, 33);
- pinnedArray.Free();
- OpenSSL.EC_KEY_set_conv_form(ecKey, OpenSSL.point_conversion_form_t.POINT_CONVERSION_UNCOMPRESSED);
- int size = OpenSSL.i2o_ECPublicKey(ecKey, IntPtr.Zero);
- byte[] result = new byte[size];
- pinnedArray = GCHandle.Alloc(result, GCHandleType.Pinned);
- pointer = pinnedArray.AddrOfPinnedObject();
- OpenSSL.i2o_ECPublicKey(ecKey, ref pointer);
- pinnedArray.Free();
- OpenSSL.EC_KEY_free(ecKey);
- return result;
- }
- public static byte[] DoubleSHA256(byte[] data)
- {
- var sha256ctx = new OpenSSL.SHA256_CTX();
- var hash = new byte[32];
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
- OpenSSL.SHA256_Final(hash, ref sha256ctx);
- return hash;
- }
- public static byte[] Hash160(byte[] data)
- {
- byte[] sha2hash = new byte[32];
- var sha256ctx = new OpenSSL.SHA256_CTX();
- OpenSSL.SHA256_Init(ref sha256ctx);
- OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
- OpenSSL.SHA256_Final(sha2hash, ref sha256ctx);
- byte[] ripemdhash = new byte[20];
- var ripemd160ctx = new OpenSSL.RIPEMD160_CTX();
- OpenSSL.RIPEMD160_Init(ref ripemd160ctx);
- OpenSSL.RIPEMD160_Update(ref ripemd160ctx, sha2hash, 32);
- OpenSSL.RIPEMD160_Final(ripemdhash, ref ripemd160ctx);
- return ripemdhash;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement