/// <summary>
        /// Constructor which attempts to redeem a completed set of three codes, and calculate the private key.
        /// </summary>
        public EscrowCodeSet(string code1, string code2, string code3)
        {
            if (code1 == null || code2 == null || code3 == null || code1 == "" || code2 == "" || code3 == "") {
                throw new ArgumentException("Three codes are required to use this function.");
            }

            string codea = null, codeb=null, codep = null;

            if (code1.StartsWith("einva")) codea = code1;
            if (code2.StartsWith("einva")) codea = code2;
            if (code3.StartsWith("einva")) codea = code3;
            if (code1.StartsWith("einvb")) codeb = code1;
            if (code2.StartsWith("einvb")) codeb = code2;
            if (code3.StartsWith("einvb")) codeb = code3;
            if (code1.StartsWith("einvp")) codep = code1;
            if (code2.StartsWith("einvp")) codep = code2;
            if (code3.StartsWith("einvp")) codep = code3;

            if (codea==null || codeb == null || codep == null) {
                throw new ArgumentException("In order to use this function, one code MUST be an Escrow Invitation A (starting " +
                    "with \"einva\"), one must be an Escrow Invitation B (starting with \"einvb\") and the last " +
                    "code MUST be a Payment Invitation (starting with \"einvp\").");
            }

            byte[] pubparta, privparta;
            int identifier30a;
            string failreason = parseEscrowCode(codea, out pubparta, out privparta, out identifier30a);
            if (failreason != null) throw new ArgumentException("Escrow Invitation Code A: " + failreason);

            byte[] pubpartb, privpartb;
            int identifier30b;
            failreason = parseEscrowCode(codeb, out pubpartb, out privpartb, out identifier30b);
            if (failreason != null) throw new ArgumentException("Escrow Invitation Code B: " + failreason);

            if (identifier30a != identifier30b) {
                throw new ArgumentException("The two Escrow Invitations are not mates and cannot unlock the private key.");
            }

            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 headp;
            byte[] invbytesp;
            string failReason = parseEitherCode(codep, notvalid, notvalid2, out invbytesp, out headp);

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

            if (identifier30L != (long)identifier30a) {
                throw new ArgumentException("The Payment Invitation was not generated from either of the provided Escrow Invitation codes and cannot be unlocked by them.");
            }

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

            // get private key
            BigInteger xyz = new BigInteger(1, privparta).Multiply(new BigInteger(1, privpartb)).Multiply(new BigInteger(1, privpartz));
            var ps = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
            xyz = xyz.Mod(ps.N);

            KeyPair kp = new KeyPair(xyz, compressedFlag, networkByte);

            // provide everything
            this.EscrowInvitationCodeA = codea;
            this.EscrowInvitationCodeB = codeb;
            this.PaymentInvitationCode = codep;
            this.BitcoinAddress = kp.AddressBase58;
            this.PrivateKey = kp.PrivateKey;
        }
Exemple #2
0
        /// <summary>	Decrypts./ </summary>
        ///
        ///		auto secret = priv.get_shared_secret(pub);
        ///      auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str());
        ///      auto plain_text = fc::aes_decrypt( nonce_plus_secret, message );
        ///      auto result = memo_message::deserialize(string(plain_text.begin(), plain_text.end()));
        ///      FC_ASSERT( result.checksum == uint32_t(digest_type::hash(result.text)._hash[0]) );
        ///      return result.text;
        /// 
        /// <remarks>	Paul, 26/10/2015. </remarks>
        ///
        /// <param name="memo">				 	The memo. </param>
        /// <param name="receiverPrivateKey">	The receiver private key. </param>
        /// <param name="senderPublicKey">   	The sender public key. </param>
        ///
        /// <returns>	A string. </returns>
        public static string Decrypt(GrapheneMemo memo, KeyPair receiverKeyPair)
        {
            PublicKey pub = new BitsharesPubKey(memo.from).GetBitcoinPubKey();
            byte[] sharedSecret = GetSharedSecret(receiverKeyPair, pub);

            string ss = StringExtensions.ByteArrayToHexString(sharedSecret, true);

            string ps = memo.nonce.ToString() + StringExtensions.ByteArrayToHexString(Crypto.ComputeSha512( sharedSecret), true);

            byte[] seed = ASCIIEncoding.ASCII.GetBytes(ps);

            string hex = StringExtensions.ByteArrayToHexString(Crypto.ComputeSha512(seed), true);

            string key = hex.Substring(0, 64);
            string iv = hex.Substring(64, 32);

            byte[] data = Util.HexStringToBytes(memo.message);

            int len = AES.AesDecrypt(data, Util.HexStringToBytes(key), Util.HexStringToBytes(iv));

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

            string message = UTF8Encoding.UTF8.GetString(result);

            return message;
        }
        /// <summary>
        /// Default constructor.  Creates a new matched pair of escrow invitation codes.
        /// </summary>
        public EscrowCodeSet()
        {
            SecureRandom sr = new SecureRandom();

            byte[] x = new byte[32];
            byte[] y = new byte[32];
            sr.NextBytes(x);
            sr.NextBytes(y);

            // Force x to be even
            // Force y to be odd
            x[31] &= 0xFE;
            y[31] |= 0x01;

            KeyPair kx = new KeyPair(x, true);
            KeyPair ky = new KeyPair(y, true);

            BigInteger xi = new BigInteger(1, x);
            BigInteger yi = new BigInteger(1, y);

            ECPoint Gx = kx.GetECPoint();
            byte[] bytesGx = Gx.GetEncoded();
            ECPoint Gy = ky.GetECPoint();
            byte[] bytesGy = Gy.GetEncoded();
            ECPoint Gxy = Gx.Multiply(yi);

            byte[] bytesGxy = Gxy.GetEncoded();
            Sha256Digest sha256 = new Sha256Digest();
            byte[] hashGxy = new byte[32];
            sha256.BlockUpdate(bytesGxy, 0, bytesGxy.Length);
            sha256.DoFinal(hashGxy, 0);
            sha256.BlockUpdate(hashGxy, 0, 32);
            sha256.DoFinal(hashGxy, 0);

            int identifier30 = ((hashGxy[0] & 0x3f) << 24) + (hashGxy[1] << 16) + (hashGxy[2] << 8) + hashGxy[3];

            byte[] invitationA = new byte[74];
            byte[] invitationB = new byte[74];

            long headA = headbaseA + (long)identifier30;
            long headB = headbaseB + (long)identifier30;

            // turn headA and headB into bytes
            for (int i = 7; i >= 0; i--) {
                invitationA[i] = (byte)(headA & 0xFF);
                invitationB[i] = (byte)(headB & 0xFF);
                headA >>= 8;
                headB >>= 8;
            }

            Array.Copy(x, 0, invitationA, 8 + 1, 32);
            Array.Copy(y, 0, invitationB, 8 + 1, 32);
            Array.Copy(bytesGy, 0, invitationA, 8 + 1 + 32, 33);
            Array.Copy(bytesGx, 0, invitationB, 8 + 1 + 32, 33);

            EscrowInvitationCodeA = Util.ByteArrayToBase58Check(invitationA);
            EscrowInvitationCodeB = Util.ByteArrayToBase58Check(invitationB);
        }
        /// <summary>
        /// Encryption constructor (non-EC-multiply)
        /// </summary>
        public Bip38KeyPair(KeyPair key, string passphrase)
        {
            if (passphrase == null && passphrase == "") {
                throw new ArgumentException("Passphrase is required");
            }

            if (key == null) throw new ArgumentException("Passphrase is required");

            this.IsCompressedPoint = key.IsCompressedPoint;
            this._addressType = key.AddressType;

            UTF8Encoding utf8 = new UTF8Encoding(false);
            byte[] addrhashfull = Util.ComputeDoubleSha256(key.AddressBase58);
            byte[] addresshash = new byte[] { addrhashfull[0], addrhashfull[1], addrhashfull[2], addrhashfull[3] };

            byte[] derivedBytes = new byte[64];
            SCrypt.ComputeKey(utf8.GetBytes(passphrase), addresshash, 16384, 8, 8, 8, derivedBytes);

            var aes = Aes.Create();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;
            byte[] aeskey = new byte[32];
            Array.Copy(derivedBytes, 32, aeskey, 0, 32);
            aes.Key = aeskey;
            ICryptoTransform encryptor = aes.CreateEncryptor();

            byte[] unencrypted = new byte[32];
            byte[] rv = new byte[39];
            Array.Copy(key.PrivateKeyBytes, unencrypted, 32);
            for (int x = 0; x < 32; x++) unencrypted[x] ^= derivedBytes[x];

            encryptor.TransformBlock(unencrypted, 0, 16, rv, 7);
            encryptor.TransformBlock(unencrypted, 0, 16, rv, 7);
            encryptor.TransformBlock(unencrypted, 16, 16, rv, 23);
            encryptor.TransformBlock(unencrypted, 16, 16, rv, 23);

            // put header
            rv[0] = 0x01;
            rv[1] = 0x42;
            rv[2] = IsCompressedPoint ? (byte)0xe0 : (byte)0xc0;

            byte[] checksum = Util.ComputeDoubleSha256(utf8.GetBytes(key.AddressBase58));
            rv[3] = checksum[0];
            rv[4] = checksum[1];
            rv[5] = checksum[2];
            rv[6] = checksum[3];

            _encryptedKey = Util.ByteArrayToBase58Check(rv);
            _pubKey = key.PublicKeyBytes;
            _hash160 = key.Hash160;
        }
        /// <summary>
        /// Encrypt constructor.
        /// Creates a new encrypted key pair with a passphrase.
        /// The resulting key pair record retains the public key and bitcoin address
        /// but not the passphrase or the unencrypted private key.
        /// </summary>
        public ShaPassphraseKeyPair(KeyPair key, string passphrase)
        {
            if (passphrase == null || passphrase == "") {
                throw new ArgumentException("Passphrase is required");
            }

            if (key == null) throw new ArgumentException("Key is required");
            IsCompressedPoint = key.IsCompressedPoint;
            _addressType = key.AddressType;
            this._hash160 = key.Hash160;
            this._pubKey = key.PublicKeyBytes;

            var aes = Aes.Create();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;

            byte[] encryptionKey = Util.ComputeSha256(passphrase);
            aes.Key = encryptionKey;
            ICryptoTransform encryptor = aes.CreateEncryptor();

            byte[] rv = new byte[36];

            encryptor.TransformBlock(_privKey, 0, 16, rv, 4);
            encryptor.TransformBlock(_privKey, 0, 16, rv, 4);
            byte[] interblock = new byte[16];
            Array.Copy(rv, 4, interblock, 0, 16);
            for (int x = 0; x < 16; x++) interblock[x] ^= _privKey[16 + x];
            encryptor.TransformBlock(interblock, 0, 16, rv, 20);
            encryptor.TransformBlock(interblock, 0, 16, rv, 20);

            // put header
            rv[0] = 0x02;
            rv[1] = 0x05;

            byte[] checksum = Util.ComputeSha256(passphrase + "?");

            rv[2] = (byte)(checksum[0] & 0x7F);
            rv[3] = (byte)(checksum[1] & 0xFE);
            if (key.IsCompressedPoint) rv[3]++;
            this._encryptedKey = Util.ByteArrayToBase58Check(rv);
        }
Exemple #6
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;
        }
        private void computeCode()
        {
            // make a compressed key out of it just by using the existing bitcoin address classes
            KeyPair kp = new KeyPair(_passfactor, compressed: true);

            _passpoint = kp.PublicKeyBytes;

            byte[] result = new byte[49];

            // 8 bytes are a constant, responsible for making the result start with the characters "passphrase"
            Array.Copy(magic, 0, result, 0, 8);
            result[7] = (byte)(LotSequencePresent ? 0x51 : 0x53);
            Array.Copy(_ownerentropy, 0, result, 8, 8);
            Array.Copy(_passpoint, 0, result, 16, 33);
            Code = Util.ByteArrayToBase58Check(result);
        }
        /// <summary>
        /// A string that allows someone to independently calculate the
        /// bitcoin address given their key material, without divulging the encrypted private key.
        /// This can be used to prove that the bitcoin address is encumbered by the passphrase.
        /// This is null if unavailable or not applicable.  When available, calculates upon first
        /// read, which involves an EC multiply and takes a little bit of CPU time.
        /// </summary>
        public string GetConfirmationCode()
        {
            if (_confirmationCode != null) return _confirmationCode;
            if (confirmationCodeInfo == null || factorb == null) return null;

            // finish calculating the confirmation code
            // use the KeyPair class to do the EC multiply for us
            KeyPair kp = new KeyPair(new BigInteger(1, factorb), true);

            // the public key is 33 bytes, or rather, 32 bytes plus one bit
            // (the first byte is either 0x02 or 0x03).
            // xor it with one bit of derived so it's not readable from the confirmation code.
            byte[] kppubbytes = kp.PublicKeyBytes;
            confirmationCodeInfo[18] = (byte)(kppubbytes[0] ^ (derived[63] & 0x01));

            // xor the pub bytes with derived[0...31] to get similar benefit like having an IV
            byte[] unencrypted = new byte[32];
            for (int i = 0; i < 32; i++) unencrypted[i] = (byte)(kppubbytes[i + 1] ^ derived[i]);

            // prepare for AES encryption
            byte[] derivedhalf2 = new byte[32];
            Array.Copy(derived, 32, derivedhalf2, 0, 32);
            var aes = Aes.Create();
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;
            aes.Key = derivedhalf2;
            ICryptoTransform encryptor = aes.CreateEncryptor();

            // encrypt remaining two blocks of 16 bytes using same derived key

            encryptor.TransformBlock(unencrypted, 0, 16, confirmationCodeInfo, 19);
            encryptor.TransformBlock(unencrypted, 0, 16, confirmationCodeInfo, 19);
            encryptor.TransformBlock(unencrypted, 16, 16, confirmationCodeInfo, 19+16);
            encryptor.TransformBlock(unencrypted, 16, 16, confirmationCodeInfo, 19+16);

            _confirmationCode = Util.ByteArrayToBase58Check(confirmationCodeInfo);
            return _confirmationCode;
        }
        public override bool DecryptWithPassphrase(string passphrase)
        {
            if (passphrase == null) {
                return false;
            }

            byte[] hex = Util.Base58CheckToByteArray(_encryptedKey);
            KeyPair tempkey = null;

            if (hex.Length == 39 && hex[0] == 1 && hex[1] == 0x42) {
                UTF8Encoding utf8 = new UTF8Encoding(false);
                byte[] addresshash = new byte[] { hex[3], hex[4], hex[5], hex[6] };

                byte[] derivedBytes = new byte[64];
                SCrypt.ComputeKey(utf8.GetBytes(passphrase), addresshash, 16384, 8, 8, 8, derivedBytes);

                var aes = Aes.Create();
                aes.KeySize = 256;
                aes.Mode = CipherMode.ECB;
                byte[] aeskey = new byte[32];
                Array.Copy(derivedBytes, 32, aeskey, 0, 32);
                aes.Key = aeskey;
                ICryptoTransform decryptor = aes.CreateDecryptor();

                byte[] decrypted = new byte[32];
                decryptor.TransformBlock(hex, 7, 16, decrypted, 0);
                decryptor.TransformBlock(hex, 7, 16, decrypted, 0);
                decryptor.TransformBlock(hex, 23, 16, decrypted, 16);
                decryptor.TransformBlock(hex, 23, 16, decrypted, 16);
                for (int x = 0; x < 32; x++) decrypted[x] ^= derivedBytes[x];

                tempkey = new KeyPair(decrypted, compressed: IsCompressedPoint);

                Sha256Digest sha256 = new Sha256Digest();
                byte[] addrhash = new byte[32];
                byte[] addrtext = utf8.GetBytes(tempkey.AddressBase58);
                sha256.BlockUpdate(addrtext, 0, addrtext.Length);
                sha256.DoFinal(addrhash, 0);
                sha256.BlockUpdate(addrhash, 0, 32);
                sha256.DoFinal(addrhash, 0);
                if (addrhash[0] != hex[3] || addrhash[1] != hex[4] || addrhash[2] != hex[5] || addrhash[3] != hex[6]) {
                    return false;
                }
                _privKey = tempkey.PrivateKeyBytes;
                _pubKey = tempkey.PublicKeyBytes;
                _hash160 = tempkey.Hash160;
                return true;
            } else if (hex.Length == 39 && hex[0] == 1 && hex[1] == 0x43) {

                // produce the intermediate from the passphrase

                // get ownersalt and encryptedpart2 since they are in the record
                byte[] ownersalt = new byte[8];
                Array.Copy(hex, 7, ownersalt, 0, 8);
                bool includeHashStep = (hex[2] & 4) == 4;
                Bip38Intermediate intermediate = new Bip38Intermediate(passphrase, ownersalt, includeHashStep);
                this.LotNumber = intermediate.LotNumber;
                this.SequenceNumber = intermediate.SequenceNumber;

                tempkey = decryptUsingIntermediate(intermediate, hex);
                if (verifyAddressHash(tempkey.AddressBase58, hex) == false) return false;
            }
            _privKey = tempkey.PrivateKeyBytes;
            _pubKey = tempkey.PublicKeyBytes;
            _hash160 = tempkey.Hash160;
            return true;
        }
        /// <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);
        }
 /// <summary>
 /// Calculates public key and returns true if calculating public key was possible.
 /// This might cause a delay of milliseconds if it must be computed from the public
 /// key, possibly more if it leads to decrypting a private key.
 /// </summary>
 protected virtual bool calculatePubKey()
 {
     if (IsUnencryptedPrivateKeyAvailable()) {
         KeyPair kp = new KeyPair(_privKey, compressed: IsCompressedPoint, addressType: _addressType);
         _pubKey = kp.PublicKeyBytes;
         return true;
     }
     return false;
 }
 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;
 }
        public void CheckBitcoinAddresses()
        {
            for (int i = 0; i < m_bitcoinPrivKeys.Count; i++)
            {
                string priv = m_bitcoinPrivKeys[i];
                string addr = m_bitcoinAddresses[i];

                KeyPair kp = new KeyPair(priv);
                Assert.AreEqual(addr, kp.AddressBase58);
            }
        }
        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.
            UTF8Encoding utf8 = new UTF8Encoding(false);
            byte[] sha256ofseed = Util.ComputeSha256(seed);

            string asbase58 = new KeyPair(sha256ofseed).PrivateKeyBase58.Replace("1","");

            string keytotry = "S" + asbase58.Substring(4, 29);
            char[] chars = keytotry.ToCharArray();
            char[] charstest = (keytotry + "?").ToCharArray();

            while (Util.ComputeSha256(utf8.GetBytes(charstest))[0] != 0) {
                // As long as key doesn't pass typo check, increment it.
                for (int i = chars.Length - 1; i >= 0; i--) {
                    char c = chars[i];
                    if (c == '9') {
                        charstest[i] = chars[i] = 'A';
                        break;
                    } else if (c == 'H') {
                        charstest[i] = chars[i] = 'J';
                        break;
                    } else if (c == 'N') {
                        charstest[i] = chars[i] = 'P';
                        break;
                    } else if (c == 'Z') {
                        charstest[i] = chars[i] = 'a';
                        break;
                    } else if (c == 'k') {
                        charstest[i] = chars[i] = 'm';
                        break;
                    } else if (c == 'z') {
                        charstest[i] = chars[i] = '2';
                        // No break - let loop increment prior character.
                    } else {
                        charstest[i] = chars[i] = ++c;
                        break;
                    }
                }
            }
            return new MiniKeyPair(new String(chars));
        }
        /// <summary>
        /// Generate a set of M-of-N parts for a specific private key.
        /// If desiredPrivKey is null, then a random key will be selected.
        /// </summary>
        public void Generate(int PartsNeededToDecode, int PartsToGenerate, byte[] desiredPrivKey)
        {
            if (PartsNeededToDecode > PartsToGenerate) {
                throw new ApplicationException("Number of parts needed exceeds number of parts to generate.");
            }

            if (PartsNeededToDecode > 8 || PartsToGenerate > 8) {
                throw new ApplicationException("Maximum number of parts is 8");
            }

            if (PartsNeededToDecode < 1 || PartsToGenerate < 1) {
                throw new ApplicationException("Minimum number of parts is 1");
            }

            if (desiredPrivKey != null && desiredPrivKey.Length != 32) {
                throw new ApplicationException("Desired private key must be 32 bytes");
            }

            KeyParts.Clear();
            decodedKeyParts.Clear();

            SecureRandom sr = new SecureRandom();

            // Get 8 random big integers into v[i].
            byte[][] vvv = new byte[8][];
            BigInteger[] v = new BigInteger[8];

            for (int i = 0; i < 8; i++) {
                byte[] b = new byte[32];
                sr.NextBytes(b, 0, 32);
                // For larger values of i, chop off some most-significant-bits to prevent overflows as they are
                // multiplied with increasingly larger factors.
                if (i >= 7) {
                    b[0] &= 0x7f;
                }
                v[i] = new BigInteger(1, b);
                Debug.WriteLine(String.Format("v({0})={1}", i, v[i].ToString()));

            }

            // if a certain private key is desired, then specify it.
            if (desiredPrivKey != null) {
                // replace v[0] with xor(v[1...7]) xor desiredPrivKey
                BigInteger newv0 = BigInteger.Zero;
                for (int i=1; i<PartsNeededToDecode; i++) {
                    newv0 = newv0.Xor(v[i]);
                }
                v[0] = newv0.Xor(new BigInteger(1,desiredPrivKey));

            }

            // Generate the expected private key from all the parts
            BigInteger privkey = new BigInteger("0");
            for (int i = 0; i < PartsNeededToDecode; i++) {
                privkey = privkey.Xor(v[i]);
            }

            // Get the bitcoin address
            byte[] keybytes = privkey.ToByteArrayUnsigned();
            // make sure we have 32 bytes, we'll need it
            if (keybytes.Length < 32) {
                byte[] array32 = new byte[32];
                Array.Copy(keybytes, 0, array32, 32 - keybytes.Length, keybytes.Length);
                keybytes = array32;
            }
            KeyPair = new KeyPair(keybytes);

            byte[] checksum = Util.ComputeSha256(BitcoinAddress);

            // Generate the parts
            for (int i = 0; i < PartsToGenerate; i++) {
                BigInteger total = new BigInteger("0");
                for (int j = 0; j < PartsNeededToDecode; j++) {

                    int factor = 1;
                    for (int ii = 0; ii <= i; ii++) factor = factor * (j + 1);

                    BigInteger bfactor = new BigInteger(factor.ToString());

                    total = total.Add(v[j].Multiply(bfactor));
                }

                Debug.WriteLine(String.Format(" pc{0}={1}", i, total.ToString()));
                byte[] parts = new byte[39];
                parts[0] = 0x4f;
                parts[1] = (byte)(0x93 + PartsNeededToDecode);
                int parts23 = (((checksum[0] << 8) + checksum[1]) & 0x1ff);
                Debug.WriteLine("checksum " + parts23.ToString());
                parts23 += 0x6000;
                parts23 += (i << 9);
                byte[] btotal = total.ToByteArrayUnsigned();
                for (int jj = 0; jj < btotal.Length; jj++) {
                    parts[jj + 4 + (35 - btotal.Length)] = btotal[jj];
                }

                parts[2] = (byte)((parts23 & 0xFF00) >> 8);
                parts[3] = (byte)(parts23 & 0xFF);

                KeyParts.Add(Util.ByteArrayToBase58Check(parts));
                decodedKeyParts.Add(parts);
            }
        }
        /// <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);
        }
        public override bool DecryptWithPassphrase(string passphrase)
        {
            if (passphrase == null)
            {
                return(false);
            }

            byte[]  hex     = Util.Base58CheckToByteArray(_encryptedKey);
            KeyPair tempkey = null;

            if (hex.Length == 39 && hex[0] == 1 && hex[1] == 0x42)
            {
                UTF8Encoding utf8        = new UTF8Encoding(false);
                byte[]       addresshash = new byte[] { hex[3], hex[4], hex[5], hex[6] };

                byte[] derivedBytes = new byte[64];
                SCrypt.ComputeKey(utf8.GetBytes(passphrase), addresshash, 16384, 8, 8, 8, derivedBytes);

                var aes = Aes.Create();
                aes.KeySize = 256;
                aes.Mode    = CipherMode.ECB;
                byte[] aeskey = new byte[32];
                Array.Copy(derivedBytes, 32, aeskey, 0, 32);
                aes.Key = aeskey;
                ICryptoTransform decryptor = aes.CreateDecryptor();

                byte[] decrypted = new byte[32];
                decryptor.TransformBlock(hex, 7, 16, decrypted, 0);
                decryptor.TransformBlock(hex, 7, 16, decrypted, 0);
                decryptor.TransformBlock(hex, 23, 16, decrypted, 16);
                decryptor.TransformBlock(hex, 23, 16, decrypted, 16);
                for (int x = 0; x < 32; x++)
                {
                    decrypted[x] ^= derivedBytes[x];
                }

                tempkey = new KeyPair(decrypted, compressed: IsCompressedPoint);

                Sha256Digest sha256   = new Sha256Digest();
                byte[]       addrhash = new byte[32];
                byte[]       addrtext = utf8.GetBytes(tempkey.AddressBase58);
                sha256.BlockUpdate(addrtext, 0, addrtext.Length);
                sha256.DoFinal(addrhash, 0);
                sha256.BlockUpdate(addrhash, 0, 32);
                sha256.DoFinal(addrhash, 0);
                if (addrhash[0] != hex[3] || addrhash[1] != hex[4] || addrhash[2] != hex[5] || addrhash[3] != hex[6])
                {
                    return(false);
                }
                _privKey = tempkey.PrivateKeyBytes;
                _pubKey  = tempkey.PublicKeyBytes;
                _hash160 = tempkey.Hash160;
                return(true);
            }
            else if (hex.Length == 39 && hex[0] == 1 && hex[1] == 0x43)
            {
                // produce the intermediate from the passphrase


                // get ownersalt and encryptedpart2 since they are in the record
                byte[] ownersalt = new byte[8];
                Array.Copy(hex, 7, ownersalt, 0, 8);
                bool includeHashStep           = (hex[2] & 4) == 4;
                Bip38Intermediate intermediate = new Bip38Intermediate(passphrase, ownersalt, includeHashStep);
                this.LotNumber      = intermediate.LotNumber;
                this.SequenceNumber = intermediate.SequenceNumber;

                tempkey = decryptUsingIntermediate(intermediate, hex);
                if (verifyAddressHash(tempkey.AddressBase58, hex) == false)
                {
                    return(false);
                }
            }
            _privKey = tempkey.PrivateKeyBytes;
            _pubKey  = tempkey.PublicKeyBytes;
            _hash160 = tempkey.Hash160;
            return(true);
        }
        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);
            }
        }
Exemple #19
0
        /// <summary>
        /// Constructor which attempts to redeem a completed set of three codes, and calculate the private key.
        /// </summary>
        public EscrowCodeSet(string code1, string code2, string code3)
        {
            if (code1 == null || code2 == null || code3 == null || code1 == "" || code2 == "" || code3 == "")
            {
                throw new ArgumentException("Three codes are required to use this function.");
            }

            string codea = null, codeb = null, codep = null;

            if (code1.StartsWith("einva"))
            {
                codea = code1;
            }
            if (code2.StartsWith("einva"))
            {
                codea = code2;
            }
            if (code3.StartsWith("einva"))
            {
                codea = code3;
            }
            if (code1.StartsWith("einvb"))
            {
                codeb = code1;
            }
            if (code2.StartsWith("einvb"))
            {
                codeb = code2;
            }
            if (code3.StartsWith("einvb"))
            {
                codeb = code3;
            }
            if (code1.StartsWith("einvp"))
            {
                codep = code1;
            }
            if (code2.StartsWith("einvp"))
            {
                codep = code2;
            }
            if (code3.StartsWith("einvp"))
            {
                codep = code3;
            }


            if (codea == null || codeb == null || codep == null)
            {
                throw new ArgumentException("In order to use this function, one code MUST be an Escrow Invitation A (starting " +
                                            "with \"einva\"), one must be an Escrow Invitation B (starting with \"einvb\") and the last " +
                                            "code MUST be a Payment Invitation (starting with \"einvp\").");
            }


            byte[] pubparta, privparta;
            int    identifier30a;
            string failreason = parseEscrowCode(codea, out pubparta, out privparta, out identifier30a);

            if (failreason != null)
            {
                throw new ArgumentException("Escrow Invitation Code A: " + failreason);
            }

            byte[] pubpartb, privpartb;
            int    identifier30b;

            failreason = parseEscrowCode(codeb, out pubpartb, out privpartb, out identifier30b);
            if (failreason != null)
            {
                throw new ArgumentException("Escrow Invitation Code B: " + failreason);
            }

            if (identifier30a != identifier30b)
            {
                throw new ArgumentException("The two Escrow Invitations are not mates and cannot unlock the private key.");
            }



            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 headp;

            byte[] invbytesp;
            string failReason = parseEitherCode(codep, notvalid, notvalid2, out invbytesp, out headp);

            if (headp < headbaseP)
            {
                throw new ArgumentException(notvalid);
            }
            long identifier30L = headp - headbaseP;

            if (identifier30L < 0 || identifier30L > 0x3FFFFFFFL)
            {
                throw new ArgumentException(notvalid);
            }

            if (identifier30L != (long)identifier30a)
            {
                throw new ArgumentException("The Payment Invitation was not generated from either of the provided Escrow Invitation codes and cannot be unlocked by them.");
            }

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


            // get private key
            BigInteger xyz = new BigInteger(1, privparta).Multiply(new BigInteger(1, privpartb)).Multiply(new BigInteger(1, privpartz));
            var        ps  = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");

            xyz = xyz.Mod(ps.N);

            KeyPair kp = new KeyPair(xyz, compressedFlag, networkByte);

            // provide everything
            this.EscrowInvitationCodeA = codea;
            this.EscrowInvitationCodeB = codeb;
            this.PaymentInvitationCode = codep;
            this.BitcoinAddress        = kp.AddressBase58;
            this.PrivateKey            = kp.PrivateKey;
        }
 public BitsharesKeyPair(string wifPrivateKey)
 {
     m_btcKeyPair = new KeyPair(wifPrivateKey);
     m_ripe = System.Security.Cryptography.RIPEMD160.Create();
 }
Exemple #21
0
        /// <summary>
        /// Default constructor.  Creates a new matched pair of escrow invitation codes.
        /// </summary>
        public EscrowCodeSet()
        {
            SecureRandom sr = new SecureRandom();

            byte[] x = new byte[32];
            byte[] y = new byte[32];
            sr.NextBytes(x);
            sr.NextBytes(y);

            // Force x to be even
            // Force y to be odd
            x[31] &= 0xFE;
            y[31] |= 0x01;

            KeyPair kx = new KeyPair(x, true);
            KeyPair ky = new KeyPair(y, true);

            BigInteger xi = new BigInteger(1, x);
            BigInteger yi = new BigInteger(1, y);

            ECPoint Gx = kx.GetECPoint();

            byte[]  bytesGx = Gx.GetEncoded();
            ECPoint Gy      = ky.GetECPoint();

            byte[]  bytesGy = Gy.GetEncoded();
            ECPoint Gxy     = Gx.Multiply(yi);

            byte[]       bytesGxy = Gxy.GetEncoded();
            Sha256Digest sha256   = new Sha256Digest();

            byte[] hashGxy = new byte[32];
            sha256.BlockUpdate(bytesGxy, 0, bytesGxy.Length);
            sha256.DoFinal(hashGxy, 0);
            sha256.BlockUpdate(hashGxy, 0, 32);
            sha256.DoFinal(hashGxy, 0);

            int identifier30 = ((hashGxy[0] & 0x3f) << 24) + (hashGxy[1] << 16) + (hashGxy[2] << 8) + hashGxy[3];

            byte[] invitationA = new byte[74];
            byte[] invitationB = new byte[74];

            long headA = headbaseA + (long)identifier30;
            long headB = headbaseB + (long)identifier30;

            // turn headA and headB into bytes
            for (int i = 7; i >= 0; i--)
            {
                invitationA[i] = (byte)(headA & 0xFF);
                invitationB[i] = (byte)(headB & 0xFF);
                headA        >>= 8;
                headB        >>= 8;
            }

            Array.Copy(x, 0, invitationA, 8 + 1, 32);
            Array.Copy(y, 0, invitationB, 8 + 1, 32);
            Array.Copy(bytesGy, 0, invitationA, 8 + 1 + 32, 33);
            Array.Copy(bytesGx, 0, invitationB, 8 + 1 + 32, 33);

            EscrowInvitationCodeA = Util.ByteArrayToBase58Check(invitationA);
            EscrowInvitationCodeB = Util.ByteArrayToBase58Check(invitationB);
        }
        private void setAddressConfirmationCode(int identifier30, byte networkbyte, byte flagbyte, byte[] z, byte[] hash160)
        {
            byte[] accbytes = new byte[74];
            long head = headconfP + (int)identifier30;
            for (int i=7; i>=0; i--) {
                accbytes[i] = (byte)(head & 0x7F);
                head >>= 8;
            }
            accbytes[8]=networkbyte;

            byte[] Gzbytes = new KeyPair(z, true).GetECPoint().GetEncoded();
            Array.Copy(Gzbytes, 0, accbytes, 8+1, 33);
            Array.Copy(hash160, 0, accbytes, 8+1+33, 20);
            accbytes[8+1+33+20] = flagbyte;
            this.AddressConfirmationCode = Util.ByteArrayToBase58Check(accbytes);
        }
 /// <summary>
 /// Returns true if a given string can be turned into a private key.
 /// </summary>
 public static bool IsValidPrivateKey(string key)
 {
     KeyPair kp = new KeyPair();
     string result = kp.constructWithKey(key, false);
     return (result == null);
 }
        public void Decode()
        {
            ChecksumMatched=false;
            Decoded=false;
            KeyPair = null;

            if (PartsAccepted < PartsNeeded) return;

            BigInteger[] pc = new BigInteger[8];
            for (int i = 0; i < decodedKeyParts.Count; i++) {
                byte[] g = decodedKeyParts[i];
                pc[i] = new BigInteger(1, g, 4, 35);
                // If there is an overflow, then add it in.
                if ((g[2] & 0x80) == 0x80) {
                    pc[i] = pc[i].Add(new BigInteger(((int)((g[2] & 0x60) >> 5)).ToString()).ShiftLeft(280));
                    Debug.WriteLine("overflow added");

                }
            }

            List<equation> equations = new List<equation>();

            // create equations for all the parts we need.
            for (int i = 0; i < PartsNeeded; i++) {
                byte[] got = decodedKeyParts[i];
                // extract out part number
                int partnumber0 = (byte)((got[2] & 0x0e) >> 1);
                equations.Add(new equation(i, PartsNeeded, partnumber0));
            }

            List<List<equation>> steps = new List<List<equation>>();
            steps.Add(equations);

            // goal: get our equation set down such that there's only one coefficient on the left side.
            while (equations.Count > 1) {
                equations = solvesome(equations);
                steps.Add(equations);
                Debug.WriteLine("-----");
                foreach (equation eq in equations) {
                    Debug.WriteLine(eq.ToString());
                }
            }

            BigInteger[] v = new BigInteger[8];

            while (steps.Count > 0) {
                // pop off the last step
                List<equation> laststeps = steps[steps.Count - 1];
                steps.RemoveAt(steps.Count - 1);
                equation laststep = laststeps[0];
                Debug.WriteLine("-----");
                Debug.WriteLine(laststep.ToString());

                // solve for v
                long divisor = laststep.leftside[0].multiplier;
                laststep.divisor = laststep.leftside[0].multiplier;
                laststep.leftside[0].multiplier = 1;
                //foreach (coefficient c in laststep.rightside) c.divisor = divisor;
                //laststep.subtractor = laststep.subtractor.Divide(new BigInteger(divisor.ToString()));

                long idx = laststep.leftside[0].vindex;
                v[idx] = laststep.SolveRight(pc);
                Debug.WriteLine(String.Format("v({0})={1}", laststep.leftside[0].vindex, v[idx].ToString()));
                // go through all other steps and see that our solved value is incorporated into the equation.
                foreach (List<equation> eqbl in steps) {
                    foreach (equation eqb in eqbl) eqb.SolveLeft(v);
                }

            }

            // xor the ones we need

            BigInteger xoraccum = BigInteger.Zero;
            for (int i = 0; i < PartsNeeded; i++) {
                xoraccum = xoraccum.Xor(v[i]);
            }

            ChecksumMatched = false;
            Decoded = true;

            byte[] keybytes = xoraccum.ToByteArrayUnsigned();
            if (keybytes.Length > 32) {
                // if more than 32 bytes, decoding probably went wrong! truncate to 32 bytes, but force a checksum failure
                byte[] newkey = new byte[32];
                for (int jj = 0; jj < 32; jj++) newkey[jj] = keybytes[jj];
                keybytes = newkey;
                return;
            } else if (keybytes.Length < 32) {
                byte[] array32 = new byte[32];
                Array.Copy(keybytes, 0, array32, 32 - keybytes.Length, keybytes.Length);
                keybytes = array32;
            }
            KeyPair = new KeyPair(keybytes);

            // Get the bitcoin address

            byte[] checksum = Util.ComputeSha256(BitcoinAddress);

            int mychecksum = ((checksum[0] & 1) << 8) + checksum[1];
            if (mychecksum == expectedChecksum) ChecksumMatched=true;
        }
        public void CheckBitcoinPubKeys()
        {
            for (int i=0; i<m_bitcoinPrivKeys.Count; i++)
            {
                string priv = m_bitcoinPrivKeys[i];
                string pub = m_bitcoinPubKeys[i];

                KeyPair kp = new KeyPair(priv);
                Assert.AreEqual( pub, kp.PublicKeyHex.ToLower() );
            }
        }
        public void CheckBtsPubKeys()
        {
            for (int i = 0; i < m_bitcoinPrivKeys.Count; i++)
            {
                string priv = m_bitcoinPrivKeys[i];
                string pub = m_btsPubKeys[i];

                KeyPair kp = new KeyPair(priv);
                string compare = BitsharesKeyPair.ComputeBitsharesPubKey(kp.GetCompressed(), m_ripe);

                Assert.AreEqual(pub, compare);
            }
        }
        /// <summary>
        /// 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.
        /// </summary>
        /// <returns></returns>
        public static MiniKeyPair CreateDeterministic(string seed, byte addressType = 0)
        {
            UTF8Encoding utf8 = new UTF8Encoding(false);
            byte[] sha256ofseed = Util.ComputeSha256(seed);

            string asbase58 = new KeyPair(sha256ofseed).PrivateKeyBase58.Replace("1","");

            string keytotry = "S" + asbase58.Substring(4, 29);
            char[] chars = keytotry.ToCharArray();
            char[] charstest = (keytotry + "?").ToCharArray();

            while (Util.ComputeSha256(utf8.GetBytes(charstest))[0] != 0) {
                // As long as key doesn't pass typo check, increment it.
                for (int i = chars.Length - 1; i >= 0; i--) {
                    char c = chars[i];
                    if (c == '9') {
                        charstest[i] = chars[i] = 'A';
                        break;
                    } else if (c == 'H') {
                        charstest[i] = chars[i] = 'J';
                        break;
                    } else if (c == 'N') {
                        charstest[i] = chars[i] = 'P';
                        break;
                    } else if (c == 'Z') {
                        charstest[i] = chars[i] = 'a';
                        break;
                    } else if (c == 'k') {
                        charstest[i] = chars[i] = 'm';
                        break;
                    } else if (c == 'z') {
                        charstest[i] = chars[i] = '2';
                        // No break - let loop increment prior character.
                    } else {
                        charstest[i] = chars[i] = ++c;
                        break;
                    }
                }
            }
            return new MiniKeyPair(new String(chars), addressType);
        }