/// <summary> /// Allows calculation of address with a different AddressType /// </summary> public AddressBase(AddressBase otheraddress, byte addressType) { // Hash160 setter validates length and throws exception if needed Hash160 = otheraddress.Hash160; this.AddressType = addressType; }
/// <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> /// 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 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> /// 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); }
public KeyCollectionItem(AddressBase address) { this.Address = address; }