mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-05 06:05:16 -04:00
Tweak godocs for lib/common
This commit is contained in:
@ -1,18 +1,23 @@
|
||||
//
|
||||
// base32 encoding using I2P's alphabet
|
||||
//
|
||||
// Package base32 implmenets utilities for encoding and decoding text using I2P's alphabet
|
||||
package base32
|
||||
|
||||
import (
|
||||
b32 "encoding/base32"
|
||||
)
|
||||
|
||||
var I2PEncoding *b32.Encoding = b32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
|
||||
// I2PEncodeAlphabet is the base32 encoding used throughout I2P.
|
||||
// RFC 3548 using lowercase characters.
|
||||
const I2PEncodeAlphabet = "abcdefghijklmnopqrstuvwxyz234567"
|
||||
|
||||
//
|
||||
// Return a go string of the I2P base32
|
||||
// encoding of the provided byte slice
|
||||
//
|
||||
// I2PEncoding is the standard base32 encoding used through I2P.
|
||||
var I2PEncoding *b32.Encoding = b32.NewEncoding(I2PEncodeAlphabet)
|
||||
|
||||
// EncodeToString encodes []byte to a base32 string using I2PEncoding
|
||||
func EncodeToString(data []byte) string {
|
||||
return I2PEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
// DecodeString decodes base64 string to []byte I2PEncoding
|
||||
func DecodeString(data string) ([]byte, error) {
|
||||
return I2PEncoding.DecodeString(data)
|
||||
}
|
||||
|
20
lib/common/base32/base32_test.go
Normal file
20
lib/common/base32/base32_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package base32
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeNotMangled(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Random pangram
|
||||
testInput := []byte("How vexingly quick daft zebras jump!")
|
||||
|
||||
encodedString := EncodeToString(testInput)
|
||||
decodedString, err := DecodeString(encodedString)
|
||||
assert.Nil(err)
|
||||
|
||||
assert.ElementsMatch(testInput, decodedString)
|
||||
}
|
@ -1,30 +1,23 @@
|
||||
//
|
||||
// base64 encoding using I2P's alphabet
|
||||
//
|
||||
// Package base64 implmenets utilities for encoding and decoding text using I2P's alphabet
|
||||
package base64
|
||||
|
||||
import (
|
||||
b64 "encoding/base64"
|
||||
)
|
||||
|
||||
// i2p base64 alphabet
|
||||
const Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"
|
||||
// I2PEncodeAlphabet is the base64 encoding used throughout I2P.
|
||||
// RFC 4648 with "/"" replaced with "~", and "+" replaced with "-".
|
||||
const I2PEncodeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"
|
||||
|
||||
// i2p base64 encoding
|
||||
var I2PEncoding *b64.Encoding = b64.NewEncoding(Alphabet)
|
||||
// I2PEncoding is the standard base64 encoding used through I2P.
|
||||
var I2PEncoding *b64.Encoding = b64.NewEncoding(I2PEncodeAlphabet)
|
||||
|
||||
//
|
||||
// Return a go string of the I2P base64
|
||||
// encoding of the provided byte slice
|
||||
//
|
||||
// I2PEncoding is the standard base64 encoding used through I2P.
|
||||
func EncodeToString(data []byte) string {
|
||||
return I2PEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
//
|
||||
// decode string using i2p base64 encoding
|
||||
// returns error if data is malfromed
|
||||
//
|
||||
func DecodeFromString(str string) (d []byte, err error) {
|
||||
// DecodeString decodes base64 string to []byte I2PEncoding
|
||||
func DecodeString(str string) ([]byte, error) {
|
||||
return I2PEncoding.DecodeString(str)
|
||||
}
|
||||
|
20
lib/common/base64/base64_test.go
Normal file
20
lib/common/base64/base64_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package base64
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeNotMangled(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Random pangram
|
||||
testInput := []byte("Glib jocks quiz nymph to vex dwarf.")
|
||||
|
||||
encodedString := EncodeToString(testInput)
|
||||
decodedString, err := DecodeString(encodedString)
|
||||
assert.Nil(err)
|
||||
|
||||
assert.ElementsMatch(testInput, decodedString)
|
||||
}
|
@ -1,9 +1,39 @@
|
||||
// Package certificate implements the certificate common-structure of I2P.
|
||||
|
||||
package certificate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
)
|
||||
|
||||
// Certificate Types
|
||||
const (
|
||||
CERT_NULL = iota
|
||||
CERT_HASHCASH
|
||||
CERT_HIDDEN
|
||||
CERT_SIGNED
|
||||
CERT_MULTIPLE
|
||||
CERT_KEY
|
||||
)
|
||||
|
||||
// CERT_MIN_SIZE is the minimum size of a valid Certificate in []byte
|
||||
// 1 byte for type
|
||||
// 2 bytes for payload length
|
||||
const CERT_MIN_SIZE = 3
|
||||
|
||||
/*
|
||||
I2P Certificate
|
||||
https://geti2p.net/spec/common-structures#certificate
|
||||
Accurate for version 0.9.24
|
||||
[I2P Certificate]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
A certifificate is a container for various receipts of proof of works used throughout the I2P network.
|
||||
|
||||
Contents
|
||||
1 byte Integer specifying certificate type, followed by a 2 byte Integer specifying the size of the certificate playload, then that many bytes.
|
||||
|
||||
+----+----+----+----+----+-//
|
||||
|type| length | payload
|
||||
@ -26,49 +56,32 @@ payload :: data
|
||||
length -> $length bytes
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
)
|
||||
|
||||
// Certificate Types
|
||||
const (
|
||||
CERT_NULL = iota
|
||||
CERT_HASHCASH
|
||||
CERT_HIDDEN
|
||||
CERT_SIGNED
|
||||
CERT_MULTIPLE
|
||||
CERT_KEY
|
||||
)
|
||||
|
||||
// Minimum size of a valid Certificate
|
||||
const (
|
||||
CERT_MIN_SIZE = 3
|
||||
)
|
||||
|
||||
// Certificate is the representation of an I2P Certificate.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#certificate
|
||||
type Certificate struct {
|
||||
kind Integer
|
||||
leng Integer
|
||||
payl []byte
|
||||
len Integer
|
||||
payload []byte
|
||||
}
|
||||
|
||||
// RawBytes returns the entire certificate in []byte form, includes excess payload data.
|
||||
func (c *Certificate) RawBytes() []byte {
|
||||
bytes := c.kind.Bytes()
|
||||
bytes = append(bytes, c.leng.Bytes()...)
|
||||
bytes = append(bytes, c.payl...)
|
||||
bytes = append(bytes, c.len.Bytes()...)
|
||||
bytes = append(bytes, c.payload...)
|
||||
return bytes
|
||||
}
|
||||
|
||||
// ExcessBytes returns the excess bytes in a certificate found after the specified payload length.
|
||||
func (c *Certificate) ExcessBytes() []byte {
|
||||
return c.payl[c.leng.Int():]
|
||||
return c.payload[c.len.Int():]
|
||||
}
|
||||
|
||||
// Bytes returns the entire certificate in []byte form, trims payload to specified length.
|
||||
func (c *Certificate) Bytes() []byte {
|
||||
bytes := c.kind.Bytes()
|
||||
bytes = append(bytes, c.leng.Bytes()...)
|
||||
bytes = append(bytes, c.len.Bytes()...)
|
||||
bytes = append(bytes, c.Data()...)
|
||||
return bytes
|
||||
}
|
||||
@ -78,44 +91,37 @@ func (c *Certificate) length() (cert_len int) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Certificate Type specified in the first byte of the Certificate,
|
||||
// and an error if the certificate is shorter than the minimum certificate size.
|
||||
//
|
||||
// Type returns the Certificate type specified in the first byte of the Certificate,
|
||||
func (c *Certificate) Type() (cert_type int) {
|
||||
cert_type = c.kind.Int()
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Look up the length of the Certificate, reporting errors if the certificate is
|
||||
// shorter than the minimum certificate size or if the reported length doesn't
|
||||
// match the provided data.
|
||||
//
|
||||
// Length returns the payload length of a Certificate.
|
||||
func (c *Certificate) Length() (length int) {
|
||||
length = c.leng.Int()
|
||||
length = c.len.Int()
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Certificate data and any errors encountered parsing the Certificate.
|
||||
//
|
||||
// Data returns the payload of a Certificate, payload is trimmed to the specified length.
|
||||
func (c *Certificate) Data() (data []byte) {
|
||||
lastElement := c.Length()
|
||||
if lastElement > len(c.payl) {
|
||||
data = c.payl
|
||||
if lastElement > len(c.payload) {
|
||||
data = c.payload
|
||||
} else {
|
||||
data = c.payl[0:lastElement]
|
||||
data = c.payload[0:lastElement]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewCertificate creates a new Certficiate from []byte
|
||||
// returns err if the certificate is too short or if the payload doesn't match specified length.
|
||||
func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
certificate = &Certificate{}
|
||||
switch len(data) {
|
||||
case 0:
|
||||
certificate.kind = Integer([]byte{0})
|
||||
certificate.leng = Integer([]byte{0})
|
||||
certificate.len = Integer([]byte{0})
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
@ -125,7 +131,7 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
return
|
||||
case 1:
|
||||
certificate.kind = Integer(data[0:0])
|
||||
certificate.leng = Integer([]byte{0})
|
||||
certificate.len = Integer([]byte{0})
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
@ -135,7 +141,7 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
return
|
||||
case 2:
|
||||
certificate.kind = Integer(data[0:1])
|
||||
certificate.leng = Integer([]byte{0})
|
||||
certificate.len = Integer([]byte{0})
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
@ -145,23 +151,23 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
return
|
||||
default:
|
||||
certificate.kind = Integer(data[0:1])
|
||||
certificate.leng = Integer(data[1:3])
|
||||
certificate.len = Integer(data[1:3])
|
||||
payleng := len(data) - CERT_MIN_SIZE
|
||||
certificate.payl = data[CERT_MIN_SIZE:]
|
||||
if certificate.leng.Int() > len(data)-CERT_MIN_SIZE {
|
||||
certificate.payload = data[CERT_MIN_SIZE:]
|
||||
if certificate.len.Int() > len(data)-CERT_MIN_SIZE {
|
||||
err = fmt.Errorf("certificate parsing warning: certificate data is shorter than specified by length")
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": certificate.leng.Int(),
|
||||
"certificate_bytes_length": certificate.len.Int(),
|
||||
"certificate_payload_length": payleng,
|
||||
"reason": err.Error(),
|
||||
}).Error("invalid certificate")
|
||||
return
|
||||
} else if certificate.leng.Int() < len(data)-CERT_MIN_SIZE {
|
||||
} else if certificate.len.Int() < len(data)-CERT_MIN_SIZE {
|
||||
err = fmt.Errorf("certificate parsing warning: certificate data is longer than specified by length")
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": certificate.leng.Int(),
|
||||
"certificate_bytes_length": certificate.len.Int(),
|
||||
"certificate_payload_length": payleng,
|
||||
"reason": err.Error(),
|
||||
}).Error("invalid certificate")
|
||||
@ -171,10 +177,8 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read a Certificate from a slice of bytes, returning any extra data on the end of the slice
|
||||
// and any errors if a valid Certificate could not be read.
|
||||
//
|
||||
// ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input.
|
||||
// returns err if the certificate could not be read.
|
||||
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
||||
certificate, err = NewCertificate(data)
|
||||
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
||||
|
@ -1,11 +1,6 @@
|
||||
// Package data implements common data structures used in higher level structures.
|
||||
package data
|
||||
|
||||
/*
|
||||
I2P Date
|
||||
https://geti2p.net/spec/common-structures#date
|
||||
Accurate for version 0.9.24
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
@ -13,32 +8,47 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DATE_SIZE is the length in bytes of an I2P Date.
|
||||
const DATE_SIZE = 8
|
||||
|
||||
/*
|
||||
[I2P Date]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
The number of milliseconds since midnight on Januyar 1, 1970 in the GMT timezone.
|
||||
If the number is 0, the date is undefined or null.
|
||||
|
||||
Contents
|
||||
8 byte Integer
|
||||
*/
|
||||
|
||||
// Date is the represenation of an I2P Date.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#date
|
||||
type Date [8]byte
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// Bytes returns the raw []byte content of a Date.
|
||||
func (i Date) Bytes() []byte {
|
||||
return i[:]
|
||||
}
|
||||
|
||||
// Int returns the Date as a Go integer.
|
||||
func (i Date) Int() int {
|
||||
return intFromBytes(i.Bytes())
|
||||
}
|
||||
|
||||
//
|
||||
// Time takes the value stored in date as an 8 byte big-endian integer representing the
|
||||
// number of milliseconds since the beginning of unix time and converts it to a Go time.Time
|
||||
// struct.
|
||||
//
|
||||
func (date Date) Time() (date_time time.Time) {
|
||||
seconds := Integer(date[:])
|
||||
date_time = time.Unix(0, int64(seconds.Int()*1000000))
|
||||
return
|
||||
}
|
||||
|
||||
// ReadDate creates a Date from []byte using the first DATE_SIZE bytes.
|
||||
// Any data after DATE_SIZE is returned as a remainder.
|
||||
func ReadDate(data []byte) (date Date, remainder []byte, err error) {
|
||||
if len(data) < 8 {
|
||||
log.WithFields(log.Fields{
|
||||
@ -52,6 +62,8 @@ func ReadDate(data []byte) (date Date, remainder []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewDate creates a new Date from []byte using ReadDate.
|
||||
// Returns a pointer to Date unlike ReadDate.
|
||||
func NewDate(data []byte) (date *Date, remainder []byte, err error) {
|
||||
objdate, remainder, err := ReadDate(data)
|
||||
date = &objdate
|
||||
|
@ -2,9 +2,7 @@ package data
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Sometimes we recieve a whole list of errors from a compound operation
|
||||
// like constructing a Map. We want to print them all out so we can see
|
||||
// what's wrong.
|
||||
// WrapErrors compiles a slice of errors and returns them wrapped together as a single error.
|
||||
func WrapErrors(errs []error) error {
|
||||
var err error
|
||||
for i, e := range errs {
|
||||
@ -13,7 +11,7 @@ func WrapErrors(errs []error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prints a list of errors to the console.
|
||||
// PrintErrors prints a formatted list of errors to the console.
|
||||
func PrintErrors(errs []error) {
|
||||
for i, e := range errs {
|
||||
fmt.Printf("\t%d: %v\n", i, e)
|
||||
|
@ -5,16 +5,31 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// sha256 hash of some data
|
||||
/*
|
||||
[I2P Hash]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Represents the SHA256 of some data.
|
||||
|
||||
Contents
|
||||
32 bytes
|
||||
|
||||
[I2P Hash]:
|
||||
*/
|
||||
|
||||
// Hash is the represenation of an I2P Hash.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#hash
|
||||
type Hash [32]byte
|
||||
|
||||
// calculate sha256 of a byte slice
|
||||
// HashData returns the SHA256 sum of a []byte input as Hash.
|
||||
func HashData(data []byte) (h Hash) {
|
||||
h = sha256.Sum256(data)
|
||||
return
|
||||
}
|
||||
|
||||
// calulate sha256 of all data being read from an io.Reader
|
||||
// HashReader returns the SHA256 sum from all data read from an io.Reader.
|
||||
// return error if one occurs while reading from reader
|
||||
func HashReader(r io.Reader) (h Hash, err error) {
|
||||
sha := sha256.New()
|
||||
|
@ -1,39 +1,40 @@
|
||||
package data
|
||||
|
||||
/*
|
||||
I2P Integer
|
||||
https://geti2p.net/spec/common-structures#integer
|
||||
Accurate for version 0.9.24
|
||||
|
||||
Description
|
||||
|
||||
Represents a non-negative integer.
|
||||
|
||||
Contents
|
||||
|
||||
1 to 8 bytes in network byte order (big endian) representing an unsigned integer.
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// Total byte length of an I2P integer
|
||||
const (
|
||||
MAX_INTEGER_SIZE = 8
|
||||
)
|
||||
// MAX_INTEGER_SIZE is the maximum length of an I2P integer in bytes.
|
||||
const MAX_INTEGER_SIZE = 8
|
||||
|
||||
/*
|
||||
[I2P Hash]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Represents a non-negative integer.
|
||||
|
||||
Contents
|
||||
1 to 8 bytes in network byte order (big endian) representing an unsigned integer.
|
||||
*/
|
||||
|
||||
// Integer is the represenation of an I2P Integer.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#integer
|
||||
type Integer []byte
|
||||
|
||||
// Bytes returns the raw []byte content of an Integer.
|
||||
func (i Integer) Bytes() []byte {
|
||||
return i[:]
|
||||
}
|
||||
|
||||
// Int returns the Date as a Go integer
|
||||
func (i Integer) Int() int {
|
||||
return intFromBytes(i.Bytes())
|
||||
}
|
||||
|
||||
// ReadInteger returns an Integer from a []byte of specified length.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
func ReadInteger(bytes []byte, size int) (Integer, []byte) {
|
||||
if len(bytes) < size {
|
||||
return bytes[:size], bytes[len(bytes):]
|
||||
@ -41,6 +42,9 @@ func ReadInteger(bytes []byte, size int) (Integer, []byte) {
|
||||
return bytes[:size], bytes[size:]
|
||||
}
|
||||
|
||||
// NewInteger creates a new Integer from []byte using ReadInteger.
|
||||
// Limits the length of the created Integer to MAX_INTEGER_SIZE.
|
||||
// Returns a pointer to Integer unlike ReadInteger.
|
||||
func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err error) {
|
||||
integerSize := MAX_INTEGER_SIZE
|
||||
if size < MAX_INTEGER_SIZE {
|
||||
@ -51,6 +55,7 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err
|
||||
return
|
||||
}
|
||||
|
||||
// NewIntegerFromInt creates a new Integer from a Go integer of a specified []byte length.
|
||||
func NewIntegerFromInt(value int, size int) (integer *Integer, err error) {
|
||||
bytes := make([]byte, MAX_INTEGER_SIZE)
|
||||
binary.BigEndian.PutUint64(bytes, uint64(value))
|
||||
@ -63,10 +68,8 @@ func NewIntegerFromInt(value int, size int) (integer *Integer, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Interpret a slice of bytes from length 0 to length 8 as a big-endian
|
||||
// integer and return an int representation.
|
||||
//
|
||||
func intFromBytes(number []byte) (value int) {
|
||||
num_len := len(number)
|
||||
if num_len < MAX_INTEGER_SIZE {
|
||||
|
@ -1,9 +1,21 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*
|
||||
I2P Mapping
|
||||
https://geti2p.net/spec/common-structures#mapping
|
||||
Accurate for version 0.9.24
|
||||
[I2P Mapping]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
A set of key/value mappings or properties
|
||||
|
||||
|
||||
Contents
|
||||
A 2-byte size Integer followed by a series of String=String; pairs
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| size |key_string (len + data) | = |
|
||||
@ -25,20 +37,15 @@ val_string :: String
|
||||
; :: A single byte containing ';'
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Mapping is the represenation of an I2P Mapping.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#mapping
|
||||
type Mapping struct {
|
||||
size *Integer
|
||||
vals *MappingValues
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the values contained in a Mapping in the form of a MappingValues.
|
||||
//
|
||||
// Values returns the values contained in a Mapping as MappingValues.
|
||||
func (mapping Mapping) Values() MappingValues {
|
||||
if mapping.vals == nil {
|
||||
return MappingValues{}
|
||||
@ -46,6 +53,7 @@ func (mapping Mapping) Values() MappingValues {
|
||||
return *mapping.vals
|
||||
}
|
||||
|
||||
// Data returns a Mapping in its []byte form.
|
||||
func (mapping *Mapping) Data() []byte {
|
||||
keyOrValIntegerLength := 1
|
||||
bytes := mapping.size.Bytes()
|
||||
@ -64,9 +72,7 @@ func (mapping *Mapping) Data() []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
//
|
||||
// Return true if two keys in a mapping are identical.
|
||||
//
|
||||
// HasDuplicateKeys returns true if two keys in a mapping are identical.
|
||||
func (mapping *Mapping) HasDuplicateKeys() bool {
|
||||
seen_values := make(map[string]bool)
|
||||
values := mapping.Values()
|
||||
@ -81,9 +87,7 @@ func (mapping *Mapping) HasDuplicateKeys() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
// Convert a Go map of unformatted strings to a sorted Mapping.
|
||||
//
|
||||
// GoMapToMapping converts a Go map of unformatted strings to *Mapping.
|
||||
func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) {
|
||||
map_vals := MappingValues{}
|
||||
for k, v := range gomap {
|
||||
@ -106,22 +110,21 @@ func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the string parsing error indicates that the Mapping
|
||||
// should no longer be parsed.
|
||||
//
|
||||
func stopValueRead(err error) bool {
|
||||
return err.Error() == "error parsing string: zero length"
|
||||
}
|
||||
|
||||
//
|
||||
// Determine if the first byte in a slice of bytes is the provided byte.
|
||||
//
|
||||
func beginsWith(bytes []byte, chr byte) bool {
|
||||
return len(bytes) != 0 &&
|
||||
bytes[0] == chr
|
||||
}
|
||||
|
||||
// ReadMapping returns Mapping from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
||||
if len(bytes) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
@ -168,6 +171,8 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
|
||||
return
|
||||
}
|
||||
|
||||
// NewMapping creates a new *Mapping from []byte using ReadMapping.
|
||||
// Returns a pointer to Mapping unlike ReadMapping.
|
||||
func NewMapping(bytes []byte) (values *Mapping, remainder []byte, err []error) {
|
||||
objvalues, remainder, err := ReadMapping(bytes)
|
||||
values = &objvalues
|
||||
|
@ -144,40 +144,6 @@ func TestFullGoMapToMappingProducesCorrectMapping(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMappingOrderSortsValuesThenKeys(t *testing.T) {
|
||||
a, _ := ToI2PString("a")
|
||||
b, _ := ToI2PString("b")
|
||||
values := MappingValues{
|
||||
[2]I2PString{b, b},
|
||||
[2]I2PString{b, a},
|
||||
[2]I2PString{a, b},
|
||||
[2]I2PString{a, a},
|
||||
}
|
||||
mappingOrder(values)
|
||||
for i, pair := range values {
|
||||
key, _ := pair[0].Data()
|
||||
value, _ := pair[1].Data()
|
||||
switch i {
|
||||
case 0:
|
||||
if !(key == "a" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 1:
|
||||
if !(key == "a" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 2:
|
||||
if !(key == "b" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 3:
|
||||
if !(key == "b" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStopValueReadTrueWhenCorrectErr(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
@ -1,30 +1,5 @@
|
||||
package data
|
||||
|
||||
/*
|
||||
I2P Mapping
|
||||
https://geti2p.net/spec/common-structures#mapping
|
||||
Accurate for version 0.9.24
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| size |key_string (len + data) | = |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| val_string (len + data) | ; | ...
|
||||
+----+----+----+----+----+----+----+
|
||||
size :: Integer
|
||||
length -> 2 bytes
|
||||
Total number of bytes that follow
|
||||
|
||||
key_string :: String
|
||||
A string (one byte length followed by UTF-8 encoded characters)
|
||||
|
||||
= :: A single byte containing '='
|
||||
|
||||
val_string :: String
|
||||
A string (one byte length followed by UTF-8 encoded characters)
|
||||
|
||||
; :: A single byte containing ';'
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
@ -32,13 +7,11 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Parsed key-values pairs inside a Mapping.
|
||||
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
||||
type MappingValues [][2]I2PString
|
||||
|
||||
//
|
||||
// Convert a MappingValue struct to a Mapping. The values are first
|
||||
// sorted in the order defined in mappingOrder.
|
||||
//
|
||||
// ValuesToMapping creates a *Mapping using MappingValues.
|
||||
// The values are sorted in the order defined in mappingOrder.
|
||||
func ValuesToMapping(values MappingValues) *Mapping {
|
||||
// Default length to 2 * len
|
||||
// 1 byte for ;
|
||||
@ -90,6 +63,9 @@ func mappingOrder(values MappingValues) {
|
||||
sort.Stable(byKey(values))
|
||||
}
|
||||
|
||||
// ReadMappingValues returns *MappingValues from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
||||
mapping := remainder
|
||||
//var remainder = mapping
|
||||
|
39
lib/common/data/mapping_values_test.go
Normal file
39
lib/common/data/mapping_values_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMappingOrderSortsValuesThenKeys(t *testing.T) {
|
||||
a, _ := ToI2PString("a")
|
||||
b, _ := ToI2PString("b")
|
||||
values := MappingValues{
|
||||
[2]I2PString{b, b},
|
||||
[2]I2PString{b, a},
|
||||
[2]I2PString{a, b},
|
||||
[2]I2PString{a, a},
|
||||
}
|
||||
mappingOrder(values)
|
||||
for i, pair := range values {
|
||||
key, _ := pair[0].Data()
|
||||
value, _ := pair[1].Data()
|
||||
switch i {
|
||||
case 0:
|
||||
if !(key == "a" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 1:
|
||||
if !(key == "a" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 2:
|
||||
if !(key == "b" && value == "a") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
case 3:
|
||||
if !(key == "b" && value == "b") {
|
||||
t.Fatal("mappingOrder produced incorrect sort output at", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +1,34 @@
|
||||
package data
|
||||
|
||||
/*
|
||||
I2P I2PString
|
||||
https://geti2p.net/spec/common-structures#string
|
||||
Accurate for version 0.9.24
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Maximum number of bytes that can be stored in an I2P string
|
||||
const (
|
||||
STRING_MAX_SIZE = 255
|
||||
)
|
||||
// STRING_MAX_SIZE is the maximum number of bytes that can be stored in an I2P string
|
||||
const STRING_MAX_SIZE = 255
|
||||
|
||||
/*
|
||||
[I2P String]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Represents a UTF-8 encoded string.
|
||||
|
||||
Contents
|
||||
1 or more bytes where the first byte is the number of bytes (not characters!) in the string
|
||||
and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array.
|
||||
Length limit is 255 bytes (not characters). Length may be 0.
|
||||
*/
|
||||
|
||||
// I2PString is the represenation of an I2P String.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#string
|
||||
type I2PString []byte
|
||||
|
||||
//
|
||||
// Look up the length of the string, reporting errors if the string is
|
||||
// invalid or the specified length does not match the provided data.
|
||||
//
|
||||
// Length returns the length specified in the first byte.
|
||||
// Returns error if the specified does not match the actual length or the string is otherwise invalid.
|
||||
func (str I2PString) Length() (length int, err error) {
|
||||
if len(str) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
@ -58,9 +64,8 @@ func (str I2PString) Length() (length int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the string data and any errors encountered by Length.
|
||||
//
|
||||
// Data returns the I2PString content as a string trimmed to the specified length and not including the length byte.
|
||||
// Returns error encountered by Length.
|
||||
func (str I2PString) Data() (data string, err error) {
|
||||
length, err := str.Length()
|
||||
if err != nil {
|
||||
@ -79,10 +84,8 @@ func (str I2PString) Data() (data string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// This function takes an unformatted Go string and returns a I2PString
|
||||
// and any errors encountered during the encoding.
|
||||
//
|
||||
// ToI2PString converts a Go string to an I2PString.
|
||||
// Returns error if the string exceeds STRING_MAX_SIZE.
|
||||
func ToI2PString(data string) (str I2PString, err error) {
|
||||
data_len := len(data)
|
||||
if data_len > STRING_MAX_SIZE {
|
||||
@ -105,6 +108,10 @@ func ToI2PString(data string) (str I2PString, err error) {
|
||||
// Read a string from a slice of bytes, returning any extra data on the end
|
||||
// of the slice and any errors encountered parsing the I2PString.
|
||||
//
|
||||
|
||||
// ReadI2PString returns I2PString from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
||||
str = I2PString(data)
|
||||
length, err := I2PString(data).Length()
|
||||
@ -116,6 +123,8 @@ func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewI2PString creates a new *I2PString from []byte using ReadI2PString.
|
||||
// Returns a pointer to I2PString unlike ReadI2PString.
|
||||
func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
|
||||
objstr, remainder, err := ReadI2PString(data)
|
||||
str = &objstr
|
||||
|
@ -1,17 +1,9 @@
|
||||
// Package destination implements the I2P Destination common data structure
|
||||
package destination
|
||||
|
||||
/*
|
||||
I2P Destination
|
||||
https://geti2p.net/spec/common-structures#destination
|
||||
Accurate for version 0.9.24
|
||||
|
||||
Identical to KeysAndCert
|
||||
*/
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/common/base32"
|
||||
@ -19,51 +11,25 @@ import (
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
)
|
||||
|
||||
/*
|
||||
[Destination]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
A Destination defines a particular endpoint to which messages can be directed for secure delivery.
|
||||
|
||||
Contents
|
||||
Identical to KeysAndCert.
|
||||
*/
|
||||
|
||||
// Destination is the represenation of an I2P Destination.
|
||||
//
|
||||
// A Destination is a KeysAndCert with functionallity
|
||||
// for generating base32 and base64 addresses.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#destination
|
||||
type Destination struct {
|
||||
*KeysAndCert
|
||||
}
|
||||
|
||||
func (destination *Destination) Bytes() []byte {
|
||||
return destination.KeysAndCert.Bytes()
|
||||
}
|
||||
|
||||
func (destination Destination) PublicKey() crypto.PublicKey {
|
||||
//return KeysAndCert(destination).PublicKey()
|
||||
return destination.KeysAndCert.PublicKey()
|
||||
}
|
||||
|
||||
func (destination Destination) SigningPublicKey() crypto.SigningPublicKey {
|
||||
//return KeysAndCert(destination).SigningPublicKey()
|
||||
return destination.KeysAndCert.SigningPublicKey()
|
||||
}
|
||||
|
||||
func (destination Destination) Certificate() *Certificate {
|
||||
//return KeysAndCert(destination).Certificate()
|
||||
return destination.KeysAndCert.Certificate()
|
||||
}
|
||||
|
||||
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
|
||||
keys_and_cert, remainder, err := NewKeysAndCert(data)
|
||||
destination = Destination{
|
||||
KeysAndCert: keys_and_cert,
|
||||
}
|
||||
//Destination(keys_and_cert)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) {
|
||||
objdestination, remainder, err := ReadDestination(data)
|
||||
destination = &objdestination
|
||||
return destination, remainder, err
|
||||
}
|
||||
|
||||
//
|
||||
// Generate the I2P base32 address for this Destination.
|
||||
//
|
||||
// Base32Address returns the I2P base32 address for this Destination.
|
||||
func (destination Destination) Base32Address() (str string) {
|
||||
dest := destination.KeysAndCert.KeyCertificate.Bytes()
|
||||
hash := crypto.SHA256(dest)
|
||||
@ -72,10 +38,27 @@ func (destination Destination) Base32Address() (str string) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Generate the I2P base64 address for this Destination.
|
||||
//
|
||||
// Base64 returns the I2P base64 address for this Destination.
|
||||
func (destination Destination) Base64() string {
|
||||
dest := destination.KeysAndCert.KeyCertificate.Bytes()
|
||||
return base64.EncodeToString(dest)
|
||||
}
|
||||
|
||||
// ReadDestination returns Destination from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
|
||||
keys_and_cert, remainder, err := NewKeysAndCert(data)
|
||||
destination = Destination{
|
||||
keys_and_cert,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewDestination creates a new *Destination from []byte using ReadDestination.
|
||||
// Returns a pointer to Destination unlike ReadDestination.
|
||||
func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) {
|
||||
objdestination, remainder, err := ReadDestination(data)
|
||||
destination = &objdestination
|
||||
return destination, remainder, err
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Package key_certificate implements the I2P Destination common data structure
|
||||
package key_certificate
|
||||
|
||||
/*
|
||||
@ -88,33 +89,23 @@ type KeyCertificate struct {
|
||||
cpkType Integer
|
||||
}
|
||||
|
||||
//
|
||||
// The data contained in the Key Certificate.
|
||||
//
|
||||
// Data returns the raw []byte contained in the Certificate.
|
||||
func (key_certificate KeyCertificate) Data() ([]byte, error) {
|
||||
return key_certificate.Certificate.RawBytes(), nil
|
||||
}
|
||||
|
||||
//
|
||||
// The SigningPublicKey type this Key Certificate describes and any errors encountered
|
||||
// parsing the KeyCertificate.
|
||||
//
|
||||
// SigningPublicKeyType returns the SigningPublicKey type as a Go integer.
|
||||
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) {
|
||||
return key_certificate.spkType.Int()
|
||||
}
|
||||
|
||||
//
|
||||
// The PublicKey type this Key Certificate describes and any errors encountered parsing
|
||||
// this KeyCertificate.
|
||||
//
|
||||
// PublicKeyType returns the PublicKey type as a Go integer.
|
||||
func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) {
|
||||
return key_certificate.cpkType.Int()
|
||||
}
|
||||
|
||||
//
|
||||
// Given some bytes, build a PublicKey using any excess data that may be stored in the KeyCertificate and return
|
||||
// it along with any errors encountered constructing the PublicKey.
|
||||
//
|
||||
// ConstructPublicKey returns a PublicKey constructed using any excess data that may be stored in the KeyCertififcate.
|
||||
// Returns enr errors encountered while parsing.
|
||||
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) {
|
||||
key_type := key_certificate.PublicKeyType()
|
||||
if err != nil {
|
||||
@ -140,10 +131,8 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Given some bytes, build a SigningPublicKey using any excess data that may be stored in the KeyCertificate and return
|
||||
// it along with any errors encountered constructing the SigningPublicKey.
|
||||
//
|
||||
// ConstructSigningPublicKey returns a SingingPublicKey constructed using any excess data that may be stored in the KeyCertificate.
|
||||
// Returns any errors encountered while parsing.
|
||||
func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
|
||||
signing_key_type := key_certificate.PublicKeyType()
|
||||
if err != nil {
|
||||
@ -193,10 +182,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the size of a Signature corresponding to the Key Certificate's
|
||||
// SigningPublicKey type.
|
||||
//
|
||||
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
|
||||
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
||||
sizes := map[int]int{
|
||||
KEYCERT_SIGN_DSA_SHA1: 40,
|
||||
@ -213,6 +199,9 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
||||
return sizes[int(key_type)]
|
||||
}
|
||||
|
||||
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
||||
var certificate *Certificate
|
||||
certificate, remainder, err = ReadCertificate(bytes)
|
||||
@ -253,6 +242,7 @@ func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder
|
||||
return
|
||||
}
|
||||
|
||||
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
|
||||
func KeyCertificateFromCertificate(certificate *Certificate) *KeyCertificate {
|
||||
k, _, _ := NewKeyCertificate(certificate.RawBytes())
|
||||
return k
|
||||
|
@ -1,9 +1,32 @@
|
||||
// Package keys_and_cert implements the I2P KeysAndCert common data structure
|
||||
package keys_and_cert
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Sizes of various KeysAndCert structures and requirements
|
||||
const (
|
||||
KEYS_AND_CERT_PUBKEY_SIZE = 256
|
||||
KEYS_AND_CERT_SPK_SIZE = 128
|
||||
KEYS_AND_CERT_MIN_SIZE = 387
|
||||
KEYS_AND_CERT_DATA_SIZE = 384
|
||||
)
|
||||
|
||||
/*
|
||||
I2P KeysAndCert
|
||||
https://geti2p.net/spec/common-structures#keysandcert
|
||||
Accurate for version 0.9.24
|
||||
[KeysAndCert]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
An encryption public key, a signing public key, and a certificate, used as either a RouterIdentity or a Destination.
|
||||
|
||||
Contents
|
||||
A PublicKey followed by a SigningPublicKey and then a Certificate.
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| public_key |
|
||||
@ -33,11 +56,11 @@ public_key :: PublicKey (partial or full)
|
||||
|
||||
padding :: random data
|
||||
length -> 0 bytes or as specified in key certificate
|
||||
padding length + signing_key length == KEYS_AND_CERT_SPK_SIZE bytes
|
||||
padding length + signing_key length == 128 bytes
|
||||
|
||||
signing__key :: SigningPublicKey (partial or full)
|
||||
length -> 128 bytes or as specified in key certificate
|
||||
padding length + signing_key length == KEYS_AND_CERT_SPK_SIZE bytes
|
||||
padding length + signing_key length == 128 bytes
|
||||
|
||||
certificate :: Certificate
|
||||
length -> >= 3 bytes
|
||||
@ -45,23 +68,9 @@ certificate :: Certificate
|
||||
total length: 387+ bytes
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Sizes of various KeysAndCert structures and requirements
|
||||
const (
|
||||
KEYS_AND_CERT_PUBKEY_SIZE = 256
|
||||
KEYS_AND_CERT_SPK_SIZE = 128
|
||||
KEYS_AND_CERT_MIN_SIZE = 387
|
||||
KEYS_AND_CERT_DATA_SIZE = 384
|
||||
)
|
||||
|
||||
// KeysAndCert is the represenation of an I2P KeysAndCert.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#keysandcert
|
||||
type KeysAndCert struct {
|
||||
KeyCertificate *KeyCertificate
|
||||
publicKey crypto.PublicKey
|
||||
@ -69,14 +78,12 @@ type KeysAndCert struct {
|
||||
signingPublicKey crypto.SigningPublicKey
|
||||
}
|
||||
|
||||
// Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length.
|
||||
func (keys_and_cert *KeysAndCert) Bytes() []byte {
|
||||
return keys_and_cert.KeyCertificate.Bytes()
|
||||
}
|
||||
|
||||
//
|
||||
// Return the PublicKey for this KeysAndCert, reading from the Key Certificate if it is present to
|
||||
// determine correct lengths.
|
||||
//
|
||||
// PublicKey returns the public key as a crypto.PublicKey.
|
||||
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
|
||||
/*cert := keys_and_cert.Certificate()
|
||||
cert_len := cert.Length()
|
||||
@ -117,10 +124,7 @@ func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
|
||||
return keys_and_cert.publicKey
|
||||
}
|
||||
|
||||
//
|
||||
// Return the SigningPublicKey for this KeysAndCert, reading from the Key Certificate if it is present to
|
||||
// determine correct lengths.
|
||||
//
|
||||
// SigningPublicKey returns the signing public key.
|
||||
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
|
||||
/*cert := keys_and_cert.Certificate()
|
||||
cert_len := cert.Length()
|
||||
@ -156,10 +160,7 @@ func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.
|
||||
return keys_and_cert.signingPublicKey
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Certificate contained in the KeysAndCert and any errors encountered while parsing the
|
||||
// KeysAndCert or Certificate.
|
||||
//
|
||||
// Certfificate returns the certificate.
|
||||
func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
|
||||
return keys_and_cert.KeyCertificate.Certificate
|
||||
}
|
||||
@ -168,6 +169,10 @@ func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
|
||||
// Read a KeysAndCert from a slice of bytes, retuning it and the remaining data as well as any errors
|
||||
// encoutered parsing the KeysAndCert.
|
||||
//
|
||||
|
||||
// ReadKeysAndCert returns KeysAndCert from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
|
||||
/*data_len := len(data)
|
||||
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
||||
@ -199,6 +204,8 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte,
|
||||
return
|
||||
}
|
||||
|
||||
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
||||
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
||||
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
|
||||
data_len := len(data)
|
||||
keys_and_cert = &KeysAndCert{}
|
||||
|
@ -1,9 +1,24 @@
|
||||
// Package lease implements the I2P lease common data structure
|
||||
package lease
|
||||
|
||||
import . "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
|
||||
// Sizes in bytes of various components of a Lease
|
||||
const (
|
||||
LEASE_SIZE = 44
|
||||
LEASE_HASH_SIZE = 32
|
||||
LEASE_TUNNEL_ID_SIZE = 4
|
||||
)
|
||||
|
||||
/*
|
||||
I2P Lease
|
||||
https://geti2p.net/spec/common-structures#lease
|
||||
Accurate for version 0.9.24
|
||||
[Lease]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Defines the authorization for a particular tunnel to receive messages targeting a Destination.
|
||||
|
||||
Contents
|
||||
SHA256 Hash of the RouterIdentity of the gateway router, then the TunnelId and finally an end Date.
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| tunnel_gw |
|
||||
@ -29,28 +44,18 @@ end_date :: Date
|
||||
length -> 8 bytes
|
||||
*/
|
||||
|
||||
import . "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
|
||||
// Sizes or various components of a Lease
|
||||
const (
|
||||
LEASE_SIZE = 44
|
||||
LEASE_HASH_SIZE = 32
|
||||
LEASE_TUNNEL_ID_SIZE = 4
|
||||
)
|
||||
|
||||
// Lease is the represenation of an I2P Lease.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#lease
|
||||
type Lease [LEASE_SIZE]byte
|
||||
|
||||
//
|
||||
// Return the first 32 bytes of the Lease as a Hash.
|
||||
//
|
||||
// TunnelGateway returns the tunnel gateway as a Hash.
|
||||
func (lease Lease) TunnelGateway() (hash Hash) {
|
||||
copy(hash[:], lease[:LEASE_HASH_SIZE])
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the TunnelID Integer in the Lease.
|
||||
//
|
||||
// TunnelID returns the tunnel id as a uint23.
|
||||
func (lease Lease) TunnelID() uint32 {
|
||||
i := Integer(lease[LEASE_HASH_SIZE : LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE])
|
||||
return uint32(
|
||||
@ -58,10 +63,23 @@ func (lease Lease) TunnelID() uint32 {
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Date inside the Lease.
|
||||
//
|
||||
// Date returns the date as an I2P Date.
|
||||
func (lease Lease) Date() (date Date) {
|
||||
copy(date[:], lease[LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE:])
|
||||
return
|
||||
}
|
||||
|
||||
// ReadLease returns Lease from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadLease(data []byte) (lease Lease, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
return
|
||||
}
|
||||
|
||||
// NewLease creates a new *NewLease from []byte using ReadLease.
|
||||
// Returns a pointer to KeysAndCert unlike ReadLease.
|
||||
func NewLease(data []byte) (lease *Lease, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
return
|
||||
}
|
||||
|
@ -1,9 +1,43 @@
|
||||
// Package lease_set implements the I2P LeastSet common data structure
|
||||
package lease_set
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/destination"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/lease"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/signature"
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Sizes of various structures in an I2P LeaseSet
|
||||
const (
|
||||
LEASE_SET_PUBKEY_SIZE = 256
|
||||
LEASE_SET_SPK_SIZE = 128
|
||||
LEASE_SET_SIG_SIZE = 40
|
||||
)
|
||||
|
||||
/*
|
||||
I2P LeaseSet
|
||||
https://geti2p.net/spec/common-structures#leaseset
|
||||
Accurate for version 0.9.24
|
||||
[LeaseSet]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Contains all of the currently authorized Leases for a particular Destination, the
|
||||
PublicKey to which garlic messages can be encrypted, and then the SigningPublicKey
|
||||
that can be used to revoke this particular version of the structure. The LeaseSet is one
|
||||
of the two structures stored in the network database (the other being RouterInfo), and
|
||||
is kered under the SHA256 of the contained Destination.
|
||||
|
||||
Contents
|
||||
Destination, followed by a PublicKey for encryption, then a SigningPublicKey which
|
||||
can be used to revoke this version of the LeaseSet, then a 1 byte Integer specifying how
|
||||
many Lease structures are in the set, followed by the actual Lease structures and
|
||||
finally a Signature of the previous bytes signed by the Destination's SigningPrivateKey.
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| destination |
|
||||
@ -80,27 +114,9 @@ signature :: Signature
|
||||
length -> 40 bytes or as specified in destination's key certificate
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/destination"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/lease"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/signature"
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Sizes of various structures in an I2P LeaseSet
|
||||
const (
|
||||
LEASE_SET_PUBKEY_SIZE = 256
|
||||
LEASE_SET_SPK_SIZE = 128
|
||||
LEASE_SET_SIG_SIZE = 40
|
||||
)
|
||||
|
||||
// LeaseSet is the represenation of an I2P LeaseSet.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#leaseset
|
||||
type LeaseSet []byte
|
||||
|
||||
/*
|
||||
@ -114,18 +130,15 @@ type LeaseSet struct {
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// Read a Destination from the LeaseSet.
|
||||
//
|
||||
// Destination returns the Destination as []byte.
|
||||
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
||||
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
|
||||
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the PublicKey in this LeaseSet and any errors ancountered parsing the LeaseSet.
|
||||
//
|
||||
// PublicKey returns the public key as crypto.ElgPublicKey.
|
||||
// Returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) {
|
||||
_, remainder, err := ReadKeysAndCert(lease_set)
|
||||
remainder_len := len(remainder)
|
||||
@ -144,10 +157,8 @@ func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the SigningPublicKey, as specified in the LeaseSet's Destination's Key Certificate if
|
||||
// present, or a legacy DSA key.
|
||||
//
|
||||
// SigningKey returns the signing public key as crypto.SigningPublicKey.
|
||||
// returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicKey, err error) {
|
||||
destination, err := lease_set.Destination()
|
||||
if err != nil {
|
||||
@ -198,9 +209,8 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the number of Leases specified by the LeaseCount value in this LeaseSet.
|
||||
//
|
||||
// LeaseCount returns the numbert of leases specified by the LeaseCount value as int.
|
||||
// returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) LeaseCount() (count int, err error) {
|
||||
_, remainder, err := ReadKeysAndCert(lease_set)
|
||||
if err != nil {
|
||||
@ -230,9 +240,8 @@ func (lease_set LeaseSet) LeaseCount() (count int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Read the Leases in this LeaseSet, returning a partial set if there is insufficient data.
|
||||
//
|
||||
// Leases returns the leases as []Lease.
|
||||
// returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) Leases() (leases []Lease, err error) {
|
||||
destination, err := lease_set.Destination()
|
||||
if err != nil {
|
||||
@ -264,10 +273,8 @@ func (lease_set LeaseSet) Leases() (leases []Lease, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Signature data for the LeaseSet, as specified in the Destination's
|
||||
// Key Certificate if present or the 40 bytes following the Leases.
|
||||
//
|
||||
// Signature returns the signature as Signature.
|
||||
// returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) Signature() (signature Signature, err error) {
|
||||
destination, err := lease_set.Destination()
|
||||
if err != nil {
|
||||
@ -305,9 +312,7 @@ func (lease_set LeaseSet) Signature() (signature Signature, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// Verify returns nil
|
||||
func (lease_set LeaseSet) Verify() error {
|
||||
//data_end := len(destination) +
|
||||
// LEASE_SET_PUBKEY_SIZE +
|
||||
@ -325,27 +330,25 @@ func (lease_set LeaseSet) Verify() error {
|
||||
return nil // verifier.Verify(data, lease_set.Signature())
|
||||
}
|
||||
|
||||
//
|
||||
// Return the oldest date from all the Leases in the LeaseSet.
|
||||
//
|
||||
func (lease_set LeaseSet) NewestExpiration() (oldest Date, err error) {
|
||||
// NewestExpiration returns the newest lease expiration as an I2P Date.
|
||||
// Returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) NewestExpiration() (newest Date, err error) {
|
||||
leases, err := lease_set.Leases()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
oldest = Date{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
newest = Date{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
for _, lease := range leases {
|
||||
date := lease.Date()
|
||||
if date.Time().After(oldest.Time()) {
|
||||
oldest = date
|
||||
if date.Time().After(newest.Time()) {
|
||||
newest = date
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Return the oldest date from all the Leases in the LeaseSet.
|
||||
//
|
||||
// OldestExpiration returns the oldest lease expiration as an I2P Date.
|
||||
// Returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) {
|
||||
leases, err := lease_set.Leases()
|
||||
if err != nil {
|
||||
|
@ -1,9 +1,33 @@
|
||||
// Package router_address implements the I2P RouterAddress common data structure
|
||||
package router_address
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Minimum number of bytes in a valid RouterAddress
|
||||
const (
|
||||
ROUTER_ADDRESS_MIN_SIZE = 9
|
||||
)
|
||||
|
||||
/*
|
||||
I2P RouterAddress
|
||||
https://geti2p.net/spec/common-structures#routeraddress
|
||||
Accurate for version 0.9.24
|
||||
[RouterAddress]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
This structure defines the means to contact a router through a transport protocol.
|
||||
|
||||
Contents
|
||||
1 byte Integer defining the relative cost of using the address, where 0 is free and 255 is
|
||||
expensive, followed by the expiration Date after which the address should not be used,
|
||||
of if null, the address never expires. After that comes a String defining the transport
|
||||
protocol this router address uses. Finally there is a Mapping containing all of the
|
||||
transport specific options necessary to establish the connection, such as IP address,
|
||||
port number, email address, URL, etc.
|
||||
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
|cost| expiration
|
||||
@ -35,18 +59,9 @@ transport_style :: String
|
||||
options :: Mapping
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Minimum number of bytes in a valid RouterAddress
|
||||
const (
|
||||
ROUTER_ADDRESS_MIN_SIZE = 9
|
||||
)
|
||||
|
||||
// RouterAddress is the represenation of an I2P RouterAddress.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#routeraddress
|
||||
type RouterAddress struct {
|
||||
cost *Integer
|
||||
expiration *Date
|
||||
@ -55,9 +70,7 @@ type RouterAddress struct {
|
||||
parserErr error
|
||||
}
|
||||
|
||||
//
|
||||
// Bytes returns the router address as a byte slice.
|
||||
//
|
||||
// Bytes returns the router address as a []byte.
|
||||
func (router_address RouterAddress) Bytes() []byte {
|
||||
bytes := make([]byte, 0)
|
||||
bytes = append(bytes, router_address.cost.Bytes()...)
|
||||
@ -74,34 +87,22 @@ func (router_address RouterAddress) Bytes() []byte {
|
||||
return bytes
|
||||
}
|
||||
|
||||
//
|
||||
// Return the cost integer for this RouterAddress and any errors encountered
|
||||
// parsing the RouterAddress.
|
||||
//
|
||||
// Cost returns the cost for this RouterAddress as a Go integer.
|
||||
func (router_address RouterAddress) Cost() int {
|
||||
return router_address.cost.Int()
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Date this RouterAddress expires and any errors encountered
|
||||
// parsing the RouterAddress.
|
||||
//
|
||||
// Expiration returns the expiration for this RouterAddress as an I2P Date.
|
||||
func (router_address RouterAddress) Expiration() Date {
|
||||
return *router_address.expiration
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Transport type for this RouterAddress and any errors encountered
|
||||
// parsing the RouterAddress.
|
||||
//
|
||||
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
||||
func (router_address RouterAddress) TransportStyle() I2PString {
|
||||
return *router_address.transport_style
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Mapping containing the options for this RouterAddress and any
|
||||
// errors encountered parsing the RouterAddress.
|
||||
//
|
||||
// Options returns the options for this RouterAddress as an I2P Mapping.
|
||||
func (router_address RouterAddress) Options() Mapping {
|
||||
return *router_address.options
|
||||
}
|
||||
@ -132,11 +133,9 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Given a slice of bytes, read a RouterAddress, returning the remaining bytes and any
|
||||
// errors encountered parsing the RouterAddress.
|
||||
//
|
||||
|
||||
// ReadRouterAddress returns RouterAddress from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
||||
if data == nil || len(data) == 0 {
|
||||
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data")
|
||||
@ -190,6 +189,8 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b
|
||||
return
|
||||
}
|
||||
|
||||
// NewRouterAddress creates a new *RouterAddress from []byte using ReadRouterAddress.
|
||||
// Returns a pointer to RouterAddress unlike ReadRouterAddress.
|
||||
func NewRouterAddress(data []byte) (router_address *RouterAddress, remainder []byte, err error) {
|
||||
objrouteraddress, remainder, err := ReadRouterAddress(data)
|
||||
router_address = &objrouteraddress
|
||||
|
@ -1,49 +1,41 @@
|
||||
// Package router_identity implements the I2P RouterIdentity common data structure
|
||||
package router_identity
|
||||
|
||||
/*
|
||||
I2P RouterIdentity
|
||||
https://geti2p.net/spec/common-structures#routeridentity
|
||||
Accurate for version 0.9.24
|
||||
|
||||
Identical to KeysAndCert
|
||||
*/
|
||||
|
||||
import (
|
||||
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/crypto"
|
||||
)
|
||||
|
||||
/*
|
||||
[RouterIdentity]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Defines the way to uniquely identify a particular router
|
||||
|
||||
Contents
|
||||
Identical to KeysAndCert.
|
||||
*/
|
||||
|
||||
// RouterIdentity is the represenation of an I2P RouterIdentity.
|
||||
//
|
||||
// A RouterIdentity is identical to KeysAndCert.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#routeridentity
|
||||
type RouterIdentity struct {
|
||||
KeysAndCert *KeysAndCert
|
||||
}
|
||||
|
||||
//[]byte
|
||||
|
||||
func (router_identity *RouterIdentity) PublicKey() crypto.PublicKey {
|
||||
return router_identity.KeysAndCert.PublicKey()
|
||||
}
|
||||
|
||||
func (router_identity *RouterIdentity) SigningPublicKey() crypto.SigningPublicKey {
|
||||
return router_identity.KeysAndCert.SigningPublicKey()
|
||||
}
|
||||
|
||||
func (router_identity *RouterIdentity) Certificate() *Certificate {
|
||||
return router_identity.KeysAndCert.Certificate()
|
||||
*KeysAndCert
|
||||
}
|
||||
|
||||
// ReadRouterIdentity returns RouterIdentity from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) {
|
||||
keys_and_cert, remainder, err := NewKeysAndCert(data)
|
||||
router_identity = RouterIdentity{
|
||||
KeysAndCert: keys_and_cert,
|
||||
} //(keys_and_cert)
|
||||
keys_and_cert,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewRouterIdentity creates a new *RouterIdentity from []byte using ReadRouterIdentity.
|
||||
// Returns a pointer to RouterIdentity unlike ReadRouterIdentity.
|
||||
func NewRouterIdentity(data []byte) (router_identity *RouterIdentity, remainder []byte, err error) {
|
||||
objrouter_identity, remainder, err := ReadRouterIdentity(data)
|
||||
router_identity = &objrouter_identity
|
||||
|
@ -1,9 +1,29 @@
|
||||
// Package router_info implements the I2P RouterInfo common data structure
|
||||
package router_info
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_address"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_identity"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/signature"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ROUTER_INFO_MIN_SIZE = 439
|
||||
|
||||
/*
|
||||
I2P RouterInfo
|
||||
https://geti2p.net/spec/common-structures#routerinfo
|
||||
Accurate for version 0.9.24
|
||||
[RouterInfo]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
Defines all of the data that a router wants to public for the network to see. The
|
||||
RouterInfo is one of two structures stored in the network database (the other being
|
||||
LeaseSet), and is keyed under the SHA256 of the contained RouterIdentity.
|
||||
|
||||
Contents
|
||||
RouterIdentity followed by the Date, when the entry was published
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| router_ident |
|
||||
@ -73,18 +93,9 @@ signature :: Signature
|
||||
length -> 40 bytes
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_address"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_identity"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/signature"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ROUTER_INFO_MIN_SIZE = 439
|
||||
|
||||
// RouterInfo is the represenation of an I2P RouterInfo.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#routerinfo
|
||||
type RouterInfo struct {
|
||||
router_identity *RouterIdentity
|
||||
published *Date
|
||||
@ -95,9 +106,7 @@ type RouterInfo struct {
|
||||
signature *Signature
|
||||
}
|
||||
|
||||
//
|
||||
// Bytes returns the RouterInfo as a slice of bytes suitable for writing to a stream.
|
||||
//
|
||||
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
|
||||
func (router_info RouterInfo) Bytes() ([]byte, error) {
|
||||
var err error
|
||||
var bytes []byte
|
||||
@ -115,58 +124,41 @@ func (router_info RouterInfo) Bytes() ([]byte, error) {
|
||||
return bytes, err
|
||||
}
|
||||
|
||||
//
|
||||
// Read a RouterIdentity from the RouterInfo, returning the RouterIdentity and any errors
|
||||
// encountered parsing the RouterIdentity.
|
||||
//
|
||||
// RouterIdentity returns the router identity as *RouterIdentity.
|
||||
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
||||
return router_info.router_identity
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate this RouterInfo's Identity Hash (the sha256 of the RouterIdentity)
|
||||
// returns error if the RouterIdentity is malformed
|
||||
//
|
||||
// IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
|
||||
func (router_info *RouterInfo) IdentHash() Hash {
|
||||
ri := router_info.RouterIdentity()
|
||||
h := HashData(ri.KeysAndCert.Certificate().Data())
|
||||
return h
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Date the RouterInfo was published and any errors encountered parsing the RouterInfo.
|
||||
//
|
||||
// Published returns the date this RouterInfo was published as an I2P Date.
|
||||
func (router_info *RouterInfo) Published() *Date {
|
||||
return router_info.published
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Integer representing the number of RouterAddresses that are contained in this RouterInfo.
|
||||
//
|
||||
// RouterAddressCount returns the count of RouterAddress in this RouterInfo as a Go integer.
|
||||
func (router_info *RouterInfo) RouterAddressCount() int {
|
||||
return router_info.size.Int()
|
||||
}
|
||||
|
||||
//
|
||||
// Read the RouterAddresses inside this RouterInfo and return them in a slice, returning
|
||||
// a partial list if data is missing.
|
||||
//
|
||||
// RouterAddresses returns all RouterAddresses for this RouterInfo as []*RouterAddress.
|
||||
func (router_info *RouterInfo) RouterAddresses() []*RouterAddress {
|
||||
return router_info.addresses
|
||||
}
|
||||
|
||||
//
|
||||
// Return the PeerSize value, currently unused and always zero.
|
||||
//
|
||||
// PeerSize returns the peer size as a Go integer.
|
||||
func (router_info *RouterInfo) PeerSize() int {
|
||||
// Peer size is unused:
|
||||
// https://geti2p.net/spec/common-structures#routeraddress
|
||||
return 0
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Options Mapping inside this RouterInfo.
|
||||
//
|
||||
// Options returns the options for this RouterInfo as an I2P Mapping.
|
||||
func (router_info RouterInfo) Options() (mapping Mapping) {
|
||||
return *router_info.options
|
||||
}
|
||||
@ -174,6 +166,8 @@ func (router_info RouterInfo) Options() (mapping Mapping) {
|
||||
//
|
||||
// Return the signature of this router info
|
||||
//
|
||||
|
||||
// Signature returns the signature for this RouterInfo as an I2P Signature.
|
||||
func (router_info RouterInfo) Signature() (signature Signature) {
|
||||
return *router_info.signature
|
||||
}
|
||||
@ -230,6 +224,9 @@ func (router_info RouterInfo) Signature() (signature Signature) {
|
||||
return
|
||||
}*/
|
||||
|
||||
// ReadRouterInfo returns RouterInfo from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) {
|
||||
identity, remainder, err := NewRouterIdentity(bytes)
|
||||
info.router_identity = identity
|
||||
@ -308,3 +305,11 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewRouterInfo creates a new *RouterInfo from []byte using ReadRouterInfo.
|
||||
// Returns a pointer to RouterInfo unlike ReadRouterInfo.
|
||||
func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) {
|
||||
routerInfo, remainder, err := ReadRouterInfo(data)
|
||||
router_info = &routerInfo
|
||||
return
|
||||
}
|
||||
|
@ -1,3 +1,34 @@
|
||||
// Package session_key implements the I2P SessionKey common data structure
|
||||
package session_key
|
||||
|
||||
/*
|
||||
[SessionKey]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
This structure is used for symmetric AES256 encryption and decryption.
|
||||
|
||||
Contents
|
||||
32 bytes
|
||||
*/
|
||||
|
||||
// SessionKey is the represenation of an I2P SessionKey.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#sessionkey
|
||||
type SessionKey [32]byte
|
||||
|
||||
// ReadSessionKey returns SessionKey from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadSessionKey(bytes []byte) (info SessionKey, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
return
|
||||
}
|
||||
|
||||
// NewSessionKey creates a new *SessionKey from []byte using ReadSessionKey.
|
||||
// Returns a pointer to SessionKey unlike ReadSessionKey.
|
||||
func NewSessionKey(data []byte) (session_key *SessionKey, remainder []byte, err error) {
|
||||
sessionKey, remainder, err := ReadSessionKey(data)
|
||||
session_key = &sessionKey
|
||||
return
|
||||
}
|
||||
|
@ -1,3 +1,34 @@
|
||||
// Package session_tag implements the I2P SessionTag common data structure
|
||||
package session_tag
|
||||
|
||||
/*
|
||||
[SessionKey]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
A random number
|
||||
|
||||
Contents
|
||||
32 bytes
|
||||
*/
|
||||
|
||||
// SessionTag is the represenation of an I2P SessionTag.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#session-tag
|
||||
type SessionTag [32]byte
|
||||
|
||||
// ReadSessionTag returns SessionTag from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadSessionTag(bytes []byte) (info SessionTag, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
return
|
||||
}
|
||||
|
||||
// NewSessionTag creates a new *SessionTag from []byte using ReadSessionTag.
|
||||
// Returns a pointer to SessionTag unlike ReadSessionTag.
|
||||
func NewSessionTag(data []byte) (session_tag *SessionTag, remainder []byte, err error) {
|
||||
sessionTag, remainder, err := ReadSessionTag(data)
|
||||
session_tag = &sessionTag
|
||||
return
|
||||
}
|
||||
|
@ -1,3 +1,49 @@
|
||||
// Package signature implements the I2P Signature common data structure
|
||||
package signature
|
||||
|
||||
// Lengths of signature keys
|
||||
const (
|
||||
DSA_SHA1_SIZE = 40
|
||||
ECDSA_SHA256_P256_SIZE = 64
|
||||
ECDSA_SHA384_P384_SIZE = 96
|
||||
ECDSA_SHA512_P512_SIZE = 132
|
||||
RSA_SHA256_2048_SIZE = 256
|
||||
RSA_SHA384_3072_SIZE = 384
|
||||
RSA_SHA512_4096_SIZE = 512
|
||||
EdDSA_SHA512_Ed25519_SIZE = 64
|
||||
EdDSA_SHA512_Ed25519ph_SIZE = 64
|
||||
RedDSA_SHA512_Ed25519_SIZE = 64
|
||||
)
|
||||
|
||||
/*
|
||||
[Signature]
|
||||
Accurate for version 0.9.49
|
||||
|
||||
Description
|
||||
This structure represents the signature of some data.
|
||||
|
||||
Contents
|
||||
Signature type and length are inferred from the type of key used. The default type is
|
||||
DSA_SHA1. As of release 0.9.12, other types may be supported, depending on context.
|
||||
*/
|
||||
|
||||
// Signature is the represenation of an I2P Signature.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#signature
|
||||
type Signature []byte
|
||||
|
||||
// ReadSignature returns Signature from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
return
|
||||
}
|
||||
|
||||
// NewSignature creates a new *Signature from []byte using ReadSignature.
|
||||
// Returns a pointer to Signature unlike ReadSignature.
|
||||
func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error) {
|
||||
sessionTag, remainder, err := ReadSignature(data)
|
||||
session_tag = &sessionTag
|
||||
return
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func (db StdNetDB) Exists() bool {
|
||||
_, err := os.Stat(p)
|
||||
if err == nil {
|
||||
// check subdirectories for skiplist
|
||||
for _, c := range base64.Alphabet {
|
||||
for _, c := range base64.I2PEncodeAlphabet {
|
||||
if _, err = os.Stat(filepath.Join(p, fmt.Sprintf("r%c", c))); err != nil {
|
||||
return false
|
||||
}
|
||||
@ -168,7 +168,7 @@ func (db StdNetDB) Create() (err error) {
|
||||
err = os.Mkdir(p, mode)
|
||||
if err == nil {
|
||||
// create all subdirectories for skiplist
|
||||
for _, c := range base64.Alphabet {
|
||||
for _, c := range base64.I2PEncodeAlphabet {
|
||||
err = os.Mkdir(filepath.Join(p, fmt.Sprintf("r%c", c)), mode)
|
||||
if err != nil {
|
||||
return
|
||||
|
Reference in New Issue
Block a user