/// <summary>
        /// Code which is actually run on the generation thread.
        /// </summary>
        private void GenerationThreadProcess()
        {
            Bip38Intermediate intermediate = null;

            if (GenChoice == GenChoices.Encrypted)
            {
                intermediate = new Bip38Intermediate(UserText, Bip38Intermediate.Interpretation.Passphrase);
            }

            int detcount = 1;

            while (RemainingToGenerate > 0 && StopRequested == false)
            {
                KeyCollectionItem newitem = null;
                switch (GenChoice)
                {
                case GenChoices.Minikey:
                    MiniKeyPair mkp = MiniKeyPair.CreateRandom(ExtraEntropy.GetEntropy());
                    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());
                    s       = kp.AddressBase58;
                    newitem = new KeyCollectionItem(kp);
                    break;

                case GenChoices.Deterministic:
                    kp = KeyPair.CreateFromString(UserText + detcount);
                    detcount++;
                    s       = kp.AddressBase58;
                    newitem = new KeyCollectionItem(kp);
                    break;

                case GenChoices.Encrypted:
                    Bip38KeyPair ekp = new Bip38KeyPair(intermediate);
                    newitem = new KeyCollectionItem(ekp);
                    break;

                case GenChoices.TwoFactor:
                    ekp = new Bip38KeyPair(intermediatesForGeneration[intermediateIdx++]);
                    if (intermediateIdx >= intermediatesForGeneration.Length)
                    {
                        intermediateIdx = 0;
                    }
                    newitem = new KeyCollectionItem(ekp);
                    break;
                }

                lock (GeneratedItems) {
                    GeneratedItems.Add(newitem);
                    RemainingToGenerate--;
                }
            }
            GeneratingEnded = true;
        }
コード例 #2
0
        private void btnEncode_Click(object sender, EventArgs e)
        {
            if ((txtPassphrase.Text ?? "") == "") {
                MessageBox.Show("Enter a passphrase first.");
                return;
            }

            try {
                Bip38Intermediate intermediate = new Bip38Intermediate(txtPassphrase.Text, Bip38Intermediate.Interpretation.Passphrase);
                txtPassphraseCode.Text = intermediate.Code;
            } catch (Exception ae) {
                MessageBox.Show(ae.Message);
            }
        }
コード例 #3
0
        private void btnEncode_Click(object sender, EventArgs e)
        {
            if ((txtPassphrase.Text ?? "") == "")
            {
                MessageBox.Show("Enter a passphrase first.");
                return;
            }

            try {
                Bip38Intermediate intermediate = new Bip38Intermediate(txtPassphrase.Text, Bip38Intermediate.Interpretation.Passphrase);
                txtPassphraseCode.Text = intermediate.Code;
            } catch (Exception ae) {
                MessageBox.Show(ae.Message);
            }
        }
コード例 #4
0
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            lblAddressHeader.Visible = false;
            lblAddressItself.Visible = false;
            lblResult.Visible        = false;


            // check for null entry
            if (txtPassphrase.Text == "")
            {
                MessageBox.Show("Passphrase is required.", "Passphrase required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            if (txtConfCode.Text == "")
            {
                MessageBox.Show("Confirmation code is required.", "Confirmation code required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            // Parse confirmation code.
            byte[] confbytes = Util.Base58CheckToByteArray(txtConfCode.Text.Trim());
            if (confbytes == null)
            {
                // is it even close?
                if (txtConfCode.Text.StartsWith("cfrm38"))
                {
                    MessageBox.Show("This is not a valid confirmation code.  It has the right prefix, but " +
                                    "doesn't contain valid confirmation data.  Possible typo or incomplete?",
                                    "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                MessageBox.Show("This is not a valid confirmation code.", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            if (confbytes.Length != 51 || confbytes[0] != 0x64 || confbytes[1] != 0x3B || confbytes[2] != 0xF6 ||
                confbytes[3] != 0xA8 || confbytes[4] != 0x9A || confbytes[18] < 0x02 || confbytes[18] > 0x03)
            {
                // Unrecognized Base58 object.  Do we know what this is?  Tell the user.
                object result = StringInterpreter.Interpret(txtConfCode.Text.Trim());
                if (result != null)
                {
                    // did we actually get an encrypted private key?  if so, just try to decrypt it.
                    if (result is PassphraseKeyPair)
                    {
                        PassphraseKeyPair ppkp = result as PassphraseKeyPair;
                        if (ppkp.DecryptWithPassphrase(txtPassphrase.Text))
                        {
                            confirmIsValid(ppkp.GetAddress().AddressBase58);
                            MessageBox.Show("What you provided contains a private key, not just a confirmation. " +
                                            "Confirmation is successful, and with this correct passphrase, " +
                                            "you are also able to spend the funds from the address.", "This is actually a private key",
                                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                            return;
                        }
                        else
                        {
                            MessageBox.Show("This is not a valid confirmation code.  It looks like an " +
                                            "encrypted private key.  Decryption was attempted but the passphrase couldn't decrypt it", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return;
                        }
                    }

                    string objectKind = result.GetType().Name;
                    if (objectKind == "AddressBase")
                    {
                        objectKind = "an Address";
                    }
                    else
                    {
                        objectKind = "a " + objectKind;
                    }

                    MessageBox.Show("This is not a valid confirmation code.  Instead, it looks like " + objectKind +
                                    ".  Perhaps you entered the wrong thing?  Confirmation codes " +
                                    "start with \"cfrm\".", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                MessageBox.Show("This is not a valid confirmation code.", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            // extract ownersalt and get an intermediate
            byte[] ownersalt = new byte[8];
            Array.Copy(confbytes, 10, ownersalt, 0, 8);

            bool includeHashStep           = (confbytes[5] & 0x04) == 0x04;
            Bip38Intermediate intermediate = new Bip38Intermediate(txtPassphrase.Text, ownersalt, includeHashStep);

            // derive the 64 bytes we need
            // get ECPoint from passpoint
            PublicKey pk = new PublicKey(intermediate.passpoint);

            byte[] addresshashplusownersalt = new byte[12];
            Array.Copy(confbytes, 6, addresshashplusownersalt, 0, 4);
            Array.Copy(intermediate.ownerentropy, 0, addresshashplusownersalt, 4, 8);

            // derive encryption key material
            byte[] derived = new byte[64];
            CryptSharp.Utility.SCrypt.ComputeKey(intermediate.passpoint, addresshashplusownersalt, 1024, 1, 1, 1, derived);

            byte[] derivedhalf2 = new byte[32];
            Array.Copy(derived, 32, derivedhalf2, 0, 32);

            byte[] unencryptedpubkey = new byte[33];
            // recover the 0x02 or 0x03 prefix
            unencryptedpubkey[0] = (byte)(confbytes[18] ^ (derived[63] & 0x01));

            // decrypt
            var aes = Aes.Create();

            aes.KeySize = 256;
            aes.Mode    = CipherMode.ECB;
            aes.Key     = derivedhalf2;
            ICryptoTransform decryptor = aes.CreateDecryptor();

            decryptor.TransformBlock(confbytes, 19, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(confbytes, 19, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(confbytes, 19 + 16, 16, unencryptedpubkey, 17);
            decryptor.TransformBlock(confbytes, 19 + 16, 16, unencryptedpubkey, 17);

            // xor out the padding
            for (int i = 0; i < 32; i++)
            {
                unencryptedpubkey[i + 1] ^= derived[i];
            }

            // reconstitute the ECPoint
            var     ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
            ECPoint point;

            try {
                point = ps.Curve.DecodePoint(unencryptedpubkey);

                // multiply passfactor.  Result is going to be compressed.
                ECPoint pubpoint = point.Multiply(new BigInteger(1, intermediate.passfactor));

                // Do we want it uncompressed?  then we will have to uncompress it.
                byte flagbyte = confbytes[5];
                if ((flagbyte & 0x20) == 0x00)
                {
                    pubpoint = ps.Curve.CreatePoint(pubpoint.X.ToBigInteger(), pubpoint.Y.ToBigInteger(), false);
                }

                // Convert to bitcoin address and check address hash.
                PublicKey generatedaddress = new PublicKey(pubpoint);

                // get addresshash
                UTF8Encoding utf8   = new UTF8Encoding(false);
                Sha256Digest sha256 = new Sha256Digest();
                byte[]       generatedaddressbytes = utf8.GetBytes(generatedaddress.AddressBase58);
                sha256.BlockUpdate(generatedaddressbytes, 0, generatedaddressbytes.Length);
                byte[] addresshashfull = new byte[32];
                sha256.DoFinal(addresshashfull, 0);
                sha256.BlockUpdate(addresshashfull, 0, 32);
                sha256.DoFinal(addresshashfull, 0);

                for (int i = 0; i < 4; i++)
                {
                    if (addresshashfull[i] != confbytes[i + 6])
                    {
                        MessageBox.Show("This passphrase is wrong or does not belong to this confirmation code.", "Invalid passphrase", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }
                }

                confirmIsValid(generatedaddress.AddressBase58);
            } catch {
                // Might throw an exception - not every 256-bit integer is a valid X coordinate
                MessageBox.Show("This passphrase is wrong or does not belong to this confirmation code.", "Invalid passphrase", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
        }
コード例 #5
0
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            lblAddressHeader.Visible = false;
            lblAddressItself.Visible = false;
            lblResult.Visible = false;

            // check for null entry
            if (txtPassphrase.Text == "") {
                MessageBox.Show("Passphrase is required.", "Passphrase required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            if (txtConfCode.Text == "") {
                MessageBox.Show("Confirmation code is required.", "Confirmation code required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            // Parse confirmation code.
            byte[] confbytes = Bitcoin.Base58CheckToByteArray(txtConfCode.Text.Trim());
            if (confbytes == null) {
                // is it even close?
                if (txtConfCode.Text.StartsWith("cfrm38")) {
                    MessageBox.Show("This is not a valid confirmation code.  It has the right prefix, but " +
                        "doesn't contain valid confirmation data.  Possible typo or incomplete?",
                        "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                MessageBox.Show("This is not a valid confirmation code.", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            if (confbytes.Length != 51 || confbytes[0] != 0x64 || confbytes[1] != 0x3B || confbytes[2] != 0xF6 ||
                confbytes[3] != 0xA8 || confbytes[4] != 0x9A || confbytes[18] < 0x02 || confbytes[18] > 0x03) {

                // Unrecognized Base58 object.  Do we know what this is?  Tell the user.
                object result = StringInterpreter.Interpret(txtConfCode.Text.Trim());
                if (result != null) {

                    // did we actually get an encrypted private key?  if so, just try to decrypt it.
                    if (result is PassphraseKeyPair) {
                        PassphraseKeyPair ppkp = result as PassphraseKeyPair;
                        if (ppkp.DecryptWithPassphrase(txtPassphrase.Text)) {
                            confirmIsValid(ppkp.GetAddress().AddressBase58);
                            MessageBox.Show("What you provided contains a private key, not just a confirmation. " +
                                "Confirmation is successful, and with this correct passphrase, " +
                                "you are also able to spend the funds from the address.", "This is actually a private key",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
                            return;
                        } else {
                            MessageBox.Show("This is not a valid confirmation code.  It looks like an " +
                                "encrypted private key.  Decryption was attempted but the passphrase couldn't decrypt it", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return;
                        }
                    }

                    string objectKind = result.GetType().Name;
                    if (objectKind == "AddressBase") {
                        objectKind = "an Address";
                    } else {
                        objectKind = "a " + objectKind;
                    }

                    MessageBox.Show("This is not a valid confirmation code.  Instead, it looks like " + objectKind +
                      ".  Perhaps you entered the wrong thing?  Confirmation codes " +
                    "start with \"cfrm\".", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                MessageBox.Show("This is not a valid confirmation code.", "Invalid confirmation code", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;

            }

            // extract ownersalt and get an intermediate
            byte[] ownersalt = new byte[8];
            Array.Copy(confbytes, 10, ownersalt, 0, 8);

            Bip38Intermediate intermediate = new Bip38Intermediate(txtPassphrase.Text, ownersalt);

            // derive the 64 bytes we need
            // get ECPoint from passpoint
            PublicKey pk = new PublicKey(intermediate.passpoint);

            byte[] addresshashplusownersalt = new byte[12];
            Array.Copy(confbytes, 6, addresshashplusownersalt, 0, 4);
            Array.Copy(intermediate.ownersalt, 0, addresshashplusownersalt, 4, 8);

            // derive encryption key material
            byte[] derived = new byte[64];
            SCrypt.ComputeKey(intermediate.passpoint, addresshashplusownersalt, 1024, 1, 1, 1, derived);

            byte[] derivedhalf2 = new byte[32];
            Array.Copy(derived, 32, derivedhalf2, 0, 32);

            byte[] unencryptedpubkey = new byte[33];
            // recover the 0x02 or 0x03 prefix
            unencryptedpubkey[0] = (byte)(confbytes[18] ^ (derived[63] & 0x01));

            // decrypt
            AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;
            aes.Key = derivedhalf2;
            ICryptoTransform decryptor = aes.CreateDecryptor();

            decryptor.TransformBlock(confbytes, 19, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(confbytes, 19, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(confbytes, 19 + 16, 16, unencryptedpubkey, 17);
            decryptor.TransformBlock(confbytes, 19 + 16, 16, unencryptedpubkey, 17);

            // xor out the padding
            for (int i = 0; i < 32; i++) unencryptedpubkey[i + 1] ^= derived[i];

            // reconstitute the ECPoint
            var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
            ECPoint point;
            try {
                point = ps.Curve.DecodePoint(unencryptedpubkey);

                // multiply passfactor.  Result is going to be compressed.
                ECPoint pubpoint = point.Multiply(new BigInteger(1, intermediate.passfactor));

                // Do we want it uncompressed?  then we will have to uncompress it.
                byte flagbyte = confbytes[5];
                if ((flagbyte & 0x20) == 0x00) {
                    pubpoint = ps.Curve.CreatePoint(pubpoint.X.ToBigInteger(), pubpoint.Y.ToBigInteger(), false);
                }

                // Convert to bitcoin address and check address hash.
                PublicKey generatedaddress = new PublicKey(pubpoint);

                // get addresshash
                UTF8Encoding utf8 = new UTF8Encoding(false);
                Sha256Digest sha256 = new Sha256Digest();
                byte[] generatedaddressbytes = utf8.GetBytes(generatedaddress.AddressBase58);
                sha256.BlockUpdate(generatedaddressbytes, 0, generatedaddressbytes.Length);
                byte[] addresshashfull = new byte[32];
                sha256.DoFinal(addresshashfull, 0);
                sha256.BlockUpdate(addresshashfull, 0, 32);
                sha256.DoFinal(addresshashfull, 0);

                for (int i = 0; i < 4; i++) {
                    if (addresshashfull[i] != confbytes[i + 6]) {
                        MessageBox.Show("This passphrase is wrong or does not belong to this confirmation code.", "Invalid passphrase", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }
                }

                confirmIsValid(generatedaddress.AddressBase58);
            } catch {
                // Might throw an exception - not every 256-bit integer is a valid X coordinate
                MessageBox.Show("This passphrase is wrong or does not belong to this confirmation code.", "Invalid passphrase", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
        }
コード例 #6
0
        private void btnGenerateAddresses_Click(object sender, EventArgs e)
        {
            if (Generating) {
                StopRequested = true;
                btnGenerateAddresses.Text = "Stopping...";
                return;
            }

            if (rdoEncrypted.Checked && txtTextInput.Text == "") {
                MessageBox.Show("An encryption passphrase is required. Choose a different option if you don't want encrypted keys.",
                    "Passphrase missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            if (rdoDeterministicWallet.Checked && txtTextInput.Text == "") {
                MessageBox.Show("A deterministic seed is required.  If you do not intend to create a deterministic " +
                    "wallet or know what one is used for, it is recommended you choose one of the other options.  An inappropriate seed can result " +
                    "in the unexpected theft of funds.",
                    "Seed missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            GenerationThread = new Thread(new ThreadStart(GenerationThreadProcess));
            RemainingToGenerate = (int)numGenCount.Value;
            UserText = txtTextInput.Text;
            RetainPrivateKeys = chkRetainPrivKey.Checked;

            if (rdoDeterministicWallet.Checked) GenChoice = GenChoices.Deterministic;
            if (rdoEncrypted.Checked) {
                GenChoice = GenChoices.Encrypted;
                // intermediate codes start with "passphrasek" thru "passphrases"
                string ti = txtTextInput.Text.Trim();
                if (txtTextInput.Text.Length > 40 && ti.CompareTo("passphrasek") > 0 && ti.CompareTo("passphraset") < 0) {
                    Bip38Intermediate inter = null;
                    // try using it as an intermediate
                    try {
                        inter = new Bip38Intermediate(txtTextInput.Text.Trim(), Bip38Intermediate.Interpretation.IntermediateCode);
                        // if this is an actual intermediate code, ensure surrounding whitespace isn't preserved.
                        txtTextInput.Text = txtTextInput.Text.Trim();
                    } catch {
                        var r = MessageBox.Show("The passphrase resembles an Intermediate Code, but isn't one. " +
                        "If this is supposed to be an intermediate code, it is invalid, malformed, or has an error. " +
                            "If you're attempting to generate from an intermediate code, the resulting keys will not work as expected. " +
                            "Do you want to continue?",
                            "Invalid intermediate code", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);

                        if (r == System.Windows.Forms.DialogResult.Cancel) {
                            return;

                        }
                    }
                    if (inter != null) {
                        MessageBox.Show("Intermediate Code accepted.  " +
                            "Intermediate Codes can be used for generating encrypted keys, but not for decrypting them. " +
                            "You will only be able to decrypt generated keys with " +
                            "the original passphrase that was used to create the Intermediate Code.", "Intermediate Code accepted", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                txtTextInput.UseSystemPasswordChar = true;
            }
            if (rdoMiniKeys.Checked) GenChoice = GenChoices.Minikey;
            if (rdoRandomWallet.Checked) GenChoice = GenChoices.WIF;

            timer1.Interval = 250;
            timer1.Enabled = true;
            Generating = true;
            GeneratingEnded = false;
            StopRequested = false;
            btnGenerateAddresses.Text = "Cancel";
            SetControlsEnabled(false);
            toolStripProgressBar1.Visible = true;
            GenerationThread.Start();
        }
コード例 #7
0
        /// <summary>
        /// Code which is actually run on the generation thread.
        /// </summary>
        private void GenerationThreadProcess()
        {
            Bip38Intermediate intermediate = null;
            if (GenChoice == GenChoices.Encrypted) {
                try {
                    intermediate = new Bip38Intermediate(txtTextInput.Text, Bip38Intermediate.Interpretation.IntermediateCode);
                } catch { } // sink exceptions - just means it's not an intermediate code
                if (intermediate == null) {
                    intermediate = new Bip38Intermediate(UserText, Bip38Intermediate.Interpretation.Passphrase);
                }
            }

            int detcount = 1;

            while (RemainingToGenerate > 0 && StopRequested == false) {
                KeyCollectionItem newitem = null;
                switch (GenChoice) {
                    case GenChoices.Minikey:
                        MiniKeyPair mkp = MiniKeyPair.CreateRandom(ExtraEntropy.GetEntropy());
                        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());
                        s = kp.AddressBase58;
                        newitem = new KeyCollectionItem(kp);
                        break;
                    case GenChoices.Deterministic:
                        kp = KeyPair.CreateFromString(UserText + detcount);
                        detcount++;
                        s = kp.AddressBase58;
                        newitem = new KeyCollectionItem(kp);
                        break;
                    case GenChoices.Encrypted:
                        Bip38KeyPair ekp = new Bip38KeyPair(intermediate);
                        newitem = new KeyCollectionItem(ekp);
                        break;
                }

                lock (GeneratedItems) {
                    GeneratedItems.Add(newitem);
                    RemainingToGenerate--;
                }
            }
            GeneratingEnded = true;
        }