Beispiel #1
0
        public bool SetI2P(string address)
        {
            address = address.ToLowerInvariant();
            if (!address.EndsWith(".b32.i2p", StringComparison.Ordinal))
            {
                return(false);
            }

            var encoded = address.Substring(0, address.Length - ".b32.i2p".Length);

            if (encoded.Length != 52)
            {
                return(false);
            }

            byte[] bytes;
            try
            {
                bytes = Encoders.Base32.DecodeData(encoded + "====");
            }
            catch (FormatException)
            {
                return(false);
            }

            if (bytes.Length != ADDR_I2P_SIZE + 3)
            {
                return(false);
            }

            network = NetworkAddressType.I2P;
            addr    = bytes.SafeSubarray(0, ADDR_I2P_SIZE);
            return(true);
        }
Beispiel #2
0
        public void SetLegacyIpv6(byte[] ipv6)
        {
            if (ipv6.Length != ADDR_IPV6_SIZE)
            {
                throw new ArgumentException("The received value is not a valid IPv6 byte array.", nameof(ipv6));
            }

            var skip = 0;

            if (HasPrefix(ipv6, IPV4_IN_IPV6_PREFIX))
            {
                network = NetworkAddressType.IPv4;
                skip    = IPV4_IN_IPV6_PREFIX.Length;
            }
            else if (HasPrefix(ipv6, TORV2_IN_IPV6_PREFIX))
            {
                // TORv2-in-IPv6
                network = NetworkAddressType.Onion;
                skip    = TORV2_IN_IPV6_PREFIX.Length;
            }
            else
            {
                // IPv6
                network = NetworkAddressType.IPv6;
            }

            addr = ipv6.SafeSubarray(skip);
        }
Beispiel #3
0
        private bool SetTor(string address)
        {
            if (!address.EndsWith(".onion", StringComparison.Ordinal))
            {
                return(false);
            }

            byte[] bytes;
            try
            {
                bytes = Encoders.Base32.DecodeData(address.Substring(0, address.Length - ".onion".Length));
            }
            catch (FormatException)
            {
                return(false);
            }

            if (bytes.Length == ADDR_TORV2_SIZE)
            {
                network = NetworkAddressType.Onion;
                addr    = bytes;
                return(true);
            }
            else if (bytes.Length == ADDR_TORV3_SIZE + TORV3_ADDR_CHECKSUM_LEN + TORV3_ADDR_VERSION_LEN)
            {
                var version = bytes[bytes.Length - 1];

                if (version != 3)
                {
                    return(false);
                }

                var pubkey = bytes.SafeSubarray(0, ADDR_TORV3_SIZE);
                var chksum = bytes.SafeSubarray(ADDR_TORV3_SIZE, TORV3_ADDR_CHECKSUM_LEN);

                var calculatedChecksum = CalculateChecksum(pubkey);

                if (!Utils.ArrayEqual(chksum, calculatedChecksum))
                {
                    return(false);
                }

                network = NetworkAddressType.Onion;
                addr    = pubkey;
                return(true);
            }
            return(false);
        }
Beispiel #4
0
        private bool SetNetFromBIP155Network(BIP155Network bip155Network, int length)
        {
            NetworkAddressType AssignIfCorrectSize(NetworkAddressType net, int expectedSize)
            {
                if (length != expectedSize)
                {
                    throw new ArgumentException($"BIP155 {(BIP155Network)bip155Network} address is {length} bytes long. Expected length is {expectedSize} bytes.");
                }
                return(net);
            }

            switch (bip155Network)
            {
            case BIP155Network.IPv4:
                network = AssignIfCorrectSize(NetworkAddressType.IPv4, ADDR_IPV4_SIZE);
                break;

            case BIP155Network.IPv6:
                network = AssignIfCorrectSize(NetworkAddressType.IPv6, ADDR_IPV6_SIZE);
                break;

            case BIP155Network.TORv2:
                network = AssignIfCorrectSize(NetworkAddressType.Onion, ADDR_TORV2_SIZE);
                break;

            case BIP155Network.TORv3:
                network = AssignIfCorrectSize(NetworkAddressType.Onion, ADDR_TORV3_SIZE);
                break;

            case BIP155Network.I2P:
                network = AssignIfCorrectSize(NetworkAddressType.I2P, ADDR_I2P_SIZE);
                break;

            case BIP155Network.Cjdns:
                network = AssignIfCorrectSize(NetworkAddressType.Cjdns, ADDR_CJDNS_SIZE);
                break;

            default:
                return(false);
            }
            return(true);
        }
Beispiel #5
0
 public NetworkAddress(EndPoint endPoint)
 {
     if (endPoint == null)
     {
         throw new ArgumentNullException(nameof(endPoint));
     }
     Endpoint = endPoint;
     if (endPoint.IsTor())
     {
         network = NetworkAddressType.Onion;
     }
     else if (endPoint is IPEndPoint ip)
     {
         SetIp(ip.Address);
     }
     else
     {
         throw new NotSupportedException($"Unsupported endpoint of type {endPoint.GetType()}");
     }
 }
Beispiel #6
0
        public virtual void ReadWrite(BitcoinStream stream)
        {
            var version = stream.ProtocolVersion ?? 0;

            if (stream.Type == SerializationType.Disk)
            {
                stream.ReadWrite(ref version);
            }
            if (
                stream.Type == SerializationType.Disk ||
                (stream.ProtocolCapabilities.SupportTimeAddress && stream.Type != SerializationType.Hash))
            {
                // The only time we serialize a CAddress object without nTime is in
                // the initial VERSION messages which contain two CAddress records.
                // At that point, the serialization version is INIT_PROTO_VERSION.
                // After the version handshake, serialization version is >=
                // MIN_PEER_PROTO_VERSION and all ADDR messages are serialized with
                // nTime.
                stream.ReadWrite(ref nTime);
            }
            if ((version & AddrV2Format) != 0)
            {
                stream.ReadWriteAsVarInt(ref services);
            }
            else
            {
                stream.ReadWrite(ref services);
            }

            var useV2Format = stream.ProtocolVersion is {} protcocolVersion&& (protcocolVersion & AddrV2Format) != 0;

            if (useV2Format)
            {
                if (stream.Serializing)
                {
                    var bip155net = (byte)GetBIP155Network();
                    stream.ReadWrite(bip155net);
                    stream.ReadWriteAsVarString(ref addr);
                }
                else
                {
                    byte n = 0;
                    stream.ReadWrite(ref n);
                    stream.ReadWriteAsVarString(ref addr);

                    if (SetNetFromBIP155Network((BIP155Network)n, addr.Length))
                    {
                        if (network == NetworkAddressType.IPv6)
                        {
                            if (HasPrefix(addr, IPV4_IN_IPV6_PREFIX) || HasPrefix(addr, TORV2_IN_IPV6_PREFIX))
                            {
                                // set to invalid because IPv4 and Torv2 should not be embeded in IPv6.
                                addr    = IPV6_NONE;
                                network = NetworkAddressType.IPv6;
                            }
                        }
                    }
                    else
                    {
                        // set to invalid because IPv4 and Torv2 should not be embeded in IPv6.
                        addr    = IPV6_NONE;
                        network = NetworkAddressType.IPv6;
                    }
                }
            }
            else
            {
                if (stream.Serializing)
                {
                    var localAddr = IsAddrV1Compatible ? SerializeV1Array() : IPV6_NONE;
                    stream.ReadWrite(ref localAddr);
                }
                else
                {
                    var localAddr = new byte[ADDR_IPV6_SIZE];
                    stream.ReadWrite(ref localAddr);
                    SetLegacyIpv6(localAddr);
                }
            }
            using (stream.BigEndianScope())
            {
                stream.ReadWrite(ref port);
            }
        }