10 Commits

48 changed files with 938 additions and 655 deletions

View File

@@ -1,8 +1,6 @@
RELEASE_TAG=0.0.1
RELEASE_VERSION=${RELEASE_TAG}
RELEASE_DESCRIPTION=`cat PASTA.md`
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
ifdef GOROOT
GO = $(GOROOT)/bin/go
endif
@@ -20,19 +18,8 @@ build: clean $(EXE)
$(EXE):
$(GO) build -v -o $(EXE)
test: fmt
$(GO) test -vv -failfast ./lib/common/...
test:
$(GO) test -v -failfast ./lib/transport/noise/...
clean:
$(GO) clean -v
fmt:
find . -name '*.go' -exec gofmt -w -s {} \;
info:
echo "GOROOT: ${GOROOT}"
echo "GO: ${GO}"
echo "REPO: ${REPO}"
release:
github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p

View File

@@ -1,18 +1,16 @@
At long last... something useful
================================
Weekly notes about what I'm working on
======================================
It's been 2 years of me mostly not having time to work on go-i2p itself since my last update.
However, after much waiting, this library is actually **useful** for something.
It is now being used in the `reseed-tools` application to examine RouterInfos prior to including them in reseed bundles.
Routers that self-report as unreachable or congested will be excluded from future reseed bundles.
Additionally, routers that self-report an old version will be excluded from reseed bundles.
This should help new users build better connections faster with the existing, working router implementations.
This is not a working release of a go-i2p router
------------------------------------------------
It is a numbered version of the go-i2p library, which is pre-release, expressly for use in the `reseed-tools` application.
The common library works, and so do some of the cryptographic primitives, however the API is unstable and the software itself is certain to have serious bugs outside of a few well-tested areas.
If you're using it for something other than parsing and analyzing RouterInfos and LeaseSets, you'll probably encounter bugs.
Please report them to the https://github.com/go-i2p/go-i2p
Use any part of it at your own risk.
I finally got back to work on go-i2p last Friday, continuing work on the Noise transport(also enhanced marek's privs as a reddit mod which has been helpful, also the Dread community does appear to have begun to step a little re: onboarding eachother)
I can now make a socket, instantiate a noise transport using the socket, and begin to use it to manage "incoming" and "outgoing" handshakes.
They don't complete yet, still working on that, but it's more like debugging now and less figuring out how to actually do it, I more or less know where the pieces go now
I'm beginning to notice drawbacks of what I've done here already, I think noiseSocket is intended at times as example of a way to use flynn/noise which is not exactly like I would do it or how a P2P application needs to do it
Some of the functions are very long and hard to break down, and they use a different Noise flavor than NTCP2 by default, so I'm breaking things down into steps until I have exactly one step of a Noise handshake, exactly one function
Which should finally give me what I've been hoping for all along, an interface where I can modify steps(i.e. add padding, eventually turn it into NTCP2) by instantiating it with different versions of that function, so I get to think about reusability now
I'm going to attempt to ask a question I don't quite know how to ask yet, and maybe won't know the answer until I try it out for myself:
Supposing:
0. Go network structures can be "nested" if they implement the common interface(`net.Conn`, `net.PacketConn`), and use the common interface to store the information about the socket in their implmentation, and only use the functions of the common interface(This is true)
1. That I can instantiate this Noise-framework Transport struct with functions to modify the process in a granular enough way that turning it into NTCP2 is a matter of writing a few custom functions and plugging them in to an instance of the struct(Sort of like what you would do with inheritance)(which I think is true)
2. that I can instantiate it with both a `net.Conn(TCP Socket interface)` and a `net.PacketConn(UDP Socket interface)` because I only use the common features of those 2 interfaces, (Which isn't true yet but I'm thinking about how to do it)
Does that potential definition of a moddable Noise-over-many-transports library mean that I can approach SSU2 mostly in terms of connection management and peer testing, because the crypto would be similar enough to NTCP2 that I could re-use the custom functions?
I'll find out the hard way eventually the first time I have to do it with SSU2, but it would be exciting to have come up with a design that has accelerating returns in such a way.

View File

@@ -51,8 +51,8 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Message handling
- NetDB
- [ ] Local storage
- [/] Persistence to disk
- [X] Reseeding
- [ ] Persistence to disk
- [ ] Reseeding
- [ ] Lookups
- [ ] Expiry
- [ ] Exploration
@@ -60,12 +60,12 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Floodfill
- [ ] LS2 and Encrypted Leasesets
- Transports
- [X] Transport manager
- [ ] Transport manager
- NTCP2
- [ ] Handshake
- [ ] Session tracking
- [ ] Automatic session creation
- SSU2
- SSU
- [ ] Handshake
- [ ] Session tracking
- [ ] Automatic session creation
@@ -78,20 +78,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Participating
- [ ] Tunnel Message Crypto
- [ ] Tunnel Message Fragmentation/Reassembly
- Common Data Structures
- [/] Keys and Cert
- [X] Key Certificates
- [X] Certificate
- [X] Lease
- [X] Lease Set
- [X] Router Info
- [X] Router Identity
- [X] Router Address
- [X] Session Key
- [X] Signature Types
- [X] Destination
- [X] Data Types
- [X] Session Tag
## Contributing

10
go.mod
View File

@@ -3,9 +3,13 @@ module github.com/go-i2p/go-i2p
go 1.16
require (
github.com/dchest/siphash v1.2.3 // indirect
github.com/emirpasic/gods v1.18.1
github.com/flynn/noise v1.1.0
github.com/sirupsen/logrus v1.9.3
github.com/flynn/noise v1.0.0
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.23.0
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
)

60
go.sum
View File

@@ -1,69 +1,43 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620 h1:MjTFQi2DyJifqefRVjAs+P2gaoUAj2rcDpYX7ERggEA=
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620/go.mod h1:y9SBFk2hEIPWY7Aj3bXG+K1xp8wWnQ6kVq2wsYSPByU=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -1,2 +1,4 @@
//
// provides generic interfaces for initial bootstrap into network and network reseeding
//
package bootstrap

View File

@@ -126,19 +126,29 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": len(data),
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
}).Error("invalid certificate, empty")
err = fmt.Errorf("error parsing certificate: certificate is empty")
}).Error("invalid certificate")
err = fmt.Errorf("error parsing certificate: certificate is too short")
return
case 1 , 2:
certificate.kind = Integer(data[0:len(data)-1])
case 1:
certificate.kind = Integer(data[0:0])
certificate.len = Integer([]byte{0})
log.WithFields(log.Fields{
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": len(data),
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
}).Error("invalid certificate, too short")
}).Error("invalid certificate")
err = fmt.Errorf("error parsing certificate: certificate is too short")
return
case 2:
certificate.kind = Integer(data[0:1])
certificate.len = Integer([]byte{0})
log.WithFields(log.Fields{
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": len(data),
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
}).Error("invalid certificate")
err = fmt.Errorf("error parsing certificate length: certificate is too short")
return
default:
certificate.kind = Integer(data[0:1])
certificate.len = Integer(data[1:3])
@@ -150,11 +160,17 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": certificate.len.Int(),
"certificate_payload_length": payleng,
"data_bytes:": string(data),
"kind_bytes": data[0:1],
"len_bytes": data[1:3],
"reason": err.Error(),
}).Error("invalid certificate, shorter than specified by length")
}).Error("invalid certificate")
return
} 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.len.Int(),
"certificate_payload_length": payleng,
"reason": err.Error(),
}).Error("invalid certificate")
return
}
return
@@ -166,8 +182,8 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
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" {
remainder = certificate.ExcessBytes()
err = nil
}
remainder = certificate.ExcessBytes()
return
}

View File

@@ -50,9 +50,7 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err
if size < MAX_INTEGER_SIZE {
integerSize = size
}
intBytes := bytes[:integerSize]
remainder = bytes[integerSize:]
i, _ := ReadInteger(intBytes, integerSize)
i, remainder := ReadInteger(bytes, integerSize)
integer = &i
return
}

View File

@@ -126,25 +126,28 @@ func beginsWith(bytes []byte, chr byte) bool {
// 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) < 3 {
if len(bytes) == 0 {
log.WithFields(log.Fields{
"at": "ReadMapping",
"reason": "zero length",
}).Warn("mapping format violation")
e := errors.New("zero length")
err = append(err, e)
return
}
size, remainder, e := NewInteger(bytes, 2)
if e != nil {
err = append(err, e)
}
if size.Int() == 0 {
return
}
mapping.size = size
map_bytes := remainder[:mapping.size.Int()]
remainder = remainder[mapping.size.Int():]
if e != nil {
log.WithFields(log.Fields{
"at": "ReadMapping",
"reason": "error parsing integer",
}).Warn("mapping format violation")
e := errors.New("error parsing integer")
err = append(err, e)
}
if len(remainder) == 0 {
log.WithFields(log.Fields{
"at": "ReadMapping",
@@ -153,10 +156,7 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
e := errors.New("zero length")
err = append(err, e)
}
// TODO: this should take the remainder and the length we already parsed above, as a parameter.
// Like tomorrow morning.
// ReadMappingValues should not attempt to figure out the length of the bytes it's reading over.
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *mapping.size)
vals, remainder, mappingValueErrs := ReadMappingValues(bytes)
err = append(err, mappingValueErrs...)
mapping.vals = vals

View File

@@ -10,17 +10,6 @@ import (
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
type MappingValues [][2]I2PString
func (m MappingValues) Get(key I2PString) I2PString {
keyBytes, _ := key.Data()
for _, pair := range m {
kb, _ := pair[0][0:].Data()
if kb == keyBytes {
return pair[1][1:]
}
}
return nil
}
// ValuesToMapping creates a *Mapping using MappingValues.
// The values are sorted in the order defined in mappingOrder.
func ValuesToMapping(values MappingValues) *Mapping {
@@ -57,11 +46,11 @@ func mappingOrder(values MappingValues) {
// 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, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
//mapping := remainder
func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) {
mapping := remainder
//var remainder = mapping
//var err error
if remainder == nil || len(remainder) < 1 {
if remainder == nil || len(remainder) < 0 {
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"reason": "data shorter than expected",
@@ -70,21 +59,31 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
return
}
map_values := make(MappingValues, 0)
int_map_length := map_length.Int()
mapping_len := len(remainder)
if mapping_len > int_map_length {
if len(remainder) < 1 {
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"reason": "data shorter than expected",
}).Error("mapping contained no data")
errs = []error{errors.New("mapping contained no data")}
return
}
l := Integer(remainder[:2])
length := l.Int()
// - 2 bytes for map length bits
mapping_len := len(mapping) - 2
if mapping_len > length {
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"mapping_bytes_length": mapping_len,
"mapping_length_field": int_map_length,
"mapping_length_field": length,
"reason": "data longer than expected",
}).Warn("mapping format warning")
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
} else if int_map_length > mapping_len {
} else if length > mapping_len {
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"mapping_bytes_length": mapping_len,
"mapping_length_field": int_map_length,
"mapping_length_field": length,
"reason": "data shorter than expected",
}).Warn("mapping format warning")
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
@@ -92,7 +91,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
encounteredKeysMap := map[string]bool{}
// pop off length bytes before parsing kv pairs
//remainder = remainder[2:]
remainder = remainder[2:]
for {
// Read a key, breaking on fatal errors
@@ -112,16 +111,16 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
break
}
key_str, more, err := ReadI2PString(remainder)
str, more, err := ReadI2PString(remainder)
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
key_str := str
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
//return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// Check if key has already been encountered in this mapping
keyBytes, _ := key_str.Data()
@@ -131,9 +130,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"reason": "duplicate key in mapping",
"key": string(key_str),
}).Error("mapping format violation")
log.Printf("DUPE: %s", key_str)
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
// Based on other implementations this does not seem to happen often?
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
@@ -145,39 +142,33 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"reason": "expected =",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, errors.New("mapping format violation, expected ="))
log.Printf("ERRVAL: %s", remainder)
break
} else {
remainder = remainder[1:]
}
remainder = remainder[1:]
// Read a value, breaking on fatal errors
// and appending warnings
val_str, more, err := ReadI2PString(remainder)
str, more, err = ReadI2PString(remainder)
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
val_str := str
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
//return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
//log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
if !beginsWith(remainder, 0x3b) {
log.WithFields(log.Fields{
"at": "(Mapping) Values",
"reason": "expected ;",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, errors.New("mapping format violation, expected ;"))
break
} else {
remainder = remainder[1:]
}
remainder = remainder[1:]
// Append the key-value pair and break if there is no more data to read
map_values = append(map_values, [2]I2PString{key_str, val_str})

View File

@@ -38,17 +38,28 @@ func (str I2PString) Length() (length int, err error) {
err = errors.New("error parsing string: zero length")
return
}
l, _, _ := NewInteger(str, 1)
l := Integer([]byte{byte(str[0])})
length = l.Int()
str_len := len(str) - 1
if length != str_len {
inferred_len := length + 1
str_len := len(str)
if inferred_len > str_len {
log.WithFields(log.Fields{
"at": "(I2PString) Length",
"string_bytes_length": str_len,
"string_length_field": length,
"reason": "data less than specified by length",
}).Error("string format warning")
"at": "(I2PString) Length",
"string_bytes_length": str_len,
"string_length_field": length,
"expected_bytes_length": inferred_len,
"reason": "data shorter than specified",
}).Warn("string format warning")
err = errors.New("string parsing warning: string data is shorter than specified by length")
} else if str_len > inferred_len {
log.WithFields(log.Fields{
"at": "(I2PString) Length",
"string_bytes_length": str_len,
"string_length_field": length,
"expected_bytes_length": inferred_len,
"reason": "data longer than specified",
}).Warn("string format warning")
err = errors.New("string parsing warning: string contains data beyond length")
}
return
}
@@ -65,14 +76,11 @@ func (str I2PString) Data() (data string, err error) {
data = string(str[1:])
return
case "string parsing warning: string contains data beyond length":
data = string(str[1:])
data = string(str[1 : length+1])
return
}
}
if length == 0 {
return
}
data = string(str[1 : length+1])
data = string(str[1:])
return
}
@@ -105,14 +113,13 @@ func ToI2PString(data string) (str I2PString, err error) {
// 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) {
length, _, err := NewInteger(data, 1)
if err != nil {
return
str = I2PString(data)
length, err := I2PString(data).Length()
if err != nil && err.Error() == "string parsing warning: string contains data beyond length" {
str = I2PString(data[:length+1])
remainder = data[length+1:]
err = nil
}
data_len := length.Int()
str = data[:data_len+1]
remainder = data[data_len+1:]
_, err = str.Length()
return
}

View File

@@ -3,7 +3,7 @@ package exportable
import common "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
func Fuzz(data []byte) int {
keys_and_cert, _, _ := common.NewKeysAndCert(data)
keys_and_cert, _, _ := common.ReadKeysAndCert(data)
keys_and_cert.Certificate()
keys_and_cert.PublicKey()
keys_and_cert.SigningPublicKey()

View File

@@ -52,10 +52,6 @@ const (
// Key Certificate Public Key Types
const (
KEYCERT_CRYPTO_ELG = iota
KEYCERT_CRYPTO_P256
KEYCERT_CRYPTO_P384
KEYCERT_CRYPTO_P521
KEYCERT_CRYPTO_X25519
)
const (
@@ -77,11 +73,7 @@ const (
// PublicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
KEYCERT_CRYPTO_P384_SIZE = 96
KEYCERT_CRYPTO_P521_SIZE = 132
KEYCERT_CRYPTO_X25519_SIZE = 32
KEYCERT_CRYPTO_ELG_SIZE = 256
)
// Sizes of structures in KeyCertificates
@@ -90,7 +82,7 @@ const (
KEYCERT_SPK_SIZE = 128
)
// type KeyCertificate []byte
//type KeyCertificate []byte
type KeyCertificate struct {
*Certificate
spkType Integer
@@ -120,7 +112,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
return
}
data_len := len(data)
if data_len < key_certificate.CryptoSize() {
if data_len < KEYCERT_PUBKEY_SIZE {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructPublicKey",
"data_len": data_len,
@@ -135,10 +127,6 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
var elg_key crypto.ElgPublicKey
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = elg_key
case KEYCERT_CRYPTO_X25519:
var ed25519_key crypto.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = ed25519_key
}
return
}
@@ -151,7 +139,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
return
}
data_len := len(data)
if data_len < key_certificate.SignatureSize() {
if data_len < KEYCERT_SPK_SIZE {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructSigningPublicKey",
"data_len": data_len,
@@ -197,51 +185,60 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
// 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: KEYCERT_SIGN_DSA_SHA1_SIZE,
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
KEYCERT_SIGN_DSA_SHA1: 40,
KEYCERT_SIGN_P256: 64,
KEYCERT_SIGN_P384: 96,
KEYCERT_SIGN_P521: 132,
KEYCERT_SIGN_RSA2048: 256,
KEYCERT_SIGN_RSA3072: 384,
KEYCERT_SIGN_RSA4096: 512,
KEYCERT_SIGN_ED25519: 64,
KEYCERT_SIGN_ED25519PH: 64,
}
key_type := key_certificate.SigningPublicKeyType()
return sizes[int(key_type)]
}
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type.
func (key_certificate KeyCertificate) CryptoSize() (size int) {
sizes := map[int]int{
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE,
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
}
key_type := key_certificate.PublicKeyType()
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)
if err != nil {
return
}
//if err != nil {
// return nil, err
//}
if len(bytes) < KEYCERT_MIN_SIZE {
err = errors.New("error parsing key certificate: not enough data")
}
key_certificate = &KeyCertificate{
Certificate: certificate,
spkType: Integer(bytes[4:5]),
cpkType: Integer(bytes[6:7]),
switch len(bytes) {
case 4:
key_certificate = &KeyCertificate{
Certificate: certificate,
spkType: Integer(bytes[4:]),
cpkType: Integer([]byte{0}),
}
case 5:
key_certificate = &KeyCertificate{
Certificate: certificate,
spkType: Integer(bytes[4:5]),
cpkType: Integer([]byte{0}),
}
case 6:
key_certificate = &KeyCertificate{
Certificate: certificate,
spkType: Integer(bytes[4:5]),
cpkType: Integer(bytes[6:]),
}
default:
key_certificate = &KeyCertificate{
Certificate: certificate,
spkType: Integer(bytes[4:5]),
cpkType: Integer(bytes[6:7]),
}
}
remainder = bytes[KEYCERT_MIN_SIZE:]
remainder = bytes[7:]
//key_certificate.PublicKey = NewPublicKey(bytes)
return
}

View File

@@ -165,22 +165,51 @@ func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
return keys_and_cert.KeyCertificate.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 {
log.WithFields(log.Fields{
"at": "ReadKeysAndCert",
"data_len": data_len,
"required_len": KEYS_AND_CERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
return
}
keys_and_cert = KeysAndCert(data[:KEYS_AND_CERT_MIN_SIZE])
cert, _ := keys_and_cert.Certificate()
cert_len := cert.Length()
if cert_len == 0 {
remainder = data[KEYS_AND_CERT_MIN_SIZE:]
return
}
if data_len < KEYS_AND_CERT_MIN_SIZE+cert_len {
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:]...)
//err = cert_len_err
} else {
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:KEYS_AND_CERT_MIN_SIZE+cert_len]...)
remainder = data[KEYS_AND_CERT_MIN_SIZE+cert_len:]
}*/
keys_and_cert_pointer, remainder, err := NewKeysAndCert(data)
keys_and_cert = *keys_and_cert_pointer
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{}
if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE {
log.WithFields(log.Fields{
"at": "ReadKeysAndCert",
"data_len": data_len,
"required_len": KEYS_AND_CERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
return
} else if data_len < KEYS_AND_CERT_DATA_SIZE {
if data_len < KEYS_AND_CERT_MIN_SIZE {
log.WithFields(log.Fields{
"at": "ReadKeysAndCert",
"data_len": data_len,
@@ -190,22 +219,22 @@ func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte,
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
return
}
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
cert, remainder, err := NewKeyCertificate(data)
keys_and_cert.KeyCertificate = cert
if err != nil {
return nil, nil, err
}
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same.
// a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE
// and KEYS_AND_CERT_SPK_SIZE constants in the future.
keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
if err != nil {
return nil, nil, err
}
keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE])
if err != nil {
return nil, nil, err
}
padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE]
padding := data[KEYS_AND_CERT_MIN_SIZE+cert.Length():]
keys_and_cert.padding = padding
publicKey, err := cert.ConstructPublicKey(padding)
keys_and_cert.publicKey = publicKey
if err != nil {
return nil, nil, err
}
signingPublicKey, err := cert.ConstructSigningPublicKey(padding)
keys_and_cert.signingPublicKey = signingPublicKey
if err != nil {
return nil, nil, err
}
return keys_and_cert, remainder, err
}

View File

@@ -6,17 +6,23 @@ import (
"github.com/stretchr/testify/assert"
)
/*func TestCertificateWithMissingData(t *testing.T) {
func TestCertificateWithMissingData(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
data := make([]byte, 128+256)
data = append(data, cert_data...)
_, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
cert := keys_and_cert.Certificate()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
}
}*/
cert_bytes := cert.Bytes()
if assert.Equal(len(cert_data), len(cert_bytes)) {
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return available data when cert was missing some data")
}
}
func TestCertificateWithValidData(t *testing.T) {
assert := assert.New(t)
@@ -24,11 +30,10 @@ func TestCertificateWithValidData(t *testing.T) {
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
data := make([]byte, 128+256)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
assert.Nil(err)
keys_and_cert, _, err := ReadKeysAndCert(data)
cert := keys_and_cert.Certificate()
assert.Nil(err)
cert_bytes := cert.Bytes()
if assert.Equal(len(cert_data), len(cert_bytes)) {
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return correct data with valid cert")
@@ -43,7 +48,7 @@ func TestPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) {
@@ -60,7 +65,7 @@ func TestPublicKeyWithBadCertificate(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) {
@@ -77,7 +82,7 @@ func TestPublicKeyWithNullCertificate(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
@@ -92,7 +97,7 @@ func TestPublicKeyWithKeyCertificate(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
@@ -107,7 +112,7 @@ func TestSigningPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 93)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) {
@@ -124,7 +129,7 @@ func TestSigningPublicKeyWithBadCertificate(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) {
@@ -141,7 +146,7 @@ func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err)
@@ -156,18 +161,18 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err)
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
}
func TestNewKeysAndCertWithMissingData(t *testing.T) {
func TestReadKeysAndCertWithMissingData(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
if assert.NotNil(err) {
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
@@ -175,56 +180,56 @@ func TestNewKeysAndCertWithMissingData(t *testing.T) {
}
func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
func TestReadKeysAndCertWithMissingCertData(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
}
}
func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) {
func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
assert.Nil(err)
}
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
assert.Nil(err)
}
func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0]))
}
assert.Nil(err)
}
func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
func TestReadKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0]))
}

View File

@@ -132,10 +132,7 @@ type LeaseSet struct {
// Destination returns the Destination as []byte.
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
keys_and_cert, _, err := NewKeysAndCert(lease_set)
if err != nil {
return
}
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
destination, _, err = ReadDestination(keys_and_cert.Bytes())
return
}
@@ -143,7 +140,7 @@ func (lease_set LeaseSet) Destination() (destination Destination, err error) {
// 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 := NewKeysAndCert(lease_set)
_, remainder, err := ReadKeysAndCert(lease_set)
remainder_len := len(remainder)
if remainder_len < LEASE_SET_PUBKEY_SIZE {
log.WithFields(log.Fields{
@@ -215,7 +212,7 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
// 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 := NewKeysAndCert(lease_set)
_, remainder, err := ReadKeysAndCert(lease_set)
if err != nil {
return
}

View File

@@ -65,8 +65,9 @@ options :: Mapping
type RouterAddress struct {
cost *Integer
expiration *Date
transport_style *I2PString
Transport_Style *I2PString
options *Mapping
parserErr error
}
// Bytes returns the router address as a []byte.
@@ -74,15 +75,15 @@ func (router_address RouterAddress) Bytes() []byte {
bytes := make([]byte, 0)
bytes = append(bytes, router_address.cost.Bytes()...)
bytes = append(bytes, router_address.expiration.Bytes()...)
strData, err := router_address.transport_style.Data()
strData, err := router_address.Transport_Style.Data()
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
}).Error("RouterAddress.Bytes: error getting Transport_Style bytes")
} else {
bytes = append(bytes, strData...)
}
bytes = append(bytes, router_address.options.Data()...)
//bytes = append(bytes, router_address.options.Bytes()...)
return bytes
}
@@ -98,7 +99,7 @@ func (router_address RouterAddress) Expiration() Date {
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
func (router_address RouterAddress) TransportStyle() I2PString {
return *router_address.transport_style
return *router_address.Transport_Style
}
// Options returns the options for this RouterAddress as an I2P Mapping.
@@ -108,6 +109,25 @@ func (router_address RouterAddress) Options() Mapping {
// Check if the RouterAddress is empty or if it is too small to contain valid data.
func (router_address RouterAddress) checkValid() (err error, exit bool) {
/*addr_len := len(router_address)
exit = false
if addr_len == 0 {
log.WithFields(log.Fields{
"at": "(RouterAddress) checkValid",
"reason": "no data",
}).Error("invalid router address")
err = errors.New("error parsing RouterAddress: no data")
exit = true
} else if addr_len < ROUTER_ADDRESS_MIN_SIZE {
log.WithFields(log.Fields{
"at": "(RouterAddress) checkValid",
"reason": "data too small (len < ROUTER_ADDRESS_MIN_SIZE)",
}).Warn("router address format warning")
err = errors.New("warning parsing RouterAddress: data too small")
}*/
if router_address.parserErr != nil {
exit = true
}
return
}
@@ -115,40 +135,54 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) {
// 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 len(data) == 0 {
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
if data == nil || len(data) == 0 {
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data")
err = errors.New("error parsing RouterAddress: no data")
router_address.parserErr = err
return
}
router_address.cost, remainder, err = NewInteger(data, 1)
cost, remainder, err := NewInteger([]byte{data[0]}, 1)
router_address.cost = cost
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing cost",
}).Warn("error parsing RouterAddress")
router_address.parserErr = err
}
router_address.expiration, remainder, err = NewDate(remainder)
expiration, remainder, err := NewDate(remainder)
router_address.expiration = expiration
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing expiration",
}).Error("error parsing RouterAddress")
router_address.parserErr = err
}
router_address.transport_style, remainder, err = NewI2PString(remainder)
Transport_Style, remainder, err := NewI2PString(remainder)
router_address.Transport_Style = Transport_Style
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing transport_style",
"reason": "error parsing Transport_Style",
}).Error("error parsing RouterAddress")
router_address.parserErr = err
}
var errs []error
router_address.options, remainder, errs = NewMapping(remainder)
options, remainder, errs := NewMapping(remainder)
for _, err := range errs {
log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing options",
"error": err,
}).Error("error parsing RouterAddress")
router_address.parserErr = err
}
router_address.options = options
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing options",
}).Error("error parsing RouterAddress")
router_address.parserErr = err
}
return
}

View File

@@ -3,7 +3,7 @@ package router_info
import (
"errors"
"strconv"
"net"
"strings"
. "github.com/go-i2p/go-i2p/lib/common/data"
@@ -15,9 +15,6 @@ import (
const ROUTER_INFO_MIN_SIZE = 439
var MIN_GOOD_VERSION = 59
const MAX_GOOD_VERSION = 99
/*
[RouterInfo]
Accurate for version 0.9.49
@@ -111,10 +108,13 @@ type RouterInfo struct {
signature *Signature
}
var routerInfoTest net.Addr = &RouterInfo{}
// 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
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
bytes = append(bytes, router_info.published.Bytes()...)
bytes = append(bytes, router_info.size.Bytes()...)
@@ -122,12 +122,35 @@ func (router_info RouterInfo) Bytes() ([]byte, error) {
bytes = append(bytes, router_address.Bytes()...)
}
bytes = append(bytes, router_info.peer_size.Bytes()...)
bytes = append(bytes, router_info.options.Data()...)
//bytes = append(bytes, []byte(*router_info.signature)...)
//bytes = append(bytes, router_info.options.Bytes()...)
bytes = append(bytes, []byte(*router_info.signature)...)
return bytes, err
}
// Network Implements net.Addr, returns comma-separated list of transport types
func (router_info *RouterInfo) Network() string {
var str []string
for _, addr := range router_info.addresses {
t, err := addr.Transport_Style.Data()
if err != nil {
return strings.Join(str, ",")
}
str = append(str, t)
}
return strings.Join(str, ",")
}
// String Implements net.Addr, returns router-info `Bytes` converted to a string
func (router_info *RouterInfo) String() string {
bytes, err := router_info.Bytes()
if err != nil {
// TODO handle this issue
return ""
}
return string(bytes)
}
// RouterIdentity returns the router identity as *RouterIdentity.
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
return router_info.router_identity
@@ -255,14 +278,6 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
err = errors.New("error parsing router info: not enough data")
}
size, remainder, err := NewInteger(remainder, 1)
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo",
"data_len": len(remainder),
"required_len": size.Int(),
"reason": "read error",
}).Error("error parsing router info size")
}
info.size = size
if err != nil {
log.WithFields(log.Fields{
@@ -273,23 +288,25 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
}).Error("error parsing router info")
err = errors.New("error parsing router info: not enough data")
}
addresses := make([]*RouterAddress, size.Int())
for i := 0; i < size.Int(); i++ {
address, more, err := NewRouterAddress(remainder)
remainder = more
address, remainder, err := NewRouterAddress(remainder)
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo",
"data_len": len(remainder),
//"required_len": ROUTER_ADDRESS_SIZE,
"reason": "not enough data",
}).Error("error parsing router address")
}).Error("error parsing router info")
err = errors.New("error parsing router info: not enough data")
}
info.addresses = append(info.addresses, address)
addresses = append(addresses, address)
}
info.peer_size, remainder, err = NewInteger(remainder, 1)
var errs []error
info.options, remainder, errs = NewMapping(remainder)
info.addresses = addresses
peer_size := Integer(remainder[:1])
info.peer_size = &peer_size
remainder = remainder[1:]
options, remainder, errs := NewMapping(remainder)
if len(errs) != 0 {
log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo",
@@ -303,6 +320,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
}
err = errors.New("error parsing router info: " + estring)
}
info.options = options
if err != nil {
log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo",
@@ -315,61 +333,6 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
return
}
func (router_info *RouterInfo) RouterCapabilities() string {
str, err := ToI2PString("caps")
if err != nil {
return ""
}
return string(router_info.options.Values().Get(str))
}
func (router_info *RouterInfo) RouterVersion() string {
str, err := ToI2PString("router.version")
if err != nil {
return ""
}
return string(router_info.options.Values().Get(str))
}
func (router_info *RouterInfo) GoodVersion() bool {
version := router_info.RouterVersion()
v := strings.Split(version, ".")
if len(v) != 3 {
return false
}
if v[0] == "0" {
if v[1] == "9" {
val, _ := strconv.Atoi(v[2])
if val >= MIN_GOOD_VERSION && val <= MAX_GOOD_VERSION {
return true
}
}
}
return false
}
func (router_info *RouterInfo) UnCongested() bool {
caps := router_info.RouterCapabilities()
if strings.Contains(caps, "K") {
return false
}
if strings.Contains(caps, "G") {
return false
}
if strings.Contains(caps, "E") {
return false
}
return true
}
func (router_info *RouterInfo) Reachable() bool {
caps := router_info.RouterCapabilities()
if strings.Contains(caps, "U") {
return false
}
return strings.Contains(caps, "R")
}
// 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) {

View File

@@ -1,2 +1,4 @@
//
// package for i2p specific crpytography
//
package crypto

View File

@@ -2,16 +2,10 @@ package crypto
import (
"crypto/ed25519"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"errors"
"io"
"math/big"
)
var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
type Ed25519PublicKey []byte
type Ed25519Verifier struct {
@@ -25,77 +19,6 @@ func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) {
return temp, nil
}
func (k Ed25519PublicKey) Len() int {
return len(k)
}
func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) {
if len(data) == 256 {
k2 := ed25519.PublicKey{}
copy(k2[:], data)
k = &k2
}
return
}
func createEd25519Encryption(pub *ed25519.PublicKey, rand io.Reader) (enc *Ed25519Encryption, err error) {
/*kbytes := make([]byte, 256)
k := new(big.Int)
for err == nil {
_, err = io.ReadFull(rand, kbytes)
k = new(big.Int).SetBytes(kbytes)
k = k.Mod(k, pub.P)
if k.Sign() != 0 {
break
}
}
if err == nil {
enc = &Ed25519Encryption{}
}*/
return
}
type Ed25519Encryption struct {
p, a, b1 *big.Int
}
func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error) {
return ed25519.EncryptPadding(data, true)
}
func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) {
if len(data) > 222 {
err = Ed25519EncryptTooBig
return
}
mbytes := make([]byte, 255)
mbytes[0] = 0xFF
copy(mbytes[33:], data)
// do sha256 of payload
d := sha256.Sum256(mbytes[33 : len(data)+33])
copy(mbytes[1:], d[:])
m := new(big.Int).SetBytes(mbytes)
// do encryption
b := new(big.Int).Mod(new(big.Int).Mul(ed25519.b1, m), ed25519.p).Bytes()
if zeroPadding {
encrypted = make([]byte, 514)
copy(encrypted[1:], ed25519.a.Bytes())
copy(encrypted[258:], b)
} else {
encrypted = make([]byte, 512)
copy(encrypted, ed25519.a.Bytes())
copy(encrypted[256:], b)
}
return
}
func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) {
k := createEd25519PublicKey(elg[:])
enc, err = createEd25519Encryption(k, rand.Reader)
return
}
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) {
if len(sig) != ed25519.SignatureSize {
err = ErrBadSignatureSize

View File

@@ -5,10 +5,9 @@ import (
"crypto/sha256"
"crypto/subtle"
"errors"
"golang.org/x/crypto/openpgp/elgamal"
"io"
"math/big"
"golang.org/x/crypto/openpgp/elgamal"
)
var elgp = new(big.Int).SetBytes([]byte{

View File

@@ -23,7 +23,9 @@ func (hk HMACKey) xor(p byte) (i []byte) {
return
}
//
// do i2p hmac
//
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) {
buff := make([]byte, 64+len(data))

View File

@@ -1 +1,5 @@
//
//
//
//
package netdb

View File

@@ -50,7 +50,9 @@ func (db StdNetDB) Path() string {
return string(db)
}
//
// return how many routers we know about in our network database
//
func (db StdNetDB) Size() (routers int) {
// TODO: implement this
var err error

View File

@@ -14,50 +14,47 @@
// content the error ErrInvalidSignature will be returned.
//
// Example usage:
//
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
// su3File, err := su3.Read(body)
// if err != nil {
// // Handle error.
// }
// // Look up this signer's key.
// key := somehow_lookup_the_key(su3File.SignerID)
// // Read the content.
// contentReader := su3File.Content(key)
// bytes, err := ioutil.ReadAll(contentReader)
// if errors.Is(err, su3.ErrInvalidSignature) {
// // The signature is invalid, OR a nil key was provided.
// } else if err != nil {
// // Handle error.
// }
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
// su3File, err := su3.Read(body)
// if err != nil {
// // Handle error.
// }
// // Look up this signer's key.
// key := somehow_lookup_the_key(su3File.SignerID)
// // Read the content.
// contentReader := su3File.Content(key)
// bytes, err := ioutil.ReadAll(contentReader)
// if errors.Is(err, su3.ErrInvalidSignature) {
// // The signature is invalid, OR a nil key was provided.
// } else if err != nil {
// // Handle error.
// }
//
// If you want to parse from a []byte, you can wrap it like this:
//
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
//
// One of the advantages of this library's design is that you can avoid buffering
// the file contents in memory. Here's how you would stream from an HTTP body
// directly to disk:
//
// su3File, err := su3.Read(body)
// if err != nil {
// // Handle error.
// }
// // Look up this signer's key.
// key := somehow_lookup_the_key(su3File.SignerID)
// // Stream directly to disk.
// f, err := os.Create("my_file.txt")
// if err != nil {
// // Handle error.
// }
// _, err := io.Copy(f, su3File.Content(key))
// if errors.Is(err, su3.ErrInvalidSignature) {
// // The signature is invalid, OR a nil key was provided.
// // Don't trust the file, delete it!
// } else if err != nil {
// // Handle error.
// }
// su3File, err := su3.Read(body)
// if err != nil {
// // Handle error.
// }
// // Look up this signer's key.
// key := somehow_lookup_the_key(su3File.SignerID)
// // Stream directly to disk.
// f, err := os.Create("my_file.txt")
// if err != nil {
// // Handle error.
// }
// _, err := io.Copy(f, su3File.Content(key))
// if errors.Is(err, su3.ErrInvalidSignature) {
// // The signature is invalid, OR a nil key was provided.
// // Don't trust the file, delete it!
// } else if err != nil {
// // Handle error.
// }
//
// Note: if you want to read the content, the Content() io.Reader must be read
// *before* the Signature() io.Reader. If you read the signature first, the

View File

@@ -1,6 +1,4 @@
/*
*
i2np messages transports
/**
i2np messages transports
*/
package transport

View File

@@ -1,15 +0,0 @@
package noise
import (
"github.com/flynn/noise"
)
func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
return
}
func (c *NoiseSession) RunClientHandshake() error {
return nil
}

View File

@@ -1,75 +0,0 @@
package noise
import (
"errors"
"sync/atomic"
log "github.com/sirupsen/logrus"
)
func (c *NoiseSession) Write(b []byte) (int, error) {
// interlock with Close below
for {
x := atomic.LoadInt32(&c.activeCall)
if x&1 != 0 {
log.WithFields(log.Fields{
"at": "(NoiseSession) Write",
"reason": "session is closed",
}).Error("session is closed")
return 0, errors.New("session is closed")
}
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
defer atomic.AddInt32(&c.activeCall, -2)
break
}
}
if err := c.RunClientHandshake(); err != nil {
return 0, err
}
c.Mutex.Lock()
defer c.Mutex.Unlock()
if !c.handshakeComplete {
return 0, errors.New("internal error")
}
n, err := c.writePacketLocked(b)
return n, err
}
func (c *NoiseSession) writePacketLocked(data []byte) (int, error) {
var n int
if len(data) == 0 { //special case to answer when everything is ok during handshake
if _, err := c.Conn.Write(make([]byte, 2)); err != nil {
return 0, err
}
}
for len(data) > 0 {
/*m := len(data)
packet := c.InitializePacket()
maxPayloadSize := c.maxPayloadSizeForWrite(packet)
if m > int(maxPayloadSize) {
m = int(maxPayloadSize)
}
if c.CipherState != nil {
////fmt.Println("writing encrypted packet:", m)
packet.reserve(uint16Size + uint16Size + m + macSize)
packet.resize(uint16Size + uint16Size + m)
copy(packet.data[uint16Size+uint16Size:], data[:m])
binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m))
//fmt.Println("encrypt size", uint16(m))
} else {
packet.resize(len(packet.data) + len(data))
copy(packet.data[uint16Size:len(packet.data)], data[:m])
binary.BigEndian.PutUint16(packet.data, uint16(len(data)))
}
b := c.encryptIfNeeded(packet)
c.freeBlock(packet)
////fmt.Println(hex.EncodeToString(b))
if _, err := c.conn.Write(b); err != nil {
return n, err
}
n += m
data = data[m:]
*/
}
return n, nil
}

View File

@@ -9,19 +9,10 @@ import (
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
c.Mutex.Lock()
defer c.Mutex.Unlock()
session, err := c.GetSession(routerInfo)
session, err := c.getSession(routerInfo)
if err != nil {
return err
}
for {
if session.(*NoiseSession).handshakeComplete {
return nil
}
if session.(*NoiseSession).Cond == nil {
break
}
session.(*NoiseSession).Cond.Wait()
}
// Set handshakeCond to indicate that this goroutine is committing to
// running the handshake.
session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex)
@@ -29,8 +20,8 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
session.(*NoiseSession).Mutex.Lock()
defer session.(*NoiseSession).Mutex.Unlock()
c.Mutex.Lock()
// if c.config.isClient {
if err := session.(*NoiseSession).RunClientHandshake(); err != nil {
if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil {
return err
}
// Wake any other goroutines that are waiting for this handshake to

View File

@@ -0,0 +1,15 @@
package noise
import "github.com/go-i2p/go-i2p/lib/i2np"
func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) {
s.SendQueue.Enqueue(msg)
}
func (s *NoiseSession) SendQueueSize() int {
return s.SendQueue.Size()
}
func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) {
return i2np.I2NPMessage{}, nil
}

View File

@@ -0,0 +1,64 @@
package noise
import (
"bytes"
"crypto/rand"
"encoding/binary"
"errors"
"io"
"log"
"github.com/flynn/noise"
)
func ComposeRecieverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
} else {
random = bytes.NewBuffer(ePrivate)
}
prologue := make([]byte, 2, uint16Size+len(negData))
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
prologue = append(prologue, negData...)
//prologue = append(initString, prologue...)
state, err = noise.NewHandshakeState(noise.Config{
StaticKeypair: s,
Initiator: false,
Pattern: pattern,
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
PeerStatic: rs,
Prologue: prologue,
Random: random,
})
if err != nil {
return
}
padBuf := make([]byte, 2+len(payload))
copy(padBuf[2:], payload)
msg, _, _, err = state.WriteMessage(msg, padBuf)
return
}
func (c *NoiseSession) RunIncomingHandshake() error {
negData, msg, state, err := ComposeRecieverHandshakeMessage(c.HandKey, nil, nil, nil)
if err != nil {
return err
}
if _, err = c.Write(negData); err != nil {
return err
}
if _, err = c.Write(msg); err != nil {
return err
}
log.Println(state)
c.handshakeComplete = true
return nil
}

View File

@@ -0,0 +1,46 @@
package noise
import (
"encoding/binary"
"github.com/flynn/noise"
)
const (
NOISE_DH_CURVE25519 = 1
NOISE_CIPHER_CHACHAPOLY = 1
NOISE_CIPHER_AESGCM = 2
NOISE_HASH_SHA256 = 3
NOISE_PATTERN_XK = 11
uint16Size = 2 // uint16 takes 2 bytes
MaxPayloadSize = 65537
)
var ciphers = map[byte]noise.CipherFunc{
NOISE_CIPHER_CHACHAPOLY: noise.CipherChaChaPoly,
NOISE_CIPHER_AESGCM: noise.CipherAESGCM,
}
var hashes = map[byte]noise.HashFunc{
NOISE_HASH_SHA256: noise.HashSHA256,
}
var patterns = map[byte]noise.HandshakePattern{
NOISE_PATTERN_XK: noise.HandshakeXK,
}
func initNegotiationData(negotiationData []byte) []byte {
if negotiationData != nil {
return negotiationData
}
negotiationData = make([]byte, 6)
binary.BigEndian.PutUint16(negotiationData, 1) //version
negotiationData[2] = NOISE_DH_CURVE25519
negotiationData[3] = NOISE_CIPHER_CHACHAPOLY
negotiationData[4] = NOISE_HASH_SHA256
return negotiationData
}

View File

@@ -0,0 +1,66 @@
package noise
import (
"bytes"
"crypto/rand"
"encoding/binary"
"errors"
"io"
"log"
"github.com/flynn/noise"
)
func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
} else {
random = bytes.NewBuffer(ePrivate)
}
prologue := make([]byte, 2, uint16Size+len(negData))
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
prologue = append(prologue, negData...)
//prologue = append(initString, prologue...)
state, err = noise.NewHandshakeState(noise.Config{
StaticKeypair: s,
Initiator: true,
Pattern: pattern,
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
PeerStatic: rs,
Prologue: prologue,
Random: random,
})
if err != nil {
return
}
padBuf := make([]byte, 2+len(payload))
copy(padBuf[2:], payload)
msg, _, _, err = state.WriteMessage(msg, padBuf)
return
}
func (c *NoiseSession) RunOutgoingHandshake() error {
negData, msg, state, err := ComposeInitiatorHandshakeMessage(c.HandKey, nil, nil, nil)
if err != nil {
return err
}
if _, err = c.Write(negData); err != nil {
return err
}
if _, err = c.Write(msg); err != nil {
return err
}
log.Println(state)
c.handshakeComplete = true
return nil
}

View File

@@ -0,0 +1,84 @@
package noise
import (
"errors"
"sync/atomic"
log "github.com/sirupsen/logrus"
)
func (c *NoiseSession) Read(b []byte) (int, error) {
// interlock with Close below
for {
x := atomic.LoadInt32(&c.activeCall)
if x&1 != 0 {
log.WithFields(log.Fields{
"at": "(NoiseSession) Read",
"reason": "session is closed",
}).Error("session is closed")
return 0, errors.New("session is closed")
}
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
defer atomic.AddInt32(&c.activeCall, -2)
break
}
}
if !c.handshakeComplete {
if err := c.RunIncomingHandshake(); err != nil {
return 0, err
}
}
c.Mutex.Lock()
defer c.Mutex.Unlock()
if !c.handshakeComplete {
return 0, errors.New("internal error")
}
n, err := c.readPacketLocked(b)
return n, err
}
func (c *NoiseSession) decryptPacket(data []byte) (int, []byte, error) {
m := len(data)
/*packet := c.InitializePacket()
maxPayloadSize := c.maxPayloadSizeForRead(packet)
if m > int(maxPayloadSize) {
m = int(maxPayloadSize)
}
if c.CipherState != nil {
////fmt.Println("writing encrypted packet:", m)
packet.reserve(uint16Size + uint16Size + m + macSize)
packet.resize(uint16Size + uint16Size + m)
copy(packet.data[uint16Size+uint16Size:], data[:m])
binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m))
//fmt.Println("encrypt size", uint16(m))
} else {
packet.resize(len(packet.data) + len(data))
copy(packet.data[uint16Size:len(packet.data)], data[:m])
binary.BigEndian.PutUint16(packet.data, uint16(len(data)))
}
b := c.encryptIfNeeded(packet)*/
//c.freeBlock(packet)
return m, data, nil
}
func (c *NoiseSession) readPacketLocked(data []byte) (int, error) {
var n int
if len(data) == 0 { //special case to answer when everything is ok during handshake
if _, err := c.Conn.Read(make([]byte, 2)); err != nil {
return 0, err
}
}
for len(data) > 0 {
m, b, err := c.encryptPacket(data)
if err != nil {
return 0, err
}
if n, err := c.Conn.Read(b); err != nil {
return n, err
} else {
n += m
data = data[m:]
}
}
return n, nil
}

View File

@@ -2,6 +2,7 @@ package noise
import (
"bytes"
"fmt"
"net"
"sync"
"time"
@@ -10,46 +11,45 @@ import (
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/i2np"
"github.com/go-i2p/go-i2p/lib/transport"
)
type NoiseSession struct {
*cb.Queue
router_info.RouterInfo
*noise.CipherState
sync.Mutex
*sync.Cond
*NoiseTransport
*NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session
RecvQueue *cb.Queue
SendQueue *cb.Queue
SendKey noise.DHKey
RecvKey noise.DHKey
HandKey noise.DHKey
VerifyCallback VerifyCallbackFunc
handshakeBuffer bytes.Buffer
activeCall int32
handshakeComplete bool
Conn net.Conn
}
// Read implements net.Conn
func (*NoiseSession) Read(b []byte) (n int, err error) {
panic("unimplemented")
}
// RemoteAddr implements net.Conn
func (*NoiseSession) RemoteAddr() net.Addr {
panic("unimplemented")
func (noise_session *NoiseSession) RemoteAddr() net.Addr {
return &noise_session.RouterInfo
}
// SetDeadline implements net.Conn
func (*NoiseSession) SetDeadline(t time.Time) error {
panic("unimplemented")
func (noise_session *NoiseSession) SetDeadline(t time.Time) error {
return noise_session.Conn.SetDeadline(t)
}
// SetReadDeadline implements net.Conn
func (*NoiseSession) SetReadDeadline(t time.Time) error {
panic("unimplemented")
func (noise_session *NoiseSession) SetReadDeadline(t time.Time) error {
return noise_session.Conn.SetReadDeadline(t)
}
// SetWriteDeadline implements net.Conn
func (*NoiseSession) SetWriteDeadline(t time.Time) error {
panic("unimplemented")
func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error {
return noise_session.Conn.SetWriteDeadline(t)
}
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
@@ -59,27 +59,40 @@ func (s *NoiseSession) LocalAddr() net.Addr {
return s.Conn.LocalAddr()
}
func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) {
s.Queue.Enqueue(msg)
}
func (s *NoiseSession) SendQueueSize() int {
return s.Queue.Size()
}
func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) {
return i2np.I2NPMessage{}, nil
}
func (s *NoiseSession) Close() error {
s.Queue.Clear()
s.SendQueue.Clear()
s.RecvQueue.Clear()
return nil
}
func NewNoiseTransportSession(ri router_info.RouterInfo, socket net.Conn) (transport.TransportSession, error) {
return &NoiseSession{
Queue: cb.New(1024),
RouterInfo: ri,
Conn: socket,
}, nil
func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error {
if c.VerifyCallback == nil {
return nil
}
err := c.VerifyCallback(publicKey, payload)
return err
}
// newBlock allocates a new packet, from hc's free list if possible.
func newBlock() []byte {
return make([]byte, MaxPayloadSize)
}
type VerifyCallbackFunc func(publicKey []byte, data []byte) error
func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) {
//socket, err := DialNoise("noise", ri)
for _, addr := range ri.RouterAddresses() {
socket, err := net.Dial("tcp", string(addr.Bytes()))
if err != nil {
return nil, err
}
return &NoiseSession{
SendQueue: cb.New(1024),
RecvQueue: cb.New(1024),
RouterInfo: ri,
Conn: socket,
}, nil
}
return nil, fmt.Errorf("Transport constructor error")
}

View File

@@ -0,0 +1 @@
package noise

View File

@@ -16,12 +16,13 @@ import (
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/transport"
log "github.com/sirupsen/logrus"
)
type NoiseTransport struct {
*noise.CipherState
router_identity.RouterIdentity
sync.Mutex
router_identity.RouterIdentity
*noise.CipherState
Listener net.Listener
peerConnections map[data.Hash]transport.TransportSession
}
@@ -33,24 +34,36 @@ var exampleNoiseTransport transport.Transport = &NoiseTransport{}
// implements net.Listener
var ExampleNoiseListener net.Listener = exampleNoiseTransport
// Accept a connection on a listening socket.
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
return noopt.Listener.Accept()
}
// Addr of the transport, for now this is returning the IP:Port the transport is listening on,
// but this might actually be the router identity
func (noopt *NoiseTransport) Addr() net.Addr {
return noopt.Listener.Addr()
}
// Name of the transport TYPE, in this case `noise`
func (noopt *NoiseTransport) Name() string {
return "noise"
}
// Set the router identity for this transport.
// SetIdentity will set the router identity for this transport.
// will bind if the underlying socket is not already
// if the underlying socket is already bound update the RouterIdentity
// returns any errors that happen if they do
func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) error {
func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (err error) {
noopt.RouterIdentity = ident
if noopt.Listener == nil {
log.WithFields(log.Fields{
"at": "(NoiseTransport) SetIdentity",
"reason": "network socket is null",
}).Error("network socket is null")
err = errors.New("network socket is null")
return
}
return nil
}
@@ -63,19 +76,34 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran
if len(hash) == 0 {
return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash")
}
if t, ok := noopt.peerConnections[hash]; ok == true {
if t, ok := noopt.peerConnections[hash]; ok {
return t, nil
}
conn, err := noopt.Accept()
if err == nil {
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, conn); err != nil {
return noopt.peerConnections[hash], err
}
var err error
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil {
return noopt.peerConnections[hash], err
}
return nil, err
}
// return true if a routerInfo is compatable with this transport
func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
session, err := c.GetSession(routerInfo)
if err != nil {
return nil, err
}
for {
if session.(*NoiseSession).handshakeComplete {
return nil, nil
}
if session.(*NoiseSession).Cond == nil {
break
}
session.(*NoiseSession).Cond.Wait()
}
return session, nil
}
// Compatable return true if a routerInfo is compatable with this transport
func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool {
_, ok := noopt.peerConnections[routerInfo.IdentHash()]
return ok
@@ -88,9 +116,20 @@ func (noopt *NoiseTransport) Close() error {
return nil
}
// NewNoiseTransport create a NoiseTransport using a supplied net.Listener
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
return &NoiseTransport{
peerConnections: make(map[data.Hash]transport.TransportSession),
Listener: netSocket,
}
}
// NewNoiseTransportSocket creates a Noise transport socket with a random
// host and port.
func NewNoiseTransportSocket() (*NoiseTransport, error) {
netSocket, err := net.Listen("tcp", "")
if err != nil {
return nil, err
}
return NewNoiseTransport(netSocket), nil
}

View File

@@ -11,6 +11,20 @@ func TestTransport(t *testing.T) {
t.Error(err)
}
nt := NewNoiseTransport(ln)
t.Log(nt.Name())
go func() {
for {
conn, err := nt.Accept()
if err != nil {
t.Log(err)
}
conn.Write([]byte("World"))
}
}()
lnn, err := net.Listen("tcp", ":42070")
if err != nil {
t.Error(err)
}
ntt := NewNoiseTransport(lnn)
t.Log(ntt.Name())
//ntt.GetSession()
}

View File

@@ -0,0 +1,84 @@
package noise
import (
"errors"
"sync/atomic"
log "github.com/sirupsen/logrus"
)
func (c *NoiseSession) Write(b []byte) (int, error) {
// interlock with Close below
for {
x := atomic.LoadInt32(&c.activeCall)
if x&1 != 0 {
log.WithFields(log.Fields{
"at": "(NoiseSession) Write",
"reason": "session is closed",
}).Error("session is closed")
return 0, errors.New("session is closed")
}
if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
defer atomic.AddInt32(&c.activeCall, -2)
break
}
}
if !c.handshakeComplete {
if err := c.RunOutgoingHandshake(); err != nil {
return 0, err
}
}
c.Mutex.Lock()
defer c.Mutex.Unlock()
if !c.handshakeComplete {
return 0, errors.New("internal error")
}
n, err := c.writePacketLocked(b)
return n, err
}
func (c *NoiseSession) encryptPacket(data []byte) (int, []byte, error) {
m := len(data)
/*packet := c.InitializePacket()
maxPayloadSize := c.maxPayloadSizeForWrite(packet)
if m > int(maxPayloadSize) {
m = int(maxPayloadSize)
}
if c.CipherState != nil {
////fmt.Println("writing encrypted packet:", m)
packet.reserve(uint16Size + uint16Size + m + macSize)
packet.resize(uint16Size + uint16Size + m)
copy(packet.data[uint16Size+uint16Size:], data[:m])
binary.BigEndian.PutUint16(packet.data[uint16Size:], uint16(m))
//fmt.Println("encrypt size", uint16(m))
} else {
packet.resize(len(packet.data) + len(data))
copy(packet.data[uint16Size:len(packet.data)], data[:m])
binary.BigEndian.PutUint16(packet.data, uint16(len(data)))
}
b := c.encryptIfNeeded(packet)*/
//c.freeBlock(packet)
return m, data, nil
}
func (c *NoiseSession) writePacketLocked(data []byte) (int, error) {
var n int
if len(data) == 0 { //special case to answer when everything is ok during handshake
if _, err := c.Conn.Write(make([]byte, 2)); err != nil {
return 0, err
}
}
for len(data) > 0 {
m, b, err := c.encryptPacket(data)
if err != nil {
return 0, err
}
if n, err := c.Conn.Write(b); err != nil {
return n, err
} else {
n += m
data = data[m:]
}
}
return n, nil
}

View File

@@ -0,0 +1,34 @@
package ntcp
import (
"math"
"github.com/flynn/noise"
)
const (
NOISE_DH_CURVE25519 = 1
NOISE_CIPHER_CHACHAPOLY = 1
NOISE_CIPHER_AESGCM = 2
NOISE_HASH_SHA256 = 3
NOISE_PATTERN_XK = 11
uint16Size = 2 // uint16 takes 2 bytes
MaxPayloadSize = math.MaxUint16 - 16 /*mac size*/ - uint16Size /*data len*/
)
var ciphers = map[byte]noise.CipherFunc{
NOISE_CIPHER_CHACHAPOLY: noise.CipherChaChaPoly,
NOISE_CIPHER_AESGCM: noise.CipherAESGCM,
}
var hashes = map[byte]noise.HashFunc{
NOISE_HASH_SHA256: noise.HashSHA256,
}
var patterns = map[byte]noise.HandshakePattern{
NOISE_PATTERN_XK: noise.HandshakeXK,
}

View File

@@ -1,6 +1,7 @@
package ntcp
import "github.com/go-i2p/go-i2p/lib/transport/noise"
// Session implements TransportSession
// An established transport session
type Session struct {
}
type Session noise.NoiseSession

View File

@@ -1,5 +1,7 @@
package ntcp
import "github.com/go-i2p/go-i2p/lib/transport/noise"
/**
* https://geti2p.net/spec/ntcp2
**/
@@ -10,6 +12,5 @@ const (
NTCP_MESSAGE_MAX_SIZE = 65537
)
// Transport is an ntcp transport implementing transport.Transport interface
type Transport struct {
}
// NTCPTransport is an ntcp transport implementing transport.Transport interface
type NTCPTransport noise.NoiseTransport

View File

@@ -1,4 +1,6 @@
/*
i2p ssu transport implementation
*/
package ssu

View File

@@ -380,9 +380,8 @@ func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32,
}
// Return the hash for these DeliveryInstructions, which varies by hash type.
//
// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if
// the type is DT_ROUTER it is the SHA256 of the router.
// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if
// the type is DT_ROUTER it is the SHA256 of the router.
func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) {
delivery_type, err := delivery_instructions.DeliveryType()
if err != nil {

View File

@@ -1,4 +1,4 @@
/*
i2p garlic tunnel implementation
i2p garlic tunnel implementation
*/
package tunnel

View File

@@ -153,8 +153,10 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelI
return decrypted_tunnel_message[4+16 : 4+4+16]
}
//
// Returns the contents of a decrypted tunnel message that contain the data for the
// DeliveryInstructions.
//
func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte {
data_area := decrypted_tunnel_message[4+4+16:]
for i := 0; i < len(data_area); i++ {
@@ -165,8 +167,11 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData()
return []byte{}
}
//
// Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions
// in the tunnel message and their corresponding MessageFragment structures.
//
//
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment {
set := make([]DeliveryInstructionsWithFragment, 0)
data := decrypted_tunnel_message.deliveryInstructionData()

View File

@@ -1,4 +1,3 @@
//go:build !windows
// +build !windows
package signals

View File

@@ -1,4 +1,3 @@
//go:build windows
// +build windows
package signals