add lease, lease_set, mapping, router_address, router_identity, and router_info
This commit is contained in:
@ -94,3 +94,17 @@ func (c KeyCert) SigningPublicKey() (k crypto.SigningPublicKey) {
|
||||
// TODO: rsa/eddsa
|
||||
return
|
||||
}
|
||||
|
||||
func (c Certificate) signatureSize() int {
|
||||
sizes := map[int]int{
|
||||
KEYCERT_SIGN_DSA_SHA1: 40,
|
||||
KEYCERT_SIGN_P256: 64,
|
||||
KEYCERT_SIGN_P384: 96,
|
||||
KEYCERT_SIGN_P521: 132,
|
||||
KEYCERT_SIGN_RSA2048: 256,
|
||||
KEYCERT_SIGN_RSA3072: 384,
|
||||
KEYCERT_SIGN_RSA4096: 512,
|
||||
KEYCERT_SIGN_ED25519: 64,
|
||||
}
|
||||
return sizes[int(c.Type())]
|
||||
}
|
||||
|
7
lib/common/keys_and_cert.go
Normal file
7
lib/common/keys_and_cert.go
Normal file
@ -0,0 +1,7 @@
|
||||
package common
|
||||
|
||||
//
|
||||
// Both Destination and RouterIdentity share the same structure
|
||||
// https://geti2p.net/en/docs/spec/common-structures#struct_KeysAndCert
|
||||
// Perhaps we can avoid repeating ourselves being using commong functions
|
||||
//
|
28
lib/common/lease.go
Normal file
28
lib/common/lease.go
Normal file
@ -0,0 +1,28 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"github.com/bounce-chat/go-i2p/lib/tunnel"
|
||||
)
|
||||
|
||||
const (
|
||||
LEASE_SIZE = 44
|
||||
)
|
||||
|
||||
type Lease [LEASE_SIZE]byte
|
||||
|
||||
func (lease Lease) TunnelGateway() (h IdentHash) {
|
||||
copy(lease[:32], h[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (lease Lease) TunnelID() tunnel.TunnelID {
|
||||
return tunnel.TunnelID(
|
||||
binary.BigEndian.Uint32(lease[32:36]),
|
||||
)
|
||||
}
|
||||
|
||||
func (lease Lease) Date() (d Date) {
|
||||
copy(lease[36:], d[:])
|
||||
return
|
||||
}
|
85
lib/common/lease_set.go
Normal file
85
lib/common/lease_set.go
Normal file
@ -0,0 +1,85 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"github.com/bounce-chat/go-i2p/lib/crypto"
|
||||
)
|
||||
|
||||
type LeaseSet []byte
|
||||
|
||||
func (lease_set LeaseSet) Destination() Destination {
|
||||
return Destination(lease_set[:387])
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) EncryptionKey() (k crypto.ElgPublicKey) {
|
||||
copy(lease_set[387:387+256], k[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) SigningKey() (k []byte) {
|
||||
size := lease_set.signingKeySize()
|
||||
head := 387 + 256
|
||||
copy(lease_set[head:head+size], k)
|
||||
return
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) LeaseCount() int {
|
||||
head := 387 + 256 + lease_set.signingKeySize()
|
||||
var count int
|
||||
buf := bytes.NewReader(
|
||||
[]byte{lease_set[head+1]},
|
||||
)
|
||||
binary.Read(buf, binary.BigEndian, &count)
|
||||
return count
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) Leases() []Lease {
|
||||
leases := make([]Lease, 0)
|
||||
offset := 387 + 256 + lease_set.signingKeySize() + 1
|
||||
for i := 0; i < lease_set.LeaseCount(); i++ {
|
||||
start := offset + (i * LEASE_SIZE)
|
||||
end := offset + (start + LEASE_SIZE)
|
||||
var lease Lease
|
||||
copy(lease_set[start:end], lease[:])
|
||||
leases = append(leases, lease)
|
||||
}
|
||||
return leases
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) Signature() []byte {
|
||||
data_end := 387 +
|
||||
256 +
|
||||
lease_set.signingKeySize() +
|
||||
1 +
|
||||
(LEASE_SIZE * lease_set.LeaseCount())
|
||||
sig_size := lease_set.
|
||||
Destination().
|
||||
Certificate().
|
||||
signatureSize()
|
||||
return lease_set[data_end : data_end+sig_size]
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) Verify() error {
|
||||
data_end := 387 +
|
||||
256 +
|
||||
lease_set.signingKeySize() +
|
||||
1 +
|
||||
(LEASE_SIZE * lease_set.LeaseCount())
|
||||
data := lease_set[:data_end]
|
||||
verifier, err := lease_set.
|
||||
Destination().
|
||||
SigningPublicKey().
|
||||
NewVerifier()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return verifier.Verify(data, lease_set.Signature())
|
||||
}
|
||||
|
||||
func (lease_set LeaseSet) signingKeySize() int {
|
||||
return lease_set.
|
||||
Destination().
|
||||
SigningPublicKey().
|
||||
Len()
|
||||
}
|
41
lib/common/mapping.go
Normal file
41
lib/common/mapping.go
Normal file
@ -0,0 +1,41 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Mapping []byte
|
||||
|
||||
func (mapping Mapping) ToMap() map[string]string {
|
||||
gomap := make(map[string]string)
|
||||
kv_store := string(mapping[2:])
|
||||
pairs := strings.Split(kv_store, ";")
|
||||
for _, pair := range pairs {
|
||||
values := strings.Split(pair, "=")
|
||||
if len(values) != 2 {
|
||||
continue
|
||||
}
|
||||
gomap[values[0]] = values[1]
|
||||
}
|
||||
return gomap
|
||||
}
|
||||
|
||||
func MappingFromMap(gomap map[string]string) Mapping {
|
||||
kv_store := make([]byte, 0)
|
||||
for k, v := range gomap {
|
||||
key_bytes := []byte(k)
|
||||
key_bytes = append(key_bytes, 0x3d)
|
||||
value_bytes := []byte(v)
|
||||
value_bytes = append(value_bytes, 0x3b)
|
||||
kv_store = append(kv_store, key_bytes...)
|
||||
kv_store = append(kv_store, value_bytes...)
|
||||
}
|
||||
kv_size := uint16(len(kv_store))
|
||||
var size [2]byte
|
||||
binary.BigEndian.PutUint16(size[:], kv_size)
|
||||
mapping := Mapping{}
|
||||
mapping = append(mapping, size[:]...)
|
||||
mapping = append(mapping, kv_store...)
|
||||
return mapping
|
||||
}
|
37
lib/common/mapping_test.go
Normal file
37
lib/common/mapping_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestToMapping(t *testing.T) {
|
||||
gomap := map[string]string{
|
||||
"a": "1",
|
||||
}
|
||||
mapping := MappingFromMap(gomap)
|
||||
if !bytes.Equal(mapping, []byte{0x00, 0x04, 0x61, 0x3d, 0x31, 0x3b}) {
|
||||
t.Fatal("go map to mapping did not create correct mapping")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMappingToMap(t *testing.T) {
|
||||
mapping := Mapping{0x00, 0x08, 0x61, 0x3d, 0x31, 0x3b, 0x62, 0x3d, 0x32, 0x3b}
|
||||
gomap := mapping.ToMap()
|
||||
if gomap["a"] != "1" {
|
||||
t.Fatal("map does not contain encoded data")
|
||||
}
|
||||
if gomap["b"] != "2" {
|
||||
t.Fatal("map does not comtain encoded data")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToAndFromMapping(t *testing.T) {
|
||||
gomap := make(map[string]string)
|
||||
gomap["foo"] = "bar"
|
||||
mapping := MappingFromMap(gomap)
|
||||
gomap2 := mapping.ToMap()
|
||||
if gomap["foo"] != gomap2["foo"] {
|
||||
t.Fatal("rebuilt map has different data")
|
||||
}
|
||||
}
|
57
lib/common/router_address.go
Normal file
57
lib/common/router_address.go
Normal file
@ -0,0 +1,57 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
type RouterAddress []byte
|
||||
|
||||
func (router_address RouterAddress) Cost() int {
|
||||
var cost int
|
||||
buf := bytes.NewReader(
|
||||
[]byte{router_address[0]},
|
||||
)
|
||||
binary.Read(buf, binary.BigEndian, &cost)
|
||||
return cost
|
||||
}
|
||||
|
||||
func (router_address RouterAddress) Expiration() (d Date) {
|
||||
copy(router_address[1:8], d[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (router_address RouterAddress) TransportStyle() string {
|
||||
return string(
|
||||
router_address[10:router_address.stringLength()],
|
||||
)
|
||||
}
|
||||
|
||||
func (router_address RouterAddress) Options() Mapping {
|
||||
var mapping Mapping
|
||||
copy(router_address[9+router_address.stringLength():], mapping[:])
|
||||
return mapping
|
||||
}
|
||||
|
||||
func (router_address RouterAddress) stringLength() int {
|
||||
var string_len int
|
||||
buf := bytes.NewReader(
|
||||
[]byte{router_address[9]},
|
||||
)
|
||||
binary.Read(buf, binary.BigEndian, &string_len)
|
||||
return string_len
|
||||
|
||||
}
|
||||
|
||||
func readRouterAddress(data []byte) (RouterAddress, []byte, error) {
|
||||
var router_address RouterAddress
|
||||
copy(data[:10], router_address)
|
||||
|
||||
string_len := router_address.stringLength()
|
||||
router_address = append(router_address, data[10:10+string_len]...)
|
||||
|
||||
options_len := int(binary.BigEndian.Uint16(data[string_len+10 : string_len+11]))
|
||||
router_address = append(router_address, data[string_len+10:11+string_len+options_len]...)
|
||||
|
||||
return router_address, data[:], nil
|
||||
}
|
41
lib/common/router_identity.go
Normal file
41
lib/common/router_identity.go
Normal file
@ -0,0 +1,41 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/bounce-chat/go-i2p/lib/crypto"
|
||||
)
|
||||
|
||||
type RouterIdentity []byte
|
||||
|
||||
func (router_identity RouterIdentity) PublicKey() (key crypto.ElgPublicKey) {
|
||||
copy(router_identity[:256], key[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (router_identity RouterIdentity) SigningPublicKey() (key crypto.SigningPublicKey) {
|
||||
cert := router_identity.Certificate()
|
||||
if cert.Type() == CERT_KEY {
|
||||
key = KeyCert(cert).SigningPublicKey()
|
||||
} else {
|
||||
var pk crypto.DSAPublicKey
|
||||
copy(pk[:], router_identity[256:256+128])
|
||||
key = pk
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (router_identity RouterIdentity) Certificate() (cert Certificate) {
|
||||
copy(router_identity[256+128:], cert)
|
||||
return
|
||||
}
|
||||
|
||||
func readRouterIdentity(data []byte) (RouterIdentity, []byte, error) {
|
||||
var router_identity RouterIdentity
|
||||
copy(data[:387], router_identity)
|
||||
n := router_identity.Certificate().Len()
|
||||
if n == -1 {
|
||||
return router_identity, data, errors.New("invalid certificate")
|
||||
}
|
||||
router_identity = append(router_identity, data[387:n]...)
|
||||
return router_identity, data[387+n:], nil
|
||||
}
|
77
lib/common/router_info.go
Normal file
77
lib/common/router_info.go
Normal file
@ -0,0 +1,77 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
type RouterInfo []byte
|
||||
|
||||
func (router_info RouterInfo) RouterIdentity() RouterIdentity {
|
||||
router_identity, _, _ := readRouterIdentity(router_info)
|
||||
return router_identity
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) Published() (d Date) {
|
||||
_, remainder, _ := readRouterIdentity(router_info)
|
||||
copy(remainder[:8], d[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) RouterAddressCount() int {
|
||||
_, remainder, _ := readRouterIdentity(router_info)
|
||||
var count int
|
||||
buf := bytes.NewReader(
|
||||
[]byte{remainder[8]},
|
||||
)
|
||||
binary.Read(buf, binary.BigEndian, &count)
|
||||
return count
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) RouterAddresses() []RouterAddress {
|
||||
var router_address RouterAddress
|
||||
remaining := router_info[9:]
|
||||
var err error
|
||||
addresses := make([]RouterAddress, 0)
|
||||
for i := 0; i < router_info.RouterAddressCount(); i++ {
|
||||
router_address, remaining, err = readRouterAddress(remaining)
|
||||
addresses = append(addresses, router_address)
|
||||
}
|
||||
return addresses
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) PeerSize() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) Options() Mapping {
|
||||
head := router_info.optionsLocation()
|
||||
size := head + router_info.optionsSize()
|
||||
return Mapping(router_info[head:size])
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) Signature() []byte {
|
||||
offset := router_info.optionsLocation() + router_info.optionsSize()
|
||||
sig_size := router_info.
|
||||
RouterIdentity().
|
||||
Certificate().
|
||||
signatureSize()
|
||||
return router_info[offset:sig_size]
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) optionsLocation() int {
|
||||
offset := 9
|
||||
var router_address RouterAddress
|
||||
remaining := router_info[9:]
|
||||
var err error
|
||||
for i := 0; i < router_info.RouterAddressCount(); i++ {
|
||||
router_address, remaining, err = readRouterAddress(remaining)
|
||||
offset := len(router_address)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (router_info RouterInfo) optionsSize() int {
|
||||
head := router_info.optionsLocation()
|
||||
return int(binary.BigEndian.Uint16(router_info[head : head+1]))
|
||||
}
|
Reference in New Issue
Block a user