-
Notifications
You must be signed in to change notification settings - Fork 297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
multi: Add getaddrv2 and addrv2. #2627
base: master
Are you sure you want to change the base?
Changes from 1 commit
650a935
77e2118
2d13ac7
a32aa05
ddf3d7d
27215a0
404ec69
c8b98b1
3632c29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,13 @@ func (netAddr *NetAddress) ipString() string { | |
case TORv2Address: | ||
base32 := base32.StdEncoding.EncodeToString(netIP[6:]) | ||
return strings.ToLower(base32) + ".onion" | ||
case TORv3Address: | ||
addrBytes := netIP | ||
checksum := calcTORv3Checksum(addrBytes) | ||
addrBytes = append(addrBytes, checksum[:]...) | ||
addrBytes = append(addrBytes, torV3VersionByte) | ||
base32 := base32.StdEncoding.EncodeToString(addrBytes) | ||
return strings.ToLower(base32) + ".onion" | ||
} | ||
return net.IP(netIP).String() | ||
} | ||
|
@@ -104,7 +111,7 @@ func canonicalizeIP(addrType NetAddressType, addrBytes []byte) []byte { | |
// deriveNetAddressType attempts to determine the network address type from | ||
// the address' raw bytes. If the type cannot be determined, an error is | ||
// returned. | ||
func deriveNetAddressType(addrBytes []byte) (NetAddressType, error) { | ||
func deriveNetAddressType(claimedType NetAddressType, addrBytes []byte) (NetAddressType, error) { | ||
len := len(addrBytes) | ||
switch { | ||
case isIPv4(addrBytes): | ||
|
@@ -113,6 +120,8 @@ func deriveNetAddressType(addrBytes []byte) (NetAddressType, error) { | |
return TORv2Address, nil | ||
case len == 16: | ||
return IPv6Address, nil | ||
case len == 32 && claimedType == TORv3Address: | ||
return TORv3Address, nil | ||
} | ||
strErr := fmt.Sprintf("unable to determine address type from raw network "+ | ||
"address bytes: %v", addrBytes) | ||
|
@@ -122,7 +131,7 @@ func deriveNetAddressType(addrBytes []byte) (NetAddressType, error) { | |
// assertNetAddressTypeValid returns an error if the suggested address type does | ||
// not appear to match the provided address. | ||
func assertNetAddressTypeValid(netAddressType NetAddressType, addrBytes []byte) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would suggest calling this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, perhaps these should all be consistent with the param name. Either one is fine, but I would prefer they are all consistent. |
||
derivedAddressType, err := deriveNetAddressType(addrBytes) | ||
derivedAddressType, err := deriveNetAddressType(netAddressType, addrBytes) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -184,7 +193,7 @@ func (a *AddrManager) newAddressFromString(addr string) (*NetAddress, error) { | |
// MUST be an IPv4, IPv6, or TORv2 address since this method does not perform | ||
// error checking on the derived network address type. | ||
func NewNetAddressIPPort(ip net.IP, port uint16, services wire.ServiceFlag) *NetAddress { | ||
netAddressType, _ := deriveNetAddressType(ip) | ||
netAddressType, _ := deriveNetAddressType(UnknownAddressType, ip) | ||
timestamp := time.Unix(time.Now().Unix(), 0) | ||
canonicalizedIP := canonicalizeIP(netAddressType, ip) | ||
return &NetAddress{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,10 +6,17 @@ | |
package addrmgr | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"net" | ||
|
||
"golang.org/x/crypto/sha3" | ||
) | ||
|
||
// torV3VersionByte represents the version byte used when encoding and decoding | ||
// a torv3 host name. | ||
const torV3VersionByte = byte(3) | ||
|
||
var ( | ||
// rfc1918Nets specifies the IPv4 private address blocks as defined by | ||
// by RFC1918 (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16). | ||
|
@@ -125,6 +132,7 @@ const ( | |
IPv4Address | ||
IPv6Address | ||
TORv2Address | ||
TORv3Address | ||
) | ||
|
||
// NetAddressTypeFilter represents a function that returns whether a particular | ||
|
@@ -224,6 +232,39 @@ func isRFC6598(netIP net.IP) bool { | |
return rfc6598Net.Contains(netIP) | ||
} | ||
|
||
// calcTORv3Checksum returns the checksum bytes given a 32 byte | ||
// TORv3 public key. | ||
func calcTORv3Checksum(publicKey []byte) []byte { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest using fixed-size and stack allocated code here to make it allocation free since it appears like this code will be called quite frequently. e.g.: func calcTORv3Checksum(publicKey [32]byte) [2]byte {
const (
prefix = ".onion checksum"
prefixLen = len(prefix)
inputLen = prefixLen + len(publicKey) + 1
)
var input [inputLen]byte
copy(input[:], prefix)
copy(input[prefixLen:], publicKey[:])
input[inputLen-1] = torV3VersionByte
digest := sha3.Sum256(input[:])
var result [2]byte
copy(result[:], digest[:])
return result
} Naturally the calling code needs to be updated to copy instead of sending in byte slices too. The result will end up being faster and avoid churning the GC. |
||
checkSumInput := []byte(".onion checksum") | ||
checkSumInput = append(checkSumInput, publicKey...) | ||
checkSumInput = append(checkSumInput, torV3VersionByte) | ||
digest := sha3.Sum256(checkSumInput) | ||
return digest[:2] | ||
} | ||
|
||
// isTORv3 returns whether or not the passed address is a valid TORv3 address | ||
// with the checksum and version bytes. If it is valid, it also returns the | ||
// public key of the tor v3 address. | ||
func isTORv3(addressBytes []byte) ([]byte, bool) { | ||
if len(addressBytes) != 35 { | ||
return nil, false | ||
} | ||
|
||
version := addressBytes[34] | ||
if version != torV3VersionByte { | ||
return nil, false | ||
} | ||
|
||
publicKey := addressBytes[:32] | ||
computedChecksum := calcTORv3Checksum(publicKey) | ||
checksum := addressBytes[32:34] | ||
if !bytes.Equal(computedChecksum, checksum) { | ||
return nil, false | ||
} | ||
|
||
return publicKey, true | ||
} | ||
|
||
// isValid returns whether or not the passed address is valid. The address is | ||
// considered invalid under the following circumstances: | ||
// IPv4: It is either a zero or all bits set address. | ||
|
@@ -266,7 +307,6 @@ func (na *NetAddress) GroupKey() string { | |
newIP := netIP[12:16] | ||
return newIP.Mask(net.CIDRMask(16, 32)).String() | ||
} | ||
|
||
if isRFC3964(netIP) { | ||
newIP := netIP[2:6] | ||
return newIP.Mask(net.CIDRMask(16, 32)).String() | ||
|
@@ -281,8 +321,12 @@ func (na *NetAddress) GroupKey() string { | |
return newIP.Mask(net.CIDRMask(16, 32)).String() | ||
} | ||
if na.Type == TORv2Address { | ||
// group is keyed off the first 4 bits of the actual onion key. | ||
return fmt.Sprintf("tor:%d", netIP[6]&((1<<4)-1)) | ||
// Group is keyed off the first 4 bits of the actual onion key. | ||
return fmt.Sprintf("torv2:%d", netIP[6]&((1<<4)-1)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't changing this mess up all of the existing entries? |
||
} | ||
if na.Type == TORv3Address { | ||
// Group is keyed off the first 4 bits of the public key. | ||
return fmt.Sprintf("torv3:%d", netIP[0]&((1<<4)-1)) | ||
} | ||
|
||
// OK, so now we know ourselves to be a IPv6 address. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything else in the code base tends to use
str
for these name here. Not a big deal, but would be better for consistency.