Advertisement
Guest User

Untitled

a guest
Feb 11th, 2014
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.64 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using BitCoin.Extensions;
  7. using BitCoin.Scripting;
  8.  
  9. namespace BitCoin
  10. {
  11.     public static class BTC
  12.     {
  13.         static string _symbols = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  14.         static IntPtr _bn58;
  15.         static IntPtr _bn0;
  16.         static IntPtr _ecKey;
  17.         static IntPtr _ecGroup;
  18.  
  19.         static byte _testnetAddrPrefix = 0x6f;
  20.         static byte _mainnetAddrPrefix = 0x00;
  21.         static byte _testnetWIFPrefix = 0xef;
  22.         static byte _mainnetWIFPrefix = 0x80;
  23.  
  24.         public static bool Testnet { get; set; }
  25.  
  26.         static BTC()
  27.         {
  28.             _bn58 = OpenSSL.BN_bin2bn(new byte[] { 58 }, 1, IntPtr.Zero);
  29.             _bn0 = OpenSSL.BN_new();
  30.             OpenSSL.BN_set_word(_bn0, 0);
  31.  
  32.             _ecKey = OpenSSL.EC_KEY_new_by_curve_name(714);
  33.             _ecGroup = OpenSSL.EC_KEY_get0_group(_ecKey);
  34.  
  35.             Testnet = false;
  36.         }
  37.  
  38.         public static string Base58Encode(byte[] data)
  39.         {
  40.             var bn = OpenSSL.BN_bin2bn(data, data.Length, IntPtr.Zero);
  41.             var dv = OpenSSL.BN_new();
  42.             var rem = OpenSSL.BN_new();
  43.             List<char> result = new List<char>(34);
  44.             while (OpenSSL.BN_cmp(bn, _bn0) != 0)
  45.             {
  46.                 OpenSSL.BN_div(dv, rem, bn, _bn58, OpenSSL.BN_CTX);
  47.                 result.Add(_symbols[(int)OpenSSL.BN_get_word(rem)]);
  48.                 OpenSSL.BN_free(bn);
  49.                 bn = dv;
  50.                 dv = OpenSSL.BN_new();
  51.             }
  52.             OpenSSL.BN_free(bn);
  53.             OpenSSL.BN_free(dv);
  54.             OpenSSL.BN_free(rem);
  55.             result.Reverse();
  56.             return new string(result.ToArray());
  57.         }
  58.  
  59.         public static byte[] Base58Decode(string str)
  60.         {
  61.             var bn = OpenSSL.BN_new();
  62.             OpenSSL.BN_set_word(bn, 0);
  63.             var mulResult = OpenSSL.BN_new();
  64.             var symbol = OpenSSL.BN_new();
  65.             for (int i = 0; i < str.Length; i++)
  66.             {
  67.                 OpenSSL.BN_mul(mulResult, bn, _bn58, OpenSSL.BN_CTX);
  68.                 OpenSSL.BN_set_word(symbol, _symbols.IndexOf(str[i]));
  69.                 OpenSSL.BN_add(bn, mulResult, symbol);
  70.             }
  71.  
  72.             var data = new byte[OpenSSL.BN_num_bytes(bn)];
  73.             OpenSSL.BN_bn2bin(bn, data);
  74.  
  75.             OpenSSL.BN_free(bn);
  76.             OpenSSL.BN_free(mulResult);
  77.             OpenSSL.BN_free(symbol);
  78.  
  79.             return data;
  80.         }
  81.  
  82.         public static string PrivateKeyToWIF(byte[] data)
  83.         {
  84.             if (data.Length != 32)
  85.                 throw new ArgumentException("data");
  86.  
  87.             var array = new byte[37];
  88.             array[0] = Testnet ? _testnetWIFPrefix : _mainnetWIFPrefix;
  89.             Array.Copy(data, 0, array, 1, data.Length);
  90.  
  91.             var hash = new byte[32];
  92.  
  93.             var sha256ctx = new OpenSSL.SHA256_CTX();
  94.             OpenSSL.SHA256_Init(ref sha256ctx);
  95.             OpenSSL.SHA256_Update(ref sha256ctx, array, 33);
  96.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  97.  
  98.             OpenSSL.SHA256_Init(ref sha256ctx);
  99.             OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
  100.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  101.  
  102.             Array.Copy(hash, 0, array, 33, 4);
  103.  
  104.             return Base58Encode(array);
  105.         }
  106.  
  107.         public static byte[] WIFToPrivateKey(string wif)
  108.         {
  109.             byte[] bytes = Base58Decode(wif);
  110.             // TODO: check not working for testnet
  111.             /*if (bytes.Length != 37)
  112.                 throw new InvalidOperationException();*/
  113.             if (bytes[0] != (Testnet ? _testnetWIFPrefix : _mainnetWIFPrefix))
  114.                 throw new InvalidOperationException();
  115.             // TODO: check hash
  116.             byte[] data = new byte[32];
  117.             Array.Copy(bytes, 1, data, 0, 32);
  118.             return data;
  119.         }
  120.  
  121.         public static byte[] FromHex(string str)
  122.         {
  123.             if (str.Length % 2 == 1)
  124.                 throw new ArgumentException("str");
  125.             byte[] data = new byte[str.Length / 2];
  126.             for (int i = 0; i < data.Length; i++)
  127.                 data[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
  128.             return data;
  129.         }
  130.  
  131.         public static string ToHex(byte[] data)
  132.         {
  133.             var sb = new StringBuilder(data.Length * 2);
  134.             for (int i = 0; i < data.Length; i++)
  135.                 sb.Append(data[i].ToString("x2"));
  136.             return sb.ToString();
  137.         }
  138.  
  139.         public static bool ArraysEqual(byte[] a1, byte[] a2)
  140.         {
  141.             if (a1.Length != a2.Length)
  142.                 return false;
  143.             int len = a1.Length;
  144.             for (int i = 0; i < len; i++)
  145.                 if (a1[i] != a2[i])
  146.                     return false;
  147.             return true;
  148.         }
  149.  
  150.         public static DateTime FromUnixTime(uint time)
  151.         {
  152.             return new DateTime(1970, 1, 1).AddSeconds(time);
  153.         }
  154.  
  155.         public static uint ToUnixTime(DateTime time)
  156.         {
  157.             return (uint)(time - new DateTime(1970, 1, 1)).TotalSeconds;
  158.         }
  159.  
  160.         public static byte[] PublicKeyToHash160(byte[] data)
  161.         {
  162.             if (data.Length != 65 && data.Length != 33)
  163.                 throw new ArgumentException("data");
  164.  
  165.             var sha2hash = new byte[32];
  166.             var ripemdhash = new byte[20];
  167.  
  168.             var sha256ctx = new OpenSSL.SHA256_CTX();
  169.             OpenSSL.SHA256_Init(ref sha256ctx);
  170.             OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
  171.             OpenSSL.SHA256_Final(sha2hash, ref sha256ctx);
  172.             var ripemd160ctx = new OpenSSL.RIPEMD160_CTX();
  173.             OpenSSL.RIPEMD160_Init(ref ripemd160ctx);
  174.             OpenSSL.RIPEMD160_Update(ref ripemd160ctx, sha2hash, 32);
  175.             OpenSSL.RIPEMD160_Final(ripemdhash, ref ripemd160ctx);
  176.  
  177.             return ripemdhash;
  178.         }
  179.  
  180.         public static string PublicKeyToAddress(byte[] data)
  181.         {
  182.             byte[] hash = PublicKeyToHash160(data);
  183.  
  184.             var array = new byte[25];
  185.             array[0] = Testnet ? _testnetAddrPrefix : _mainnetAddrPrefix;
  186.             Array.Copy(hash, 0, array, 1, 20);
  187.  
  188.             var sha256ctx = new OpenSSL.SHA256_CTX();
  189.             OpenSSL.SHA256_Init(ref sha256ctx);
  190.             OpenSSL.SHA256_Update(ref sha256ctx, array, 21);
  191.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  192.  
  193.             OpenSSL.SHA256_Init(ref sha256ctx);
  194.             OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
  195.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  196.  
  197.             Array.Copy(hash, 0, array, 21, 4);
  198.  
  199.             int index = 0;
  200.             string prefix = "";
  201.             while (array[index++] == 0)
  202.                 prefix += "1";
  203.  
  204.             return prefix + Base58Encode(array);
  205.         }
  206.  
  207.         public static byte[] AddressToHash160(string address)
  208.         {
  209.             var bytes = Base58Decode(address);
  210.             var hash = new byte[20];
  211.             if (Testnet)
  212.                 Array.Copy(bytes, 1, hash, 0, 20);
  213.             else
  214.                 Array.Copy(bytes, 0, hash, 24 - bytes.Length, bytes.Length - 4);
  215.             return hash;
  216.         }
  217.  
  218.         public static string PrivateKeyToAddressUncompressed(byte[] data)
  219.         {
  220.             return PublicKeyToAddress(PrivateKeyToPublicKeyUncompressed(data));
  221.         }
  222.  
  223.         public static byte[] PrivateKeyToPublicKeyUncompressed(byte[] data)
  224.         {
  225.             if (data.Length != 32)
  226.                 throw new ArgumentException("data");
  227.  
  228.             var ecPoint = OpenSSL.EC_POINT_new(_ecGroup);
  229.             var privKeyBN = OpenSSL.BN_bin2bn(data, 32, IntPtr.Zero);
  230.             OpenSSL.EC_POINT_mul(_ecGroup, ecPoint, privKeyBN, IntPtr.Zero, IntPtr.Zero, OpenSSL.BN_CTX);
  231.             var bn = OpenSSL.EC_POINT_point2bn(_ecGroup, ecPoint,
  232.                 OpenSSL.point_conversion_form_t.POINT_CONVERSION_UNCOMPRESSED,
  233.                 OpenSSL.BN_new(), OpenSSL.BN_CTX);
  234.  
  235.             var publicKey = new byte[65];
  236.             OpenSSL.BN_bn2bin(bn, publicKey);
  237.  
  238.             OpenSSL.EC_POINT_free(ecPoint);
  239.             OpenSSL.BN_free(privKeyBN);
  240.             OpenSSL.BN_free(bn);
  241.  
  242.             return publicKey;
  243.         }
  244.  
  245.         public static string PrivateKeyToAddressCompressed(byte[] data)
  246.         {
  247.             return PublicKeyToAddress(PrivateKeyToPublicKeyCompressed(data));
  248.         }
  249.  
  250.         public static byte[] PrivateKeyToPublicKeyCompressed(byte[] data)
  251.         {
  252.             if (data.Length != 32)
  253.                 throw new ArgumentException("data");
  254.  
  255.             var ecPoint = OpenSSL.EC_POINT_new(_ecGroup);
  256.             var privKeyBN = OpenSSL.BN_bin2bn(data, 32, IntPtr.Zero);
  257.             OpenSSL.EC_POINT_mul(_ecGroup, ecPoint, privKeyBN, IntPtr.Zero, IntPtr.Zero, OpenSSL.BN_CTX);
  258.             var bn = OpenSSL.EC_POINT_point2bn(_ecGroup, ecPoint,
  259.                 OpenSSL.point_conversion_form_t.POINT_CONVERSION_COMPRESSED,
  260.                 OpenSSL.BN_new(), OpenSSL.BN_CTX);
  261.  
  262.             var publicKey = new byte[33];
  263.             OpenSSL.BN_bn2bin(bn, publicKey);
  264.  
  265.             OpenSSL.EC_POINT_free(ecPoint);
  266.             OpenSSL.BN_free(privKeyBN);
  267.             OpenSSL.BN_free(bn);
  268.  
  269.             return publicKey;
  270.         }
  271.  
  272.         public static byte[] CompressedKeyToUncompressed(byte[] data)
  273.         {
  274.             if (data.Length != 33)
  275.                 throw new ArgumentException("data");
  276.             if (data[0] != 2 && data[0] != 3)
  277.                 throw new ArgumentException("data");
  278.  
  279.             GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
  280.             IntPtr pointer = pinnedArray.AddrOfPinnedObject();
  281.             IntPtr ecKey = OpenSSL.EC_KEY_new_by_curve_name(714);
  282.             OpenSSL.o2i_ECPublicKey(ref ecKey, ref pointer, 33);
  283.             pinnedArray.Free();
  284.  
  285.             OpenSSL.EC_KEY_set_conv_form(ecKey, OpenSSL.point_conversion_form_t.POINT_CONVERSION_UNCOMPRESSED);
  286.  
  287.             int size = OpenSSL.i2o_ECPublicKey(ecKey, IntPtr.Zero);
  288.             byte[] result = new byte[size];
  289.             pinnedArray = GCHandle.Alloc(result, GCHandleType.Pinned);
  290.             pointer = pinnedArray.AddrOfPinnedObject();
  291.             OpenSSL.i2o_ECPublicKey(ecKey, ref pointer);
  292.             pinnedArray.Free();
  293.  
  294.             OpenSSL.EC_KEY_free(ecKey);
  295.  
  296.             return result;
  297.         }
  298.  
  299.         public static byte[] DoubleSHA256(byte[] data)
  300.         {
  301.             var sha256ctx = new OpenSSL.SHA256_CTX();
  302.             var hash = new byte[32];
  303.  
  304.             OpenSSL.SHA256_Init(ref sha256ctx);
  305.             OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
  306.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  307.  
  308.             OpenSSL.SHA256_Init(ref sha256ctx);
  309.             OpenSSL.SHA256_Update(ref sha256ctx, hash, 32);
  310.             OpenSSL.SHA256_Final(hash, ref sha256ctx);
  311.  
  312.             return hash;
  313.         }
  314.  
  315.         public static byte[] Hash160(byte[] data)
  316.         {
  317.             byte[] sha2hash = new byte[32];
  318.             var sha256ctx = new OpenSSL.SHA256_CTX();
  319.             OpenSSL.SHA256_Init(ref sha256ctx);
  320.             OpenSSL.SHA256_Update(ref sha256ctx, data, data.Length);
  321.             OpenSSL.SHA256_Final(sha2hash, ref sha256ctx);
  322.  
  323.             byte[] ripemdhash = new byte[20];
  324.             var ripemd160ctx = new OpenSSL.RIPEMD160_CTX();
  325.             OpenSSL.RIPEMD160_Init(ref ripemd160ctx);
  326.             OpenSSL.RIPEMD160_Update(ref ripemd160ctx, sha2hash, 32);
  327.             OpenSSL.RIPEMD160_Final(ripemdhash, ref ripemd160ctx);
  328.  
  329.             return ripemdhash;
  330.         }
  331.     }
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement