Exemple #1
0
        /// <summary>	Gets shared secret. </summary>
        ///
        /// def get_shared_secret(priv, pub) :
        ///    pub_point  = pub.point()
        ///    priv_point = int(repr(priv),16)
        ///    res     = pub_point * priv_point
        ///    res_hex = '%032x' % res.x()
        ///    return res_hex
        ///    
        /// <remarks>	Paul, 26/10/2015. </remarks>
        ///
        /// <returns>	The shared secret. </returns>
        public static byte[] GetSharedSecret(KeyPair priv, PublicKey pub)
        {
            var ps = SecNamedCurves.GetByName("secp256k1");

            BigInteger ipriv = new BigInteger(1, priv.PrivateKeyBytes);
            ECPoint pubPoint = pub.GetECPoint();

            ECPoint shared = pubPoint.Multiply(ipriv);

            BigInteger s = shared.X.ToBigInteger();

            byte[] data = s.ToByteArray();

            int leadingZeros=-1;
            while(data[++leadingZeros] == 0);

            byte[] result = new byte[data.Length - leadingZeros];
            Buffer.BlockCopy(data, leadingZeros, result, 0, result.Length);

            return result;
        }
 public static bool IsValidPublicKey(string hex)
 {
     byte[] pubKeyBytes = Util.HexStringToBytes(hex);
     PublicKey pk = new PublicKey();
     string result = pk.constructFromBytes(pubKeyBytes);
     return (result == null);
 }
        /// <summary>
        /// Constructor that calculates the address given one escrow invitation code and one matching payment invitation code.
        /// They can be provided in any order.
        /// </summary>
        public EscrowCodeSet(string code1, string code2)
        {
            if (code1 == null || code2 == null || code1 == "" || code2 == "") {
                throw new ArgumentException("Two codes are required to use this function.");
            }

            string escrowInvitationCode=null, paymentInvitationCode=null;

            if (code1.StartsWith("einva") || code1.StartsWith("einvb")) escrowInvitationCode = code1;
            if (code2.StartsWith("einva") || code2.StartsWith("einvb")) escrowInvitationCode = code2;
            if (code1.StartsWith("einvp")) paymentInvitationCode = code1;
            if (code2.StartsWith("einvp")) paymentInvitationCode = code2;

            if (escrowInvitationCode == null || paymentInvitationCode == null) {
                throw new ArgumentException("In order to use this function, one code MUST be an Escrow Invitation (starting " +
                    "with \"einva\" or \"einvb\") and the other code MUST be a Payment Invitation (starting with \"einvp\").");
            }

            byte[] pubpart, privpart;
            int identifier30;
            string failreason = parseEscrowCode(escrowInvitationCode, out pubpart, out privpart, out identifier30);
            if (failreason != null) throw new ArgumentException(failreason);

            // Look for first 40 bits being all 0's or all 1's

            string notvalid = "Not a valid Payment Invitation Code";
            string notvalid2 = "Code is not a valid Payment Invitation Code or may have a typo or other error.";
            string notvalid3 = "The Payment Invitation does not belong to the provided Escrow Invitation.";

            long head;
            byte[] invbytes;
            string failReason = parseEitherCode(paymentInvitationCode, notvalid, notvalid2, out invbytes, out head);

            if (head < headbaseP) throw new ArgumentException(notvalid);
            long identifier30L = head - headbaseP;
            if (identifier30L < 0 || identifier30L > 0x3FFFFFFFL) throw new ArgumentException(notvalid);

            if ((long)identifier30 != identifier30L) {
                throw new ArgumentException(notvalid3);
            }

            byte[] privpartz = new byte[32];
            Array.Copy(invbytes, 8 + 1 + 1, privpartz, 0, 32);
            byte networkByte = invbytes[8];
            bool compressedFlag = (invbytes[8+1+1+32+20] & 0x1) == 1;

            // get bitcoin address
            PublicKey pk = new PublicKey(pubpart);
            ECPoint Gxyz = pk.GetECPoint().Multiply(new BigInteger(1, privpart)).Multiply(new BigInteger(1, privpartz));
            // uncompress if compress is not indicated
            if (compressedFlag == false) Gxyz = PublicKey.GetUncompressed(Gxyz);

            // We can get the Bitcoin address now, so do so
            PublicKey pkxyz = new PublicKey(Gxyz);
            byte[] addrhash160 = pkxyz.Hash160;
            BitcoinAddress = new AddressBase(addrhash160, networkByte).AddressBase58;

            // Does the hash160 match?
            for (int i = 0; i < 20; i++) {
                if (addrhash160[i] != invbytes[8+1+1+32+i]) {
                    throw new ArgumentException(notvalid3);
                }
            }

            this.PaymentInvitationCode = paymentInvitationCode;

            byte expectedabflag = (byte)(escrowInvitationCode.StartsWith("einva") ? 2 : 0);
            if ((invbytes[8+1+1+32+20] & 0x2) != expectedabflag) {
                SamePartyWarningApplies = true;
            }
        }
        /// <summary>
        /// Constructor that takes a single Escrow Invitation Code and produces a Payment Invitation Code.
        /// </summary>
        public EscrowCodeSet(string escrowInvitationCode, bool doCompressed=false, byte networkByte = 0)
        {
            byte[] pubpart, privpart;
            int identifier30;
            string failreason = parseEscrowCode(escrowInvitationCode, out pubpart, out privpart, out identifier30);
            if (failreason != null) throw new ArgumentException(failreason);

            // Look for mismatched parity.
            // (we expect LSB of einva's private part to be 0 and LSB of einvb's private part to be 1)
            // (this is to guarantee that einva's and einvb's private parts aren't equal)
            if ((escrowInvitationCode.StartsWith("einva") && (privpart[31] & 0x01) == 1) ||
                (escrowInvitationCode.StartsWith("einvb") && (privpart[31] & 0x01) == 0)) {
                throw new ArgumentException("This escrow invitation has mismatched parity.  Ask your escrow agent to " +
                    "generate a new pair using the latest version of the software.");
            }

            // Look for 48 0's or 48 1's
            if (privpart[0] == privpart[1] && privpart[1] == privpart[2] && privpart[2] == privpart[3] &&
               privpart[3] == privpart[4] && privpart[4] == privpart[5] && privpart[5] == privpart[6] &&
               privpart[6] == privpart[7] && privpart[7] == privpart[8]) {
                if (privpart[0] == 0x00 || privpart[0] == 0xFF) {
                    throw new ArgumentException("This escrow invitation is invalid and cannot be used (bad private key).");
                }
            }

            // produce a new factor
            byte[] z = new byte[32];
            SecureRandom sr = new SecureRandom();
            sr.NextBytes(z);

            // calculate Gxy then Gxyz
            PublicKey pk = new PublicKey(pubpart);
            ECPoint Gxyz = pk.GetECPoint().Multiply(new BigInteger(1, privpart)).Multiply(new BigInteger(1, z));

            // Uncompress it
            Gxyz = PublicKey.GetUncompressed(Gxyz);

            // We can get the Bitcoin address now, so do so
            PublicKey pkxyz = new PublicKey(Gxyz);
            byte[] hash160 = pkxyz.Hash160;
            BitcoinAddress = new AddressBase(hash160, networkByte).AddressBase58;

            // make the payment invitation record
            byte[] invp = new byte[74];
            long headP = headbaseP + (long)identifier30;
            for (int i = 7; i >= 0; i--) {
                invp[i] = (byte)(headP & 0xff);
                headP >>= 8;
            }
            invp[8] = networkByte;
            Array.Copy(z, 0, invp, 8 + 1 + 1, 32);

            // set flag to indicate if einvb was used to generate this, and make it available in the object
            if (escrowInvitationCode.StartsWith("einvb")) {
                invp[8 + 1 + 1 + 32 + 20] = 0x2;
            }

            // copy hash160
            Array.Copy(hash160, 0, invp, 8 + 1 + 1 + 32, 20);

            PaymentInvitationCode = Util.ByteArrayToBase58Check(invp);
            setAddressConfirmationCode(identifier30, networkByte, invp[8 + 1 + 1 + 32 + 20], z, hash160);
        }
        /// <summary>
        /// Encryption constructor to create a new random key from an intermediate
        /// </summary>
        public Bip38KeyPair(Bip38Intermediate intermediate, bool retainPrivateKeyWhenPossible=false)
        {
            // generate seedb
            byte[] seedb = new byte[24];
            SecureRandom sr = new SecureRandom();
            sr.NextBytes(seedb);

            // get factorb as sha256(sha256(seedb))
            Sha256Digest sha256 = new Sha256Digest();
            sha256.BlockUpdate(seedb, 0, 24);
            factorb = new byte[32];
            sha256.DoFinal(factorb, 0);
            sha256.BlockUpdate(factorb, 0, 32);
            sha256.DoFinal(factorb, 0);

            // get ECPoint from passpoint
            PublicKey pk = new PublicKey(intermediate.passpoint);

            ECPoint generatedpoint = pk.GetECPoint().Multiply(new BigInteger(1, factorb));
            byte[] generatedpointbytes = generatedpoint.GetEncoded();
            PublicKey generatedaddress = new PublicKey(generatedpointbytes);

            // get addresshash
            UTF8Encoding utf8 = new UTF8Encoding(false);
            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);

            byte[] addresshashplusownerentropy = new byte[12];
            Array.Copy(addresshashfull, 0, addresshashplusownerentropy, 0, 4);
            Array.Copy(intermediate.ownerentropy, 0, addresshashplusownerentropy, 4, 8);

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

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

            byte[] unencryptedpart1 = new byte[16];
            for (int i = 0; i < 16; i++) {
                unencryptedpart1[i] = (byte)(seedb[i] ^ derived[i]);
            }
            byte[] encryptedpart1 = new byte[16];

            // encrypt it
            var aes = Aes.Create();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;
            aes.Key = derivedhalf2;
            ICryptoTransform encryptor = aes.CreateEncryptor();

            encryptor.TransformBlock(unencryptedpart1, 0, 16, encryptedpart1, 0);
            encryptor.TransformBlock(unencryptedpart1, 0, 16, encryptedpart1, 0);

            byte[] unencryptedpart2 = new byte[16];
            for (int i = 0; i < 8; i++) {
                unencryptedpart2[i] = (byte)(encryptedpart1[i + 8] ^ derived[i + 16]);
            }
            for (int i = 0; i < 8; i++) {
                unencryptedpart2[i + 8] = (byte)(seedb[i + 16] ^ derived[i + 24]);
            }

            byte[] encryptedpart2 = new byte[16];
            encryptor.TransformBlock(unencryptedpart2, 0, 16, encryptedpart2, 0);
            encryptor.TransformBlock(unencryptedpart2, 0, 16, encryptedpart2, 0);

            byte[] result = new byte[39];
            result[0] = 0x01;
            result[1] = 0x43;
            result[2] = generatedaddress.IsCompressedPoint ? (byte)0x20 : (byte)0x00;
            if (intermediate.LotSequencePresent) result[2] |= 0x04;

            Array.Copy(addresshashfull, 0, result, 3, 4);
            Array.Copy(intermediate.ownerentropy, 0, result, 7, 8);
            Array.Copy(encryptedpart1, 0, result, 15, 8);
            Array.Copy(encryptedpart2, 0, result, 23, 16);

            _encryptedKey = Util.ByteArrayToBase58Check(result);
            _pubKey = generatedaddress.PublicKeyBytes;
            _hash160 = generatedaddress.Hash160;

            var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");

            if (retainPrivateKeyWhenPossible && intermediate.passfactor != null) {
                BigInteger privatekey = new BigInteger(1, intermediate.passfactor).Multiply(new BigInteger(1, factorb)).Mod(ps.N);
                _privKey = new KeyPair(privatekey).PrivateKeyBytes;

            }

            // create the confirmation code
            confirmationCodeInfo = new byte[51];
            // constant provides for prefix "cfrm38"
            confirmationCodeInfo[0] = 0x64;
            confirmationCodeInfo[1] = 0x3B;
            confirmationCodeInfo[2] = 0xF6;
            confirmationCodeInfo[3] = 0xA8;
            confirmationCodeInfo[4] = 0x9A;
            // fields for flagbyte, addresshash, and ownerentropy all copy verbatim
            Array.Copy(result, 2, confirmationCodeInfo, 5, 1 + 4 + 8);
        }
 protected virtual bool calculateHash160()
 {
     if (IsPublicKeyAvailable()) {
         if (_pubKey == null) {
             KeyPair kp = new KeyPair(_privKey, this.IsCompressedPoint, this._addressType);
             _pubKey = kp.PublicKeyBytes;
             _hash160 = kp.Hash160;
         } else {
             PublicKey pub = new PublicKey(_pubKey);
             _hash160 = pub.Hash160;
         }
         return true;
     }
     return false;
 }
 protected virtual bool calculateHash160()
 {
     if (IsPublicKeyAvailable()) {
         PublicKey pub = new PublicKey(_pubKey);
         _hash160 = pub.Hash160;
         return true;
     }
     return false;
 }
        public Exception DecryptWithPassphrase(string passphrase)
        {
            // check for null entry
            if (passphrase == null || passphrase == "") {
                return new ArgumentException("Passphrase is required");
            }

            Bip38Intermediate intermediate = new Bip38Intermediate(passphrase, _ownerentropy, LotSequencePresent);

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

            byte[] addresshashplusownerentropy = Util.ConcatenateByteArrays(_addressHash, intermediate.ownerentropy);

            // derive encryption key material
            byte[] derived = new byte[64];
            SCrypt.ComputeKey(intermediate.passpoint, addresshashplusownerentropy, 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)(_encryptedpointb[0] ^ (derived[63] & 0x01));

            // decrypt
            var aes = Aes.Create();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;
            aes.Key = derivedhalf2;
            ICryptoTransform decryptor = aes.CreateDecryptor();

            decryptor.TransformBlock(_encryptedpointb, 1, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(_encryptedpointb, 1, 16, unencryptedpubkey, 1);
            decryptor.TransformBlock(_encryptedpointb, 1 + 16, 16, unencryptedpubkey, 17);
            decryptor.TransformBlock(_encryptedpointb, 1 + 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.
                if (IsCompressedPoint==false) {
                    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] != _addressHash[i]) {
                        return new ArgumentException("This passphrase is wrong or does not belong to this confirmation code.");
                    }
                }

                this.PublicKey = generatedaddress;
            } catch {
                return new ArgumentException("This passphrase is wrong or does not belong to this confirmation code.");
            }
            return null;
        }
        /// <summary>	Converts this bitshares public key into to a bitcoin address. </summary>
        ///
        /// <remarks>	Paul, 08/12/2014. </remarks>
        ///
        /// <returns>	This object as a string. </returns>
        public string ToBitcoinAddress(bool compressed, byte addressType)
        {
            PublicKey bitcoin = new PublicKey(m_compressed, addressType);

            if (!compressed)
            {
                bitcoin = new PublicKey( bitcoin.GetUncompressed(), addressType );
            }

            return bitcoin.AddressBase58;
        }
 /// <summary>	Create a bitshares public key from a hex bitcoin public key </summary>
 ///
 /// <remarks>	Paul, 08/12/2014. </remarks>
 ///
 /// <param name="bitcoinHexPublicKey">	The bitcoin hexadecimal public key. </param>
 ///
 /// <returns>	A BitsharesPubKey. </returns>
 public static BitsharesPubKey FromBitcoinHex(string bitcoinHexPublicKey, byte addressByteType=0)
 {
     PublicKey bitcoin = new PublicKey(bitcoinHexPublicKey, addressByteType);
     return new BitsharesPubKey(bitcoin.GetCompressed());
 }
Exemple #11
0
        /// <summary>
        /// Constructor that takes a single Escrow Invitation Code and produces a Payment Invitation Code.
        /// </summary>
        public EscrowCodeSet(string escrowInvitationCode, bool doCompressed=false, byte networkByte = 0)
        {
            byte[] pubpart, privpart;
            int identifier30;
            string failreason = parseEscrowCode(escrowInvitationCode, out pubpart, out privpart, out identifier30);
            if (failreason != null) throw new ArgumentException(failreason);

            // produce a new factor
            byte[] z = new byte[32];
            SecureRandom sr = new SecureRandom();
            sr.NextBytes(z);

            // calculate Gxy then Gxyz
            PublicKey pk = new PublicKey(pubpart);
            ECPoint Gxyz = pk.GetECPoint().Multiply(new BigInteger(1, privpart)).Multiply(new BigInteger(1, z));

            // Uncompress it
            Gxyz = PublicKey.GetUncompressed(Gxyz);

            // We can get the Bitcoin address now, so do so
            PublicKey pkxyz = new PublicKey(Gxyz);
            byte[] hash160 = pkxyz.Hash160;
            BitcoinAddress = new AddressBase(hash160, networkByte).AddressBase58;

            // make the payment invitation record
            byte[] invp = new byte[74];
            long headP = headbaseP + (long)identifier30;
            for (int i = 7; i >= 0; i--) {
                invp[i] = (byte)(headP & 0xff);
                headP >>= 8;
            }
            invp[8] = networkByte;
            Array.Copy(z, 0, invp, 8 + 1 + 1, 32);

            // set flag to indicate if einvb was used to generate this, and make it available in the object
            if (escrowInvitationCode.StartsWith("einvb")) {
                invp[8 + 1 + 1 + 32 + 20] = 0x2;
            }

            // copy hash160
            Array.Copy(hash160, 0, invp, 8 + 1 + 1 + 32, 20);

            PaymentInvitationCode = Util.ByteArrayToBase58Check(invp);
            setAddressConfirmationCode(identifier30, networkByte, invp[8 + 1 + 1 + 32 + 20], z, hash160);
        }
        private void btnVccVerifyConfirmationCode_Click(object sender, EventArgs e)
        {
            lblResult.Visible = false;

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

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

            // Parse confirmation code.
            byte[] confbytes = Util.Base58CheckToByteArray(tbxVccConfirmationCode.Text.Trim());
            if (confbytes == null) {
                // is it even close?
                if (tbxVccConfirmationCode.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(tbxVccConfirmationCode.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(tbxVccPassphrase.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(tbxVccPassphrase.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];
            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;
            }
        }
Exemple #13
0
        /// <summary>	Refund bitcoin deposit. </summary>
        ///
        /// <remarks>	Paul, 15/01/2015. </remarks>
        ///
        /// <param name="t">	The TransactionSinceBlock to process. </param>
        protected virtual void RefundBitcoinDeposit(TransactionSinceBlock t, string notes)
        {
            MarkTransactionAsRefundedStart(t.TxId);

            // get public key out of transaction
            string firstPubKey = GetAllPubkeysFromBitcoinTransaction(t.TxId).First();
            PublicKey pk = new PublicKey(firstPubKey, m_addressByteType);

            // refund deposit
            string sentTxid = m_bitcoin.SendToAddress(pk.AddressBase58, t.Amount);

            // mark as such
            MarkTransactionAsRefundedEnd(t.TxId, sentTxid, t.Amount, DaemonTransactionType.bitcoinRefund, notes);
        }
Exemple #14
0
        /// <summary>	Refund bitcoin deposit. </summary>
        ///
        /// <remarks>	Paul, 15/01/2015. </remarks>
        ///
        /// <param name="t">	The TransactionSinceBlock to process. </param>
        protected void RefundBitcoinDeposit(TransactionSinceBlock t, string notes, SenderToDepositRow s2d, MetaOrderType orderType)
        {
            m_daemon.MarkTransactionAsRefundedStart(t.TxId, s2d.deposit_address, m_market.symbol_pair, orderType);

            // get public key out of transaction
            string firstPubKey = GetAllPubkeysFromBitcoinTransaction(t.TxId).First();
            PublicKey pk = new PublicKey(firstPubKey, m_daemon.m_AddressByteType);

            // refund deposit
            string sentTxid = m_bitcoin.SendToAddress(pk.AddressBase58, t.Amount);

            // mark as such
            m_daemon.MarkTransactionAsRefundedEnd(t.TxId, sentTxid, MetaOrderStatus.refunded, t.Amount, notes);
        }