mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-08-19 09:45:28 -04:00
Compare commits
10 Commits
reseed-too
...
noise-tran
Author | SHA1 | Date | |
---|---|---|---|
![]() |
65febb5dcf | ||
![]() |
116e22f8da | ||
![]() |
0419665d7b | ||
![]() |
dab108c270 | ||
![]() |
0fcded4c51 | ||
![]() |
7d16b0b257 | ||
![]() |
a689f26d73 | ||
![]() |
fdc34b382e | ||
![]() |
a4ed06e530 | ||
![]() |
6b5ea57cbd |
19
Makefile
19
Makefile
@@ -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))))
|
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
|
||||||
|
|
||||||
ifdef GOROOT
|
ifdef GOROOT
|
||||||
GO = $(GOROOT)/bin/go
|
GO = $(GOROOT)/bin/go
|
||||||
endif
|
endif
|
||||||
@@ -20,19 +18,8 @@ build: clean $(EXE)
|
|||||||
$(EXE):
|
$(EXE):
|
||||||
$(GO) build -v -o $(EXE)
|
$(GO) build -v -o $(EXE)
|
||||||
|
|
||||||
test: fmt
|
test:
|
||||||
$(GO) test -vv -failfast ./lib/common/...
|
$(GO) test -v -failfast ./lib/transport/noise/...
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(GO) clean -v
|
$(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
|
|
||||||
|
32
PASTA.md
32
PASTA.md
@@ -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.
|
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)
|
||||||
However, after much waiting, this library is actually **useful** for something.
|
I can now make a socket, instantiate a noise transport using the socket, and begin to use it to manage "incoming" and "outgoing" handshakes.
|
||||||
It is now being used in the `reseed-tools` application to examine RouterInfos prior to including them in reseed bundles.
|
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
|
||||||
Routers that self-report as unreachable or congested will be excluded from future reseed bundles.
|
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
|
||||||
Additionally, routers that self-report an old version will be excluded from reseed bundles.
|
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
|
||||||
This should help new users build better connections faster with the existing, working router implementations.
|
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:
|
||||||
This is not a working release of a go-i2p router
|
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)
|
||||||
It is a numbered version of the go-i2p library, which is pre-release, expressly for use in the `reseed-tools` application.
|
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)
|
||||||
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.
|
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?
|
||||||
If you're using it for something other than parsing and analyzing RouterInfos and LeaseSets, you'll probably encounter bugs.
|
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.
|
||||||
Please report them to the https://github.com/go-i2p/go-i2p
|
|
||||||
Use any part of it at your own risk.
|
|
23
README.md
23
README.md
@@ -51,8 +51,8 @@ please keep up with these changes, as they will not be backward compatible and r
|
|||||||
- [ ] Message handling
|
- [ ] Message handling
|
||||||
- NetDB
|
- NetDB
|
||||||
- [ ] Local storage
|
- [ ] Local storage
|
||||||
- [/] Persistence to disk
|
- [ ] Persistence to disk
|
||||||
- [X] Reseeding
|
- [ ] Reseeding
|
||||||
- [ ] Lookups
|
- [ ] Lookups
|
||||||
- [ ] Expiry
|
- [ ] Expiry
|
||||||
- [ ] Exploration
|
- [ ] Exploration
|
||||||
@@ -60,12 +60,12 @@ please keep up with these changes, as they will not be backward compatible and r
|
|||||||
- [ ] Floodfill
|
- [ ] Floodfill
|
||||||
- [ ] LS2 and Encrypted Leasesets
|
- [ ] LS2 and Encrypted Leasesets
|
||||||
- Transports
|
- Transports
|
||||||
- [X] Transport manager
|
- [ ] Transport manager
|
||||||
- NTCP2
|
- NTCP2
|
||||||
- [ ] Handshake
|
- [ ] Handshake
|
||||||
- [ ] Session tracking
|
- [ ] Session tracking
|
||||||
- [ ] Automatic session creation
|
- [ ] Automatic session creation
|
||||||
- SSU2
|
- SSU
|
||||||
- [ ] Handshake
|
- [ ] Handshake
|
||||||
- [ ] Session tracking
|
- [ ] Session tracking
|
||||||
- [ ] Automatic session creation
|
- [ ] Automatic session creation
|
||||||
@@ -78,20 +78,7 @@ please keep up with these changes, as they will not be backward compatible and r
|
|||||||
- [ ] Participating
|
- [ ] Participating
|
||||||
- [ ] Tunnel Message Crypto
|
- [ ] Tunnel Message Crypto
|
||||||
- [ ] Tunnel Message Fragmentation/Reassembly
|
- [ ] 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
|
## Contributing
|
||||||
|
|
||||||
|
10
go.mod
10
go.mod
@@ -3,9 +3,13 @@ module github.com/go-i2p/go-i2p
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/dchest/siphash v1.2.3 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1
|
github.com/emirpasic/gods v1.18.1
|
||||||
github.com/flynn/noise v1.1.0
|
github.com/flynn/noise v1.0.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
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
|
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
60
go.sum
@@ -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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
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.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||||
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
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 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
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/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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
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/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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
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-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.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
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/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
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.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
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/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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-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-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.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
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 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
|
//
|
||||||
// provides generic interfaces for initial bootstrap into network and network reseeding
|
// provides generic interfaces for initial bootstrap into network and network reseeding
|
||||||
|
//
|
||||||
package bootstrap
|
package bootstrap
|
||||||
|
@@ -126,19 +126,29 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": len(data),
|
"certificate_bytes_length": len(data),
|
||||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||||
}).Error("invalid certificate, empty")
|
}).Error("invalid certificate")
|
||||||
err = fmt.Errorf("error parsing certificate: certificate is empty")
|
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
||||||
return
|
return
|
||||||
case 1 , 2:
|
case 1:
|
||||||
certificate.kind = Integer(data[0:len(data)-1])
|
certificate.kind = Integer(data[0:0])
|
||||||
certificate.len = Integer([]byte{0})
|
certificate.len = Integer([]byte{0})
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": len(data),
|
"certificate_bytes_length": len(data),
|
||||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
"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")
|
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
||||||
return
|
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:
|
default:
|
||||||
certificate.kind = Integer(data[0:1])
|
certificate.kind = Integer(data[0:1])
|
||||||
certificate.len = Integer(data[1:3])
|
certificate.len = Integer(data[1:3])
|
||||||
@@ -150,11 +160,17 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": certificate.len.Int(),
|
"certificate_bytes_length": certificate.len.Int(),
|
||||||
"certificate_payload_length": payleng,
|
"certificate_payload_length": payleng,
|
||||||
"data_bytes:": string(data),
|
|
||||||
"kind_bytes": data[0:1],
|
|
||||||
"len_bytes": data[1:3],
|
|
||||||
"reason": err.Error(),
|
"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
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -166,8 +182,8 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
||||||
certificate, err = NewCertificate(data)
|
certificate, err = NewCertificate(data)
|
||||||
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
||||||
|
remainder = certificate.ExcessBytes()
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
remainder = certificate.ExcessBytes()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -50,9 +50,7 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err
|
|||||||
if size < MAX_INTEGER_SIZE {
|
if size < MAX_INTEGER_SIZE {
|
||||||
integerSize = size
|
integerSize = size
|
||||||
}
|
}
|
||||||
intBytes := bytes[:integerSize]
|
i, remainder := ReadInteger(bytes, integerSize)
|
||||||
remainder = bytes[integerSize:]
|
|
||||||
i, _ := ReadInteger(intBytes, integerSize)
|
|
||||||
integer = &i
|
integer = &i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -126,25 +126,28 @@ func beginsWith(bytes []byte, chr byte) bool {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
||||||
if len(bytes) < 3 {
|
if len(bytes) == 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadMapping",
|
"at": "ReadMapping",
|
||||||
"reason": "zero length",
|
"reason": "zero length",
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
e := errors.New("zero length")
|
e := errors.New("zero length")
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
size, remainder, e := NewInteger(bytes, 2)
|
size, remainder, e := NewInteger(bytes, 2)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
}
|
}
|
||||||
if size.Int() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mapping.size = size
|
mapping.size = size
|
||||||
map_bytes := remainder[:mapping.size.Int()]
|
if e != nil {
|
||||||
remainder = remainder[mapping.size.Int():]
|
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 {
|
if len(remainder) == 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadMapping",
|
"at": "ReadMapping",
|
||||||
@@ -153,10 +156,7 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
|
|||||||
e := errors.New("zero length")
|
e := errors.New("zero length")
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
}
|
}
|
||||||
// TODO: this should take the remainder and the length we already parsed above, as a parameter.
|
vals, remainder, mappingValueErrs := ReadMappingValues(bytes)
|
||||||
// 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)
|
|
||||||
|
|
||||||
err = append(err, mappingValueErrs...)
|
err = append(err, mappingValueErrs...)
|
||||||
mapping.vals = vals
|
mapping.vals = vals
|
||||||
|
@@ -10,17 +10,6 @@ import (
|
|||||||
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
||||||
type MappingValues [][2]I2PString
|
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.
|
// ValuesToMapping creates a *Mapping using MappingValues.
|
||||||
// The values are sorted in the order defined in mappingOrder.
|
// The values are sorted in the order defined in mappingOrder.
|
||||||
func ValuesToMapping(values MappingValues) *Mapping {
|
func ValuesToMapping(values MappingValues) *Mapping {
|
||||||
@@ -57,11 +46,11 @@ func mappingOrder(values MappingValues) {
|
|||||||
// ReadMappingValues returns *MappingValues from a []byte.
|
// ReadMappingValues returns *MappingValues from a []byte.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
||||||
//mapping := remainder
|
mapping := remainder
|
||||||
//var remainder = mapping
|
//var remainder = mapping
|
||||||
//var err error
|
//var err error
|
||||||
if remainder == nil || len(remainder) < 1 {
|
if remainder == nil || len(remainder) < 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "data shorter than expected",
|
"reason": "data shorter than expected",
|
||||||
@@ -70,21 +59,31 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
map_values := make(MappingValues, 0)
|
map_values := make(MappingValues, 0)
|
||||||
int_map_length := map_length.Int()
|
if len(remainder) < 1 {
|
||||||
mapping_len := len(remainder)
|
log.WithFields(log.Fields{
|
||||||
if mapping_len > int_map_length {
|
"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{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"mapping_bytes_length": mapping_len,
|
"mapping_bytes_length": mapping_len,
|
||||||
"mapping_length_field": int_map_length,
|
"mapping_length_field": length,
|
||||||
"reason": "data longer than expected",
|
"reason": "data longer than expected",
|
||||||
}).Warn("mapping format warning")
|
}).Warn("mapping format warning")
|
||||||
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
|
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{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"mapping_bytes_length": mapping_len,
|
"mapping_bytes_length": mapping_len,
|
||||||
"mapping_length_field": int_map_length,
|
"mapping_length_field": length,
|
||||||
"reason": "data shorter than expected",
|
"reason": "data shorter than expected",
|
||||||
}).Warn("mapping format warning")
|
}).Warn("mapping format warning")
|
||||||
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
|
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{}
|
encounteredKeysMap := map[string]bool{}
|
||||||
// pop off length bytes before parsing kv pairs
|
// pop off length bytes before parsing kv pairs
|
||||||
//remainder = remainder[2:]
|
remainder = remainder[2:]
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// Read a key, breaking on fatal errors
|
// Read a key, breaking on fatal errors
|
||||||
@@ -112,16 +111,16 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
|||||||
break
|
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 err != nil {
|
||||||
if stopValueRead(err) {
|
if stopValueRead(err) {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
//return
|
//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
|
// Check if key has already been encountered in this mapping
|
||||||
keyBytes, _ := key_str.Data()
|
keyBytes, _ := key_str.Data()
|
||||||
@@ -131,9 +130,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
|||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "duplicate key in mapping",
|
"reason": "duplicate key in mapping",
|
||||||
"key": string(key_str),
|
|
||||||
}).Error("mapping format violation")
|
}).Error("mapping format violation")
|
||||||
log.Printf("DUPE: %s", key_str)
|
|
||||||
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
||||||
// Based on other implementations this does not seem to happen often?
|
// 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.
|
// 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{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "expected =",
|
"reason": "expected =",
|
||||||
"value:": string(remainder),
|
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
errs = append(errs, errors.New("mapping format violation, expected ="))
|
errs = append(errs, errors.New("mapping format violation, expected ="))
|
||||||
log.Printf("ERRVAL: %s", remainder)
|
|
||||||
break
|
break
|
||||||
} else {
|
|
||||||
remainder = remainder[1:]
|
|
||||||
}
|
}
|
||||||
|
remainder = remainder[1:]
|
||||||
|
|
||||||
// Read a value, breaking on fatal errors
|
// Read a value, breaking on fatal errors
|
||||||
// and appending warnings
|
// 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 err != nil {
|
||||||
if stopValueRead(err) {
|
if stopValueRead(err) {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
//return
|
//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) {
|
if !beginsWith(remainder, 0x3b) {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "expected ;",
|
"reason": "expected ;",
|
||||||
"value:": string(remainder),
|
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
errs = append(errs, errors.New("mapping format violation, expected ;"))
|
errs = append(errs, errors.New("mapping format violation, expected ;"))
|
||||||
break
|
break
|
||||||
} else {
|
|
||||||
remainder = remainder[1:]
|
|
||||||
}
|
}
|
||||||
|
remainder = remainder[1:]
|
||||||
|
|
||||||
// Append the key-value pair and break if there is no more data to read
|
// 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})
|
map_values = append(map_values, [2]I2PString{key_str, val_str})
|
||||||
|
@@ -38,17 +38,28 @@ func (str I2PString) Length() (length int, err error) {
|
|||||||
err = errors.New("error parsing string: zero length")
|
err = errors.New("error parsing string: zero length")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l, _, _ := NewInteger(str, 1)
|
l := Integer([]byte{byte(str[0])})
|
||||||
length = l.Int()
|
length = l.Int()
|
||||||
str_len := len(str) - 1
|
inferred_len := length + 1
|
||||||
if length != str_len {
|
str_len := len(str)
|
||||||
|
if inferred_len > str_len {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(I2PString) Length",
|
"at": "(I2PString) Length",
|
||||||
"string_bytes_length": str_len,
|
"string_bytes_length": str_len,
|
||||||
"string_length_field": length,
|
"string_length_field": length,
|
||||||
"reason": "data less than specified by length",
|
"expected_bytes_length": inferred_len,
|
||||||
}).Error("string format warning")
|
"reason": "data shorter than specified",
|
||||||
|
}).Warn("string format warning")
|
||||||
err = errors.New("string parsing warning: string data is shorter than specified by length")
|
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
|
return
|
||||||
}
|
}
|
||||||
@@ -65,14 +76,11 @@ func (str I2PString) Data() (data string, err error) {
|
|||||||
data = string(str[1:])
|
data = string(str[1:])
|
||||||
return
|
return
|
||||||
case "string parsing warning: string contains data beyond length":
|
case "string parsing warning: string contains data beyond length":
|
||||||
data = string(str[1:])
|
data = string(str[1 : length+1])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if length == 0 {
|
data = string(str[1:])
|
||||||
return
|
|
||||||
}
|
|
||||||
data = string(str[1 : length+1])
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,14 +113,13 @@ func ToI2PString(data string) (str I2PString, err error) {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
||||||
length, _, err := NewInteger(data, 1)
|
str = I2PString(data)
|
||||||
if err != nil {
|
length, err := I2PString(data).Length()
|
||||||
return
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ package exportable
|
|||||||
import common "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
import common "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||||
|
|
||||||
func Fuzz(data []byte) int {
|
func Fuzz(data []byte) int {
|
||||||
keys_and_cert, _, _ := common.NewKeysAndCert(data)
|
keys_and_cert, _, _ := common.ReadKeysAndCert(data)
|
||||||
keys_and_cert.Certificate()
|
keys_and_cert.Certificate()
|
||||||
keys_and_cert.PublicKey()
|
keys_and_cert.PublicKey()
|
||||||
keys_and_cert.SigningPublicKey()
|
keys_and_cert.SigningPublicKey()
|
||||||
|
@@ -52,10 +52,6 @@ const (
|
|||||||
// Key Certificate Public Key Types
|
// Key Certificate Public Key Types
|
||||||
const (
|
const (
|
||||||
KEYCERT_CRYPTO_ELG = iota
|
KEYCERT_CRYPTO_ELG = iota
|
||||||
KEYCERT_CRYPTO_P256
|
|
||||||
KEYCERT_CRYPTO_P384
|
|
||||||
KEYCERT_CRYPTO_P521
|
|
||||||
KEYCERT_CRYPTO_X25519
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -77,11 +73,7 @@ const (
|
|||||||
|
|
||||||
// PublicKey sizes for Public Key Types
|
// PublicKey sizes for Public Key Types
|
||||||
const (
|
const (
|
||||||
KEYCERT_CRYPTO_ELG_SIZE = 256
|
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sizes of structures in KeyCertificates
|
// Sizes of structures in KeyCertificates
|
||||||
@@ -90,7 +82,7 @@ const (
|
|||||||
KEYCERT_SPK_SIZE = 128
|
KEYCERT_SPK_SIZE = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
// type KeyCertificate []byte
|
//type KeyCertificate []byte
|
||||||
type KeyCertificate struct {
|
type KeyCertificate struct {
|
||||||
*Certificate
|
*Certificate
|
||||||
spkType Integer
|
spkType Integer
|
||||||
@@ -120,7 +112,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
data_len := len(data)
|
data_len := len(data)
|
||||||
if data_len < key_certificate.CryptoSize() {
|
if data_len < KEYCERT_PUBKEY_SIZE {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(KeyCertificate) ConstructPublicKey",
|
"at": "(KeyCertificate) ConstructPublicKey",
|
||||||
"data_len": data_len,
|
"data_len": data_len,
|
||||||
@@ -135,10 +127,6 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
|||||||
var elg_key crypto.ElgPublicKey
|
var elg_key crypto.ElgPublicKey
|
||||||
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
||||||
public_key = elg_key
|
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
|
return
|
||||||
}
|
}
|
||||||
@@ -151,7 +139,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
data_len := len(data)
|
data_len := len(data)
|
||||||
if data_len < key_certificate.SignatureSize() {
|
if data_len < KEYCERT_SPK_SIZE {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(KeyCertificate) ConstructSigningPublicKey",
|
"at": "(KeyCertificate) ConstructSigningPublicKey",
|
||||||
"data_len": data_len,
|
"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.
|
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
|
||||||
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
||||||
sizes := map[int]int{
|
sizes := map[int]int{
|
||||||
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
|
KEYCERT_SIGN_DSA_SHA1: 40,
|
||||||
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
|
KEYCERT_SIGN_P256: 64,
|
||||||
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
|
KEYCERT_SIGN_P384: 96,
|
||||||
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
|
KEYCERT_SIGN_P521: 132,
|
||||||
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
|
KEYCERT_SIGN_RSA2048: 256,
|
||||||
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
|
KEYCERT_SIGN_RSA3072: 384,
|
||||||
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
|
KEYCERT_SIGN_RSA4096: 512,
|
||||||
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
|
KEYCERT_SIGN_ED25519: 64,
|
||||||
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
|
KEYCERT_SIGN_ED25519PH: 64,
|
||||||
}
|
}
|
||||||
key_type := key_certificate.SigningPublicKeyType()
|
key_type := key_certificate.SigningPublicKeyType()
|
||||||
return sizes[int(key_type)]
|
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.
|
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
||||||
var certificate *Certificate
|
var certificate *Certificate
|
||||||
certificate, remainder, err = ReadCertificate(bytes)
|
certificate, remainder, err = ReadCertificate(bytes)
|
||||||
if err != nil {
|
//if err != nil {
|
||||||
return
|
// return nil, err
|
||||||
}
|
//}
|
||||||
if len(bytes) < KEYCERT_MIN_SIZE {
|
if len(bytes) < KEYCERT_MIN_SIZE {
|
||||||
err = errors.New("error parsing key certificate: not enough data")
|
err = errors.New("error parsing key certificate: not enough data")
|
||||||
}
|
}
|
||||||
key_certificate = &KeyCertificate{
|
switch len(bytes) {
|
||||||
Certificate: certificate,
|
case 4:
|
||||||
spkType: Integer(bytes[4:5]),
|
key_certificate = &KeyCertificate{
|
||||||
cpkType: Integer(bytes[6:7]),
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -165,22 +165,51 @@ func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
|
|||||||
return keys_and_cert.KeyCertificate.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.
|
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
||||||
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
||||||
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
|
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
|
||||||
data_len := len(data)
|
data_len := len(data)
|
||||||
keys_and_cert = &KeysAndCert{}
|
keys_and_cert = &KeysAndCert{}
|
||||||
if data_len < KEYS_AND_CERT_MIN_SIZE && 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,
|
|
||||||
"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 {
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadKeysAndCert",
|
"at": "ReadKeysAndCert",
|
||||||
"data_len": data_len,
|
"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")
|
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
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.
|
padding := data[KEYS_AND_CERT_MIN_SIZE+cert.Length():]
|
||||||
// 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]
|
|
||||||
keys_and_cert.padding = padding
|
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
|
return keys_and_cert, remainder, err
|
||||||
}
|
}
|
||||||
|
@@ -6,17 +6,23 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*func TestCertificateWithMissingData(t *testing.T) {
|
func TestCertificateWithMissingData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
|
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
|
||||||
data := make([]byte, 128+256)
|
data := make([]byte, 128+256)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
_, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
|
||||||
|
cert := keys_and_cert.Certificate()
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
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) {
|
func TestCertificateWithValidData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
@@ -24,11 +30,10 @@ func TestCertificateWithValidData(t *testing.T) {
|
|||||||
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
|
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
|
||||||
data := make([]byte, 128+256)
|
data := make([]byte, 128+256)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
assert.Nil(err)
|
|
||||||
|
|
||||||
cert := keys_and_cert.Certificate()
|
cert := keys_and_cert.Certificate()
|
||||||
|
assert.Nil(err)
|
||||||
cert_bytes := cert.Bytes()
|
cert_bytes := cert.Bytes()
|
||||||
if assert.Equal(len(cert_data), len(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")
|
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 := make([]byte, 128)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
|
||||||
pub_key := keys_and_cert.PublicKey()
|
pub_key := keys_and_cert.PublicKey()
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
@@ -60,7 +65,7 @@ func TestPublicKeyWithBadCertificate(t *testing.T) {
|
|||||||
data := make([]byte, 128)
|
data := make([]byte, 128)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
|
||||||
pub_key := keys_and_cert.PublicKey()
|
pub_key := keys_and_cert.PublicKey()
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
@@ -77,7 +82,7 @@ func TestPublicKeyWithNullCertificate(t *testing.T) {
|
|||||||
data := make([]byte, 128)
|
data := make([]byte, 128)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
|
||||||
pub_key := keys_and_cert.PublicKey()
|
pub_key := keys_and_cert.PublicKey()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
@@ -92,7 +97,7 @@ func TestPublicKeyWithKeyCertificate(t *testing.T) {
|
|||||||
data := make([]byte, 128)
|
data := make([]byte, 128)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
|
||||||
pub_key := keys_and_cert.PublicKey()
|
pub_key := keys_and_cert.PublicKey()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
@@ -107,7 +112,7 @@ func TestSigningPublicKeyWithBadData(t *testing.T) {
|
|||||||
data := make([]byte, 93)
|
data := make([]byte, 93)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_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()
|
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
@@ -124,7 +129,7 @@ func TestSigningPublicKeyWithBadCertificate(t *testing.T) {
|
|||||||
data := make([]byte, 128)
|
data := make([]byte, 128)
|
||||||
data = append(data, pub_key_data...)
|
data = append(data, pub_key_data...)
|
||||||
data = append(data, cert_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()
|
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
@@ -141,7 +146,7 @@ func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
|
|||||||
signing_pub_key_data := make([]byte, 128)
|
signing_pub_key_data := make([]byte, 128)
|
||||||
data := append(pub_key_data, signing_pub_key_data...)
|
data := append(pub_key_data, signing_pub_key_data...)
|
||||||
data = append(data, cert_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()
|
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
@@ -156,18 +161,18 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
|
|||||||
signing_pub_key_data := make([]byte, 128)
|
signing_pub_key_data := make([]byte, 128)
|
||||||
data := append(pub_key_data, signing_pub_key_data...)
|
data := append(pub_key_data, signing_pub_key_data...)
|
||||||
data = append(data, cert_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()
|
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
|
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)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128)
|
cert_data := make([]byte, 128)
|
||||||
_, remainder, err := NewKeysAndCert(cert_data)
|
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||||
assert.Equal(0, len(remainder))
|
assert.Equal(0, len(remainder))
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
|
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)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
|
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))
|
assert.Equal(0, len(remainder))
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
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)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
|
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.Equal(0, len(remainder))
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
|
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.Equal(0, len(remainder))
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...)
|
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)) {
|
if assert.Equal(1, len(remainder)) {
|
||||||
assert.Equal("A", string(remainder[0]))
|
assert.Equal("A", string(remainder[0]))
|
||||||
}
|
}
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
func TestReadKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...)
|
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)) {
|
if assert.Equal(1, len(remainder)) {
|
||||||
assert.Equal("A", string(remainder[0]))
|
assert.Equal("A", string(remainder[0]))
|
||||||
}
|
}
|
||||||
|
@@ -132,10 +132,7 @@ type LeaseSet struct {
|
|||||||
|
|
||||||
// Destination returns the Destination as []byte.
|
// Destination returns the Destination as []byte.
|
||||||
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
||||||
keys_and_cert, _, err := NewKeysAndCert(lease_set)
|
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -143,7 +140,7 @@ func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
|||||||
// PublicKey returns the public key as crypto.ElgPublicKey.
|
// PublicKey returns the public key as crypto.ElgPublicKey.
|
||||||
// Returns errors encountered during parsing.
|
// Returns errors encountered during parsing.
|
||||||
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) {
|
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)
|
remainder_len := len(remainder)
|
||||||
if remainder_len < LEASE_SET_PUBKEY_SIZE {
|
if remainder_len < LEASE_SET_PUBKEY_SIZE {
|
||||||
log.WithFields(log.Fields{
|
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.
|
// LeaseCount returns the numbert of leases specified by the LeaseCount value as int.
|
||||||
// returns errors encountered during parsing.
|
// returns errors encountered during parsing.
|
||||||
func (lease_set LeaseSet) LeaseCount() (count int, err error) {
|
func (lease_set LeaseSet) LeaseCount() (count int, err error) {
|
||||||
_, remainder, err := NewKeysAndCert(lease_set)
|
_, remainder, err := ReadKeysAndCert(lease_set)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -65,8 +65,9 @@ options :: Mapping
|
|||||||
type RouterAddress struct {
|
type RouterAddress struct {
|
||||||
cost *Integer
|
cost *Integer
|
||||||
expiration *Date
|
expiration *Date
|
||||||
transport_style *I2PString
|
Transport_Style *I2PString
|
||||||
options *Mapping
|
options *Mapping
|
||||||
|
parserErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the router address as a []byte.
|
// Bytes returns the router address as a []byte.
|
||||||
@@ -74,15 +75,15 @@ func (router_address RouterAddress) Bytes() []byte {
|
|||||||
bytes := make([]byte, 0)
|
bytes := make([]byte, 0)
|
||||||
bytes = append(bytes, router_address.cost.Bytes()...)
|
bytes = append(bytes, router_address.cost.Bytes()...)
|
||||||
bytes = append(bytes, router_address.expiration.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 {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
|
}).Error("RouterAddress.Bytes: error getting Transport_Style bytes")
|
||||||
} else {
|
} else {
|
||||||
bytes = append(bytes, strData...)
|
bytes = append(bytes, strData...)
|
||||||
}
|
}
|
||||||
bytes = append(bytes, router_address.options.Data()...)
|
//bytes = append(bytes, router_address.options.Bytes()...)
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +99,7 @@ func (router_address RouterAddress) Expiration() Date {
|
|||||||
|
|
||||||
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
||||||
func (router_address RouterAddress) TransportStyle() 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.
|
// 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.
|
// 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) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,40 +135,54 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
||||||
if len(data) == 0 {
|
if data == nil || len(data) == 0 {
|
||||||
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
|
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data")
|
||||||
err = errors.New("error parsing RouterAddress: no data")
|
err = errors.New("error parsing RouterAddress: no data")
|
||||||
|
router_address.parserErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
router_address.cost, remainder, err = NewInteger(data, 1)
|
cost, remainder, err := NewInteger([]byte{data[0]}, 1)
|
||||||
|
router_address.cost = cost
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing cost",
|
"reason": "error parsing cost",
|
||||||
}).Warn("error parsing RouterAddress")
|
}).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 {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing expiration",
|
"reason": "error parsing expiration",
|
||||||
}).Error("error parsing RouterAddress")
|
}).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 {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing transport_style",
|
"reason": "error parsing Transport_Style",
|
||||||
}).Error("error parsing RouterAddress")
|
}).Error("error parsing RouterAddress")
|
||||||
|
router_address.parserErr = err
|
||||||
}
|
}
|
||||||
var errs []error
|
options, remainder, errs := NewMapping(remainder)
|
||||||
router_address.options, remainder, errs = NewMapping(remainder)
|
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing options",
|
"reason": "error parsing options",
|
||||||
"error": err,
|
|
||||||
}).Error("error parsing RouterAddress")
|
}).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
|
return
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ package router_info
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||||
@@ -15,9 +15,6 @@ import (
|
|||||||
|
|
||||||
const ROUTER_INFO_MIN_SIZE = 439
|
const ROUTER_INFO_MIN_SIZE = 439
|
||||||
|
|
||||||
var MIN_GOOD_VERSION = 59
|
|
||||||
const MAX_GOOD_VERSION = 99
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[RouterInfo]
|
[RouterInfo]
|
||||||
Accurate for version 0.9.49
|
Accurate for version 0.9.49
|
||||||
@@ -111,10 +108,13 @@ type RouterInfo struct {
|
|||||||
signature *Signature
|
signature *Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var routerInfoTest net.Addr = &RouterInfo{}
|
||||||
|
|
||||||
// Bytes returns the RouterInfo as a []byte 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) {
|
func (router_info RouterInfo) Bytes() ([]byte, error) {
|
||||||
var err error
|
var err error
|
||||||
var bytes []byte
|
var bytes []byte
|
||||||
|
|
||||||
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
|
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
|
||||||
bytes = append(bytes, router_info.published.Bytes()...)
|
bytes = append(bytes, router_info.published.Bytes()...)
|
||||||
bytes = append(bytes, router_info.size.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_address.Bytes()...)
|
||||||
}
|
}
|
||||||
bytes = append(bytes, router_info.peer_size.Bytes()...)
|
bytes = append(bytes, router_info.peer_size.Bytes()...)
|
||||||
bytes = append(bytes, router_info.options.Data()...)
|
//bytes = append(bytes, router_info.options.Bytes()...)
|
||||||
//bytes = append(bytes, []byte(*router_info.signature)...)
|
bytes = append(bytes, []byte(*router_info.signature)...)
|
||||||
|
|
||||||
return bytes, err
|
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.
|
// RouterIdentity returns the router identity as *RouterIdentity.
|
||||||
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
||||||
return router_info.router_identity
|
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")
|
err = errors.New("error parsing router info: not enough data")
|
||||||
}
|
}
|
||||||
size, remainder, err := NewInteger(remainder, 1)
|
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
|
info.size = size
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@@ -273,23 +288,25 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
}).Error("error parsing router info")
|
}).Error("error parsing router info")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
err = errors.New("error parsing router info: not enough data")
|
||||||
}
|
}
|
||||||
|
addresses := make([]*RouterAddress, size.Int())
|
||||||
for i := 0; i < size.Int(); i++ {
|
for i := 0; i < size.Int(); i++ {
|
||||||
address, more, err := NewRouterAddress(remainder)
|
address, remainder, err := NewRouterAddress(remainder)
|
||||||
remainder = more
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
"data_len": len(remainder),
|
"data_len": len(remainder),
|
||||||
//"required_len": ROUTER_ADDRESS_SIZE,
|
//"required_len": ROUTER_ADDRESS_SIZE,
|
||||||
"reason": "not enough data",
|
"reason": "not enough data",
|
||||||
}).Error("error parsing router address")
|
}).Error("error parsing router info")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
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)
|
info.addresses = addresses
|
||||||
var errs []error
|
peer_size := Integer(remainder[:1])
|
||||||
info.options, remainder, errs = NewMapping(remainder)
|
info.peer_size = &peer_size
|
||||||
|
remainder = remainder[1:]
|
||||||
|
options, remainder, errs := NewMapping(remainder)
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"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)
|
err = errors.New("error parsing router info: " + estring)
|
||||||
}
|
}
|
||||||
|
info.options = options
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
@@ -315,61 +333,6 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
return
|
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.
|
// NewRouterInfo creates a new *RouterInfo from []byte using ReadRouterInfo.
|
||||||
// Returns a pointer to RouterInfo unlike ReadRouterInfo.
|
// Returns a pointer to RouterInfo unlike ReadRouterInfo.
|
||||||
func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) {
|
func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) {
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
|
//
|
||||||
// package for i2p specific crpytography
|
// package for i2p specific crpytography
|
||||||
|
//
|
||||||
package crypto
|
package crypto
|
||||||
|
@@ -2,16 +2,10 @@ package crypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"crypto/rand"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
|
|
||||||
|
|
||||||
type Ed25519PublicKey []byte
|
type Ed25519PublicKey []byte
|
||||||
|
|
||||||
type Ed25519Verifier struct {
|
type Ed25519Verifier struct {
|
||||||
@@ -25,77 +19,6 @@ func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) {
|
|||||||
return temp, nil
|
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) {
|
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) {
|
||||||
if len(sig) != ed25519.SignatureSize {
|
if len(sig) != ed25519.SignatureSize {
|
||||||
err = ErrBadSignatureSize
|
err = ErrBadSignatureSize
|
||||||
|
@@ -5,10 +5,9 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
|
"golang.org/x/crypto/openpgp/elgamal"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/elgamal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var elgp = new(big.Int).SetBytes([]byte{
|
var elgp = new(big.Int).SetBytes([]byte{
|
||||||
|
@@ -23,7 +23,9 @@ func (hk HMACKey) xor(p byte) (i []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// do i2p hmac
|
// do i2p hmac
|
||||||
|
//
|
||||||
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) {
|
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) {
|
||||||
|
|
||||||
buff := make([]byte, 64+len(data))
|
buff := make([]byte, 64+len(data))
|
||||||
|
@@ -1 +1,5 @@
|
|||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
package netdb
|
package netdb
|
||||||
|
@@ -50,7 +50,9 @@ func (db StdNetDB) Path() string {
|
|||||||
return string(db)
|
return string(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// return how many routers we know about in our network database
|
// return how many routers we know about in our network database
|
||||||
|
//
|
||||||
func (db StdNetDB) Size() (routers int) {
|
func (db StdNetDB) Size() (routers int) {
|
||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
var err error
|
var err error
|
||||||
|
@@ -14,50 +14,47 @@
|
|||||||
// content the error ErrInvalidSignature will be returned.
|
// content the error ErrInvalidSignature will be returned.
|
||||||
//
|
//
|
||||||
// Example usage:
|
// Example usage:
|
||||||
//
|
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
|
||||||
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
|
// su3File, err := su3.Read(body)
|
||||||
// su3File, err := su3.Read(body)
|
// if err != nil {
|
||||||
// if err != nil {
|
// // Handle error.
|
||||||
// // Handle error.
|
// }
|
||||||
// }
|
// // Look up this signer's key.
|
||||||
// // Look up this signer's key.
|
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
// // Read the content.
|
||||||
// // Read the content.
|
// contentReader := su3File.Content(key)
|
||||||
// contentReader := su3File.Content(key)
|
// bytes, err := ioutil.ReadAll(contentReader)
|
||||||
// bytes, err := ioutil.ReadAll(contentReader)
|
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
// // The signature is invalid, OR a nil key was provided.
|
||||||
// // The signature is invalid, OR a nil key was provided.
|
// } else if err != nil {
|
||||||
// } else if err != nil {
|
// // Handle error.
|
||||||
// // Handle error.
|
// }
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// If you want to parse from a []byte, you can wrap it like this:
|
// If you want to parse from a []byte, you can wrap it like this:
|
||||||
//
|
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
|
||||||
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
|
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
|
||||||
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
|
|
||||||
//
|
//
|
||||||
// One of the advantages of this library's design is that you can avoid buffering
|
// 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
|
// the file contents in memory. Here's how you would stream from an HTTP body
|
||||||
// directly to disk:
|
// directly to disk:
|
||||||
//
|
// su3File, err := su3.Read(body)
|
||||||
// su3File, err := su3.Read(body)
|
// if err != nil {
|
||||||
// if err != nil {
|
// // Handle error.
|
||||||
// // Handle error.
|
// }
|
||||||
// }
|
// // Look up this signer's key.
|
||||||
// // Look up this signer's key.
|
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
// // Stream directly to disk.
|
||||||
// // Stream directly to disk.
|
// f, err := os.Create("my_file.txt")
|
||||||
// f, err := os.Create("my_file.txt")
|
// if err != nil {
|
||||||
// if err != nil {
|
// // Handle error.
|
||||||
// // Handle error.
|
// }
|
||||||
// }
|
// _, err := io.Copy(f, su3File.Content(key))
|
||||||
// _, err := io.Copy(f, su3File.Content(key))
|
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
// // The signature is invalid, OR a nil key was provided.
|
||||||
// // The signature is invalid, OR a nil key was provided.
|
// // Don't trust the file, delete it!
|
||||||
// // Don't trust the file, delete it!
|
// } else if err != nil {
|
||||||
// } else if err != nil {
|
// // Handle error.
|
||||||
// // Handle error.
|
// }
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// Note: if you want to read the content, the Content() io.Reader must be read
|
// 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
|
// *before* the Signature() io.Reader. If you read the signature first, the
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
/*
|
/**
|
||||||
*
|
i2np messages transports
|
||||||
|
|
||||||
i2np messages transports
|
|
||||||
*/
|
*/
|
||||||
package transport
|
package transport
|
||||||
|
@@ -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
|
|
||||||
}
|
|
@@ -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
|
|
||||||
}
|
|
@@ -9,19 +9,10 @@ import (
|
|||||||
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
|
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
|
||||||
c.Mutex.Lock()
|
c.Mutex.Lock()
|
||||||
defer c.Mutex.Unlock()
|
defer c.Mutex.Unlock()
|
||||||
session, err := c.GetSession(routerInfo)
|
session, err := c.getSession(routerInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// Set handshakeCond to indicate that this goroutine is committing to
|
||||||
// running the handshake.
|
// running the handshake.
|
||||||
session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex)
|
session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex)
|
||||||
@@ -29,8 +20,8 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
|
|||||||
session.(*NoiseSession).Mutex.Lock()
|
session.(*NoiseSession).Mutex.Lock()
|
||||||
defer session.(*NoiseSession).Mutex.Unlock()
|
defer session.(*NoiseSession).Mutex.Unlock()
|
||||||
c.Mutex.Lock()
|
c.Mutex.Lock()
|
||||||
// if c.config.isClient {
|
|
||||||
if err := session.(*NoiseSession).RunClientHandshake(); err != nil {
|
if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Wake any other goroutines that are waiting for this handshake to
|
// Wake any other goroutines that are waiting for this handshake to
|
||||||
|
15
lib/transport/noise/i2np.go
Normal file
15
lib/transport/noise/i2np.go
Normal 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
|
||||||
|
}
|
64
lib/transport/noise/incoming_handshake.go
Normal file
64
lib/transport/noise/incoming_handshake.go
Normal 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
|
||||||
|
}
|
46
lib/transport/noise/noise_constants.go
Normal file
46
lib/transport/noise/noise_constants.go
Normal 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
|
||||||
|
}
|
66
lib/transport/noise/outgoing_handshake.go
Normal file
66
lib/transport/noise/outgoing_handshake.go
Normal 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
|
||||||
|
}
|
84
lib/transport/noise/read_session.go
Normal file
84
lib/transport/noise/read_session.go
Normal 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
|
||||||
|
}
|
@@ -2,6 +2,7 @@ package noise
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -10,46 +11,45 @@ import (
|
|||||||
"github.com/flynn/noise"
|
"github.com/flynn/noise"
|
||||||
|
|
||||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
"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"
|
"github.com/go-i2p/go-i2p/lib/transport"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NoiseSession struct {
|
type NoiseSession struct {
|
||||||
*cb.Queue
|
|
||||||
router_info.RouterInfo
|
router_info.RouterInfo
|
||||||
*noise.CipherState
|
*noise.CipherState
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
*sync.Cond
|
*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
|
handshakeBuffer bytes.Buffer
|
||||||
activeCall int32
|
activeCall int32
|
||||||
handshakeComplete bool
|
handshakeComplete bool
|
||||||
Conn net.Conn
|
Conn net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read implements net.Conn
|
|
||||||
func (*NoiseSession) Read(b []byte) (n int, err error) {
|
|
||||||
panic("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoteAddr implements net.Conn
|
// RemoteAddr implements net.Conn
|
||||||
func (*NoiseSession) RemoteAddr() net.Addr {
|
func (noise_session *NoiseSession) RemoteAddr() net.Addr {
|
||||||
panic("unimplemented")
|
return &noise_session.RouterInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline implements net.Conn
|
// SetDeadline implements net.Conn
|
||||||
func (*NoiseSession) SetDeadline(t time.Time) error {
|
func (noise_session *NoiseSession) SetDeadline(t time.Time) error {
|
||||||
panic("unimplemented")
|
return noise_session.Conn.SetDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReadDeadline implements net.Conn
|
// SetReadDeadline implements net.Conn
|
||||||
func (*NoiseSession) SetReadDeadline(t time.Time) error {
|
func (noise_session *NoiseSession) SetReadDeadline(t time.Time) error {
|
||||||
panic("unimplemented")
|
return noise_session.Conn.SetReadDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWriteDeadline implements net.Conn
|
// SetWriteDeadline implements net.Conn
|
||||||
func (*NoiseSession) SetWriteDeadline(t time.Time) error {
|
func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error {
|
||||||
panic("unimplemented")
|
return noise_session.Conn.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
|
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
|
||||||
@@ -59,27 +59,40 @@ func (s *NoiseSession) LocalAddr() net.Addr {
|
|||||||
return s.Conn.LocalAddr()
|
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 {
|
func (s *NoiseSession) Close() error {
|
||||||
s.Queue.Clear()
|
s.SendQueue.Clear()
|
||||||
|
s.RecvQueue.Clear()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNoiseTransportSession(ri router_info.RouterInfo, socket net.Conn) (transport.TransportSession, error) {
|
func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error {
|
||||||
return &NoiseSession{
|
if c.VerifyCallback == nil {
|
||||||
Queue: cb.New(1024),
|
return nil
|
||||||
RouterInfo: ri,
|
}
|
||||||
Conn: socket,
|
err := c.VerifyCallback(publicKey, payload)
|
||||||
}, nil
|
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")
|
||||||
}
|
}
|
||||||
|
1
lib/transport/noise/session_test.go
Normal file
1
lib/transport/noise/session_test.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package noise
|
@@ -16,12 +16,13 @@ import (
|
|||||||
"github.com/go-i2p/go-i2p/lib/common/router_identity"
|
"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/common/router_info"
|
||||||
"github.com/go-i2p/go-i2p/lib/transport"
|
"github.com/go-i2p/go-i2p/lib/transport"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NoiseTransport struct {
|
type NoiseTransport struct {
|
||||||
*noise.CipherState
|
|
||||||
router_identity.RouterIdentity
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
router_identity.RouterIdentity
|
||||||
|
*noise.CipherState
|
||||||
Listener net.Listener
|
Listener net.Listener
|
||||||
peerConnections map[data.Hash]transport.TransportSession
|
peerConnections map[data.Hash]transport.TransportSession
|
||||||
}
|
}
|
||||||
@@ -33,24 +34,36 @@ var exampleNoiseTransport transport.Transport = &NoiseTransport{}
|
|||||||
// implements net.Listener
|
// implements net.Listener
|
||||||
var ExampleNoiseListener net.Listener = exampleNoiseTransport
|
var ExampleNoiseListener net.Listener = exampleNoiseTransport
|
||||||
|
|
||||||
|
// Accept a connection on a listening socket.
|
||||||
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
|
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
|
||||||
return noopt.Listener.Accept()
|
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 {
|
func (noopt *NoiseTransport) Addr() net.Addr {
|
||||||
return noopt.Listener.Addr()
|
return noopt.Listener.Addr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name of the transport TYPE, in this case `noise`
|
||||||
func (noopt *NoiseTransport) Name() string {
|
func (noopt *NoiseTransport) Name() string {
|
||||||
return "noise"
|
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
|
// will bind if the underlying socket is not already
|
||||||
// if the underlying socket is already bound update the RouterIdentity
|
// if the underlying socket is already bound update the RouterIdentity
|
||||||
// returns any errors that happen if they do
|
// 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
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,19 +76,34 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran
|
|||||||
if len(hash) == 0 {
|
if len(hash) == 0 {
|
||||||
return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash")
|
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
|
return t, nil
|
||||||
}
|
}
|
||||||
conn, err := noopt.Accept()
|
var err error
|
||||||
if err == nil {
|
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil {
|
||||||
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, conn); err != nil {
|
return noopt.peerConnections[hash], err
|
||||||
return noopt.peerConnections[hash], err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil, 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 {
|
func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool {
|
||||||
_, ok := noopt.peerConnections[routerInfo.IdentHash()]
|
_, ok := noopt.peerConnections[routerInfo.IdentHash()]
|
||||||
return ok
|
return ok
|
||||||
@@ -88,9 +116,20 @@ func (noopt *NoiseTransport) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewNoiseTransport create a NoiseTransport using a supplied net.Listener
|
||||||
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
|
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
|
||||||
return &NoiseTransport{
|
return &NoiseTransport{
|
||||||
peerConnections: make(map[data.Hash]transport.TransportSession),
|
peerConnections: make(map[data.Hash]transport.TransportSession),
|
||||||
Listener: netSocket,
|
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
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,20 @@ func TestTransport(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
nt := NewNoiseTransport(ln)
|
nt := NewNoiseTransport(ln)
|
||||||
|
go func() {
|
||||||
t.Log(nt.Name())
|
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()
|
||||||
}
|
}
|
||||||
|
84
lib/transport/noise/write_session.go
Normal file
84
lib/transport/noise/write_session.go
Normal 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
|
||||||
|
}
|
34
lib/transport/ntcp/constants.go
Normal file
34
lib/transport/ntcp/constants.go
Normal 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,
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package ntcp
|
package ntcp
|
||||||
|
|
||||||
|
import "github.com/go-i2p/go-i2p/lib/transport/noise"
|
||||||
|
|
||||||
// Session implements TransportSession
|
// Session implements TransportSession
|
||||||
// An established transport session
|
// An established transport session
|
||||||
type Session struct {
|
type Session noise.NoiseSession
|
||||||
}
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package ntcp
|
package ntcp
|
||||||
|
|
||||||
|
import "github.com/go-i2p/go-i2p/lib/transport/noise"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://geti2p.net/spec/ntcp2
|
* https://geti2p.net/spec/ntcp2
|
||||||
**/
|
**/
|
||||||
@@ -10,6 +12,5 @@ const (
|
|||||||
NTCP_MESSAGE_MAX_SIZE = 65537
|
NTCP_MESSAGE_MAX_SIZE = 65537
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transport is an ntcp transport implementing transport.Transport interface
|
// NTCPTransport is an ntcp transport implementing transport.Transport interface
|
||||||
type Transport struct {
|
type NTCPTransport noise.NoiseTransport
|
||||||
}
|
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
i2p ssu transport implementation
|
i2p ssu transport implementation
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package ssu
|
package ssu
|
||||||
|
@@ -380,9 +380,8 @@ func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the hash for these DeliveryInstructions, which varies by hash type.
|
// 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
|
||||||
// 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.
|
||||||
// the type is DT_ROUTER it is the SHA256 of the router.
|
|
||||||
func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) {
|
func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) {
|
||||||
delivery_type, err := delivery_instructions.DeliveryType()
|
delivery_type, err := delivery_instructions.DeliveryType()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
i2p garlic tunnel implementation
|
i2p garlic tunnel implementation
|
||||||
*/
|
*/
|
||||||
package tunnel
|
package tunnel
|
||||||
|
@@ -153,8 +153,10 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelI
|
|||||||
return decrypted_tunnel_message[4+16 : 4+4+16]
|
return decrypted_tunnel_message[4+16 : 4+4+16]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// Returns the contents of a decrypted tunnel message that contain the data for the
|
// Returns the contents of a decrypted tunnel message that contain the data for the
|
||||||
// DeliveryInstructions.
|
// DeliveryInstructions.
|
||||||
|
//
|
||||||
func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte {
|
func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte {
|
||||||
data_area := decrypted_tunnel_message[4+4+16:]
|
data_area := decrypted_tunnel_message[4+4+16:]
|
||||||
for i := 0; i < len(data_area); i++ {
|
for i := 0; i < len(data_area); i++ {
|
||||||
@@ -165,8 +167,11 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData()
|
|||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions
|
// Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions
|
||||||
// in the tunnel message and their corresponding MessageFragment structures.
|
// in the tunnel message and their corresponding MessageFragment structures.
|
||||||
|
//
|
||||||
|
//
|
||||||
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment {
|
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment {
|
||||||
set := make([]DeliveryInstructionsWithFragment, 0)
|
set := make([]DeliveryInstructionsWithFragment, 0)
|
||||||
data := decrypted_tunnel_message.deliveryInstructionData()
|
data := decrypted_tunnel_message.deliveryInstructionData()
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
//go:build !windows
|
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package signals
|
package signals
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
//go:build windows
|
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package signals
|
package signals
|
||||||
|
Reference in New Issue
Block a user