Exemple #1
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);
            }

            // 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);
        }
Exemple #2
0
        /// <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>	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;
        }