Beispiel #1
0
        private void btnPrivWIFToHex_Click(object sender, EventArgs e)
        {
            ChangeFlag++;
            try {
                object  interpretation = StringInterpreter.Interpret(txtPrivWIF.Text, compressed: compressToolStripMenuItem.Checked, addressType: this.AddressTypeByte);
                KeyPair kp             = null;
                if (interpretation is PassphraseKeyPair)
                {
                    if (txtPassphrase.Text == "")
                    {
                        MessageBox.Show("This is an encrypted key. A passphrase is required.");
                        return;
                    }
                    PassphraseKeyPair ppkp = (PassphraseKeyPair)interpretation;
                    if (ppkp.DecryptWithPassphrase(txtPassphrase.Text) == false)
                    {
                        MessageBox.Show("The passphrase is incorrect.");
                        return;
                    }
                    kp = ppkp.GetUnencryptedPrivateKey();
                }
                else if (interpretation is KeyPair)
                {
                    kp = (KeyPair)interpretation;
                }


                if (kp == null)
                {
                    MessageBox.Show("Not a valid private key.");
                    return;
                }

                SetText(txtPrivHex, kp.PrivateKeyHex);
                SetText(txtPubHex, kp.PublicKeyHex);
                SetText(txtPubHash, kp.Hash160Hex);
                SetText(txtBtcAddr, new AddressBase(kp, AddressTypeByte).AddressBase58);
            } catch (Exception ae) {
                MessageBox.Show(ae.Message);
            } finally {
                ChangeFlag--;
            }
        }
        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;
            }
        }
Beispiel #3
0
        private void btnDecrypt_Click(object sender, EventArgs e)
        {
            // Remove any spaces or dashes from the encrypted key (in case they were typed)
            txtEncrypted.Text = txtEncrypted.Text.Replace("-", "").Replace(" ", "");

            if (txtEncrypted.Text == "" || txtPassphrase.Text == "")
            {
                MessageBox.Show("Enter an encrypted key and its passphrase.", "Entries Required", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // What were we given as encrypted text?

            object encrypted = StringInterpreter.Interpret(txtEncrypted.Text);

            if (encrypted == null)
            {
                if (txtEncrypted.Text.StartsWith("cfrm38"))
                {
                    var r = MessageBox.Show("This is not a private key.  This looks like a confirmation code.  " +
                                            "Do you want to open the Confirmation Code Validator?", "Invalid private key", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                    if (r == DialogResult.Yes)
                    {
                        Program.ShowConfValidator();
                    }
                    return;
                }


                string containsL = "";
                if (txtEncrypted.Text.Contains("l"))
                {
                    containsL = " Your entry contains the lowercase letter l.  Private keys are far " +
                                "more likely to contain the digit 1, and not the lowercase letter l.";
                }

                MessageBox.Show("The private key entry (top box) was invalid.  " +
                                "Please verify the private key was properly typed." + containsL, "Invalid private key", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            if (encrypted is PassphraseKeyPair)
            {
                PassphraseKeyPair pkp = encrypted as PassphraseKeyPair;
                if (pkp.DecryptWithPassphrase(txtPassphrase.Text) == false)
                {
                    MessageBox.Show("The passphrase is incorrect.", "Could not decrypt", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                MessageBox.Show("Decryption successful.", "Decryption", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Program.ShowAddressUtility();
                Program.AddressUtility.DisplayKeyCollectionItem(new KeyCollectionItem(pkp.GetUnencryptedPrivateKey()));
                return;
            }
            else if (encrypted is KeyPair)
            {
                // it's unencrypted - perhaps we're doing an EC multiply and the passphrase is a private key.

                object encrypted2 = StringInterpreter.Interpret(txtPassphrase.Text);
                if (encrypted2 == null)
                {
                    var r = MessageBox.Show("Does the key you entered belong to the following address?: " + (encrypted as KeyPair).AddressBase58,
                                            "Key appears unencrypted",
                                            MessageBoxButtons.YesNo);

                    if (r == DialogResult.Yes)
                    {
                        r = MessageBox.Show("Then this key is already unencrypted and you don't need to decrypt it.  " +
                                            "Would you like to open it in the Address Utility screen to see its various forms?", "Key is not encrypted", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        if (r == DialogResult.Yes)
                        {
                            Program.ShowAddressUtility();
                            Program.AddressUtility.DisplayKeyCollectionItem(new KeyCollectionItem(encrypted as KeyPair));
                        }
                    }
                    else
                    {
                        MessageBox.Show("The passphrase or secondary key is incorrect.  Please verify it was properly typed.", "Second entry is not a valid private key", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                    return;
                }


                BigInteger n1         = new BigInteger(1, (encrypted as KeyPair).PrivateKeyBytes);
                BigInteger n2         = new BigInteger(1, (encrypted2 as KeyPair).PrivateKeyBytes);
                var        ps         = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
                BigInteger privatekey = n1.Multiply(n2).Mod(ps.N);
                MessageBox.Show("Keys successfully combined using EC multiplication.", "EC multiplication successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                if (n1.Equals(n2))
                {
                    MessageBox.Show("The two key entries have the same public hash.  The results you see might be wrong.", "Duplicate key hash", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                // use private key
                KeyPair kp = new KeyPair(privatekey);
                Program.ShowAddressUtility();
                Program.AddressUtility.DisplayKeyCollectionItem(new KeyCollectionItem(kp));
            }
            else if (encrypted is AddressBase)
            {
                MessageBox.Show("This is not a private key.  It looks like an address or a public key.  Private keys usually start with 5, 6, or S.", "Not a private key", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                MessageBox.Show("This is not a private key that this program can decrypt.", "Not a recognized private key", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }