diff --git a/BtcAddress.csproj b/BtcAddress.csproj
index 853c0be..b129049 100644
--- a/BtcAddress.csproj
+++ b/BtcAddress.csproj
@@ -63,6 +63,7 @@
+
@@ -250,7 +251,6 @@
-
PreserveNewest
diff --git a/Forms/AddressGen.Designer.cs b/Forms/AddressGen.Designer.cs
index 84908d0..90ce34f 100644
--- a/Forms/AddressGen.Designer.cs
+++ b/Forms/AddressGen.Designer.cs
@@ -226,7 +226,6 @@ partial class AddressGen {
this.lblCoinType.Size = new System.Drawing.Size(51, 13);
this.lblCoinType.TabIndex = 15;
this.lblCoinType.Text = "Coin type";
- this.lblCoinType.Visible = false;
//
// cboCoinType
//
@@ -241,7 +240,6 @@ partial class AddressGen {
this.cboCoinType.Size = new System.Drawing.Size(90, 21);
this.cboCoinType.TabIndex = 23;
this.cboCoinType.Text = "Bitcoin";
- this.cboCoinType.Visible = false;
//
// AddressGen
//
diff --git a/Forms/AddressGen.cs b/Forms/AddressGen.cs
index 12f63e6..0b1922d 100644
--- a/Forms/AddressGen.cs
+++ b/Forms/AddressGen.cs
@@ -26,7 +26,6 @@
using System.Threading;
using System.Diagnostics;
using Casascius.Bitcoin;
-using BtcAddress.Model;
namespace BtcAddress.Forms {
public partial class AddressGen : Form {
@@ -40,7 +39,7 @@ private enum GenChoices {
private GenChoices GenChoice;
- private byte ChosenAddressVersion = 0;
+ private byte ChosenAddressType = 0;
private bool Generating = false;
private bool GeneratingEnded = false;
@@ -67,8 +66,8 @@ private enum GenChoices {
txtTextInput.Text = "";
txtTextInput.Visible = (rdoDeterministicWallet.Checked || rdoEncrypted.Checked);
lblTextInput.Visible = (rdoDeterministicWallet.Checked || rdoEncrypted.Checked || rdoTwoFactor.Checked);
- cboCoinType.Visible = rdoRandomWallet.Checked;
- lblCoinType.Visible = rdoRandomWallet.Checked;
+ cboCoinType.Visible = rdoMiniKeys.Checked || rdoRandomWallet.Checked;
+ lblCoinType.Visible = rdoMiniKeys.Checked || rdoRandomWallet.Checked;
if (rdoDeterministicWallet.Checked) {
lblTextInput.Text = "Seed for deterministic generation";
@@ -158,22 +157,8 @@ private enum GenChoices {
GenChoice = GenChoices.TwoFactor;
}
- switch (cboCoinType.SelectedItem.ToString())
- {
- case "Namecoin":
- ChosenAddressVersion = AddressVersion.Namecoin;
- break;
- case "Testnet":
- ChosenAddressVersion = AddressVersion.Testnet;
- break;
- case "Litecoin":
- ChosenAddressVersion = AddressVersion.Litecoin;
- break;
- default:
- ChosenAddressVersion = AddressVersion.Bitcoin;
- break;
- }
-
+ ChosenAddressType = AddressType.ToAddressType(cboCoinType.SelectedItem.ToString());
+
timer1.Interval = 250;
timer1.Enabled = true;
Generating = true;
@@ -218,12 +203,12 @@ private enum GenChoices {
KeyCollectionItem newitem = null;
switch (GenChoice) {
case GenChoices.Minikey:
- MiniKeyPair mkp = MiniKeyPair.CreateRandom(ExtraEntropy.GetEntropy());
+ MiniKeyPair mkp = MiniKeyPair.CreateRandom(ExtraEntropy.GetEntropy(), ChosenAddressType);
string s = mkp.AddressBase58; // read the property to entice it to compute everything
newitem = new KeyCollectionItem(mkp);
break;
case GenChoices.WIF:
- KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), false, ChosenAddressVersion);
+ KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), false, ChosenAddressType);
s = kp.AddressBase58;
newitem = new KeyCollectionItem(kp);
break;
diff --git a/Forms/Form1.cs b/Forms/Form1.cs
index 3b932c9..510a1e9 100644
--- a/Forms/Form1.cs
+++ b/Forms/Form1.cs
@@ -39,7 +39,6 @@
using System.Drawing.Printing;
using Casascius.Bitcoin;
-using BtcAddress.Model;
namespace BtcAddress {
public partial class Form1 : Form {
@@ -53,12 +52,16 @@ public partial class Form1 : Form {
/// Item may represent an AddressBase, PublicKey, KeyPair, MiniKey, or an EncryptedKeyPair
///
public void DisplayKeyCollectionItem(KeyCollectionItem item) {
+ if (item != null && item.Address != null) {
+ cboCoinType.Text = AddressType.FromAddressType(item.Address.AddressType);
+ }
+
try {
ChangeFlag++;
if (item.EncryptedKeyPair != null) {
SetText(txtPrivWIF, item.EncryptedKeyPair.EncryptedPrivateKey);
// blank out any validation info of the minikey
- UpdateMinikeyDescription();
+ UpdateMinikeyDescription(item.Address.AddressType);
SetText(txtPassphrase, "");
if (item.EncryptedKeyPair.IsUnencryptedPrivateKeyAvailable()) {
SetText(txtPrivHex, item.EncryptedKeyPair.GetUnencryptedPrivateKey().PublicKeyHex);
@@ -90,7 +93,7 @@ public partial class Form1 : Form {
}
// update the label to indicate whether this is a valid minikey (or blank it out if n/a)
- UpdateMinikeyDescription();
+ UpdateMinikeyDescription(item.Address.AddressType);
if (item.Address != null) {
@@ -123,8 +126,8 @@ public partial class Form1 : Form {
}
- private void UpdateMinikeyDescription() {
- int isminikey = MiniKeyPair.IsValidMiniKey(txtMinikey.Text);
+ private void UpdateMinikeyDescription(byte addressType) {
+ int isminikey = MiniKeyPair.IsValidMiniKey(txtMinikey.Text, addressType);
if (isminikey == 1) {
lblWhyNot.Visible = false;
lblNotSafe.Visible = true;
@@ -152,7 +155,7 @@ public partial class Form1 : Form {
ChangeFlag++;
try {
SetText(txtPrivHex, RemoveSpacesIf(Util.PassphraseToPrivHex(txtMinikey.Text)));
- UpdateMinikeyDescription();
+ UpdateMinikeyDescription(0);
btnPrivHexToWIF_Click(null, null);
btnPrivToPub_Click(null, null);
@@ -304,7 +307,7 @@ public partial class Form1 : Form {
lblWhyNot.Visible = false;
SetText(txtMinikey, "");
- KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), compressToolStripMenuItem.Checked);
+ KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), compressToolStripMenuItem.Checked, AddressType.ToAddressType(cboCoinType.Text));
if (txtPassphrase.Text != "") {
SetText(txtPrivWIF, new Bip38KeyPair(kp, txtPassphrase.Text).EncryptedPrivateKey);
@@ -396,12 +399,12 @@ public partial class Form1 : Form {
private byte AddressTypeByte {
get {
- string cointype = cboCoinType.SelectedText.ToLowerInvariant();
+ string cointype = cboCoinType.Text.ToLowerInvariant();
switch (cointype) {
- case "bitcoin": return AddressVersion.Bitcoin;
- case "namecoin": return AddressVersion.Namecoin;
- case "testnet": return AddressVersion.Testnet;
- case "litecoin": return AddressVersion.Litecoin;
+ case "bitcoin": return AddressType.Bitcoin;
+ case "namecoin": return AddressType.Namecoin;
+ case "testnet": return AddressType.Testnet;
+ case "litecoin": return AddressType.Litecoin;
}
byte b = 0;
if (Byte.TryParse(cointype, out b)) return b;
diff --git a/Forms/KeyCollectionView.cs b/Forms/KeyCollectionView.cs
index 7be94fa..6cdbcde 100644
--- a/Forms/KeyCollectionView.cs
+++ b/Forms/KeyCollectionView.cs
@@ -28,7 +28,6 @@
using System.Xml.Serialization;
using System.Drawing.Printing;
using Casascius.Bitcoin;
-using BtcAddress.Model;
namespace BtcAddress.Forms {
@@ -41,23 +40,23 @@ public partial class KeyCollectionView : Form {
}
private void newBtcAddressToolStripMenuItem_Click(object sender, EventArgs e) {
- AddKey(AddressVersion.Bitcoin);
+ AddKey(AddressType.Bitcoin);
}
private void newTestnetAddressToolStripMenuItem_Click(object sender, EventArgs e) {
- AddKey(AddressVersion.Testnet);
+ AddKey(AddressType.Testnet);
}
private void newNmcAddressToolStripMenuItem_Click(object sender, EventArgs e) {
- AddKey(AddressVersion.Namecoin);
+ AddKey(AddressType.Namecoin);
}
private void newLtcAddressToolStripMenuItem_Click(object sender, EventArgs e) {
- AddKey(AddressVersion.Litecoin);
+ AddKey(AddressType.Litecoin);
}
- private void AddKey(byte addressVersion) {
- KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), false, addressVersion);
+ private void AddKey(byte addressType) {
+ KeyPair kp = KeyPair.Create(ExtraEntropy.GetEntropy(), false, addressType);
KeyCollectionItem item = new KeyCollectionItem(kp);
KeyCollection.AddItem(item);
}
diff --git a/Model/AddressVersion.cs b/Model/AddressType.cs
similarity index 52%
rename from Model/AddressVersion.cs
rename to Model/AddressType.cs
index ae2bf50..39fc7f3 100644
--- a/Model/AddressVersion.cs
+++ b/Model/AddressType.cs
@@ -19,15 +19,44 @@
using System.Linq;
using System.Text;
-namespace BtcAddress.Model
+namespace Casascius.Bitcoin
{
///
/// Class containing constant version numbers of different address types.
///
- public class AddressVersion {
+ public static class AddressType {
public const byte Bitcoin = 0;
public const byte Litecoin = 48;
public const byte Namecoin = 52;
public const byte Testnet = 111;
+
+ public static byte ToAddressType(string type) {
+ switch (type)
+ {
+ case "Namecoin":
+ return AddressType.Namecoin;
+ case "Testnet":
+ return AddressType.Testnet;
+ case "Litecoin":
+ return AddressType.Litecoin;
+ default:
+ return AddressType.Bitcoin;
+ }
+ }
+
+ public static string FromAddressType(byte addressType)
+ {
+ switch (addressType)
+ {
+ case AddressType.Namecoin:
+ return "Namecoin";
+ case AddressType.Testnet:
+ return "Testnet";
+ case AddressType.Litecoin:
+ return "Litecoin";
+ default:
+ return "Bitcoin";
+ }
+ }
}
}
diff --git a/Model/Bitcoin.cs b/Model/Bitcoin.cs
index 3f092cf..69af6ea 100644
--- a/Model/Bitcoin.cs
+++ b/Model/Bitcoin.cs
@@ -29,7 +29,6 @@
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Math.EC;
-using BtcAddress.Model;
namespace Casascius.Bitcoin {
public class Util {
@@ -321,27 +320,24 @@ public class Util {
}
- public static string PubHashToAddress(string PubHash, string AddressType) {
+ public static string PubHashToAddress(string PubHash, string addressType) {
byte[] hex = ValidateAndGetHexPublicHash(PubHash);
if (hex == null) throw new ApplicationException("Invalid public hex key");
byte[] hex2 = new byte[21];
Array.Copy(hex, 0, hex2, 1, 20);
- int cointype = AddressVersion.Bitcoin;
- if (Int32.TryParse(AddressType, out cointype) == false) cointype = AddressVersion.Bitcoin;
+ byte cointype = AddressType.Bitcoin;
+ if (byte.TryParse(addressType, out cointype) == false) cointype = AddressType.Bitcoin;
- if (AddressType == "Testnet") cointype = AddressVersion.Testnet;
- if (AddressType == "Namecoin") cointype = AddressVersion.Namecoin;
- if (AddressType == "Litecoin") cointype = AddressVersion.Litecoin;
+ if (addressType == "Testnet") cointype = AddressType.Testnet;
+ if (addressType == "Namecoin") cointype = AddressType.Namecoin;
+ if (addressType == "Litecoin") cointype = AddressType.Litecoin;
hex2[0] = (byte)(cointype & 0xff);
return ByteArrayToBase58Check(hex2);
-
-
}
public static bool PassphraseTooSimple(string passphrase) {
-
int Lowercase = 0, Uppercase = 0, Numbers = 0, Symbols = 0, Spaces = 0;
foreach (char c in passphrase.ToCharArray()) {
if (c >= 'a' && c <= 'z') {
@@ -358,14 +354,13 @@ public class Util {
}
// let mini private keys through - they won't contain words, they are nonsense characters, so their entropy is a bit better per character
- if (MiniKeyPair.IsValidMiniKey(passphrase) != 1) return false;
+ if (MiniKeyPair.IsValidMiniKey(passphrase, 0) != 1) return false;
if (passphrase.Length < 30 && (Lowercase < 10 || Uppercase < 3 || Numbers < 2 || Symbols < 2)) {
return true;
}
return false;
-
}
public static byte[] ComputeSha256(string ofwhat) {
diff --git a/Model/KeyPair.cs b/Model/KeyPair.cs
index c05fdc7..4cd794c 100644
--- a/Model/KeyPair.cs
+++ b/Model/KeyPair.cs
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Bitcoin Address Utility. If not, see http://www.gnu.org/licenses/.
-
using System;
using System.Collections.Generic;
using System.Linq;
@@ -112,7 +111,7 @@ public class KeyPair : PublicKey {
/// Create a Bitcoin address from a key represented in a string.
///
public KeyPair(string key, bool compressed=false, byte addressType=0) {
- this._addressType = addressType;
+ _addressType = addressType;
string result = constructWithKey(key, compressed);
if (result != null) throw new ArgumentException(result);
@@ -127,8 +126,8 @@ public class KeyPair : PublicKey {
hex = Util.HexStringToBytes(key, true);
if (hex == null) {
// tolerate a minikey
- if (MiniKeyPair.IsValidMiniKey(key) > 0) {
- PrivateKeyBytes = new MiniKeyPair(key).PrivateKeyBytes;
+ if (MiniKeyPair.IsValidMiniKey(key, _addressType) > 0) {
+ PrivateKeyBytes = new MiniKeyPair(key, _addressType).PrivateKeyBytes;
return null;
} else {
return "Invalid private key";
diff --git a/Model/MiniKeyPair.cs b/Model/MiniKeyPair.cs
index c431de9..4617a4b 100644
--- a/Model/MiniKeyPair.cs
+++ b/Model/MiniKeyPair.cs
@@ -32,16 +32,18 @@
namespace Casascius.Bitcoin {
public class MiniKeyPair : KeyPair {
-
- public static MiniKeyPair CreateDeterministic(string seed) {
-
- // flow:
- // 1. take SHA256 of seed to yield 32 bytes
- // 2. base58-encode those 32 bytes as though it were a regular private key. now we have 51 characters.
- // 3. remove all instances of the digit 1. (likely source of typos)
- // 4. take 29 characters starting with position 4
- // (this is to skip those first characters of a base58check-encoded private key with low entropy)
- // 5. test to see if it matches the typo check. while it does not, increment and try again.
+
+ ///
+ /// flow:
+ /// 1. take SHA256 of seed to yield 32 bytes
+ /// 2. base58-encode those 32 bytes as though it were a regular private key. now we have 51 characters.
+ /// 3. remove all instances of the digit 1. (likely source of typos)
+ /// 4. take 29 characters starting with position 4
+ /// (this is to skip those first characters of a base58check-encoded private key with low entropy)
+ /// 5. test to see if it matches the typo check. while it does not, increment and try again.
+ ///
+ ///
+ public static MiniKeyPair CreateDeterministic(string seed, byte addressType = 0) {
UTF8Encoding utf8 = new UTF8Encoding(false);
byte[] sha256ofseed = Util.ComputeSha256(seed);
@@ -51,7 +53,7 @@ public class MiniKeyPair : KeyPair {
char[] chars = keytotry.ToCharArray();
char[] charstest = (keytotry + "?").ToCharArray();
- while (Util.ComputeSha256(utf8.GetBytes(charstest))[0] != 0) {
+ while (Util.ComputeSha256(utf8.GetBytes(charstest))[0] != addressType) {
// As long as key doesn't pass typo check, increment it.
for (int i = chars.Length - 1; i >= 0; i--) {
char c = chars[i];
@@ -79,7 +81,7 @@ public class MiniKeyPair : KeyPair {
}
}
}
- return new MiniKeyPair(new String(chars));
+ return new MiniKeyPair(new String(chars), addressType);
}
///
@@ -87,7 +89,7 @@ public class MiniKeyPair : KeyPair {
/// Entropy is taken from .NET's SecureRandom, the system clock,
/// and any optionally provided salt.
///
- public static MiniKeyPair CreateRandom(string usersalt) {
+ public static MiniKeyPair CreateRandom(string usersalt, byte addressType = 0) {
if (usersalt == null) usersalt = "ok, whatever";
usersalt += DateTime.UtcNow.Ticks.ToString();
SecureRandom sr = new SecureRandom();
@@ -95,11 +97,12 @@ public class MiniKeyPair : KeyPair {
for (int i = 0; i < 64; i++) {
chars[i] = (char)(32 + (sr.NextInt() % 64));
}
- return CreateDeterministic(usersalt + new String(chars));
+ return CreateDeterministic(usersalt + new String(chars), addressType);
}
- public MiniKeyPair(string key) {
+ public MiniKeyPair(string key, byte addressType = 0) {
+ _addressType = addressType;
MiniKey = key;
}
@@ -121,7 +124,7 @@ public class MiniKeyPair : KeyPair {
if (value == null) {
PrivateKeyBytes = null;
} else {
- if (IsValidMiniKey(value) <= 0) {
+ if (IsValidMiniKey(value, _addressType) <= 0) {
throw new ApplicationException("Not a valid minikey");
}
_minikey = value;
@@ -140,13 +143,13 @@ public class MiniKeyPair : KeyPair {
/// Zero or negative indicates not a valid Mini Private Key.
/// -1 means well formed but fails typo check.
///
- public static int IsValidMiniKey(string candidate) {
+ public static int IsValidMiniKey(string candidate, byte addressType) {
if (candidate.Length != 22 && candidate.Length != 26 && candidate.Length != 30) return 0;
if (candidate.StartsWith("S") == false) return 0;
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("^S[1-9A-HJ-NP-Za-km-z]{21,29}$");
if (reg.IsMatch(candidate) == false) return 0;
byte[] ahash = Util.ComputeSha256(candidate + "?"); // first round
- if (ahash[0] == 0) return 1;
+ if ((int)ahash[0] == addressType) return 1;
// for (int ct = 0; ct < 716; ct++) ahash = sha256.ComputeHash(ahash); // second thru 717th
// if (ahash[0] == 0) return 1;
return -1;
diff --git a/Model/StringInterpreter.cs b/Model/StringInterpreter.cs
index ece5f0d..76ffcad 100644
--- a/Model/StringInterpreter.cs
+++ b/Model/StringInterpreter.cs
@@ -141,7 +141,7 @@ public class StringInterpreter {
} catch { }
}
- if (MiniKeyPair.IsValidMiniKey(what) == 1) return new MiniKeyPair(what);
+ if (MiniKeyPair.IsValidMiniKey(what, addressType) == 1) return new MiniKeyPair(what, addressType);
return null;