Tweak godocs for lib/common

This commit is contained in:
thulium
2022-09-12 08:31:02 +00:00
parent 68a6ed02be
commit c8c4196c6f
26 changed files with 704 additions and 532 deletions

View File

@ -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)
}

View 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)
}

View File

@ -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)
}

View 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)
}

View File

@ -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" {

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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

View 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)
}
}
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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{}

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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