github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/address/address.go (about) 1 // Package address contains the types used by yggdrasil to represent IPv6 addresses or prefixes, as well as functions for working with these types. 2 // Of particular importance are the functions used to derive addresses or subnets from a NodeID, or to get the NodeID and bitmask of the bits visible from an address, which is needed for DHT searches. 3 package address 4 5 import ( 6 "crypto/ed25519" 7 ) 8 9 // Address represents an IPv6 address in the yggdrasil address range. 10 type Address [16]byte 11 12 // Subnet represents an IPv6 /64 subnet in the yggdrasil subnet range. 13 type Subnet [8]byte 14 15 // GetPrefix returns the address prefix used by yggdrasil. 16 // The current implementation requires this to be a multiple of 8 bits + 7 bits. 17 // The 8th bit of the last byte is used to signal nodes (0) or /64 prefixes (1). 18 // Nodes that configure this differently will be unable to communicate with each other using IP packets, though routing and the DHT machinery *should* still work. 19 func GetPrefix() [1]byte { 20 return [...]byte{0x02} 21 } 22 23 // IsValid returns true if an address falls within the range used by nodes in the network. 24 func (a *Address) IsValid() bool { 25 prefix := GetPrefix() 26 for idx := range prefix { 27 if (*a)[idx] != prefix[idx] { 28 return false 29 } 30 } 31 return true 32 } 33 34 // IsValid returns true if a prefix falls within the range usable by the network. 35 func (s *Subnet) IsValid() bool { 36 prefix := GetPrefix() 37 l := len(prefix) 38 for idx := range prefix[:l-1] { 39 if (*s)[idx] != prefix[idx] { 40 return false 41 } 42 } 43 return (*s)[l-1] == prefix[l-1]|0x01 44 } 45 46 // AddrForKey takes an ed25519.PublicKey as an argument and returns an *Address. 47 // This function returns nil if the key length is not ed25519.PublicKeySize. 48 // This address begins with the contents of GetPrefix(), with the last bit set to 0 to indicate an address. 49 // The following 8 bits are set to the number of leading 1 bits in the bitwise inverse of the public key. 50 // The bitwise inverse of the key, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the address. 51 func AddrForKey(publicKey ed25519.PublicKey) *Address { 52 // 128 bit address 53 // Begins with prefix 54 // Next bit is a 0 55 // Next 7 bits, interpreted as a uint, are # of leading 1s in the NodeID 56 // Leading 1s and first leading 0 of the NodeID are truncated off 57 // The rest is appended to the IPv6 address (truncated to 128 bits total) 58 if len(publicKey) != ed25519.PublicKeySize { 59 return nil 60 } 61 var buf [ed25519.PublicKeySize]byte 62 copy(buf[:], publicKey) 63 for idx := range buf { 64 buf[idx] = ^buf[idx] 65 } 66 var addr Address 67 var temp = make([]byte, 0, 32) 68 done := false 69 ones := byte(0) 70 bits := byte(0) 71 nBits := 0 72 for idx := 0; idx < 8*len(buf); idx++ { 73 bit := (buf[idx/8] & (0x80 >> byte(idx%8))) >> byte(7-(idx%8)) 74 if !done && bit != 0 { 75 ones++ 76 continue 77 } 78 if !done && bit == 0 { 79 done = true 80 continue // FIXME? this assumes that ones <= 127, probably only worth changing by using a variable length uint64, but that would require changes to the addressing scheme, and I'm not sure ones > 127 is realistic 81 } 82 bits = (bits << 1) | bit 83 nBits++ 84 if nBits == 8 { 85 nBits = 0 86 temp = append(temp, bits) 87 } 88 } 89 prefix := GetPrefix() 90 copy(addr[:], prefix[:]) 91 addr[len(prefix)] = ones 92 copy(addr[len(prefix)+1:], temp) 93 return &addr 94 } 95 96 // SubnetForKey takes an ed25519.PublicKey as an argument and returns a *Subnet. 97 // This function returns nil if the key length is not ed25519.PublicKeySize. 98 // The subnet begins with the address prefix, with the last bit set to 1 to indicate a prefix. 99 // The following 8 bits are set to the number of leading 1 bits in the bitwise inverse of the key. 100 // The bitwise inverse of the key, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the subnet. 101 func SubnetForKey(publicKey ed25519.PublicKey) *Subnet { 102 // Exactly as the address version, with two exceptions: 103 // 1) The first bit after the fixed prefix is a 1 instead of a 0 104 // 2) It's truncated to a subnet prefix length instead of 128 bits 105 addr := AddrForKey(publicKey) 106 if addr == nil { 107 return nil 108 } 109 var snet Subnet 110 copy(snet[:], addr[:]) 111 prefix := GetPrefix() // nolint:staticcheck 112 snet[len(prefix)-1] |= 0x01 113 return &snet 114 } 115 116 // GetKet returns the partial ed25519.PublicKey for the Address. 117 // This is used for key lookup. 118 func (a *Address) GetKey() ed25519.PublicKey { 119 var key [ed25519.PublicKeySize]byte 120 prefix := GetPrefix() // nolint:staticcheck 121 ones := int(a[len(prefix)]) 122 for idx := 0; idx < ones; idx++ { 123 key[idx/8] |= 0x80 >> byte(idx%8) 124 } 125 keyOffset := ones + 1 126 addrOffset := 8*len(prefix) + 8 127 for idx := addrOffset; idx < 8*len(a); idx++ { 128 bits := a[idx/8] & (0x80 >> byte(idx%8)) 129 bits <<= byte(idx % 8) 130 keyIdx := keyOffset + (idx - addrOffset) 131 bits >>= byte(keyIdx % 8) 132 idx := keyIdx / 8 133 if idx >= len(key) { 134 break 135 } 136 key[idx] |= bits 137 } 138 for idx := range key { 139 key[idx] = ^key[idx] 140 } 141 return ed25519.PublicKey(key[:]) 142 } 143 144 // GetKet returns the partial ed25519.PublicKey for the Subnet. 145 // This is used for key lookup. 146 func (s *Subnet) GetKey() ed25519.PublicKey { 147 var addr Address 148 copy(addr[:], s[:]) 149 return addr.GetKey() 150 }