Created
November 23, 2018 04:39
-
-
Save Coding-Enthusiast/2aa47cb1b0f59fbc4026cdde25a04c79 to your computer and use it in GitHub Desktop.
MiniPrivateKey class from CryptoCurrency.Net library.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using CryptoCurrency.Net.Coins; | |
using CryptoCurrency.Net.Extensions; | |
using CryptoCurrency.Net.Hashing; | |
using System; | |
using System.Linq; | |
using System.Text; | |
namespace CryptoCurrency.Net.KeyPairs | |
{ | |
/// <summary> | |
/// These are keys used in some physical bitcoins. | |
/// <para/>https://en.bitcoin.it/wiki/Mini_private_key_format | |
/// </summary> | |
public class MiniPrivateKey | |
{ | |
/// <summary> | |
/// Initializes a new instance of <see cref="MiniPrivateKey"/> using the key string. | |
/// </summary> | |
/// <exception cref="ArgumentException"/> | |
/// <param name="key">Key to use (should be 22, 26, or 30 character long and start with 'S')</param> | |
public MiniPrivateKey(string key) | |
{ | |
if (!IsValid(key)) | |
{ | |
throw new ArgumentException("Invalid key."); | |
} | |
miniKey = key; | |
bytes = Encoding.UTF8.GetBytes(key); | |
} | |
private readonly byte[] bytes; | |
private readonly string miniKey; | |
private const string b58Chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | |
/// <summary> | |
/// Initializes a new instance of <see cref="MiniPrivateKey"/> with a randomly generated key. | |
/// </summary> | |
/// <remarks> | |
/// This is the way Casascius does it. | |
/// https://github.com/casascius/Bitcoin-Address-Utility/blob/e493d51e4a1da7536fc8e8aea38eeaee38abf4cb/Model/MiniKeyPair.cs#L54-L80 | |
/// </remarks> | |
/// <returns>A new random <see cref="MiniPrivateKey"/>.</returns> | |
public static MiniPrivateKey CreateRandom() | |
{ | |
// Create a random 256 bit key. It will only be used for its characters | |
PrivateKey tempKey = new PrivateKey(new Bitcoin()); | |
string b58 = 'S' + tempKey.ToWif(false, NetworkType.MainNet).Replace("1", "").Substring(4, 29); | |
char[] chars = b58.ToCharArray(); | |
char[] charstest = (b58 + "?").ToCharArray(); | |
while (HashFunctions.ComputeSha256(Encoding.UTF8.GetBytes(charstest))[0] != 0) | |
{ | |
// As long as key doesn't pass typo check, increment it. | |
for (int i = chars.Length - 1; i >= 0; i--) | |
{ | |
char c = chars[i]; | |
if (c == '9') | |
{ | |
charstest[i] = chars[i] = 'A'; | |
break; | |
} | |
else if (c == 'H') | |
{ | |
charstest[i] = chars[i] = 'J'; | |
break; | |
} | |
else if (c == 'N') | |
{ | |
charstest[i] = chars[i] = 'P'; | |
break; | |
} | |
else if (c == 'Z') | |
{ | |
charstest[i] = chars[i] = 'a'; | |
break; | |
} | |
else if (c == 'k') | |
{ | |
charstest[i] = chars[i] = 'm'; | |
break; | |
} | |
else if (c == 'z') | |
{ | |
charstest[i] = chars[i] = '2'; | |
// No break - let loop increment prior character. | |
} | |
else | |
{ | |
charstest[i] = chars[i] = ++c; | |
break; | |
} | |
} | |
} | |
return new MiniPrivateKey(new string(chars)); | |
} | |
/// <summary> | |
/// Checks a given string to see if it is a valid mini-private-key. | |
/// </summary> | |
/// <param name="key">Key string to check.</param> | |
/// <returns>True if valid, false if not.</returns> | |
public static bool IsValid(string key) | |
{ | |
if (string.IsNullOrEmpty(key)) | |
{ | |
return false; | |
} | |
if (key.Length != 22 && key.Length != 26 && key.Length != 30) | |
{ | |
return false; | |
} | |
if (!key.StartsWith("S")) | |
{ | |
return false; | |
} | |
if (!key.All(x => b58Chars.Contains(x))) | |
{ | |
return false; | |
} | |
byte[] bytes = Encoding.UTF8.GetBytes(key); | |
if (HashFunctions.ComputeSha256(bytes.AppendToEnd((byte)'?'))[0] != 0) | |
{ | |
return false; | |
} | |
return true; | |
} | |
/// <summary> | |
/// Returns the 256-bit byte sequence of this instance. | |
/// </summary> | |
/// <returns>An array of bytes.</returns> | |
public byte[] To32Bytes() | |
{ | |
return HashFunctions.ComputeSha256(bytes); | |
} | |
/// <summary> | |
/// Returns the string representation of this instance. | |
/// </summary> | |
/// <returns>The mini key string.</returns> | |
public override string ToString() | |
{ | |
return miniKey; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment