mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-08-18 23:45:25 -04:00
Compare commits
10 Commits
0.0.1
...
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))))
|
||||
|
||||
|
||||
ifdef GOROOT
|
||||
GO = $(GOROOT)/bin/go
|
||||
endif
|
||||
@@ -20,19 +18,8 @@ build: clean $(EXE)
|
||||
$(EXE):
|
||||
$(GO) build -v -o $(EXE)
|
||||
|
||||
test: fmt
|
||||
$(GO) test -vv -failfast ./lib/common/...
|
||||
test:
|
||||
$(GO) test -v -failfast ./lib/transport/noise/...
|
||||
|
||||
clean:
|
||||
$(GO) clean -v
|
||||
|
||||
fmt:
|
||||
find . -name '*.go' -exec gofmt -w -s {} \;
|
||||
|
||||
info:
|
||||
echo "GOROOT: ${GOROOT}"
|
||||
echo "GO: ${GO}"
|
||||
echo "REPO: ${REPO}"
|
||||
|
||||
release:
|
||||
github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p
|
||||
|
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.
|
||||
However, after much waiting, this library is actually **useful** for something.
|
||||
It is now being used in the `reseed-tools` application to examine RouterInfos prior to including them in reseed bundles.
|
||||
Routers that self-report as unreachable or congested will be excluded from future reseed bundles.
|
||||
Additionally, routers that self-report an old version will be excluded from reseed bundles.
|
||||
This should help new users build better connections faster with the existing, working router implementations.
|
||||
|
||||
This is not a working release of a go-i2p router
|
||||
------------------------------------------------
|
||||
|
||||
It is a numbered version of the go-i2p library, which is pre-release, expressly for use in the `reseed-tools` application.
|
||||
The common library works, and so do some of the cryptographic primitives, however the API is unstable and the software itself is certain to have serious bugs outside of a few well-tested areas.
|
||||
If you're using it for something other than parsing and analyzing RouterInfos and LeaseSets, you'll probably encounter bugs.
|
||||
Please report them to the https://github.com/go-i2p/go-i2p
|
||||
Use any part of it at your own risk.
|
||||
I finally got back to work on go-i2p last Friday, continuing work on the Noise transport(also enhanced marek's privs as a reddit mod which has been helpful, also the Dread community does appear to have begun to step a little re: onboarding eachother)
|
||||
I can now make a socket, instantiate a noise transport using the socket, and begin to use it to manage "incoming" and "outgoing" handshakes.
|
||||
They don't complete yet, still working on that, but it's more like debugging now and less figuring out how to actually do it, I more or less know where the pieces go now
|
||||
I'm beginning to notice drawbacks of what I've done here already, I think noiseSocket is intended at times as example of a way to use flynn/noise which is not exactly like I would do it or how a P2P application needs to do it
|
||||
Some of the functions are very long and hard to break down, and they use a different Noise flavor than NTCP2 by default, so I'm breaking things down into steps until I have exactly one step of a Noise handshake, exactly one function
|
||||
Which should finally give me what I've been hoping for all along, an interface where I can modify steps(i.e. add padding, eventually turn it into NTCP2) by instantiating it with different versions of that function, so I get to think about reusability now
|
||||
I'm going to attempt to ask a question I don't quite know how to ask yet, and maybe won't know the answer until I try it out for myself:
|
||||
Supposing:
|
||||
0. Go network structures can be "nested" if they implement the common interface(`net.Conn`, `net.PacketConn`), and use the common interface to store the information about the socket in their implmentation, and only use the functions of the common interface(This is true)
|
||||
1. That I can instantiate this Noise-framework Transport struct with functions to modify the process in a granular enough way that turning it into NTCP2 is a matter of writing a few custom functions and plugging them in to an instance of the struct(Sort of like what you would do with inheritance)(which I think is true)
|
||||
2. that I can instantiate it with both a `net.Conn(TCP Socket interface)` and a `net.PacketConn(UDP Socket interface)` because I only use the common features of those 2 interfaces, (Which isn't true yet but I'm thinking about how to do it)
|
||||
Does that potential definition of a moddable Noise-over-many-transports library mean that I can approach SSU2 mostly in terms of connection management and peer testing, because the crypto would be similar enough to NTCP2 that I could re-use the custom functions?
|
||||
I'll find out the hard way eventually the first time I have to do it with SSU2, but it would be exciting to have come up with a design that has accelerating returns in such a way.
|
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
|
||||
- NetDB
|
||||
- [ ] Local storage
|
||||
- [/] Persistence to disk
|
||||
- [X] Reseeding
|
||||
- [ ] Persistence to disk
|
||||
- [ ] Reseeding
|
||||
- [ ] Lookups
|
||||
- [ ] Expiry
|
||||
- [ ] Exploration
|
||||
@@ -60,12 +60,12 @@ please keep up with these changes, as they will not be backward compatible and r
|
||||
- [ ] Floodfill
|
||||
- [ ] LS2 and Encrypted Leasesets
|
||||
- Transports
|
||||
- [X] Transport manager
|
||||
- [ ] Transport manager
|
||||
- NTCP2
|
||||
- [ ] Handshake
|
||||
- [ ] Session tracking
|
||||
- [ ] Automatic session creation
|
||||
- SSU2
|
||||
- SSU
|
||||
- [ ] Handshake
|
||||
- [ ] Session tracking
|
||||
- [ ] Automatic session creation
|
||||
@@ -78,20 +78,7 @@ please keep up with these changes, as they will not be backward compatible and r
|
||||
- [ ] Participating
|
||||
- [ ] Tunnel Message Crypto
|
||||
- [ ] Tunnel Message Fragmentation/Reassembly
|
||||
- Common Data Structures
|
||||
- [/] Keys and Cert
|
||||
- [X] Key Certificates
|
||||
- [X] Certificate
|
||||
- [X] Lease
|
||||
- [X] Lease Set
|
||||
- [X] Router Info
|
||||
- [X] Router Identity
|
||||
- [X] Router Address
|
||||
- [X] Session Key
|
||||
- [X] Signature Types
|
||||
- [X] Destination
|
||||
- [X] Data Types
|
||||
- [X] Session Tag
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
|
10
go.mod
10
go.mod
@@ -3,9 +3,13 @@ module github.com/go-i2p/go-i2p
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/dchest/siphash v1.2.3 // indirect
|
||||
github.com/emirpasic/gods v1.18.1
|
||||
github.com/flynn/noise v1.1.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/flynn/noise v1.0.0
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.23.0
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
)
|
||||
|
60
go.sum
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
|
||||
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
|
||||
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620 h1:MjTFQi2DyJifqefRVjAs+P2gaoUAj2rcDpYX7ERggEA=
|
||||
github.com/go-noisesocket/noisesocket v0.0.0-20191014121341-f487ac765620/go.mod h1:y9SBFk2hEIPWY7Aj3bXG+K1xp8wWnQ6kVq2wsYSPByU=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
@@ -1,2 +1,4 @@
|
||||
//
|
||||
// provides generic interfaces for initial bootstrap into network and network reseeding
|
||||
//
|
||||
package bootstrap
|
||||
|
@@ -126,19 +126,29 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||
}).Error("invalid certificate, empty")
|
||||
err = fmt.Errorf("error parsing certificate: certificate is empty")
|
||||
}).Error("invalid certificate")
|
||||
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
||||
return
|
||||
case 1 , 2:
|
||||
certificate.kind = Integer(data[0:len(data)-1])
|
||||
case 1:
|
||||
certificate.kind = Integer(data[0:0])
|
||||
certificate.len = Integer([]byte{0})
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||
}).Error("invalid certificate, too short")
|
||||
}).Error("invalid certificate")
|
||||
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
||||
return
|
||||
case 2:
|
||||
certificate.kind = Integer(data[0:1])
|
||||
certificate.len = Integer([]byte{0})
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": len(data),
|
||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||
}).Error("invalid certificate")
|
||||
err = fmt.Errorf("error parsing certificate length: certificate is too short")
|
||||
return
|
||||
default:
|
||||
certificate.kind = Integer(data[0:1])
|
||||
certificate.len = Integer(data[1:3])
|
||||
@@ -150,11 +160,17 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": certificate.len.Int(),
|
||||
"certificate_payload_length": payleng,
|
||||
"data_bytes:": string(data),
|
||||
"kind_bytes": data[0:1],
|
||||
"len_bytes": data[1:3],
|
||||
"reason": err.Error(),
|
||||
}).Error("invalid certificate, shorter than specified by length")
|
||||
}).Error("invalid certificate")
|
||||
return
|
||||
} else if certificate.len.Int() < len(data)-CERT_MIN_SIZE {
|
||||
err = fmt.Errorf("certificate parsing warning: certificate data is longer than specified by length")
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Certificate) NewCertificate",
|
||||
"certificate_bytes_length": certificate.len.Int(),
|
||||
"certificate_payload_length": payleng,
|
||||
"reason": err.Error(),
|
||||
}).Error("invalid certificate")
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -166,8 +182,8 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
||||
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
||||
certificate, err = NewCertificate(data)
|
||||
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
||||
remainder = certificate.ExcessBytes()
|
||||
err = nil
|
||||
}
|
||||
remainder = certificate.ExcessBytes()
|
||||
return
|
||||
}
|
||||
|
@@ -50,9 +50,7 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err
|
||||
if size < MAX_INTEGER_SIZE {
|
||||
integerSize = size
|
||||
}
|
||||
intBytes := bytes[:integerSize]
|
||||
remainder = bytes[integerSize:]
|
||||
i, _ := ReadInteger(intBytes, integerSize)
|
||||
i, remainder := ReadInteger(bytes, integerSize)
|
||||
integer = &i
|
||||
return
|
||||
}
|
||||
|
@@ -126,25 +126,28 @@ func beginsWith(bytes []byte, chr byte) bool {
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
||||
if len(bytes) < 3 {
|
||||
if len(bytes) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadMapping",
|
||||
"reason": "zero length",
|
||||
}).Warn("mapping format violation")
|
||||
e := errors.New("zero length")
|
||||
err = append(err, e)
|
||||
return
|
||||
}
|
||||
size, remainder, e := NewInteger(bytes, 2)
|
||||
if e != nil {
|
||||
err = append(err, e)
|
||||
}
|
||||
if size.Int() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
mapping.size = size
|
||||
map_bytes := remainder[:mapping.size.Int()]
|
||||
remainder = remainder[mapping.size.Int():]
|
||||
if e != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadMapping",
|
||||
"reason": "error parsing integer",
|
||||
}).Warn("mapping format violation")
|
||||
e := errors.New("error parsing integer")
|
||||
err = append(err, e)
|
||||
}
|
||||
if len(remainder) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadMapping",
|
||||
@@ -153,10 +156,7 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
|
||||
e := errors.New("zero length")
|
||||
err = append(err, e)
|
||||
}
|
||||
// TODO: this should take the remainder and the length we already parsed above, as a parameter.
|
||||
// Like tomorrow morning.
|
||||
// ReadMappingValues should not attempt to figure out the length of the bytes it's reading over.
|
||||
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *mapping.size)
|
||||
vals, remainder, mappingValueErrs := ReadMappingValues(bytes)
|
||||
|
||||
err = append(err, mappingValueErrs...)
|
||||
mapping.vals = vals
|
||||
|
@@ -10,17 +10,6 @@ import (
|
||||
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
||||
type MappingValues [][2]I2PString
|
||||
|
||||
func (m MappingValues) Get(key I2PString) I2PString {
|
||||
keyBytes, _ := key.Data()
|
||||
for _, pair := range m {
|
||||
kb, _ := pair[0][0:].Data()
|
||||
if kb == keyBytes {
|
||||
return pair[1][1:]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValuesToMapping creates a *Mapping using MappingValues.
|
||||
// The values are sorted in the order defined in mappingOrder.
|
||||
func ValuesToMapping(values MappingValues) *Mapping {
|
||||
@@ -57,11 +46,11 @@ func mappingOrder(values MappingValues) {
|
||||
// ReadMappingValues returns *MappingValues from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
||||
//mapping := remainder
|
||||
func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
||||
mapping := remainder
|
||||
//var remainder = mapping
|
||||
//var err error
|
||||
if remainder == nil || len(remainder) < 1 {
|
||||
if remainder == nil || len(remainder) < 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "data shorter than expected",
|
||||
@@ -70,21 +59,31 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
||||
return
|
||||
}
|
||||
map_values := make(MappingValues, 0)
|
||||
int_map_length := map_length.Int()
|
||||
mapping_len := len(remainder)
|
||||
if mapping_len > int_map_length {
|
||||
if len(remainder) < 1 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "data shorter than expected",
|
||||
}).Error("mapping contained no data")
|
||||
errs = []error{errors.New("mapping contained no data")}
|
||||
return
|
||||
}
|
||||
l := Integer(remainder[:2])
|
||||
length := l.Int()
|
||||
// - 2 bytes for map length bits
|
||||
mapping_len := len(mapping) - 2
|
||||
if mapping_len > length {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"mapping_bytes_length": mapping_len,
|
||||
"mapping_length_field": int_map_length,
|
||||
"mapping_length_field": length,
|
||||
"reason": "data longer than expected",
|
||||
}).Warn("mapping format warning")
|
||||
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
|
||||
} else if int_map_length > mapping_len {
|
||||
} else if length > mapping_len {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"mapping_bytes_length": mapping_len,
|
||||
"mapping_length_field": int_map_length,
|
||||
"mapping_length_field": length,
|
||||
"reason": "data shorter than expected",
|
||||
}).Warn("mapping format warning")
|
||||
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
|
||||
@@ -92,7 +91,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
||||
|
||||
encounteredKeysMap := map[string]bool{}
|
||||
// pop off length bytes before parsing kv pairs
|
||||
//remainder = remainder[2:]
|
||||
remainder = remainder[2:]
|
||||
|
||||
for {
|
||||
// Read a key, breaking on fatal errors
|
||||
@@ -112,16 +111,16 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
||||
break
|
||||
}
|
||||
|
||||
key_str, more, err := ReadI2PString(remainder)
|
||||
str, more, err := ReadI2PString(remainder)
|
||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||
remainder = more
|
||||
key_str := str
|
||||
if err != nil {
|
||||
if stopValueRead(err) {
|
||||
errs = append(errs, err)
|
||||
//return
|
||||
}
|
||||
}
|
||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||
remainder = more
|
||||
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
|
||||
|
||||
// Check if key has already been encountered in this mapping
|
||||
keyBytes, _ := key_str.Data()
|
||||
@@ -131,9 +130,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "duplicate key in mapping",
|
||||
"key": string(key_str),
|
||||
}).Error("mapping format violation")
|
||||
log.Printf("DUPE: %s", key_str)
|
||||
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
||||
// Based on other implementations this does not seem to happen often?
|
||||
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
|
||||
@@ -145,39 +142,33 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "expected =",
|
||||
"value:": string(remainder),
|
||||
}).Warn("mapping format violation")
|
||||
errs = append(errs, errors.New("mapping format violation, expected ="))
|
||||
log.Printf("ERRVAL: %s", remainder)
|
||||
break
|
||||
} else {
|
||||
remainder = remainder[1:]
|
||||
}
|
||||
remainder = remainder[1:]
|
||||
|
||||
// Read a value, breaking on fatal errors
|
||||
// and appending warnings
|
||||
val_str, more, err := ReadI2PString(remainder)
|
||||
str, more, err = ReadI2PString(remainder)
|
||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||
remainder = more
|
||||
val_str := str
|
||||
if err != nil {
|
||||
if stopValueRead(err) {
|
||||
errs = append(errs, err)
|
||||
//return
|
||||
}
|
||||
}
|
||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||
remainder = more
|
||||
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
|
||||
//log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
|
||||
if !beginsWith(remainder, 0x3b) {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(Mapping) Values",
|
||||
"reason": "expected ;",
|
||||
"value:": string(remainder),
|
||||
}).Warn("mapping format violation")
|
||||
errs = append(errs, errors.New("mapping format violation, expected ;"))
|
||||
break
|
||||
} else {
|
||||
remainder = remainder[1:]
|
||||
}
|
||||
remainder = remainder[1:]
|
||||
|
||||
// Append the key-value pair and break if there is no more data to read
|
||||
map_values = append(map_values, [2]I2PString{key_str, val_str})
|
||||
|
@@ -38,17 +38,28 @@ func (str I2PString) Length() (length int, err error) {
|
||||
err = errors.New("error parsing string: zero length")
|
||||
return
|
||||
}
|
||||
l, _, _ := NewInteger(str, 1)
|
||||
l := Integer([]byte{byte(str[0])})
|
||||
length = l.Int()
|
||||
str_len := len(str) - 1
|
||||
if length != str_len {
|
||||
inferred_len := length + 1
|
||||
str_len := len(str)
|
||||
if inferred_len > str_len {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(I2PString) Length",
|
||||
"string_bytes_length": str_len,
|
||||
"string_length_field": length,
|
||||
"reason": "data less than specified by length",
|
||||
}).Error("string format warning")
|
||||
"at": "(I2PString) Length",
|
||||
"string_bytes_length": str_len,
|
||||
"string_length_field": length,
|
||||
"expected_bytes_length": inferred_len,
|
||||
"reason": "data shorter than specified",
|
||||
}).Warn("string format warning")
|
||||
err = errors.New("string parsing warning: string data is shorter than specified by length")
|
||||
} else if str_len > inferred_len {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(I2PString) Length",
|
||||
"string_bytes_length": str_len,
|
||||
"string_length_field": length,
|
||||
"expected_bytes_length": inferred_len,
|
||||
"reason": "data longer than specified",
|
||||
}).Warn("string format warning")
|
||||
err = errors.New("string parsing warning: string contains data beyond length")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -65,14 +76,11 @@ func (str I2PString) Data() (data string, err error) {
|
||||
data = string(str[1:])
|
||||
return
|
||||
case "string parsing warning: string contains data beyond length":
|
||||
data = string(str[1:])
|
||||
data = string(str[1 : length+1])
|
||||
return
|
||||
}
|
||||
}
|
||||
if length == 0 {
|
||||
return
|
||||
}
|
||||
data = string(str[1 : length+1])
|
||||
data = string(str[1:])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,14 +113,13 @@ func ToI2PString(data string) (str I2PString, err error) {
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
||||
length, _, err := NewInteger(data, 1)
|
||||
if err != nil {
|
||||
return
|
||||
str = I2PString(data)
|
||||
length, err := I2PString(data).Length()
|
||||
if err != nil && err.Error() == "string parsing warning: string contains data beyond length" {
|
||||
str = I2PString(data[:length+1])
|
||||
remainder = data[length+1:]
|
||||
err = nil
|
||||
}
|
||||
data_len := length.Int()
|
||||
str = data[:data_len+1]
|
||||
remainder = data[data_len+1:]
|
||||
_, err = str.Length()
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ package exportable
|
||||
import common "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
keys_and_cert, _, _ := common.NewKeysAndCert(data)
|
||||
keys_and_cert, _, _ := common.ReadKeysAndCert(data)
|
||||
keys_and_cert.Certificate()
|
||||
keys_and_cert.PublicKey()
|
||||
keys_and_cert.SigningPublicKey()
|
||||
|
@@ -52,10 +52,6 @@ const (
|
||||
// Key Certificate Public Key Types
|
||||
const (
|
||||
KEYCERT_CRYPTO_ELG = iota
|
||||
KEYCERT_CRYPTO_P256
|
||||
KEYCERT_CRYPTO_P384
|
||||
KEYCERT_CRYPTO_P521
|
||||
KEYCERT_CRYPTO_X25519
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -77,11 +73,7 @@ const (
|
||||
|
||||
// PublicKey sizes for Public Key Types
|
||||
const (
|
||||
KEYCERT_CRYPTO_ELG_SIZE = 256
|
||||
KEYCERT_CRYPTO_P256_SIZE = 64
|
||||
KEYCERT_CRYPTO_P384_SIZE = 96
|
||||
KEYCERT_CRYPTO_P521_SIZE = 132
|
||||
KEYCERT_CRYPTO_X25519_SIZE = 32
|
||||
KEYCERT_CRYPTO_ELG_SIZE = 256
|
||||
)
|
||||
|
||||
// Sizes of structures in KeyCertificates
|
||||
@@ -90,7 +82,7 @@ const (
|
||||
KEYCERT_SPK_SIZE = 128
|
||||
)
|
||||
|
||||
// type KeyCertificate []byte
|
||||
//type KeyCertificate []byte
|
||||
type KeyCertificate struct {
|
||||
*Certificate
|
||||
spkType Integer
|
||||
@@ -120,7 +112,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
||||
return
|
||||
}
|
||||
data_len := len(data)
|
||||
if data_len < key_certificate.CryptoSize() {
|
||||
if data_len < KEYCERT_PUBKEY_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(KeyCertificate) ConstructPublicKey",
|
||||
"data_len": data_len,
|
||||
@@ -135,10 +127,6 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
||||
var elg_key crypto.ElgPublicKey
|
||||
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
||||
public_key = elg_key
|
||||
case KEYCERT_CRYPTO_X25519:
|
||||
var ed25519_key crypto.Ed25519PublicKey
|
||||
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
||||
public_key = ed25519_key
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -151,7 +139,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
||||
return
|
||||
}
|
||||
data_len := len(data)
|
||||
if data_len < key_certificate.SignatureSize() {
|
||||
if data_len < KEYCERT_SPK_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(KeyCertificate) ConstructSigningPublicKey",
|
||||
"data_len": data_len,
|
||||
@@ -197,51 +185,60 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
||||
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
|
||||
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
||||
sizes := map[int]int{
|
||||
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
|
||||
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
|
||||
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
|
||||
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
|
||||
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
|
||||
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
|
||||
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
|
||||
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
|
||||
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
|
||||
KEYCERT_SIGN_DSA_SHA1: 40,
|
||||
KEYCERT_SIGN_P256: 64,
|
||||
KEYCERT_SIGN_P384: 96,
|
||||
KEYCERT_SIGN_P521: 132,
|
||||
KEYCERT_SIGN_RSA2048: 256,
|
||||
KEYCERT_SIGN_RSA3072: 384,
|
||||
KEYCERT_SIGN_RSA4096: 512,
|
||||
KEYCERT_SIGN_ED25519: 64,
|
||||
KEYCERT_SIGN_ED25519PH: 64,
|
||||
}
|
||||
key_type := key_certificate.SigningPublicKeyType()
|
||||
return sizes[int(key_type)]
|
||||
}
|
||||
|
||||
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type.
|
||||
func (key_certificate KeyCertificate) CryptoSize() (size int) {
|
||||
sizes := map[int]int{
|
||||
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
|
||||
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
|
||||
KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE,
|
||||
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
|
||||
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
|
||||
}
|
||||
key_type := key_certificate.PublicKeyType()
|
||||
return sizes[int(key_type)]
|
||||
}
|
||||
|
||||
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
||||
var certificate *Certificate
|
||||
certificate, remainder, err = ReadCertificate(bytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
if len(bytes) < KEYCERT_MIN_SIZE {
|
||||
err = errors.New("error parsing key certificate: not enough data")
|
||||
}
|
||||
key_certificate = &KeyCertificate{
|
||||
Certificate: certificate,
|
||||
spkType: Integer(bytes[4:5]),
|
||||
cpkType: Integer(bytes[6:7]),
|
||||
switch len(bytes) {
|
||||
case 4:
|
||||
key_certificate = &KeyCertificate{
|
||||
Certificate: certificate,
|
||||
spkType: Integer(bytes[4:]),
|
||||
cpkType: Integer([]byte{0}),
|
||||
}
|
||||
case 5:
|
||||
key_certificate = &KeyCertificate{
|
||||
Certificate: certificate,
|
||||
spkType: Integer(bytes[4:5]),
|
||||
cpkType: Integer([]byte{0}),
|
||||
}
|
||||
case 6:
|
||||
key_certificate = &KeyCertificate{
|
||||
Certificate: certificate,
|
||||
spkType: Integer(bytes[4:5]),
|
||||
cpkType: Integer(bytes[6:]),
|
||||
}
|
||||
default:
|
||||
key_certificate = &KeyCertificate{
|
||||
Certificate: certificate,
|
||||
spkType: Integer(bytes[4:5]),
|
||||
cpkType: Integer(bytes[6:7]),
|
||||
}
|
||||
}
|
||||
remainder = bytes[KEYCERT_MIN_SIZE:]
|
||||
remainder = bytes[7:]
|
||||
//key_certificate.PublicKey = NewPublicKey(bytes)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -165,22 +165,51 @@ func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
|
||||
return keys_and_cert.KeyCertificate.Certificate
|
||||
}
|
||||
|
||||
//
|
||||
// Read a KeysAndCert from a slice of bytes, retuning it and the remaining data as well as any errors
|
||||
// encoutered parsing the KeysAndCert.
|
||||
//
|
||||
|
||||
// ReadKeysAndCert returns KeysAndCert from a []byte.
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
|
||||
/*data_len := len(data)
|
||||
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadKeysAndCert",
|
||||
"data_len": data_len,
|
||||
"required_len": KEYS_AND_CERT_MIN_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing keys and cert")
|
||||
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||
return
|
||||
}
|
||||
keys_and_cert = KeysAndCert(data[:KEYS_AND_CERT_MIN_SIZE])
|
||||
cert, _ := keys_and_cert.Certificate()
|
||||
cert_len := cert.Length()
|
||||
if cert_len == 0 {
|
||||
remainder = data[KEYS_AND_CERT_MIN_SIZE:]
|
||||
return
|
||||
}
|
||||
if data_len < KEYS_AND_CERT_MIN_SIZE+cert_len {
|
||||
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:]...)
|
||||
//err = cert_len_err
|
||||
} else {
|
||||
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:KEYS_AND_CERT_MIN_SIZE+cert_len]...)
|
||||
remainder = data[KEYS_AND_CERT_MIN_SIZE+cert_len:]
|
||||
}*/
|
||||
keys_and_cert_pointer, remainder, err := NewKeysAndCert(data)
|
||||
keys_and_cert = *keys_and_cert_pointer
|
||||
return
|
||||
}
|
||||
|
||||
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
||||
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
||||
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
|
||||
data_len := len(data)
|
||||
keys_and_cert = &KeysAndCert{}
|
||||
if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadKeysAndCert",
|
||||
"data_len": data_len,
|
||||
"required_len": KEYS_AND_CERT_MIN_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing keys and cert")
|
||||
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||
keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
|
||||
return
|
||||
} else if data_len < KEYS_AND_CERT_DATA_SIZE {
|
||||
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "ReadKeysAndCert",
|
||||
"data_len": data_len,
|
||||
@@ -190,22 +219,22 @@ func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte,
|
||||
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||
return
|
||||
}
|
||||
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
|
||||
cert, remainder, err := NewKeyCertificate(data)
|
||||
keys_and_cert.KeyCertificate = cert
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same.
|
||||
// a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE
|
||||
// and KEYS_AND_CERT_SPK_SIZE constants in the future.
|
||||
keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE]
|
||||
padding := data[KEYS_AND_CERT_MIN_SIZE+cert.Length():]
|
||||
keys_and_cert.padding = padding
|
||||
publicKey, err := cert.ConstructPublicKey(padding)
|
||||
keys_and_cert.publicKey = publicKey
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
signingPublicKey, err := cert.ConstructSigningPublicKey(padding)
|
||||
keys_and_cert.signingPublicKey = signingPublicKey
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return keys_and_cert, remainder, err
|
||||
}
|
||||
|
@@ -6,17 +6,23 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*func TestCertificateWithMissingData(t *testing.T) {
|
||||
func TestCertificateWithMissingData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
|
||||
data := make([]byte, 128+256)
|
||||
data = append(data, cert_data...)
|
||||
_, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
cert := keys_and_cert.Certificate()
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
||||
}
|
||||
}*/
|
||||
cert_bytes := cert.Bytes()
|
||||
if assert.Equal(len(cert_data), len(cert_bytes)) {
|
||||
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return available data when cert was missing some data")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertificateWithValidData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
@@ -24,11 +30,10 @@ func TestCertificateWithValidData(t *testing.T) {
|
||||
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
|
||||
data := make([]byte, 128+256)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
assert.Nil(err)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
cert := keys_and_cert.Certificate()
|
||||
|
||||
assert.Nil(err)
|
||||
cert_bytes := cert.Bytes()
|
||||
if assert.Equal(len(cert_data), len(cert_bytes)) {
|
||||
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return correct data with valid cert")
|
||||
@@ -43,7 +48,7 @@ func TestPublicKeyWithBadData(t *testing.T) {
|
||||
data := make([]byte, 128)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
pub_key := keys_and_cert.PublicKey()
|
||||
if assert.NotNil(err) {
|
||||
@@ -60,7 +65,7 @@ func TestPublicKeyWithBadCertificate(t *testing.T) {
|
||||
data := make([]byte, 128)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
pub_key := keys_and_cert.PublicKey()
|
||||
if assert.NotNil(err) {
|
||||
@@ -77,7 +82,7 @@ func TestPublicKeyWithNullCertificate(t *testing.T) {
|
||||
data := make([]byte, 128)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
pub_key := keys_and_cert.PublicKey()
|
||||
assert.Nil(err)
|
||||
@@ -92,7 +97,7 @@ func TestPublicKeyWithKeyCertificate(t *testing.T) {
|
||||
data := make([]byte, 128)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
pub_key := keys_and_cert.PublicKey()
|
||||
assert.Nil(err)
|
||||
@@ -107,7 +112,7 @@ func TestSigningPublicKeyWithBadData(t *testing.T) {
|
||||
data := make([]byte, 93)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||
if assert.NotNil(err) {
|
||||
@@ -124,7 +129,7 @@ func TestSigningPublicKeyWithBadCertificate(t *testing.T) {
|
||||
data := make([]byte, 128)
|
||||
data = append(data, pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||
if assert.NotNil(err) {
|
||||
@@ -141,7 +146,7 @@ func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
|
||||
signing_pub_key_data := make([]byte, 128)
|
||||
data := append(pub_key_data, signing_pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||
assert.Nil(err)
|
||||
@@ -156,18 +161,18 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
|
||||
signing_pub_key_data := make([]byte, 128)
|
||||
data := append(pub_key_data, signing_pub_key_data...)
|
||||
data = append(data, cert_data...)
|
||||
keys_and_cert, _, err := NewKeysAndCert(data)
|
||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||
|
||||
signing_pub_key := keys_and_cert.SigningPublicKey()
|
||||
assert.Nil(err)
|
||||
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithMissingData(t *testing.T) {
|
||||
func TestReadKeysAndCertWithMissingData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
assert.Equal(0, len(remainder))
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
|
||||
@@ -175,56 +180,56 @@ func TestNewKeysAndCertWithMissingData(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
|
||||
func TestReadKeysAndCertWithMissingCertData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128+256)
|
||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
assert.Equal(0, len(remainder))
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) {
|
||||
func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128+256)
|
||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
assert.Equal(0, len(remainder))
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
||||
func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128+256)
|
||||
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
assert.Equal(0, len(remainder))
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
||||
func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128+256)
|
||||
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
if assert.Equal(1, len(remainder)) {
|
||||
assert.Equal("A", string(remainder[0]))
|
||||
}
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
||||
func TestReadKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cert_data := make([]byte, 128+256)
|
||||
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...)
|
||||
_, remainder, err := NewKeysAndCert(cert_data)
|
||||
_, remainder, err := ReadKeysAndCert(cert_data)
|
||||
if assert.Equal(1, len(remainder)) {
|
||||
assert.Equal("A", string(remainder[0]))
|
||||
}
|
||||
|
@@ -132,10 +132,7 @@ type LeaseSet struct {
|
||||
|
||||
// Destination returns the Destination as []byte.
|
||||
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
||||
keys_and_cert, _, err := NewKeysAndCert(lease_set)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
|
||||
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
||||
return
|
||||
}
|
||||
@@ -143,7 +140,7 @@ func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
||||
// PublicKey returns the public key as crypto.ElgPublicKey.
|
||||
// Returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) {
|
||||
_, remainder, err := NewKeysAndCert(lease_set)
|
||||
_, remainder, err := ReadKeysAndCert(lease_set)
|
||||
remainder_len := len(remainder)
|
||||
if remainder_len < LEASE_SET_PUBKEY_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
@@ -215,7 +212,7 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
|
||||
// LeaseCount returns the numbert of leases specified by the LeaseCount value as int.
|
||||
// returns errors encountered during parsing.
|
||||
func (lease_set LeaseSet) LeaseCount() (count int, err error) {
|
||||
_, remainder, err := NewKeysAndCert(lease_set)
|
||||
_, remainder, err := ReadKeysAndCert(lease_set)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@@ -65,8 +65,9 @@ options :: Mapping
|
||||
type RouterAddress struct {
|
||||
cost *Integer
|
||||
expiration *Date
|
||||
transport_style *I2PString
|
||||
Transport_Style *I2PString
|
||||
options *Mapping
|
||||
parserErr error
|
||||
}
|
||||
|
||||
// Bytes returns the router address as a []byte.
|
||||
@@ -74,15 +75,15 @@ func (router_address RouterAddress) Bytes() []byte {
|
||||
bytes := make([]byte, 0)
|
||||
bytes = append(bytes, router_address.cost.Bytes()...)
|
||||
bytes = append(bytes, router_address.expiration.Bytes()...)
|
||||
strData, err := router_address.transport_style.Data()
|
||||
strData, err := router_address.Transport_Style.Data()
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"error": err,
|
||||
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
|
||||
}).Error("RouterAddress.Bytes: error getting Transport_Style bytes")
|
||||
} else {
|
||||
bytes = append(bytes, strData...)
|
||||
}
|
||||
bytes = append(bytes, router_address.options.Data()...)
|
||||
//bytes = append(bytes, router_address.options.Bytes()...)
|
||||
return bytes
|
||||
}
|
||||
|
||||
@@ -98,7 +99,7 @@ func (router_address RouterAddress) Expiration() Date {
|
||||
|
||||
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
||||
func (router_address RouterAddress) TransportStyle() I2PString {
|
||||
return *router_address.transport_style
|
||||
return *router_address.Transport_Style
|
||||
}
|
||||
|
||||
// Options returns the options for this RouterAddress as an I2P Mapping.
|
||||
@@ -108,6 +109,25 @@ func (router_address RouterAddress) Options() Mapping {
|
||||
|
||||
// Check if the RouterAddress is empty or if it is too small to contain valid data.
|
||||
func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
||||
/*addr_len := len(router_address)
|
||||
exit = false
|
||||
if addr_len == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) checkValid",
|
||||
"reason": "no data",
|
||||
}).Error("invalid router address")
|
||||
err = errors.New("error parsing RouterAddress: no data")
|
||||
exit = true
|
||||
} else if addr_len < ROUTER_ADDRESS_MIN_SIZE {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) checkValid",
|
||||
"reason": "data too small (len < ROUTER_ADDRESS_MIN_SIZE)",
|
||||
}).Warn("router address format warning")
|
||||
err = errors.New("warning parsing RouterAddress: data too small")
|
||||
}*/
|
||||
if router_address.parserErr != nil {
|
||||
exit = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -115,40 +135,54 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
||||
if len(data) == 0 {
|
||||
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
|
||||
if data == nil || len(data) == 0 {
|
||||
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data")
|
||||
err = errors.New("error parsing RouterAddress: no data")
|
||||
router_address.parserErr = err
|
||||
return
|
||||
}
|
||||
router_address.cost, remainder, err = NewInteger(data, 1)
|
||||
cost, remainder, err := NewInteger([]byte{data[0]}, 1)
|
||||
router_address.cost = cost
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||
"reason": "error parsing cost",
|
||||
}).Warn("error parsing RouterAddress")
|
||||
router_address.parserErr = err
|
||||
}
|
||||
router_address.expiration, remainder, err = NewDate(remainder)
|
||||
expiration, remainder, err := NewDate(remainder)
|
||||
router_address.expiration = expiration
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||
"reason": "error parsing expiration",
|
||||
}).Error("error parsing RouterAddress")
|
||||
router_address.parserErr = err
|
||||
}
|
||||
router_address.transport_style, remainder, err = NewI2PString(remainder)
|
||||
Transport_Style, remainder, err := NewI2PString(remainder)
|
||||
router_address.Transport_Style = Transport_Style
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||
"reason": "error parsing transport_style",
|
||||
"reason": "error parsing Transport_Style",
|
||||
}).Error("error parsing RouterAddress")
|
||||
router_address.parserErr = err
|
||||
}
|
||||
var errs []error
|
||||
router_address.options, remainder, errs = NewMapping(remainder)
|
||||
options, remainder, errs := NewMapping(remainder)
|
||||
for _, err := range errs {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||
"reason": "error parsing options",
|
||||
"error": err,
|
||||
}).Error("error parsing RouterAddress")
|
||||
router_address.parserErr = err
|
||||
}
|
||||
router_address.options = options
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||
"reason": "error parsing options",
|
||||
}).Error("error parsing RouterAddress")
|
||||
router_address.parserErr = err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package router_info
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
@@ -15,9 +15,6 @@ import (
|
||||
|
||||
const ROUTER_INFO_MIN_SIZE = 439
|
||||
|
||||
const MIN_GOOD_VERSION = 58
|
||||
const MAX_GOOD_VERSION = 99
|
||||
|
||||
/*
|
||||
[RouterInfo]
|
||||
Accurate for version 0.9.49
|
||||
@@ -111,10 +108,13 @@ type RouterInfo struct {
|
||||
signature *Signature
|
||||
}
|
||||
|
||||
var routerInfoTest net.Addr = &RouterInfo{}
|
||||
|
||||
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
|
||||
func (router_info RouterInfo) Bytes() ([]byte, error) {
|
||||
var err error
|
||||
var bytes []byte
|
||||
|
||||
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
|
||||
bytes = append(bytes, router_info.published.Bytes()...)
|
||||
bytes = append(bytes, router_info.size.Bytes()...)
|
||||
@@ -122,12 +122,35 @@ func (router_info RouterInfo) Bytes() ([]byte, error) {
|
||||
bytes = append(bytes, router_address.Bytes()...)
|
||||
}
|
||||
bytes = append(bytes, router_info.peer_size.Bytes()...)
|
||||
bytes = append(bytes, router_info.options.Data()...)
|
||||
//bytes = append(bytes, []byte(*router_info.signature)...)
|
||||
//bytes = append(bytes, router_info.options.Bytes()...)
|
||||
bytes = append(bytes, []byte(*router_info.signature)...)
|
||||
|
||||
return bytes, err
|
||||
}
|
||||
|
||||
// Network Implements net.Addr, returns comma-separated list of transport types
|
||||
func (router_info *RouterInfo) Network() string {
|
||||
var str []string
|
||||
for _, addr := range router_info.addresses {
|
||||
t, err := addr.Transport_Style.Data()
|
||||
if err != nil {
|
||||
return strings.Join(str, ",")
|
||||
}
|
||||
str = append(str, t)
|
||||
}
|
||||
return strings.Join(str, ",")
|
||||
}
|
||||
|
||||
// String Implements net.Addr, returns router-info `Bytes` converted to a string
|
||||
func (router_info *RouterInfo) String() string {
|
||||
bytes, err := router_info.Bytes()
|
||||
if err != nil {
|
||||
// TODO handle this issue
|
||||
return ""
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// RouterIdentity returns the router identity as *RouterIdentity.
|
||||
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
||||
return router_info.router_identity
|
||||
@@ -255,14 +278,6 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
size, remainder, err := NewInteger(remainder, 1)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
"required_len": size.Int(),
|
||||
"reason": "read error",
|
||||
}).Error("error parsing router info size")
|
||||
}
|
||||
info.size = size
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
@@ -273,23 +288,25 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
addresses := make([]*RouterAddress, size.Int())
|
||||
for i := 0; i < size.Int(); i++ {
|
||||
address, more, err := NewRouterAddress(remainder)
|
||||
remainder = more
|
||||
address, remainder, err := NewRouterAddress(remainder)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
//"required_len": ROUTER_ADDRESS_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router address")
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
info.addresses = append(info.addresses, address)
|
||||
addresses = append(addresses, address)
|
||||
}
|
||||
info.peer_size, remainder, err = NewInteger(remainder, 1)
|
||||
var errs []error
|
||||
info.options, remainder, errs = NewMapping(remainder)
|
||||
info.addresses = addresses
|
||||
peer_size := Integer(remainder[:1])
|
||||
info.peer_size = &peer_size
|
||||
remainder = remainder[1:]
|
||||
options, remainder, errs := NewMapping(remainder)
|
||||
if len(errs) != 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
@@ -303,6 +320,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
||||
}
|
||||
err = errors.New("error parsing router info: " + estring)
|
||||
}
|
||||
info.options = options
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
@@ -315,61 +333,6 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (router_info *RouterInfo) RouterCapabilities() string {
|
||||
str, err := ToI2PString("caps")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(router_info.options.Values().Get(str))
|
||||
}
|
||||
|
||||
func (router_info *RouterInfo) RouterVersion() string {
|
||||
str, err := ToI2PString("router.version")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(router_info.options.Values().Get(str))
|
||||
}
|
||||
|
||||
func (router_info *RouterInfo) GoodVersion() bool {
|
||||
version := router_info.RouterVersion()
|
||||
v := strings.Split(version, ".")
|
||||
if len(v) != 3 {
|
||||
return false
|
||||
}
|
||||
if v[0] == "0" {
|
||||
if v[1] == "9" {
|
||||
val, _ := strconv.Atoi(v[2])
|
||||
if val >= MIN_GOOD_VERSION && val <= MAX_GOOD_VERSION {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (router_info *RouterInfo) UnCongested() bool {
|
||||
caps := router_info.RouterCapabilities()
|
||||
if strings.Contains(caps, "K") {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(caps, "G") {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(caps, "E") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (router_info *RouterInfo) Reachable() bool {
|
||||
caps := router_info.RouterCapabilities()
|
||||
if strings.Contains(caps, "U") {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(caps, "R")
|
||||
}
|
||||
|
||||
// NewRouterInfo creates a new *RouterInfo from []byte using ReadRouterInfo.
|
||||
// Returns a pointer to RouterInfo unlike ReadRouterInfo.
|
||||
func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) {
|
||||
|
@@ -1,2 +1,4 @@
|
||||
//
|
||||
// package for i2p specific crpytography
|
||||
//
|
||||
package crypto
|
||||
|
@@ -2,16 +2,10 @@ package crypto
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
|
||||
|
||||
type Ed25519PublicKey []byte
|
||||
|
||||
type Ed25519Verifier struct {
|
||||
@@ -25,77 +19,6 @@ func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) {
|
||||
return temp, nil
|
||||
}
|
||||
|
||||
func (k Ed25519PublicKey) Len() int {
|
||||
return len(k)
|
||||
}
|
||||
|
||||
func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) {
|
||||
if len(data) == 256 {
|
||||
k2 := ed25519.PublicKey{}
|
||||
copy(k2[:], data)
|
||||
k = &k2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createEd25519Encryption(pub *ed25519.PublicKey, rand io.Reader) (enc *Ed25519Encryption, err error) {
|
||||
/*kbytes := make([]byte, 256)
|
||||
k := new(big.Int)
|
||||
for err == nil {
|
||||
_, err = io.ReadFull(rand, kbytes)
|
||||
k = new(big.Int).SetBytes(kbytes)
|
||||
k = k.Mod(k, pub.P)
|
||||
if k.Sign() != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
enc = &Ed25519Encryption{}
|
||||
}*/
|
||||
return
|
||||
}
|
||||
|
||||
type Ed25519Encryption struct {
|
||||
p, a, b1 *big.Int
|
||||
}
|
||||
|
||||
func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error) {
|
||||
return ed25519.EncryptPadding(data, true)
|
||||
}
|
||||
|
||||
func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) {
|
||||
if len(data) > 222 {
|
||||
err = Ed25519EncryptTooBig
|
||||
return
|
||||
}
|
||||
mbytes := make([]byte, 255)
|
||||
mbytes[0] = 0xFF
|
||||
copy(mbytes[33:], data)
|
||||
// do sha256 of payload
|
||||
d := sha256.Sum256(mbytes[33 : len(data)+33])
|
||||
copy(mbytes[1:], d[:])
|
||||
m := new(big.Int).SetBytes(mbytes)
|
||||
// do encryption
|
||||
b := new(big.Int).Mod(new(big.Int).Mul(ed25519.b1, m), ed25519.p).Bytes()
|
||||
|
||||
if zeroPadding {
|
||||
encrypted = make([]byte, 514)
|
||||
copy(encrypted[1:], ed25519.a.Bytes())
|
||||
copy(encrypted[258:], b)
|
||||
} else {
|
||||
encrypted = make([]byte, 512)
|
||||
copy(encrypted, ed25519.a.Bytes())
|
||||
copy(encrypted[256:], b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) {
|
||||
k := createEd25519PublicKey(elg[:])
|
||||
enc, err = createEd25519Encryption(k, rand.Reader)
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) {
|
||||
if len(sig) != ed25519.SignatureSize {
|
||||
err = ErrBadSignatureSize
|
||||
|
@@ -5,10 +5,9 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"golang.org/x/crypto/openpgp/elgamal"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/openpgp/elgamal"
|
||||
)
|
||||
|
||||
var elgp = new(big.Int).SetBytes([]byte{
|
||||
|
@@ -23,7 +23,9 @@ func (hk HMACKey) xor(p byte) (i []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// do i2p hmac
|
||||
//
|
||||
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) {
|
||||
|
||||
buff := make([]byte, 64+len(data))
|
||||
|
@@ -1 +1,5 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
package netdb
|
||||
|
@@ -50,7 +50,9 @@ func (db StdNetDB) Path() string {
|
||||
return string(db)
|
||||
}
|
||||
|
||||
//
|
||||
// return how many routers we know about in our network database
|
||||
//
|
||||
func (db StdNetDB) Size() (routers int) {
|
||||
// TODO: implement this
|
||||
var err error
|
||||
|
@@ -14,50 +14,47 @@
|
||||
// content the error ErrInvalidSignature will be returned.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
|
||||
// su3File, err := su3.Read(body)
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// // Look up this signer's key.
|
||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||
// // Read the content.
|
||||
// contentReader := su3File.Content(key)
|
||||
// bytes, err := ioutil.ReadAll(contentReader)
|
||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||
// // The signature is invalid, OR a nil key was provided.
|
||||
// } else if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// // Let's say we are reading an SU3 file from an HTTP body, which is an io.Reader.
|
||||
// su3File, err := su3.Read(body)
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// // Look up this signer's key.
|
||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||
// // Read the content.
|
||||
// contentReader := su3File.Content(key)
|
||||
// bytes, err := ioutil.ReadAll(contentReader)
|
||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||
// // The signature is invalid, OR a nil key was provided.
|
||||
// } else if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
//
|
||||
// If you want to parse from a []byte, you can wrap it like this:
|
||||
//
|
||||
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
|
||||
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
|
||||
// mySU3FileBytes := []byte{0x00, 0x01, 0x02, 0x03}
|
||||
// su3File, err := su3.Read(bytes.NewReader(mySU3FileBytes))
|
||||
//
|
||||
// One of the advantages of this library's design is that you can avoid buffering
|
||||
// the file contents in memory. Here's how you would stream from an HTTP body
|
||||
// directly to disk:
|
||||
//
|
||||
// su3File, err := su3.Read(body)
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// // Look up this signer's key.
|
||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||
// // Stream directly to disk.
|
||||
// f, err := os.Create("my_file.txt")
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// _, err := io.Copy(f, su3File.Content(key))
|
||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||
// // The signature is invalid, OR a nil key was provided.
|
||||
// // Don't trust the file, delete it!
|
||||
// } else if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// su3File, err := su3.Read(body)
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// // Look up this signer's key.
|
||||
// key := somehow_lookup_the_key(su3File.SignerID)
|
||||
// // Stream directly to disk.
|
||||
// f, err := os.Create("my_file.txt")
|
||||
// if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
// _, err := io.Copy(f, su3File.Content(key))
|
||||
// if errors.Is(err, su3.ErrInvalidSignature) {
|
||||
// // The signature is invalid, OR a nil key was provided.
|
||||
// // Don't trust the file, delete it!
|
||||
// } else if err != nil {
|
||||
// // Handle error.
|
||||
// }
|
||||
//
|
||||
// Note: if you want to read the content, the Content() io.Reader must be read
|
||||
// *before* the Signature() io.Reader. If you read the signature first, the
|
||||
|
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
*
|
||||
|
||||
i2np messages transports
|
||||
/**
|
||||
i2np messages transports
|
||||
*/
|
||||
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 {
|
||||
c.Mutex.Lock()
|
||||
defer c.Mutex.Unlock()
|
||||
session, err := c.GetSession(routerInfo)
|
||||
session, err := c.getSession(routerInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
if session.(*NoiseSession).handshakeComplete {
|
||||
return nil
|
||||
}
|
||||
if session.(*NoiseSession).Cond == nil {
|
||||
break
|
||||
}
|
||||
session.(*NoiseSession).Cond.Wait()
|
||||
}
|
||||
// Set handshakeCond to indicate that this goroutine is committing to
|
||||
// running the handshake.
|
||||
session.(*NoiseSession).Cond = sync.NewCond(&c.Mutex)
|
||||
@@ -29,8 +20,8 @@ func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
|
||||
session.(*NoiseSession).Mutex.Lock()
|
||||
defer session.(*NoiseSession).Mutex.Unlock()
|
||||
c.Mutex.Lock()
|
||||
// if c.config.isClient {
|
||||
if err := session.(*NoiseSession).RunClientHandshake(); err != nil {
|
||||
|
||||
if err := session.(*NoiseSession).RunOutgoingHandshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Wake any other goroutines that are waiting for this handshake to
|
||||
|
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -10,46 +11,45 @@ import (
|
||||
"github.com/flynn/noise"
|
||||
|
||||
"github.com/go-i2p/go-i2p/lib/common/router_info"
|
||||
"github.com/go-i2p/go-i2p/lib/i2np"
|
||||
"github.com/go-i2p/go-i2p/lib/transport"
|
||||
)
|
||||
|
||||
type NoiseSession struct {
|
||||
*cb.Queue
|
||||
router_info.RouterInfo
|
||||
*noise.CipherState
|
||||
sync.Mutex
|
||||
*sync.Cond
|
||||
*NoiseTransport
|
||||
*NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session
|
||||
RecvQueue *cb.Queue
|
||||
SendQueue *cb.Queue
|
||||
SendKey noise.DHKey
|
||||
RecvKey noise.DHKey
|
||||
HandKey noise.DHKey
|
||||
VerifyCallback VerifyCallbackFunc
|
||||
handshakeBuffer bytes.Buffer
|
||||
activeCall int32
|
||||
handshakeComplete bool
|
||||
Conn net.Conn
|
||||
}
|
||||
|
||||
// Read implements net.Conn
|
||||
func (*NoiseSession) Read(b []byte) (n int, err error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// RemoteAddr implements net.Conn
|
||||
func (*NoiseSession) RemoteAddr() net.Addr {
|
||||
panic("unimplemented")
|
||||
func (noise_session *NoiseSession) RemoteAddr() net.Addr {
|
||||
return &noise_session.RouterInfo
|
||||
}
|
||||
|
||||
// SetDeadline implements net.Conn
|
||||
func (*NoiseSession) SetDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
func (noise_session *NoiseSession) SetDeadline(t time.Time) error {
|
||||
return noise_session.Conn.SetDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadDeadline implements net.Conn
|
||||
func (*NoiseSession) SetReadDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
func (noise_session *NoiseSession) SetReadDeadline(t time.Time) error {
|
||||
return noise_session.Conn.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements net.Conn
|
||||
func (*NoiseSession) SetWriteDeadline(t time.Time) error {
|
||||
panic("unimplemented")
|
||||
func (noise_session *NoiseSession) SetWriteDeadline(t time.Time) error {
|
||||
return noise_session.Conn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
|
||||
@@ -59,27 +59,40 @@ func (s *NoiseSession) LocalAddr() net.Addr {
|
||||
return s.Conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (s *NoiseSession) QueueSendI2NP(msg i2np.I2NPMessage) {
|
||||
s.Queue.Enqueue(msg)
|
||||
}
|
||||
|
||||
func (s *NoiseSession) SendQueueSize() int {
|
||||
return s.Queue.Size()
|
||||
}
|
||||
|
||||
func (s *NoiseSession) ReadNextI2NP() (i2np.I2NPMessage, error) {
|
||||
return i2np.I2NPMessage{}, nil
|
||||
}
|
||||
|
||||
func (s *NoiseSession) Close() error {
|
||||
s.Queue.Clear()
|
||||
s.SendQueue.Clear()
|
||||
s.RecvQueue.Clear()
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewNoiseTransportSession(ri router_info.RouterInfo, socket net.Conn) (transport.TransportSession, error) {
|
||||
return &NoiseSession{
|
||||
Queue: cb.New(1024),
|
||||
RouterInfo: ri,
|
||||
Conn: socket,
|
||||
}, nil
|
||||
func (c *NoiseSession) processCallback(publicKey []byte, payload []byte) error {
|
||||
if c.VerifyCallback == nil {
|
||||
return nil
|
||||
}
|
||||
err := c.VerifyCallback(publicKey, payload)
|
||||
return err
|
||||
}
|
||||
|
||||
// newBlock allocates a new packet, from hc's free list if possible.
|
||||
func newBlock() []byte {
|
||||
return make([]byte, MaxPayloadSize)
|
||||
}
|
||||
|
||||
type VerifyCallbackFunc func(publicKey []byte, data []byte) error
|
||||
|
||||
func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSession, error) {
|
||||
//socket, err := DialNoise("noise", ri)
|
||||
for _, addr := range ri.RouterAddresses() {
|
||||
socket, err := net.Dial("tcp", string(addr.Bytes()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NoiseSession{
|
||||
SendQueue: cb.New(1024),
|
||||
RecvQueue: cb.New(1024),
|
||||
RouterInfo: ri,
|
||||
Conn: socket,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Transport constructor error")
|
||||
}
|
||||
|
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_info"
|
||||
"github.com/go-i2p/go-i2p/lib/transport"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type NoiseTransport struct {
|
||||
*noise.CipherState
|
||||
router_identity.RouterIdentity
|
||||
sync.Mutex
|
||||
router_identity.RouterIdentity
|
||||
*noise.CipherState
|
||||
Listener net.Listener
|
||||
peerConnections map[data.Hash]transport.TransportSession
|
||||
}
|
||||
@@ -33,24 +34,36 @@ var exampleNoiseTransport transport.Transport = &NoiseTransport{}
|
||||
// implements net.Listener
|
||||
var ExampleNoiseListener net.Listener = exampleNoiseTransport
|
||||
|
||||
// Accept a connection on a listening socket.
|
||||
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
|
||||
return noopt.Listener.Accept()
|
||||
}
|
||||
|
||||
// Addr of the transport, for now this is returning the IP:Port the transport is listening on,
|
||||
// but this might actually be the router identity
|
||||
func (noopt *NoiseTransport) Addr() net.Addr {
|
||||
return noopt.Listener.Addr()
|
||||
}
|
||||
|
||||
// Name of the transport TYPE, in this case `noise`
|
||||
func (noopt *NoiseTransport) Name() string {
|
||||
return "noise"
|
||||
}
|
||||
|
||||
// Set the router identity for this transport.
|
||||
// SetIdentity will set the router identity for this transport.
|
||||
// will bind if the underlying socket is not already
|
||||
// if the underlying socket is already bound update the RouterIdentity
|
||||
// returns any errors that happen if they do
|
||||
func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) error {
|
||||
func (noopt *NoiseTransport) SetIdentity(ident router_identity.RouterIdentity) (err error) {
|
||||
noopt.RouterIdentity = ident
|
||||
if noopt.Listener == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(NoiseTransport) SetIdentity",
|
||||
"reason": "network socket is null",
|
||||
}).Error("network socket is null")
|
||||
err = errors.New("network socket is null")
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,19 +76,34 @@ func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (tran
|
||||
if len(hash) == 0 {
|
||||
return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash")
|
||||
}
|
||||
if t, ok := noopt.peerConnections[hash]; ok == true {
|
||||
if t, ok := noopt.peerConnections[hash]; ok {
|
||||
return t, nil
|
||||
}
|
||||
conn, err := noopt.Accept()
|
||||
if err == nil {
|
||||
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo, conn); err != nil {
|
||||
return noopt.peerConnections[hash], err
|
||||
}
|
||||
var err error
|
||||
if noopt.peerConnections[hash], err = NewNoiseTransportSession(routerInfo); err != nil {
|
||||
return noopt.peerConnections[hash], err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return true if a routerInfo is compatable with this transport
|
||||
func (c *NoiseTransport) getSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
|
||||
session, err := c.GetSession(routerInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if session.(*NoiseSession).handshakeComplete {
|
||||
return nil, nil
|
||||
}
|
||||
if session.(*NoiseSession).Cond == nil {
|
||||
break
|
||||
}
|
||||
session.(*NoiseSession).Cond.Wait()
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// Compatable return true if a routerInfo is compatable with this transport
|
||||
func (noopt *NoiseTransport) Compatable(routerInfo router_info.RouterInfo) bool {
|
||||
_, ok := noopt.peerConnections[routerInfo.IdentHash()]
|
||||
return ok
|
||||
@@ -88,9 +116,20 @@ func (noopt *NoiseTransport) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewNoiseTransport create a NoiseTransport using a supplied net.Listener
|
||||
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
|
||||
return &NoiseTransport{
|
||||
peerConnections: make(map[data.Hash]transport.TransportSession),
|
||||
Listener: netSocket,
|
||||
}
|
||||
}
|
||||
|
||||
// NewNoiseTransportSocket creates a Noise transport socket with a random
|
||||
// host and port.
|
||||
func NewNoiseTransportSocket() (*NoiseTransport, error) {
|
||||
netSocket, err := net.Listen("tcp", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewNoiseTransport(netSocket), nil
|
||||
}
|
||||
|
@@ -11,6 +11,20 @@ func TestTransport(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
nt := NewNoiseTransport(ln)
|
||||
|
||||
t.Log(nt.Name())
|
||||
go func() {
|
||||
for {
|
||||
conn, err := nt.Accept()
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
conn.Write([]byte("World"))
|
||||
}
|
||||
}()
|
||||
lnn, err := net.Listen("tcp", ":42070")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
ntt := NewNoiseTransport(lnn)
|
||||
t.Log(ntt.Name())
|
||||
//ntt.GetSession()
|
||||
}
|
||||
|
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
|
||||
|
||||
import "github.com/go-i2p/go-i2p/lib/transport/noise"
|
||||
|
||||
// Session implements TransportSession
|
||||
// An established transport session
|
||||
type Session struct {
|
||||
}
|
||||
type Session noise.NoiseSession
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package ntcp
|
||||
|
||||
import "github.com/go-i2p/go-i2p/lib/transport/noise"
|
||||
|
||||
/**
|
||||
* https://geti2p.net/spec/ntcp2
|
||||
**/
|
||||
@@ -10,6 +12,5 @@ const (
|
||||
NTCP_MESSAGE_MAX_SIZE = 65537
|
||||
)
|
||||
|
||||
// Transport is an ntcp transport implementing transport.Transport interface
|
||||
type Transport struct {
|
||||
}
|
||||
// NTCPTransport is an ntcp transport implementing transport.Transport interface
|
||||
type NTCPTransport noise.NoiseTransport
|
||||
|
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
|
||||
i2p ssu transport implementation
|
||||
|
||||
*/
|
||||
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.
|
||||
//
|
||||
// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if
|
||||
// the type is DT_ROUTER it is the SHA256 of the router.
|
||||
// If the type is DT_TUNNEL, hash is the SHA256 of the gateway router, if
|
||||
// the type is DT_ROUTER it is the SHA256 of the router.
|
||||
func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error) {
|
||||
delivery_type, err := delivery_instructions.DeliveryType()
|
||||
if err != nil {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
i2p garlic tunnel implementation
|
||||
i2p garlic tunnel implementation
|
||||
*/
|
||||
package tunnel
|
||||
|
@@ -153,8 +153,10 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelI
|
||||
return decrypted_tunnel_message[4+16 : 4+4+16]
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the contents of a decrypted tunnel message that contain the data for the
|
||||
// DeliveryInstructions.
|
||||
//
|
||||
func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte {
|
||||
data_area := decrypted_tunnel_message[4+4+16:]
|
||||
for i := 0; i < len(data_area); i++ {
|
||||
@@ -165,8 +167,11 @@ func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData()
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions
|
||||
// in the tunnel message and their corresponding MessageFragment structures.
|
||||
//
|
||||
//
|
||||
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment {
|
||||
set := make([]DeliveryInstructionsWithFragment, 0)
|
||||
data := decrypted_tunnel_message.deliveryInstructionData()
|
||||
|
@@ -1,4 +1,3 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package signals
|
||||
|
@@ -1,4 +1,3 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package signals
|
||||
|
Reference in New Issue
Block a user