22 Commits

Author SHA1 Message Date
Haris Khan
8fa355f067 !WIP! router_timestamper 2024-09-29 22:03:30 -04:00
eyedeekay
0c7a3f0f22 force static builds for slightly easier debugging 2024-09-09 20:13:20 -04:00
eyedeekay
3d535f67a1 Work on curve25519 stuff so I can generate my own routerInfos instead of just sending crap to other people 2024-09-09 20:10:38 -04:00
eyedeekay
bba9350506 WOO some of the important fields are actually populated with correct values 2024-08-28 20:47:54 -04:00
eyedeekay
cbc0de4e7e Start working on de-obfuscating ephemeral keys from remote peers 2024-08-28 18:32:42 -04:00
eyedeekay
310ef07d3c generate godoc locally so I can go over it offline 2024-08-26 16:21:54 -04:00
eyedeekay
14fc6fc3a8 Work on noise tools, comment details of handshake stuff 2024-08-25 23:22:21 -04:00
eyedeekay
a3ce9d36c6 If string data is shorter than specified by length create a new string based on the content after the first byte 2024-07-08 10:46:16 -04:00
eyedeekay
58a43cdfaf Fix string length checks, sortof 2024-07-05 23:12:03 -04:00
eyedeekay
15a5ca5daf Try and make noise work and also fix some tests 2024-07-05 18:12:58 -04:00
eyedeekay
08a41686b6 Work on noise wrapper. It is now good enough to fail to connect to a remote I2P router in a way which is discernible on that remote router. 2024-07-03 01:19:31 -04:00
eyedeekay
8318fd8f57 Work on noise wrapper. It is now good enough to fail to connect to a remote I2P router in a way which is discernible on that remote router. 2024-07-03 01:17:36 -04:00
eyedeekay
9c0552e236 Make some netDb loading stuff work so I have RI's to talk to 2024-07-02 16:54:30 -04:00
eyedeekay
20b018a708 Make some netDb loading stuff work so I have RI's to talk to 2024-07-02 16:53:57 -04:00
eyedeekay
6c62faa49b finish stubbing out noise transport stuff 2024-07-01 21:37:05 -04:00
eyedeekay
a7e31b7833 implement more noise stuff 2024-07-01 21:34:09 -04:00
eyedeekay
c09161c824 check in beginnings of new cleaned-up noise prototype 2024-07-01 18:50:13 -04:00
eyedeekay
aca62174e6 Load RI's into netDb struct for later referencing 2024-06-30 23:14:48 -04:00
eyedeekay
bd27f00959 add my unzip fork which fixes the permissions bug 2024-06-29 00:36:11 -04:00
eyedeekay
05c4d3d973 add my unzip fork which fixes the permissions bug 2024-06-29 00:25:23 -04:00
eyedeekay
40d0ea5ff5 Start making it so I can configure things, so I can configure it to read the netDb I already have and attempt to make a connection. Implement a reseed puller, or at least most of one. 2024-06-29 00:23:55 -04:00
eyedeekay
58e8f78c56 Start making it so I can configure things, so I can configure it to read the netDb I already have and attempt to make a connection. Implement a reseed puller, or at least most of one. 2024-06-29 00:23:42 -04:00
114 changed files with 6213 additions and 802 deletions

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@
go-i2p go-i2p
*.exe *.exe
.idea/ .idea/
router.info
log

View File

@@ -2,6 +2,7 @@ RELEASE_TAG=0.0.1
RELEASE_VERSION=${RELEASE_TAG} RELEASE_VERSION=${RELEASE_TAG}
RELEASE_DESCRIPTION=`cat PASTA.md` RELEASE_DESCRIPTION=`cat PASTA.md`
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
CGO_ENABLED=0
ifdef GOROOT ifdef GOROOT
GO = $(GOROOT)/bin/go GO = $(GOROOT)/bin/go
@@ -18,16 +19,16 @@ endif
build: clean $(EXE) build: clean $(EXE)
$(EXE): $(EXE):
$(GO) build -v -o $(EXE) $(GO) build --tags netgo,osusergo -v -o $(EXE)
test: fmt test: fmt
$(GO) test -vv -failfast ./lib/common/... $(GO) test -v -failfast ./lib/common/...
clean: clean:
$(GO) clean -v $(GO) clean -v
fmt: fmt:
find . -name '*.go' -exec gofmt -w -s {} \; find . -name '*.go' -exec gofumpt -w {} \;
info: info:
echo "GOROOT: ${GOROOT}" echo "GOROOT: ${GOROOT}"
@@ -36,3 +37,9 @@ info:
release: release:
github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p
callvis:
go-callvis -format svg -focus upgrade -group pkg,type -limit github.com/go-i2p/go-i2p github.com/go-i2p/go-i2p
godoc:
find lib -type d -exec bash -c "ls {}/*.go && godocdown -o ./{}/doc.md ./{}" \;

View File

@@ -41,7 +41,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Elligator2 - [ ] Elligator2
- [ ] HKDF - [ ] HKDF
- [ ] HMAC - [ ] HMAC
- [ ] Noise subsystem - [/] Noise subsystem
- End-to-End Crypto - End-to-End Crypto
- [ ] Garlic messages - [ ] Garlic messages
- [ ] ElGamal/AES+SessionTag - [ ] ElGamal/AES+SessionTag
@@ -50,7 +50,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Message parsing - [ ] Message parsing
- [ ] Message handling - [ ] Message handling
- NetDB - NetDB
- [ ] Local storage - [/] Local storage
- [/] Persistence to disk - [/] Persistence to disk
- [X] Reseeding - [X] Reseeding
- [ ] Lookups - [ ] Lookups
@@ -79,7 +79,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Tunnel Message Crypto - [ ] Tunnel Message Crypto
- [ ] Tunnel Message Fragmentation/Reassembly - [ ] Tunnel Message Fragmentation/Reassembly
- Common Data Structures - Common Data Structures
- [/] Keys and Cert - [X] Keys and Cert
- [X] Key Certificates - [X] Key Certificates
- [X] Certificate - [X] Certificate
- [X] Lease - [X] Lease

21
go.mod
View File

@@ -1,11 +1,24 @@
module github.com/go-i2p/go-i2p module github.com/go-i2p/go-i2p
go 1.16 go 1.22
toolchain go1.22.5
require ( require (
github.com/emirpasic/gods v1.18.1 github.com/beevik/ntp v1.4.3
github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e
github.com/flynn/noise v1.1.0 github.com/flynn/noise v1.1.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.23.0 go.step.sm/crypto v0.51.2
golang.org/x/crypto v0.26.0
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.24.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )

62
go.sum
View File

@@ -1,8 +1,12 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e h1:NMjWYVkgcQHGOy0/VxU0TU6smrcoxzj9hwDesx2sB0w=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e/go.mod h1:fKfFM3BsOOyjtZmEty7FsGzGabXo8Eb/dHjyIhTtxsE=
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= 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.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
@@ -15,57 +19,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 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.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.step.sm/crypto v0.51.2 h1:5EiCGIMg7IvQTGmJrwRosbXeprtT80OhoS/PJarg60o=
go.step.sm/crypto v0.51.2/go.mod h1:QK7czLjN2k+uqVp5CHXxJbhc70kVRSP+0CQF3zsR5M0=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

23
lib/bootstrap/doc.md Normal file
View File

@@ -0,0 +1,23 @@
# bootstrap
--
import "github.com/go-i2p/go-i2p/lib/bootstrap"
provides generic interfaces for initial bootstrap into network and network
### reseeding
## Usage
#### type Bootstrap
```go
type Bootstrap interface {
// get more peers for bootstrap
// try obtaining at most n router infos
// if n is 0 then try obtaining as many router infos as possible
// returns nil and error if we cannot fetch ANY router infos
// returns a channel that yields 1 slice of router infos containing n or fewer router infos, caller must close channel after use
GetPeers(n int) (chan []router_info.RouterInfo, error)
}
```
interface defining a way to bootstrap into the i2p network

33
lib/common/base32/doc.md Normal file
View File

@@ -0,0 +1,33 @@
# base32
--
import "github.com/go-i2p/go-i2p/lib/common/base32"
Package base32 implmenets utilities for encoding and decoding text using I2P's
### alphabet
## Usage
```go
const I2PEncodeAlphabet = "abcdefghijklmnopqrstuvwxyz234567"
```
I2PEncodeAlphabet is the base32 encoding used throughout I2P. RFC 3548 using
lowercase characters.
```go
var I2PEncoding *b32.Encoding = b32.NewEncoding(I2PEncodeAlphabet)
```
I2PEncoding is the standard base32 encoding used through I2P.
#### func DecodeString
```go
func DecodeString(data string) ([]byte, error)
```
DecodeString decodes base64 string to []byte I2PEncoding
#### func EncodeToString
```go
func EncodeToString(data []byte) string
```
EncodeToString encodes []byte to a base32 string using I2PEncoding

33
lib/common/base64/doc.md Normal file
View File

@@ -0,0 +1,33 @@
# base64
--
import "github.com/go-i2p/go-i2p/lib/common/base64"
Package base64 implmenets utilities for encoding and decoding text using I2P's
### alphabet
## Usage
```go
const I2PEncodeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"
```
I2PEncodeAlphabet is the base64 encoding used throughout I2P. RFC 4648 with "/""
replaced with "~", and "+" replaced with "-".
```go
var I2PEncoding *b64.Encoding = b64.NewEncoding(I2PEncodeAlphabet)
```
I2PEncoding is the standard base64 encoding used through I2P.
#### func DecodeString
```go
func DecodeString(str string) ([]byte, error)
```
DecodeString decodes base64 string to []byte I2PEncoding
#### func EncodeToString
```go
func EncodeToString(data []byte) string
```
I2PEncoding is the standard base64 encoding used through I2P.

View File

@@ -75,7 +75,10 @@ func (c *Certificate) RawBytes() []byte {
// ExcessBytes returns the excess bytes in a certificate found after the specified payload length. // ExcessBytes returns the excess bytes in a certificate found after the specified payload length.
func (c *Certificate) ExcessBytes() []byte { func (c *Certificate) ExcessBytes() []byte {
return c.payload[c.len.Int():] if len(c.payload) >= c.len.Int() {
return c.payload[c.len.Int():]
}
return nil
} }
// Bytes returns the entire certificate in []byte form, trims payload to specified length. // Bytes returns the entire certificate in []byte form, trims payload to specified length.
@@ -116,8 +119,8 @@ func (c *Certificate) Data() (data []byte) {
// NewCertificate creates a new Certficiate from []byte // NewCertificate creates a new Certficiate from []byte
// returns err if the certificate is too short or if the payload doesn't match specified length. // returns err if the certificate is too short or if the payload doesn't match specified length.
func NewCertificate(data []byte) (certificate *Certificate, err error) { func NewCertificate(data []byte) (certificate Certificate, err error) {
certificate = &Certificate{} certificate = Certificate{}
switch len(data) { switch len(data) {
case 0: case 0:
certificate.kind = Integer([]byte{0}) certificate.kind = Integer([]byte{0})
@@ -129,8 +132,8 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
}).Error("invalid certificate, empty") }).Error("invalid certificate, empty")
err = fmt.Errorf("error parsing certificate: certificate is empty") err = fmt.Errorf("error parsing certificate: certificate is empty")
return return
case 1 , 2: case 1, 2:
certificate.kind = Integer(data[0:len(data)-1]) certificate.kind = Integer(data[0 : len(data)-1])
certificate.len = Integer([]byte{0}) certificate.len = Integer([]byte{0})
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Certificate) NewCertificate", "at": "(Certificate) NewCertificate",
@@ -163,7 +166,7 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
// ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input. // ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input.
// returns err if the certificate could not be read. // returns err if the certificate could not be read.
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) { func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) {
certificate, err = NewCertificate(data) certificate, err = NewCertificate(data)
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" { if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
err = nil err = nil

View File

@@ -32,12 +32,12 @@ func TestCertificateLengthErrWhenTooShort(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
bytes := []byte{0x03, 0x01} bytes := []byte{0x03, 0x01}
certificate, err := NewCertificate(bytes) certificate, _, err := ReadCertificate(bytes)
cert_len := certificate.Length() cert_len := certificate.Length()
assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data") assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data")
if assert.NotNil(err) { if assert.NotNil(err) {
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned") assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
} }
} }
@@ -71,13 +71,10 @@ func TestCertificateDataWhenTooLong(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa} bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
certificate, err := NewCertificate(bytes) certificate, _, _ := ReadCertificate(bytes)
cert_data := certificate.Data() cert_data := certificate.Data()
if assert.NotNil(err) { cert_len := certificate.Length() // len(cert_data)
assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned")
}
cert_len := certificate.Length() //len(cert_data)
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long") assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
if cert_data[0] != 0xff || cert_data[1] != 0xff { if cert_data[0] != 0xff || cert_data[1] != 0xff {
t.Fatal("certificate.Data() returned incorrect data when data was too long") t.Fatal("certificate.Data() returned incorrect data when data was too long")
@@ -144,6 +141,6 @@ func TestReadCertificateWithInvalidLength(t *testing.T) {
assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid") assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid")
assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate") assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate")
if assert.NotNil(err) { if assert.NotNil(err) {
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned") assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
} }
} }

View File

@@ -0,0 +1,98 @@
# certificate
--
import "github.com/go-i2p/go-i2p/lib/common/certificate"
## Usage
```go
const (
CERT_NULL = iota
CERT_HASHCASH
CERT_HIDDEN
CERT_SIGNED
CERT_MULTIPLE
CERT_KEY
)
```
Certificate Types
```go
const CERT_MIN_SIZE = 3
```
CERT_MIN_SIZE is the minimum size of a valid Certificate in []byte 1 byte for
type 2 bytes for payload length
#### type Certificate
```go
type Certificate struct {
}
```
Certificate is the representation of an I2P Certificate.
https://geti2p.net/spec/common-structures#certificate
#### func NewCertificate
```go
func NewCertificate(data []byte) (certificate Certificate, err error)
```
NewCertificate creates a new Certficiate from []byte returns err if the
certificate is too short or if the payload doesn't match specified length.
#### func ReadCertificate
```go
func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error)
```
ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at
the end of the input. returns err if the certificate could not be read.
#### func (*Certificate) Bytes
```go
func (c *Certificate) Bytes() []byte
```
Bytes returns the entire certificate in []byte form, trims payload to specified
length.
#### func (*Certificate) Data
```go
func (c *Certificate) Data() (data []byte)
```
Data returns the payload of a Certificate, payload is trimmed to the specified
length.
#### func (*Certificate) ExcessBytes
```go
func (c *Certificate) ExcessBytes() []byte
```
ExcessBytes returns the excess bytes in a certificate found after the specified
payload length.
#### func (*Certificate) Length
```go
func (c *Certificate) Length() (length int)
```
Length returns the payload length of a Certificate.
#### func (*Certificate) RawBytes
```go
func (c *Certificate) RawBytes() []byte
```
RawBytes returns the entire certificate in []byte form, includes excess payload
data.
#### func (*Certificate) Type
```go
func (c *Certificate) Type() (cert_type int)
```
Type returns the Certificate type specified in the first byte of the
Certificate,

297
lib/common/data/doc.md Normal file
View File

@@ -0,0 +1,297 @@
# data
--
import "github.com/go-i2p/go-i2p/lib/common/data"
Package data implements common data structures used in higher level structures.
## Usage
```go
const DATE_SIZE = 8
```
DATE_SIZE is the length in bytes of an I2P Date.
```go
const MAX_INTEGER_SIZE = 8
```
MAX_INTEGER_SIZE is the maximum length of an I2P integer in bytes.
```go
const STRING_MAX_SIZE = 255
```
STRING_MAX_SIZE is the maximum number of bytes that can be stored in an I2P
string
#### func PrintErrors
```go
func PrintErrors(errs []error)
```
PrintErrors prints a formatted list of errors to the console.
#### func WrapErrors
```go
func WrapErrors(errs []error) error
```
WrapErrors compiles a slice of errors and returns them wrapped together as a
single error.
#### type Date
```go
type Date [8]byte
```
Date is the represenation of an I2P Date.
https://geti2p.net/spec/common-structures#date
#### func NewDate
```go
func NewDate(data []byte) (date *Date, remainder []byte, err error)
```
NewDate creates a new Date from []byte using ReadDate. Returns a pointer to Date
unlike ReadDate.
#### func ReadDate
```go
func ReadDate(data []byte) (date Date, remainder []byte, err error)
```
ReadDate creates a Date from []byte using the first DATE_SIZE bytes. Any data
after DATE_SIZE is returned as a remainder.
#### func (Date) Bytes
```go
func (i Date) Bytes() []byte
```
Bytes returns the raw []byte content of a Date.
#### func (Date) Int
```go
func (i Date) Int() int
```
Int returns the Date as a Go integer.
#### func (Date) Time
```go
func (date Date) Time() (date_time time.Time)
```
Time takes the value stored in date as an 8 byte big-endian integer representing
the number of milliseconds since the beginning of unix time and converts it to a
Go time.Time struct.
#### type Hash
```go
type Hash [32]byte
```
Hash is the represenation of an I2P Hash.
https://geti2p.net/spec/common-structures#hash
#### func HashData
```go
func HashData(data []byte) (h Hash)
```
HashData returns the SHA256 sum of a []byte input as Hash.
#### func HashReader
```go
func HashReader(r io.Reader) (h Hash, err error)
```
HashReader returns the SHA256 sum from all data read from an io.Reader. return
error if one occurs while reading from reader
#### func (Hash) Bytes
```go
func (h Hash) Bytes() [32]byte
```
#### type I2PString
```go
type I2PString []byte
```
I2PString is the represenation of an I2P String.
https://geti2p.net/spec/common-structures#string
#### func ReadI2PString
```go
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error)
```
ReadI2PString returns I2PString from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.
#### func ToI2PString
```go
func ToI2PString(data string) (str I2PString, err error)
```
ToI2PString converts a Go string to an I2PString. Returns error if the string
exceeds STRING_MAX_SIZE.
#### func (I2PString) Data
```go
func (str I2PString) Data() (data string, err error)
```
Data returns the I2PString content as a string trimmed to the specified length
and not including the length byte. Returns error encountered by Length.
#### func (I2PString) Length
```go
func (str I2PString) Length() (length int, err error)
```
Length returns the length specified in the first byte. Returns error if the
specified does not match the actual length or the string is otherwise invalid.
#### type Integer
```go
type Integer []byte
```
Integer is the represenation of an I2P Integer.
https://geti2p.net/spec/common-structures#integer
#### func NewInteger
```go
func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err error)
```
NewInteger creates a new Integer from []byte using ReadInteger. Limits the
length of the created Integer to MAX_INTEGER_SIZE. Returns a pointer to Integer
unlike ReadInteger.
#### func NewIntegerFromInt
```go
func NewIntegerFromInt(value int, size int) (integer *Integer, err error)
```
NewIntegerFromInt creates a new Integer from a Go integer of a specified []byte
length.
#### func ReadInteger
```go
func ReadInteger(bytes []byte, size int) (Integer, []byte)
```
ReadInteger returns an Integer from a []byte of specified length. The remaining
bytes after the specified length are also returned.
#### func (Integer) Bytes
```go
func (i Integer) Bytes() []byte
```
Bytes returns the raw []byte content of an Integer.
#### func (Integer) Int
```go
func (i Integer) Int() int
```
Int returns the Date as a Go integer
#### type Mapping
```go
type Mapping struct {
}
```
Mapping is the represenation of an I2P Mapping.
https://geti2p.net/spec/common-structures#mapping
#### func GoMapToMapping
```go
func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error)
```
GoMapToMapping converts a Go map of unformatted strings to *Mapping.
#### func NewMapping
```go
func NewMapping(bytes []byte) (values *Mapping, remainder []byte, err []error)
```
NewMapping creates a new *Mapping from []byte using ReadMapping. Returns a
pointer to Mapping unlike ReadMapping.
#### func ReadMapping
```go
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
```
ReadMapping returns Mapping from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.
#### func ValuesToMapping
```go
func ValuesToMapping(values MappingValues) *Mapping
```
ValuesToMapping creates a *Mapping using MappingValues. The values are sorted in
the order defined in mappingOrder.
#### func (*Mapping) Data
```go
func (mapping *Mapping) Data() []byte
```
Data returns a Mapping in its []byte form.
#### func (*Mapping) HasDuplicateKeys
```go
func (mapping *Mapping) HasDuplicateKeys() bool
```
HasDuplicateKeys returns true if two keys in a mapping are identical.
#### func (Mapping) Values
```go
func (mapping Mapping) Values() MappingValues
```
Values returns the values contained in a Mapping as MappingValues.
#### type MappingValues
```go
type MappingValues [][2]I2PString
```
MappingValues represents the parsed key value pairs inside of an I2P Mapping.
#### func ReadMappingValues
```go
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error)
```
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 (MappingValues) Get
```go
func (m MappingValues) Get(key I2PString) I2PString
```

View File

@@ -23,8 +23,13 @@ Contents
// https://geti2p.net/spec/common-structures#hash // https://geti2p.net/spec/common-structures#hash
type Hash [32]byte type Hash [32]byte
func (h Hash) Bytes() [32]byte {
return h
}
// HashData returns the SHA256 sum of a []byte input as Hash. // HashData returns the SHA256 sum of a []byte input as Hash.
func HashData(data []byte) (h Hash) { func HashData(data []byte) (h Hash) {
// log.Println("Hashing Data:", data)
h = sha256.Sum256(data) h = sha256.Sum256(data)
return return
} }

View File

@@ -27,7 +27,6 @@ func TestValuesExclusesPairWithBadData(t *testing.T) {
assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key") assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key")
assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key") assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key")
} }
} }
func TestValuesWarnsMissingData(t *testing.T) { func TestValuesWarnsMissingData(t *testing.T) {

View File

@@ -58,9 +58,9 @@ func mappingOrder(values MappingValues) {
// The remaining bytes after the specified length are also returned. // The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing. // Returns a list of errors that occurred during parsing.
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) { func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
//mapping := remainder // mapping := remainder
//var remainder = mapping // var remainder = mapping
//var err error // var err error
if remainder == nil || len(remainder) < 1 { if remainder == nil || len(remainder) < 1 {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Mapping) Values", "at": "(Mapping) Values",
@@ -92,7 +92,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
encounteredKeysMap := map[string]bool{} encounteredKeysMap := map[string]bool{}
// pop off length bytes before parsing kv pairs // pop off length bytes before parsing kv pairs
//remainder = remainder[2:] // remainder = remainder[2:]
for { for {
// Read a key, breaking on fatal errors // Read a key, breaking on fatal errors
@@ -116,12 +116,12 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
if err != nil { if err != nil {
if stopValueRead(err) { if stopValueRead(err) {
errs = append(errs, err) errs = append(errs, err)
//return // return
} }
} }
// overwriting remainder with more as another var to prevent memory weirdness in loops // overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder) // log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// Check if key has already been encountered in this mapping // Check if key has already been encountered in this mapping
keyBytes, _ := key_str.Data() keyBytes, _ := key_str.Data()
@@ -160,13 +160,13 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
if err != nil { if err != nil {
if stopValueRead(err) { if stopValueRead(err) {
errs = append(errs, err) errs = append(errs, err)
//return // return
} }
} }
// overwriting remainder with more as another var to prevent memory weirdness in loops // overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder) // log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
//log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str) // log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
if !beginsWith(remainder, 0x3b) { if !beginsWith(remainder, 0x3b) {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Mapping) Values", "at": "(Mapping) Values",
@@ -190,5 +190,4 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
} }
values = &map_values values = &map_values
return return
} }

View File

@@ -2,6 +2,7 @@ package data
import ( import (
"errors" "errors"
"fmt"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@@ -38,16 +39,20 @@ func (str I2PString) Length() (length int, err error) {
err = errors.New("error parsing string: zero length") err = errors.New("error parsing string: zero length")
return return
} }
l, _, _ := NewInteger(str, 1) l, _, err := NewInteger(str[:], 1)
if err != nil {
return l.Int(), err
}
length = l.Int() length = l.Int()
str_len := len(str) - 1 str_len := len(str)
if length != str_len { if length > str_len {
log.WithFields(log.Fields{ /*log.WithFields(log.Fields{
"at": "(I2PString) Length", "at": "(I2PString) Length",
"string_bytes_length": str_len, "string_bytes_length": str_len,
"string_length_field": length, "string_length_field": length,
"data": string(str),
"reason": "data less than specified by length", "reason": "data less than specified by length",
}).Error("string format warning") }).Error("string format warning")*/
err = errors.New("string parsing warning: string data is shorter than specified by length") err = errors.New("string parsing warning: string data is shorter than specified by length")
} }
return return
@@ -62,8 +67,11 @@ func (str I2PString) Data() (data string, err error) {
case "error parsing string: zero length": case "error parsing string: zero length":
return return
case "string parsing warning: string data is shorter than specified by length": case "string parsing warning: string data is shorter than specified by length":
data = string(str[1:]) if is, e := ToI2PString(string(str[:])); e != nil {
return return "", e
} else {
return is.Data()
}
case "string parsing warning: string contains data beyond length": case "string parsing warning: string contains data beyond length":
data = string(str[1:]) data = string(str[1:])
return return
@@ -109,17 +117,21 @@ func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
if err != nil { if err != nil {
return return
} }
data_len := length.Int() data_len := length.Int() + 1
str = data[:data_len+1] str = data[:data_len]
remainder = data[data_len+1:] remainder = data[data_len:]
_, err = str.Length() l, err := str.Length()
if l != data_len-1 {
err = fmt.Errorf("error reading I2P string, length does not match data")
return
}
return return
} }
// NewI2PString creates a new *I2PString from []byte using ReadI2PString. // NewI2PString creates a new *I2PString from []byte using ReadI2PString.
// Returns a pointer to I2PString unlike ReadI2PString. // Returns a pointer to I2PString unlike ReadI2PString.
func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) { /*func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
objstr, remainder, err := ReadI2PString(data) objstr, remainder, err := ReadI2PString(data)
str = &objstr str = &objstr
return return
} }*/

View File

@@ -26,7 +26,7 @@ Identical to KeysAndCert.
// //
// https://geti2p.net/spec/common-structures#destination // https://geti2p.net/spec/common-structures#destination
type Destination struct { type Destination struct {
*KeysAndCert KeysAndCert
} }
// Base32Address returns the I2P base32 address for this Destination. // Base32Address returns the I2P base32 address for this Destination.
@@ -48,17 +48,9 @@ func (destination Destination) Base64() string {
// The remaining bytes after the specified length are also returned. // The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing. // Returns a list of errors that occurred during parsing.
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) { func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
keys_and_cert, remainder, err := NewKeysAndCert(data) keys_and_cert, remainder, err := ReadKeysAndCert(data)
destination = Destination{ destination = Destination{
keys_and_cert, keys_and_cert,
} }
return return
} }
// NewDestination creates a new *Destination from []byte using ReadDestination.
// Returns a pointer to Destination unlike ReadDestination.
func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) {
objdestination, remainder, err := ReadDestination(data)
destination = &objdestination
return destination, remainder, err
}

View File

@@ -0,0 +1,42 @@
# destination
--
import "github.com/go-i2p/go-i2p/lib/common/destination"
Package destination implements the I2P Destination common data structure
## Usage
#### type Destination
```go
type Destination struct {
KeysAndCert
}
```
Destination is the represenation of an I2P Destination.
https://geti2p.net/spec/common-structures#destination
#### func ReadDestination
```go
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error)
```
ReadDestination returns Destination from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.
#### func (Destination) Base32Address
```go
func (destination Destination) Base32Address() (str string)
```
Base32Address returns the I2P base32 address for this Destination.
#### func (Destination) Base64
```go
func (destination Destination) Base64() string
```
Base64 returns the I2P base64 address for this Destination.

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/certificate"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/destination"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/keys_and_cert"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

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

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/router_address"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/router_identity"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/common/fuzz/string"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

View File

@@ -0,0 +1,154 @@
# key_certificate
--
import "github.com/go-i2p/go-i2p/lib/common/key_certificate"
Package key_certificate implements the I2P Destination common data structure
## Usage
```go
const (
KEYCERT_SIGN_DSA_SHA1 = iota
KEYCERT_SIGN_P256
KEYCERT_SIGN_P384
KEYCERT_SIGN_P521
KEYCERT_SIGN_RSA2048
KEYCERT_SIGN_RSA3072
KEYCERT_SIGN_RSA4096
KEYCERT_SIGN_ED25519
KEYCERT_SIGN_ED25519PH
)
```
Key Certificate Signing Key Types
```go
const (
KEYCERT_CRYPTO_ELG = iota
KEYCERT_CRYPTO_P256
KEYCERT_CRYPTO_P384
KEYCERT_CRYPTO_P521
KEYCERT_CRYPTO_X25519
)
```
Key Certificate Public Key Types
```go
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
KEYCERT_SIGN_P384_SIZE = 96
KEYCERT_SIGN_P521_SIZE = 132
KEYCERT_SIGN_RSA2048_SIZE = 256
KEYCERT_SIGN_RSA3072_SIZE = 384
KEYCERT_SIGN_RSA4096_SIZE = 512
KEYCERT_SIGN_ED25519_SIZE = 32
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
```
SigningPublicKey sizes for Signing Key Types
```go
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
)
```
PublicKey sizes for Public Key Types
```go
const (
KEYCERT_PUBKEY_SIZE = 256
KEYCERT_SPK_SIZE = 128
)
```
Sizes of structures in KeyCertificates
```go
const (
KEYCERT_MIN_SIZE = 7
)
```
#### type KeyCertificate
```go
type KeyCertificate struct {
Certificate
}
```
type KeyCertificate []byte
#### func KeyCertificateFromCertificate
```go
func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate
```
KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
#### func NewKeyCertificate
```go
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error)
```
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 (KeyCertificate) ConstructPublicKey
```go
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error)
```
ConstructPublicKey returns a PublicKey constructed using any excess data that
may be stored in the KeyCertififcate. Returns enr errors encountered while
parsing.
#### func (KeyCertificate) ConstructSigningPublicKey
```go
func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error)
```
ConstructSigningPublicKey returns a SingingPublicKey constructed using any
excess data that may be stored in the KeyCertificate. Returns any errors
encountered while parsing.
#### func (KeyCertificate) CryptoSize
```go
func (key_certificate KeyCertificate) CryptoSize() (size int)
```
CryptoSize return the size of a Public Key corresponding to the Key
Certificate's PublicKey type.
#### func (KeyCertificate) Data
```go
func (key_certificate KeyCertificate) Data() ([]byte, error)
```
Data returns the raw []byte contained in the Certificate.
#### func (KeyCertificate) PublicKeyType
```go
func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int)
```
PublicKeyType returns the PublicKey type as a Go integer.
#### func (KeyCertificate) SignatureSize
```go
func (key_certificate KeyCertificate) SignatureSize() (size int)
```
SignatureSize return the size of a Signature corresponding to the Key
Certificate's SigningPublicKey type.
#### func (KeyCertificate) SigningPublicKeyType
```go
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int)
```
SigningPublicKeyType returns the SigningPublicKey type as a Go integer.

View File

@@ -92,7 +92,7 @@ const (
// type KeyCertificate []byte // type KeyCertificate []byte
type KeyCertificate struct { type KeyCertificate struct {
*Certificate Certificate
spkType Integer spkType Integer
cpkType Integer cpkType Integer
} }
@@ -181,11 +181,11 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra]) copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra])
signing_public_key = ec_key signing_public_key = ec_key
case KEYCERT_SIGN_RSA2048: case KEYCERT_SIGN_RSA2048:
//var rsa_key crypto.RSA2048PublicKey // var rsa_key crypto.RSA2048PublicKey
//extra := KEYCERT_SIGN_RSA2048_SIZE - 128 // extra := KEYCERT_SIGN_RSA2048_SIZE - 128
//copy(rsa_key[:], data) // copy(rsa_key[:], data)
//copy(rsa_key[128:], key_certificate[4:4+extra]) // copy(rsa_key[128:], key_certificate[4:4+extra])
//signing_public_key = rsa_key // signing_public_key = rsa_key
case KEYCERT_SIGN_RSA3072: case KEYCERT_SIGN_RSA3072:
case KEYCERT_SIGN_RSA4096: case KEYCERT_SIGN_RSA4096:
case KEYCERT_SIGN_ED25519: case KEYCERT_SIGN_ED25519:
@@ -228,25 +228,29 @@ func (key_certificate KeyCertificate) CryptoSize() (size int) {
// The remaining bytes after the specified length are also returned. // The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing. // Returns a list of errors that occurred during parsing.
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) { func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
var certificate *Certificate var certificate Certificate
certificate, remainder, err = ReadCertificate(bytes) certificate, remainder, err = ReadCertificate(bytes)
if err != nil { if err != nil {
return return
} }
if len(bytes) < KEYCERT_MIN_SIZE { if len(bytes) < KEYCERT_MIN_SIZE {
err = errors.New("error parsing key certificate: not enough data") err = errors.New("error parsing key certificate: not enough data")
remainder = bytes[KEYCERT_MIN_SIZE:]
} }
key_certificate = &KeyCertificate{ key_certificate = &KeyCertificate{
Certificate: certificate, Certificate: certificate,
spkType: Integer(bytes[4:5]),
cpkType: Integer(bytes[6:7]),
} }
remainder = bytes[KEYCERT_MIN_SIZE:] if len(bytes) >= 5 {
key_certificate.spkType = Integer(bytes[4:5])
}
if len(bytes) >= 7 {
key_certificate.cpkType = Integer(bytes[6:7])
}
return return
} }
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate. // KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
func KeyCertificateFromCertificate(certificate *Certificate) *KeyCertificate { func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate {
k, _, _ := NewKeyCertificate(certificate.RawBytes()) k, _, _ := NewKeyCertificate(certificate.RawBytes())
return k return k
} }

View File

@@ -0,0 +1,66 @@
# keys_and_cert
--
import "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
Package keys_and_cert implements the I2P KeysAndCert common data structure
## Usage
```go
const (
KEYS_AND_CERT_PUBKEY_SIZE = 256
KEYS_AND_CERT_SPK_SIZE = 128
KEYS_AND_CERT_MIN_SIZE = 387
KEYS_AND_CERT_DATA_SIZE = 384
)
```
Sizes of various KeysAndCert structures and requirements
#### type KeysAndCert
```go
type KeysAndCert struct {
KeyCertificate *KeyCertificate
}
```
KeysAndCert is the represenation of an I2P KeysAndCert.
https://geti2p.net/spec/common-structures#keysandcert
#### func ReadKeysAndCert
```go
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error)
```
ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
#### func (KeysAndCert) Bytes
```go
func (keys_and_cert KeysAndCert) Bytes() []byte
```
Bytes returns the entire KeyCertificate in []byte form, trims payload to
specified length.
#### func (*KeysAndCert) Certificate
```go
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate)
```
Certfificate returns the certificate.
#### func (*KeysAndCert) PublicKey
```go
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey)
```
PublicKey returns the public key as a crypto.PublicKey.
#### func (*KeysAndCert) SigningPublicKey
```go
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey)
```
SigningPublicKey returns the signing public key.

View File

@@ -79,97 +79,30 @@ type KeysAndCert struct {
} }
// Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length. // Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length.
func (keys_and_cert *KeysAndCert) Bytes() []byte { func (keys_and_cert KeysAndCert) Bytes() []byte {
return keys_and_cert.KeyCertificate.Bytes() return keys_and_cert.KeyCertificate.Bytes()
} }
// PublicKey returns the public key as a crypto.PublicKey. // PublicKey returns the public key as a crypto.PublicKey.
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) { func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
/*cert := keys_and_cert.Certificate()
cert_len := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
} else {
// A Certificate is present in this KeysAndCert
cert_type := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a PublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
key, err = KeyCertificateFromCertificate(cert).ConstructPublicKey(
keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey. No other Certificate
// types are currently in use.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
log.WithFields(log.Fields{
"at": "(KeysAndCert) PublicKey",
"cert_type": cert_type,
}).Warn("unused certificate type observed")
}
}
return*/
return keys_and_cert.publicKey return keys_and_cert.publicKey
} }
// SigningPublicKey returns the signing public key. // SigningPublicKey returns the signing public key.
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) { func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
/*cert := keys_and_cert.Certificate()
cert_len := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
} else {
// A Certificate is present in this KeysAndCert
cert_type := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a SigningPublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey(
keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy SHA DSA1 SigningPublicKey.
// No other Certificate types are currently in use.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
}
}*/
return keys_and_cert.signingPublicKey return keys_and_cert.signingPublicKey
} }
// Certfificate returns the certificate. // Certfificate returns the certificate.
func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) { func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) {
return keys_and_cert.KeyCertificate.Certificate return keys_and_cert.KeyCertificate.Certificate
} }
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert. // ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert. // Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) { func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
data_len := len(data) data_len := len(data)
keys_and_cert = &KeysAndCert{} // keys_and_cert = KeysAndCert{}
if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE { if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "ReadKeysAndCert", "at": "ReadKeysAndCert",
@@ -192,20 +125,20 @@ func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte,
} }
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:]) keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
if err != nil { if err != nil {
return nil, nil, err return
} }
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same. // 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 // 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. // 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()]) keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
if err != nil { if err != nil {
return nil, nil, err return
} }
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]) 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 { if err != nil {
return nil, nil, err return
} }
padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE] padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE]
keys_and_cert.padding = padding keys_and_cert.padding = padding
return keys_and_cert, remainder, err return
} }

View File

@@ -24,7 +24,7 @@ func TestCertificateWithValidData(t *testing.T) {
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00} cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
data := make([]byte, 128+256) data := make([]byte, 128+256)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
assert.Nil(err) assert.Nil(err)
cert := keys_and_cert.Certificate() cert := keys_and_cert.Certificate()
@@ -43,7 +43,7 @@ func TestPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 128) data := make([]byte, 128)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey() pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) { if assert.NotNil(err) {
@@ -60,7 +60,7 @@ func TestPublicKeyWithBadCertificate(t *testing.T) {
data := make([]byte, 128) data := make([]byte, 128)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey() pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) { if assert.NotNil(err) {
@@ -77,7 +77,7 @@ func TestPublicKeyWithNullCertificate(t *testing.T) {
data := make([]byte, 128) data := make([]byte, 128)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey() pub_key := keys_and_cert.PublicKey()
assert.Nil(err) assert.Nil(err)
@@ -92,7 +92,7 @@ func TestPublicKeyWithKeyCertificate(t *testing.T) {
data := make([]byte, 128) data := make([]byte, 128)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey() pub_key := keys_and_cert.PublicKey()
assert.Nil(err) assert.Nil(err)
@@ -107,7 +107,7 @@ func TestSigningPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 93) data := make([]byte, 93)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey() signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) { if assert.NotNil(err) {
@@ -124,7 +124,7 @@ func TestSigningPublicKeyWithBadCertificate(t *testing.T) {
data := make([]byte, 128) data := make([]byte, 128)
data = append(data, pub_key_data...) data = append(data, pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey() signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) { if assert.NotNil(err) {
@@ -141,7 +141,7 @@ func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128) signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...) data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey() signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err) assert.Nil(err)
@@ -156,7 +156,7 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128) signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...) data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...) data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data) keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey() signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err) assert.Nil(err)
@@ -167,12 +167,11 @@ func TestNewKeysAndCertWithMissingData(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
cert_data := make([]byte, 128) cert_data := make([]byte, 128)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder)) assert.Equal(0, len(remainder))
if assert.NotNil(err) { if assert.NotNil(err) {
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error()) assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
} }
} }
func TestNewKeysAndCertWithMissingCertData(t *testing.T) { func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
@@ -180,7 +179,7 @@ func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
cert_data := make([]byte, 128+256) cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...) cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder)) assert.Equal(0, len(remainder))
if assert.NotNil(err) { if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error()) assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
@@ -192,7 +191,7 @@ func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) {
cert_data := make([]byte, 128+256) cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...) cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder)) assert.Equal(0, len(remainder))
assert.Nil(err) assert.Nil(err)
} }
@@ -202,7 +201,7 @@ func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
cert_data := make([]byte, 128+256) cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...) cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder)) assert.Equal(0, len(remainder))
assert.Nil(err) assert.Nil(err)
} }
@@ -212,7 +211,7 @@ func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
cert_data := make([]byte, 128+256) cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...) cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) { if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0])) assert.Equal("A", string(remainder[0]))
} }
@@ -224,7 +223,7 @@ func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T)
cert_data := make([]byte, 128+256) cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...) cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data) _, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) { if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0])) assert.Equal("A", string(remainder[0]))
} }

View File

@@ -0,0 +1,18 @@
package keys_and_cert
import "crypto"
// PrivateKeysAndCert contains a KeysAndCert along with the corresponding private keys for the
// Public Key and the Signing Public Key
type PrivateKeysAndCert struct {
KeysAndCert
PK_KEY crypto.PrivateKey
SPK_KEY crypto.PrivateKey
}
func NewPrivateKeysAndCert() (*PrivateKeysAndCert, error) {
var pkc PrivateKeysAndCert
var err error
//pkc.PK_KEY, err =
return &pkc, err
}

63
lib/common/lease/doc.md Normal file
View File

@@ -0,0 +1,63 @@
# lease
--
import "github.com/go-i2p/go-i2p/lib/common/lease"
Package lease implements the I2P lease common data structure
## Usage
```go
const (
LEASE_SIZE = 44
LEASE_HASH_SIZE = 32
LEASE_TUNNEL_ID_SIZE = 4
)
```
Sizes in bytes of various components of a Lease
#### type Lease
```go
type Lease [LEASE_SIZE]byte
```
Lease is the represenation of an I2P Lease.
https://geti2p.net/spec/common-structures#lease
#### func NewLease
```go
func NewLease(data []byte) (lease *Lease, remainder []byte, err error)
```
NewLease creates a new *NewLease from []byte using ReadLease. Returns a pointer
to KeysAndCert unlike ReadLease.
#### func ReadLease
```go
func ReadLease(data []byte) (lease Lease, remainder []byte, err error)
```
ReadLease returns Lease from a []byte. The remaining bytes after the specified
length are also returned. Returns a list of errors that occurred during parsing.
#### func (Lease) Date
```go
func (lease Lease) Date() (date Date)
```
Date returns the date as an I2P Date.
#### func (Lease) TunnelGateway
```go
func (lease Lease) TunnelGateway() (hash Hash)
```
TunnelGateway returns the tunnel gateway as a Hash.
#### func (Lease) TunnelID
```go
func (lease Lease) TunnelID() uint32
```
TunnelID returns the tunnel id as a uint23.

View File

@@ -0,0 +1,95 @@
# lease_set
--
import "github.com/go-i2p/go-i2p/lib/common/lease_set"
Package lease_set implements the I2P LeastSet common data structure
## Usage
```go
const (
LEASE_SET_PUBKEY_SIZE = 256
LEASE_SET_SPK_SIZE = 128
LEASE_SET_SIG_SIZE = 40
)
```
Sizes of various structures in an I2P LeaseSet
#### type LeaseSet
```go
type LeaseSet []byte
```
LeaseSet is the represenation of an I2P LeaseSet.
https://geti2p.net/spec/common-structures#leaseset
#### func (LeaseSet) Destination
```go
func (lease_set LeaseSet) Destination() (destination Destination, err error)
```
Destination returns the Destination as []byte.
#### func (LeaseSet) LeaseCount
```go
func (lease_set LeaseSet) LeaseCount() (count int, err error)
```
LeaseCount returns the numbert of leases specified by the LeaseCount value as
int. returns errors encountered during parsing.
#### func (LeaseSet) Leases
```go
func (lease_set LeaseSet) Leases() (leases []Lease, err error)
```
Leases returns the leases as []Lease. returns errors encountered during parsing.
#### func (LeaseSet) NewestExpiration
```go
func (lease_set LeaseSet) NewestExpiration() (newest Date, err error)
```
NewestExpiration returns the newest lease expiration as an I2P Date. Returns
errors encountered during parsing.
#### func (LeaseSet) OldestExpiration
```go
func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error)
```
OldestExpiration returns the oldest lease expiration as an I2P Date. Returns
errors encountered during parsing.
#### func (LeaseSet) PublicKey
```go
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error)
```
PublicKey returns the public key as crypto.ElgPublicKey. Returns errors
encountered during parsing.
#### func (LeaseSet) Signature
```go
func (lease_set LeaseSet) Signature() (signature Signature, err error)
```
Signature returns the signature as Signature. returns errors encountered during
parsing.
#### func (LeaseSet) SigningKey
```go
func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicKey, err error)
```
SigningKey returns the signing public key as crypto.SigningPublicKey. returns
errors encountered during parsing.
#### func (LeaseSet) Verify
```go
func (lease_set LeaseSet) Verify() error
```
Verify returns nil

View File

@@ -132,7 +132,7 @@ type LeaseSet struct {
// Destination returns the Destination as []byte. // Destination returns the Destination as []byte.
func (lease_set LeaseSet) Destination() (destination Destination, err error) { func (lease_set LeaseSet) Destination() (destination Destination, err error) {
keys_and_cert, _, err := NewKeysAndCert(lease_set) keys_and_cert, _, err := ReadKeysAndCert(lease_set)
if err != nil { if err != nil {
return return
} }
@@ -143,7 +143,7 @@ func (lease_set LeaseSet) Destination() (destination Destination, err error) {
// PublicKey returns the public key as crypto.ElgPublicKey. // PublicKey returns the public key as crypto.ElgPublicKey.
// Returns errors encountered during parsing. // Returns errors encountered during parsing.
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) { func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) {
_, remainder, err := NewKeysAndCert(lease_set) _, remainder, err := ReadKeysAndCert(lease_set)
remainder_len := len(remainder) remainder_len := len(remainder)
if remainder_len < LEASE_SET_PUBKEY_SIZE { if remainder_len < LEASE_SET_PUBKEY_SIZE {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@@ -215,7 +215,7 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
// LeaseCount returns the numbert of leases specified by the LeaseCount value as int. // LeaseCount returns the numbert of leases specified by the LeaseCount value as int.
// returns errors encountered during parsing. // returns errors encountered during parsing.
func (lease_set LeaseSet) LeaseCount() (count int, err error) { func (lease_set LeaseSet) LeaseCount() (count int, err error) {
_, remainder, err := NewKeysAndCert(lease_set) _, remainder, err := ReadKeysAndCert(lease_set)
if err != nil { if err != nil {
return return
} }

View File

@@ -14,9 +14,9 @@ import (
func buildDestination() *router_identity.RouterIdentity { func buildDestination() *router_identity.RouterIdentity {
router_ident_data := make([]byte, 128+256) router_ident_data := make([]byte, 128+256)
router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...) router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
ident, _, err := router_identity.NewRouterIdentity(router_ident_data) ident, _, err := router_identity.ReadRouterIdentity(router_ident_data)
panic(err) panic(err)
return ident return &ident
} }
func buildPublicKey() []byte { func buildPublicKey() []byte {
@@ -77,7 +77,7 @@ func TestDestinationIsCorrect(t *testing.T) {
dest, err := lease_set.Destination() dest, err := lease_set.Destination()
assert.Nil(err) assert.Nil(err)
dest_cert := dest.Certificate() dest_cert := dest.Certificate()
//assert.Nil(err) // assert.Nil(err)
cert_type := dest_cert.Type() cert_type := dest_cert.Type()
assert.Nil(err) assert.Nil(err)
assert.Equal(certificate.CERT_KEY, cert_type) assert.Equal(certificate.CERT_KEY, cert_type)

View File

@@ -0,0 +1,179 @@
# router_address
--
import "github.com/go-i2p/go-i2p/lib/common/router_address"
Package router_address implements the I2P RouterAddress common data structure
## Usage
```go
const (
ROUTER_ADDRESS_MIN_SIZE = 9
)
```
Minimum number of bytes in a valid RouterAddress
#### type RouterAddress
```go
type RouterAddress struct {
TransportCost *Integer
ExpirationDate *Date
TransportType I2PString
TransportOptions *Mapping
}
```
RouterAddress is the represenation of an I2P RouterAddress.
https://geti2p.net/spec/common-structures#routeraddress
#### func ReadRouterAddress
```go
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error)
```
ReadRouterAddress returns RouterAddress from a []byte. The remaining bytes after
the specified length are also returned. Returns a list of errors that occurred
during parsing.
#### func (RouterAddress) Bytes
```go
func (router_address RouterAddress) Bytes() []byte
```
Bytes returns the router address as a []byte.
#### func (RouterAddress) Cost
```go
func (router_address RouterAddress) Cost() int
```
Cost returns the cost for this RouterAddress as a Go integer.
#### func (RouterAddress) Expiration
```go
func (router_address RouterAddress) Expiration() Date
```
Expiration returns the expiration for this RouterAddress as an I2P Date.
#### func (RouterAddress) GetOption
```go
func (router_address RouterAddress) GetOption(key I2PString) I2PString
```
GetOption returns the value of the option specified by the key
#### func (RouterAddress) Host
```go
func (router_address RouterAddress) Host() (net.Addr, error)
```
#### func (RouterAddress) HostString
```go
func (router_address RouterAddress) HostString() I2PString
```
#### func (RouterAddress) InitializationVector
```go
func (router_address RouterAddress) InitializationVector() ([32]byte, error)
```
#### func (RouterAddress) InitializationVectorString
```go
func (router_address RouterAddress) InitializationVectorString() I2PString
```
#### func (RouterAddress) IntroducerExpirationString
```go
func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString
```
#### func (RouterAddress) IntroducerHashString
```go
func (router_address RouterAddress) IntroducerHashString(num int) I2PString
```
#### func (RouterAddress) IntroducerTagString
```go
func (router_address RouterAddress) IntroducerTagString(num int) I2PString
```
#### func (*RouterAddress) Network
```go
func (router_address *RouterAddress) Network() string
```
Network implements net.Addr. It returns the transport type
#### func (RouterAddress) Options
```go
func (router_address RouterAddress) Options() Mapping
```
Options returns the options for this RouterAddress as an I2P Mapping.
#### func (RouterAddress) Port
```go
func (router_address RouterAddress) Port() (string, error)
```
#### func (RouterAddress) PortString
```go
func (router_address RouterAddress) PortString() I2PString
```
#### func (RouterAddress) ProtocolVersion
```go
func (router_address RouterAddress) ProtocolVersion() (string, error)
```
#### func (RouterAddress) ProtocolVersionString
```go
func (router_address RouterAddress) ProtocolVersionString() I2PString
```
#### func (RouterAddress) StaticKey
```go
func (router_address RouterAddress) StaticKey() ([32]byte, error)
```
#### func (RouterAddress) StaticKeyString
```go
func (router_address RouterAddress) StaticKeyString() I2PString
```
#### func (*RouterAddress) String
```go
func (router_address *RouterAddress) String() string
```
String implements net.Addr. It returns the IP address, followed by the options
#### func (RouterAddress) TransportStyle
```go
func (router_address RouterAddress) TransportStyle() I2PString
```
TransportStyle returns the transport style for this RouterAddress as an
I2PString.
#### func (*RouterAddress) UDP
```go
func (router_address *RouterAddress) UDP() bool
```

View File

@@ -3,6 +3,10 @@ package router_address
import ( import (
"errors" "errors"
"fmt"
"net"
"strconv"
"strings"
. "github.com/go-i2p/go-i2p/lib/common/data" . "github.com/go-i2p/go-i2p/lib/common/data"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@@ -63,18 +67,71 @@ options :: Mapping
// //
// https://geti2p.net/spec/common-structures#routeraddress // https://geti2p.net/spec/common-structures#routeraddress
type RouterAddress struct { type RouterAddress struct {
cost *Integer TransportCost *Integer
expiration *Date ExpirationDate *Date
transport_style *I2PString TransportType I2PString
options *Mapping TransportOptions *Mapping
} }
// Network implements net.Addr. It returns the transport type plus 4 or 6
func (router_address *RouterAddress) Network() string {
if router_address.TransportType == nil {
return ""
}
str, err := router_address.TransportType.Data()
if err != nil {
return ""
}
return string(str) + router_address.IPVersion()
}
// IPVersion returns a string "4" for IPv4 or 6 for IPv6
func (router_address *RouterAddress) IPVersion() string {
str, err := router_address.CapsString().Data()
if err != nil {
return ""
}
if strings.HasSuffix(str, "6") {
return "6"
}
return "4"
}
func (router_address *RouterAddress) UDP() bool {
return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
}
// String implements net.Addr. It returns the IP address, followed by the options
func (router_address *RouterAddress) String() string {
var rv []string
rv = append(rv, string(router_address.TransportStyle()))
rv = append(rv, string(router_address.HostString()))
rv = append(rv, string(router_address.PortString()))
rv = append(rv, string(router_address.StaticKeyString()))
rv = append(rv, string(router_address.InitializationVectorString()))
rv = append(rv, string(router_address.ProtocolVersionString()))
if router_address.UDP() {
rv = append(rv, string(router_address.IntroducerHashString(0)))
rv = append(rv, string(router_address.IntroducerExpirationString(0)))
rv = append(rv, string(router_address.IntroducerTagString(0)))
rv = append(rv, string(router_address.IntroducerHashString(1)))
rv = append(rv, string(router_address.IntroducerExpirationString(1)))
rv = append(rv, string(router_address.IntroducerTagString(1)))
rv = append(rv, string(router_address.IntroducerHashString(2)))
rv = append(rv, string(router_address.IntroducerExpirationString(2)))
rv = append(rv, string(router_address.IntroducerTagString(2)))
}
return strings.TrimSpace(strings.Join(rv, " "))
}
var ex_addr net.Addr = &RouterAddress{}
// Bytes returns the router address as a []byte. // Bytes returns the router address as a []byte.
func (router_address RouterAddress) Bytes() []byte { func (router_address RouterAddress) Bytes() []byte {
bytes := make([]byte, 0) bytes := make([]byte, 0)
bytes = append(bytes, router_address.cost.Bytes()...) bytes = append(bytes, router_address.TransportCost.Bytes()...)
bytes = append(bytes, router_address.expiration.Bytes()...) bytes = append(bytes, router_address.ExpirationDate.Bytes()...)
strData, err := router_address.transport_style.Data() strData, err := router_address.TransportType.Data()
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"error": err, "error": err,
@@ -82,28 +139,139 @@ func (router_address RouterAddress) Bytes() []byte {
} else { } else {
bytes = append(bytes, strData...) bytes = append(bytes, strData...)
} }
bytes = append(bytes, router_address.options.Data()...) bytes = append(bytes, router_address.TransportOptions.Data()...)
return bytes return bytes
} }
// Cost returns the cost for this RouterAddress as a Go integer. // Cost returns the cost for this RouterAddress as a Go integer.
func (router_address RouterAddress) Cost() int { func (router_address RouterAddress) Cost() int {
return router_address.cost.Int() return router_address.TransportCost.Int()
} }
// Expiration returns the expiration for this RouterAddress as an I2P Date. // Expiration returns the expiration for this RouterAddress as an I2P Date.
func (router_address RouterAddress) Expiration() Date { func (router_address RouterAddress) Expiration() Date {
return *router_address.expiration return *router_address.ExpirationDate
} }
// TransportStyle returns the transport style for this RouterAddress as an I2PString. // TransportStyle returns the transport style for this RouterAddress as an I2PString.
func (router_address RouterAddress) TransportStyle() I2PString { func (router_address RouterAddress) TransportStyle() I2PString {
return *router_address.transport_style return router_address.TransportType
}
// GetOption returns the value of the option specified by the key
func (router_address RouterAddress) GetOption(key I2PString) I2PString {
return router_address.Options().Values().Get(key)
}
func (router_address RouterAddress) HostString() I2PString {
host, _ := ToI2PString("host")
return router_address.GetOption(host)
}
func (router_address RouterAddress) PortString() I2PString {
port, _ := ToI2PString("port")
return router_address.GetOption(port)
}
func (router_address RouterAddress) CapsString() I2PString {
caps, _ := ToI2PString("caps")
return router_address.GetOption(caps)
}
func (router_address RouterAddress) StaticKeyString() I2PString {
sk, _ := ToI2PString("s")
return router_address.GetOption(sk)
}
func (router_address RouterAddress) InitializationVectorString() I2PString {
iv, _ := ToI2PString("i")
return router_address.GetOption(iv)
}
func (router_address RouterAddress) ProtocolVersionString() I2PString {
v, _ := ToI2PString("v")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerHashString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("ih" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("ih0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("iexp" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("iexp0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerTagString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("itag" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("itag0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) Host() (net.Addr, error) {
host := router_address.HostString()
hostBytes, err := host.Data()
if err != nil {
return nil, err
}
ip := net.ParseIP(hostBytes)
if ip == nil {
return nil, fmt.Errorf("null host error")
}
return net.ResolveIPAddr("", ip.String())
}
func (router_address RouterAddress) Port() (string, error) {
port := router_address.PortString()
portBytes, err := port.Data()
if err != nil {
return "", err
}
val, err := strconv.Atoi(portBytes)
if err != nil {
return "", err
}
return strconv.Itoa(val), nil
}
func (router_address RouterAddress) StaticKey() ([32]byte, error) {
sk := router_address.StaticKeyString()
if len([]byte(sk)) != 32 {
return [32]byte{}, fmt.Errorf("error: invalid static key")
}
return [32]byte(sk), nil
}
func (router_address RouterAddress) InitializationVector() ([32]byte, error) {
iv := router_address.InitializationVectorString()
if len([]byte(iv)) != 32 {
return [32]byte{}, fmt.Errorf("error: invalid static key")
}
return [32]byte(iv), nil
}
func (router_address RouterAddress) ProtocolVersion() (string, error) {
return router_address.ProtocolVersionString().Data()
} }
// Options returns the options for this RouterAddress as an I2P Mapping. // Options returns the options for this RouterAddress as an I2P Mapping.
func (router_address RouterAddress) Options() Mapping { func (router_address RouterAddress) Options() Mapping {
return *router_address.options return *router_address.TransportOptions
} }
// Check if the RouterAddress is empty or if it is too small to contain valid data. // Check if the RouterAddress is empty or if it is too small to contain valid data.
@@ -120,21 +288,21 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b
err = errors.New("error parsing RouterAddress: no data") err = errors.New("error parsing RouterAddress: no data")
return return
} }
router_address.cost, remainder, err = NewInteger(data, 1) router_address.TransportCost, remainder, err = NewInteger(data, 1)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress", "at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing cost", "reason": "error parsing cost",
}).Warn("error parsing RouterAddress") }).Warn("error parsing RouterAddress")
} }
router_address.expiration, remainder, err = NewDate(remainder) router_address.ExpirationDate, remainder, err = NewDate(remainder)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress", "at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing expiration", "reason": "error parsing expiration",
}).Error("error parsing RouterAddress") }).Error("error parsing RouterAddress")
} }
router_address.transport_style, remainder, err = NewI2PString(remainder) router_address.TransportType, remainder, err = ReadI2PString(remainder)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress", "at": "(RouterAddress) ReadNewRouterAddress",
@@ -142,21 +310,13 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b
}).Error("error parsing RouterAddress") }).Error("error parsing RouterAddress")
} }
var errs []error var errs []error
router_address.options, remainder, errs = NewMapping(remainder) router_address.TransportOptions, remainder, errs = NewMapping(remainder)
for _, err := range errs { for _, err := range errs {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterAddress) ReadNewRouterAddress", "at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing options", "reason": "error parsing options",
"error": err, "error": err,
}).Error("error parsing RouterAddress") }).Error("error parsing RozuterAddress")
} }
return return
} }
// NewRouterAddress creates a new *RouterAddress from []byte using ReadRouterAddress.
// Returns a pointer to RouterAddress unlike ReadRouterAddress.
func NewRouterAddress(data []byte) (router_address *RouterAddress, remainder []byte, err error) {
objrouteraddress, remainder, err := ReadRouterAddress(data)
router_address = &objrouteraddress
return
}

View File

@@ -31,7 +31,6 @@ func TestCheckRouterAddressValidReportsDataMissing(t *testing.T) {
err, exit := router_address.checkValid() err, exit := router_address.checkValid()
assert.Equal(exit, false, "checkValid indicates to stop parsing when some fields may be present") assert.Equal(exit, false, "checkValid indicates to stop parsing when some fields may be present")
} }
func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) { func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) {
@@ -40,8 +39,8 @@ func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) {
router_address, _, _ := ReadRouterAddress([]byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) router_address, _, _ := ReadRouterAddress([]byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
mapping, err := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"}) mapping, err := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"})
assert.Nil(err, "GoMapToMapping() returned error with valid data") assert.Nil(err, "GoMapToMapping() returned error with valid data")
router_address.options = mapping router_address.TransportOptions = mapping
//router_address = append(router_address, mapping...) // router_address = append(router_address, mapping...)
err, exit := router_address.checkValid() err, exit := router_address.checkValid()
assert.Nil(err, "checkValid() reported error with valid data") assert.Nil(err, "checkValid() reported error with valid data")

View File

@@ -0,0 +1,28 @@
# router_identity
--
import "github.com/go-i2p/go-i2p/lib/common/router_identity"
Package router_identity implements the I2P RouterIdentity common data structure
## Usage
#### type RouterIdentity
```go
type RouterIdentity struct {
KeysAndCert
}
```
RouterIdentity is the represenation of an I2P RouterIdentity.
https://geti2p.net/spec/common-structures#routeridentity
#### func ReadRouterIdentity
```go
func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error)
```
ReadRouterIdentity returns RouterIdentity from a []byte. The remaining bytes
after the specified length are also returned. Returns a list of errors that
occurred during parsing.

View File

@@ -20,24 +20,16 @@ Identical to KeysAndCert.
// //
// https://geti2p.net/spec/common-structures#routeridentity // https://geti2p.net/spec/common-structures#routeridentity
type RouterIdentity struct { type RouterIdentity struct {
*KeysAndCert KeysAndCert
} }
// ReadRouterIdentity returns RouterIdentity from a []byte. // ReadRouterIdentity returns RouterIdentity from a []byte.
// The remaining bytes after the specified length are also returned. // The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing. // Returns a list of errors that occurred during parsing.
func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) { func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) {
keys_and_cert, remainder, err := NewKeysAndCert(data) keys_and_cert, remainder, err := ReadKeysAndCert(data)
router_identity = RouterIdentity{ router_identity = RouterIdentity{
keys_and_cert, keys_and_cert,
} }
return return
} }
// NewRouterIdentity creates a new *RouterIdentity from []byte using ReadRouterIdentity.
// Returns a pointer to RouterIdentity unlike ReadRouterIdentity.
func NewRouterIdentity(data []byte) (router_identity *RouterIdentity, remainder []byte, err error) {
objrouter_identity, remainder, err := ReadRouterIdentity(data)
router_identity = &objrouter_identity
return
}

View File

@@ -0,0 +1,139 @@
# router_info
--
import "github.com/go-i2p/go-i2p/lib/common/router_info"
Package router_info implements the I2P RouterInfo common data structure
## Usage
```go
const (
MIN_GOOD_VERSION = 58
MAX_GOOD_VERSION = 99
)
```
```go
const ROUTER_INFO_MIN_SIZE = 439
```
#### type RouterInfo
```go
type RouterInfo struct {
}
```
RouterInfo is the represenation of an I2P RouterInfo.
https://geti2p.net/spec/common-structures#routerinfo
#### func ReadRouterInfo
```go
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
```
ReadRouterInfo returns RouterInfo from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.
#### func (RouterInfo) Bytes
```go
func (router_info RouterInfo) Bytes() (bytes []byte, err error)
```
Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
#### func (*RouterInfo) GoodVersion
```go
func (router_info *RouterInfo) GoodVersion() bool
```
#### func (*RouterInfo) IdentHash
```go
func (router_info *RouterInfo) IdentHash() Hash
```
IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
#### func (RouterInfo) Options
```go
func (router_info RouterInfo) Options() (mapping Mapping)
```
Options returns the options for this RouterInfo as an I2P Mapping.
#### func (*RouterInfo) PeerSize
```go
func (router_info *RouterInfo) PeerSize() int
```
PeerSize returns the peer size as a Go integer.
#### func (*RouterInfo) Published
```go
func (router_info *RouterInfo) Published() *Date
```
Published returns the date this RouterInfo was published as an I2P Date.
#### func (*RouterInfo) Reachable
```go
func (router_info *RouterInfo) Reachable() bool
```
#### func (*RouterInfo) RouterAddressCount
```go
func (router_info *RouterInfo) RouterAddressCount() int
```
RouterAddressCount returns the count of RouterAddress in this RouterInfo as a Go
integer.
#### func (*RouterInfo) RouterAddresses
```go
func (router_info *RouterInfo) RouterAddresses() []*RouterAddress
```
RouterAddresses returns all RouterAddresses for this RouterInfo as
[]*RouterAddress.
#### func (*RouterInfo) RouterCapabilities
```go
func (router_info *RouterInfo) RouterCapabilities() string
```
#### func (*RouterInfo) RouterIdentity
```go
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity
```
RouterIdentity returns the router identity as *RouterIdentity.
#### func (*RouterInfo) RouterVersion
```go
func (router_info *RouterInfo) RouterVersion() string
```
#### func (RouterInfo) Signature
```go
func (router_info RouterInfo) Signature() (signature Signature)
```
Signature returns the signature for this RouterInfo as an I2P Signature.
#### func (RouterInfo) String
```go
func (router_info RouterInfo) String() string
```
#### func (*RouterInfo) UnCongested
```go
func (router_info *RouterInfo) UnCongested() bool
```

View File

@@ -15,8 +15,10 @@ import (
const ROUTER_INFO_MIN_SIZE = 439 const ROUTER_INFO_MIN_SIZE = 439
const MIN_GOOD_VERSION = 58 const (
const MAX_GOOD_VERSION = 99 MIN_GOOD_VERSION = 58
MAX_GOOD_VERSION = 99
)
/* /*
[RouterInfo] [RouterInfo]
@@ -102,7 +104,7 @@ signature :: Signature
// //
// https://geti2p.net/spec/common-structures#routerinfo // https://geti2p.net/spec/common-structures#routerinfo
type RouterInfo struct { type RouterInfo struct {
router_identity *RouterIdentity router_identity RouterIdentity
published *Date published *Date
size *Integer size *Integer
addresses []*RouterAddress addresses []*RouterAddress
@@ -112,9 +114,7 @@ type RouterInfo struct {
} }
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream. // Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
func (router_info RouterInfo) Bytes() ([]byte, error) { func (router_info RouterInfo) Bytes() (bytes []byte, err error) {
var err error
var bytes []byte
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...) bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
bytes = append(bytes, router_info.published.Bytes()...) bytes = append(bytes, router_info.published.Bytes()...)
bytes = append(bytes, router_info.size.Bytes()...) bytes = append(bytes, router_info.size.Bytes()...)
@@ -123,21 +123,33 @@ func (router_info RouterInfo) Bytes() ([]byte, error) {
} }
bytes = append(bytes, router_info.peer_size.Bytes()...) bytes = append(bytes, router_info.peer_size.Bytes()...)
bytes = append(bytes, router_info.options.Data()...) bytes = append(bytes, router_info.options.Data()...)
//bytes = append(bytes, []byte(*router_info.signature)...) bytes = append(bytes, []byte(*router_info.signature)...)
return bytes, err return bytes, err
} }
func (router_info RouterInfo) String() string {
str := "Certificate: " + string(router_info.router_identity.KeysAndCert.Bytes())
str += "Published: " + string(router_info.published.Bytes())
str += "Addresses:" + string(router_info.size.Bytes())
for index, router_address := range router_info.addresses {
str += "Address " + strconv.Itoa(index) + ": " + router_address.String()
}
str += "Peer Size: " + string(router_info.peer_size.Bytes())
str += "Options: " + string(router_info.options.Data())
str += "Signature: " + string([]byte(*router_info.signature))
return str
}
// RouterIdentity returns the router identity as *RouterIdentity. // RouterIdentity returns the router identity as *RouterIdentity.
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity { func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
return router_info.router_identity return &router_info.router_identity
} }
// IndentHash returns the identity hash (sha256 sum) for this RouterInfo. // IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
func (router_info *RouterInfo) IdentHash() Hash { func (router_info *RouterInfo) IdentHash() Hash {
ri := router_info.RouterIdentity() data, _ := router_info.RouterIdentity().KeyCertificate.Data()
h := HashData(ri.KeysAndCert.Certificate().Data()) return HashData(data)
return h
} }
// Published returns the date this RouterInfo was published as an I2P Date. // Published returns the date this RouterInfo was published as an I2P Date.
@@ -167,73 +179,21 @@ func (router_info RouterInfo) Options() (mapping Mapping) {
return *router_info.options return *router_info.options
} }
//
// Return the signature of this router info
//
// Signature returns the signature for this RouterInfo as an I2P Signature. // Signature returns the signature for this RouterInfo as an I2P Signature.
func (router_info RouterInfo) Signature() (signature Signature) { func (router_info RouterInfo) Signature() (signature Signature) {
return *router_info.signature return *router_info.signature
} }
// // Network implements net.Addr
// Used during parsing to determine where in the RouterInfo the Mapping data begins. func (router_info RouterInfo) Network() string {
// return "i2p"
/*func (router_info RouterInfo) optionsLocation() (location int) { }
data, remainder, err := ReadRouterIdentity(router_info)
if err != nil {
return
}
location += len(data)
remainder_len := len(remainder)
if remainder_len < 9 {
log.WithFields(log.Fields{
"at": "(RouterInfo) optionsLocation",
"data_len": remainder_len,
"required_len": 9,
"reason": "not enough data",
}).Error("error parsing router info")
err = errors.New("error parsing router addresses: not enough data")
return
}
location += 9
remaining := remainder[9:]
var router_address RouterAddress
var router_addresses []RouterAddress
addr_count, cerr := router_info.RouterAddressCount()
if cerr != nil {
err = cerr
return
}
for i := 0; i < addr_count; i++ {
router_address, remaining, err = ReadRouterAddress(remaining)
if err == nil {
location += len(router_address)
router_addresses = append(router_addresses, router_address)
}
}
location += 1
return
}*/
//
// Used during parsing to determine the size of the options in the RouterInfo.
//
/*func (router_info RouterInfo) optionsSize() (size int) {
head := router_info.optionsLocation()
s := Integer(router_info[head : head+2])
size = s.Int() + 2
return
}*/
// ReadRouterInfo returns RouterInfo from a []byte. // ReadRouterInfo returns RouterInfo from a []byte.
// The remaining bytes after the specified length are also returned. // The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing. // Returns a list of errors that occurred during parsing.
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) { func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) {
identity, remainder, err := NewRouterIdentity(bytes) info.router_identity, remainder, err = ReadRouterIdentity(bytes)
info.router_identity = identity
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo", "at": "(RouterInfo) ReadRouterInfo",
@@ -242,9 +202,9 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
"reason": "not enough data", "reason": "not enough data",
}).Error("error parsing router info") }).Error("error parsing router info")
err = errors.New("error parsing router info: not enough data") err = errors.New("error parsing router info: not enough data")
return
} }
date, remainder, err := NewDate(remainder) info.published, remainder, err = NewDate(remainder)
info.published = date
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo", "at": "(RouterInfo) ReadRouterInfo",
@@ -254,27 +214,17 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
}).Error("error parsing router info") }).Error("error parsing router info")
err = errors.New("error parsing router info: not enough data") err = errors.New("error parsing router info: not enough data")
} }
size, remainder, err := NewInteger(remainder, 1) info.size, remainder, err = NewInteger(remainder, 1)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo", "at": "(RouterInfo) ReadRouterInfo",
"data_len": len(remainder), "data_len": len(remainder),
"required_len": size.Int(), "required_len": info.size.Int(),
"reason": "read error", "reason": "read error",
}).Error("error parsing router info size") }).Error("error parsing router info size")
} }
info.size = size for i := 0; i < info.size.Int(); i++ {
if err != nil { address, more, err := ReadRouterAddress(remainder)
log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo",
"data_len": len(remainder),
"required_len": size.Int(),
"reason": "not enough data",
}).Error("error parsing router info")
err = errors.New("error parsing router info: not enough data")
}
for i := 0; i < size.Int(); i++ {
address, more, err := NewRouterAddress(remainder)
remainder = more remainder = more
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@@ -285,7 +235,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
}).Error("error parsing router address") }).Error("error parsing router address")
err = errors.New("error parsing router info: not enough data") err = errors.New("error parsing router info: not enough data")
} }
info.addresses = append(info.addresses, address) info.addresses = append(info.addresses, &address)
} }
info.peer_size, remainder, err = NewInteger(remainder, 1) info.peer_size, remainder, err = NewInteger(remainder, 1)
var errs []error var errs []error
@@ -303,6 +253,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
} }
err = errors.New("error parsing router info: " + estring) err = errors.New("error parsing router info: " + estring)
} }
info.signature, remainder, err = NewSignature(remainder)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(RouterInfo) ReadRouterInfo", "at": "(RouterInfo) ReadRouterInfo",
@@ -369,11 +320,3 @@ func (router_info *RouterInfo) Reachable() bool {
} }
return strings.Contains(caps, "R") 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) {
routerInfo, remainder, err := ReadRouterInfo(data)
router_info = &routerInfo
return
}

View File

@@ -131,7 +131,6 @@ func TestRouterAddressesReturnsAddresses(t *testing.T) {
), ),
) )
} }
} }
func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) { func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
@@ -162,7 +161,6 @@ func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
) )
} }
} }
} }
func TestPeerSizeIsZero(t *testing.T) { func TestPeerSizeIsZero(t *testing.T) {
@@ -200,7 +198,7 @@ func TestRouterIdentityIsCorrect(t *testing.T) {
router_info, _ := buildFullRouterInfo() router_info, _ := buildFullRouterInfo()
router_identity := router_info.RouterIdentity() router_identity := router_info.RouterIdentity()
//assert.Nil(err) // assert.Nil(err)
assert.Equal( assert.Equal(
0, 0,
bytes.Compare( bytes.Compare(

View File

@@ -0,0 +1,34 @@
# session_key
--
import "github.com/go-i2p/go-i2p/lib/common/session_key"
Package session_key implements the I2P SessionKey common data structure
## Usage
#### type SessionKey
```go
type SessionKey [32]byte
```
SessionKey is the represenation of an I2P SessionKey.
https://geti2p.net/spec/common-structures#sessionkey
#### func NewSessionKey
```go
func NewSessionKey(data []byte) (session_key *SessionKey, remainder []byte, err error)
```
NewSessionKey creates a new *SessionKey from []byte using ReadSessionKey.
Returns a pointer to SessionKey unlike ReadSessionKey.
#### func ReadSessionKey
```go
func ReadSessionKey(bytes []byte) (info SessionKey, remainder []byte, err error)
```
ReadSessionKey returns SessionKey from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.

View File

@@ -0,0 +1,34 @@
# session_tag
--
import "github.com/go-i2p/go-i2p/lib/common/session_tag"
Package session_tag implements the I2P SessionTag common data structure
## Usage
#### type SessionTag
```go
type SessionTag [32]byte
```
SessionTag is the represenation of an I2P SessionTag.
https://geti2p.net/spec/common-structures#session-tag
#### func NewSessionTag
```go
func NewSessionTag(data []byte) (session_tag *SessionTag, remainder []byte, err error)
```
NewSessionTag creates a new *SessionTag from []byte using ReadSessionTag.
Returns a pointer to SessionTag unlike ReadSessionTag.
#### func ReadSessionTag
```go
func ReadSessionTag(bytes []byte) (info SessionTag, remainder []byte, err error)
```
ReadSessionTag returns SessionTag from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.

View File

@@ -0,0 +1,50 @@
# signature
--
import "github.com/go-i2p/go-i2p/lib/common/signature"
Package signature implements the I2P Signature common data structure
## Usage
```go
const (
DSA_SHA1_SIZE = 40
ECDSA_SHA256_P256_SIZE = 64
ECDSA_SHA384_P384_SIZE = 96
ECDSA_SHA512_P512_SIZE = 132
RSA_SHA256_2048_SIZE = 256
RSA_SHA384_3072_SIZE = 384
RSA_SHA512_4096_SIZE = 512
EdDSA_SHA512_Ed25519_SIZE = 64
EdDSA_SHA512_Ed25519ph_SIZE = 64
RedDSA_SHA512_Ed25519_SIZE = 64
)
```
Lengths of signature keys
#### type Signature
```go
type Signature []byte
```
Signature is the represenation of an I2P Signature.
https://geti2p.net/spec/common-structures#signature
#### func NewSignature
```go
func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error)
```
NewSignature creates a new *Signature from []byte using ReadSignature. Returns a
pointer to Signature unlike ReadSignature.
#### func ReadSignature
```go
func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error)
```
ReadSignature returns Signature from a []byte. The remaining bytes after the
specified length are also returned. Returns a list of errors that occurred
during parsing.

85
lib/config/doc.md Normal file
View File

@@ -0,0 +1,85 @@
# config
--
import "github.com/go-i2p/go-i2p/lib/config"
## Usage
```go
var DefaultBootstrapConfig = BootstrapConfig{
LowPeerThreshold: 10,
ReseedServers: []*ReseedConfig{},
}
```
default configuration for network bootstrap
```go
var DefaultNetDbConfig = NetDbConfig{
Path: filepath.Join(defaultConfig(), "netDb"),
}
```
default settings for netdb
```go
var RouterConfigProperties = DefaultRouterConfig()
```
#### type BootstrapConfig
```go
type BootstrapConfig struct {
// if we have less than this many peers we should reseed
LowPeerThreshold int
// reseed servers
ReseedServers []*ReseedConfig
}
```
#### type NetDbConfig
```go
type NetDbConfig struct {
// path to network database directory
Path string
}
```
local network database configuration
#### type ReseedConfig
```go
type ReseedConfig struct {
// url of reseed server
Url string
// fingerprint of reseed su3 signing key
SU3Fingerprint string
}
```
configuration for 1 reseed server
#### type RouterConfig
```go
type RouterConfig struct {
// the path to the base config directory where per-system defaults are stored
BaseDir string
// the path to the working config directory where files are changed
WorkingDir string
// netdb configuration
NetDb *NetDbConfig
// configuration for bootstrapping into the network
Bootstrap *BootstrapConfig
}
```
router.config options
#### func DefaultRouterConfig
```go
func DefaultRouterConfig() *RouterConfig
```

View File

@@ -12,5 +12,5 @@ type NetDbConfig struct {
// default settings for netdb // default settings for netdb
var DefaultNetDbConfig = NetDbConfig{ var DefaultNetDbConfig = NetDbConfig{
Path: filepath.Join(".", "netDb"), Path: filepath.Join(defaultConfig(), "netDb"),
} }

View File

@@ -1,15 +1,48 @@
package config package config
import (
"os"
"path/filepath"
)
// router.config options // router.config options
type RouterConfig struct { type RouterConfig struct {
// the path to the base config directory where per-system defaults are stored
BaseDir string
// the path to the working config directory where files are changed
WorkingDir string
// netdb configuration // netdb configuration
NetDb *NetDbConfig NetDb *NetDbConfig
// configuration for bootstrapping into the network // configuration for bootstrapping into the network
Bootstrap *BootstrapConfig Bootstrap *BootstrapConfig
} }
// defaults for router func home() string {
var DefaultRouterConfig = &RouterConfig{ h, err := os.UserHomeDir()
NetDb: &DefaultNetDbConfig, if err != nil {
Bootstrap: &DefaultBootstrapConfig, panic(err)
}
return h
} }
func defaultBase() string {
return filepath.Join(home(), "go-i2p", "base")
}
func defaultConfig() string {
return filepath.Join(home(), "go-i2p", "config")
}
// defaults for router
var defaultRouterConfig = &RouterConfig{
NetDb: &DefaultNetDbConfig,
Bootstrap: &DefaultBootstrapConfig,
BaseDir: defaultBase(),
WorkingDir: defaultConfig(),
}
func DefaultRouterConfig() *RouterConfig {
return defaultRouterConfig
}
var RouterConfigProperties = DefaultRouterConfig()

141
lib/crypto/curve25519.go Normal file
View File

@@ -0,0 +1,141 @@
package crypto
import (
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"errors"
"io"
"math/big"
curve25519 "go.step.sm/crypto/x25519"
)
var Curve25519EncryptTooBig = errors.New("failed to encrypt data, too big for Curve25519")
type Curve25519PublicKey []byte
type Curve25519Verifier struct {
k []byte
}
func (k Curve25519PublicKey) NewVerifier() (v Verifier, err error) {
temp := new(Curve25519Verifier)
temp.k = k
v = temp
return temp, nil
}
func (k Curve25519PublicKey) Len() int {
return len(k)
}
func createCurve25519PublicKey(data []byte) (k *curve25519.PublicKey) {
if len(data) == 256 {
k2 := curve25519.PublicKey{}
copy(k2[:], data)
k = &k2
}
return
}
func createCurve25519Encryption(pub *curve25519.PublicKey, rand io.Reader) (enc *Curve25519Encryption, 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 = &Curve25519Encryption{}
}*/
return
}
type Curve25519Encryption struct {
p, a, b1 *big.Int
}
func (curve25519 *Curve25519Encryption) Encrypt(data []byte) (enc []byte, err error) {
return curve25519.EncryptPadding(data, true)
}
func (curve25519 *Curve25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error) {
if len(data) > 222 {
err = Curve25519EncryptTooBig
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(curve25519.b1, m), curve25519.p).Bytes()
if zeroPadding {
encrypted = make([]byte, 514)
copy(encrypted[1:], curve25519.a.Bytes())
copy(encrypted[258:], b)
} else {
encrypted = make([]byte, 512)
copy(encrypted, curve25519.a.Bytes())
copy(encrypted[256:], b)
}
return
}
func (elg Curve25519PublicKey) NewEncrypter() (enc Encrypter, err error) {
k := createCurve25519PublicKey(elg[:])
enc, err = createCurve25519Encryption(k, rand.Reader)
return
}
func (v *Curve25519Verifier) VerifyHash(h, sig []byte) (err error) {
if len(sig) != curve25519.SignatureSize {
err = ErrBadSignatureSize
return
}
if len(v.k) != curve25519.PublicKeySize {
err = errors.New("failed to verify: invalid curve25519 public key size")
return
}
ok := curve25519.Verify(v.k, h, sig)
if !ok {
err = errors.New("failed to verify: invalid signature")
}
return
}
func (v *Curve25519Verifier) Verify(data, sig []byte) (err error) {
h := sha512.Sum512(data)
err = v.VerifyHash(h[:], sig)
return
}
type Curve25519PrivateKey curve25519.PrivateKey
type Curve25519Signer struct {
k []byte
}
func (s *Curve25519Signer) Sign(data []byte) (sig []byte, err error) {
if len(s.k) != curve25519.PrivateKeySize {
err = errors.New("failed to sign: invalid curve25519 private key size")
return
}
h := sha512.Sum512(data)
sig, err = s.SignHash(h[:])
return
}
func (s *Curve25519Signer) SignHash(h []byte) (sig []byte, err error) {
return curve25519.Sign(rand.Reader, s.k, h)
}

View File

@@ -8,7 +8,6 @@ type Decrypter interface {
} }
type PrivateEncryptionKey interface { type PrivateEncryptionKey interface {
// create a new decryption object for this private key to decrypt data encrypted to our public key // create a new decryption object for this private key to decrypt data encrypted to our public key
// returns decrypter or nil and error if the private key is in a bad format // returns decrypter or nil and error if the private key is in a bad format
NewDecrypter() (Decrypter, error) NewDecrypter() (Decrypter, error)

623
lib/crypto/doc.md Normal file
View File

@@ -0,0 +1,623 @@
# crypto
--
import "github.com/go-i2p/go-i2p/lib/crypto"
package for i2p specific crpytography
## Usage
```go
const (
IPAD = byte(0x36)
OPAD = byte(0x5C)
)
```
```go
var (
ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data")
ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal")
)
```
```go
var (
ErrBadSignatureSize = errors.New("bad signature size")
ErrInvalidKeyFormat = errors.New("invalid key format")
ErrInvalidSignature = errors.New("invalid signature")
)
```
```go
var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
```
```go
var SHA256 = sha256.Sum256
```
#### func ElgamalGenerate
```go
func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error)
```
generate an elgamal key pair
#### type DSAPrivateKey
```go
type DSAPrivateKey [20]byte
```
#### func (DSAPrivateKey) Generate
```go
func (k DSAPrivateKey) Generate() (s DSAPrivateKey, err error)
```
#### func (DSAPrivateKey) Len
```go
func (k DSAPrivateKey) Len() int
```
#### func (DSAPrivateKey) NewSigner
```go
func (k DSAPrivateKey) NewSigner() (s Signer, err error)
```
create a new dsa signer
#### func (DSAPrivateKey) Public
```go
func (k DSAPrivateKey) Public() (pk DSAPublicKey, err error)
```
#### type DSAPublicKey
```go
type DSAPublicKey [128]byte
```
#### func (DSAPublicKey) Len
```go
func (k DSAPublicKey) Len() int
```
#### func (DSAPublicKey) NewVerifier
```go
func (k DSAPublicKey) NewVerifier() (v Verifier, err error)
```
create a new dsa verifier
#### type DSASigner
```go
type DSASigner struct {
}
```
#### func (*DSASigner) Sign
```go
func (ds *DSASigner) Sign(data []byte) (sig []byte, err error)
```
#### func (*DSASigner) SignHash
```go
func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error)
```
#### type DSAVerifier
```go
type DSAVerifier struct {
}
```
#### func (*DSAVerifier) Verify
```go
func (v *DSAVerifier) Verify(data, sig []byte) (err error)
```
verify data with a dsa public key
#### func (*DSAVerifier) VerifyHash
```go
func (v *DSAVerifier) VerifyHash(h, sig []byte) (err error)
```
verify hash of data with a dsa public key
#### type Decrypter
```go
type Decrypter interface {
// decrypt a block of data
// return decrypted block or nil and error if error happens
Decrypt(data []byte) ([]byte, error)
}
```
decrypts data
#### type ECDSAVerifier
```go
type ECDSAVerifier struct {
}
```
#### func (*ECDSAVerifier) Verify
```go
func (v *ECDSAVerifier) Verify(data, sig []byte) (err error)
```
verify a block of data by hashing it and comparing the hash against the
signature
#### func (*ECDSAVerifier) VerifyHash
```go
func (v *ECDSAVerifier) VerifyHash(h, sig []byte) (err error)
```
verify a signature given the hash
#### type ECP256PrivateKey
```go
type ECP256PrivateKey [32]byte
```
#### type ECP256PublicKey
```go
type ECP256PublicKey [64]byte
```
#### func (ECP256PublicKey) Len
```go
func (k ECP256PublicKey) Len() int
```
#### func (ECP256PublicKey) NewVerifier
```go
func (k ECP256PublicKey) NewVerifier() (Verifier, error)
```
#### type ECP384PrivateKey
```go
type ECP384PrivateKey [48]byte
```
#### type ECP384PublicKey
```go
type ECP384PublicKey [96]byte
```
#### func (ECP384PublicKey) Len
```go
func (k ECP384PublicKey) Len() int
```
#### func (ECP384PublicKey) NewVerifier
```go
func (k ECP384PublicKey) NewVerifier() (Verifier, error)
```
#### type ECP521PrivateKey
```go
type ECP521PrivateKey [66]byte
```
#### type ECP521PublicKey
```go
type ECP521PublicKey [132]byte
```
#### func (ECP521PublicKey) Len
```go
func (k ECP521PublicKey) Len() int
```
#### func (ECP521PublicKey) NewVerifier
```go
func (k ECP521PublicKey) NewVerifier() (Verifier, error)
```
#### type Ed25519Encryption
```go
type Ed25519Encryption struct {
}
```
#### func (*Ed25519Encryption) Encrypt
```go
func (ed25519 *Ed25519Encryption) Encrypt(data []byte) (enc []byte, err error)
```
#### func (*Ed25519Encryption) EncryptPadding
```go
func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error)
```
#### type Ed25519PrivateKey
```go
type Ed25519PrivateKey ed25519.PrivateKey
```
#### type Ed25519PublicKey
```go
type Ed25519PublicKey []byte
```
#### func (Ed25519PublicKey) Len
```go
func (k Ed25519PublicKey) Len() int
```
#### func (Ed25519PublicKey) NewEncrypter
```go
func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error)
```
#### func (Ed25519PublicKey) NewVerifier
```go
func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error)
```
#### type Ed25519Signer
```go
type Ed25519Signer struct {
}
```
#### func (*Ed25519Signer) Sign
```go
func (s *Ed25519Signer) Sign(data []byte) (sig []byte, err error)
```
#### func (*Ed25519Signer) SignHash
```go
func (s *Ed25519Signer) SignHash(h []byte) (sig []byte, err error)
```
#### type Ed25519Verifier
```go
type Ed25519Verifier struct {
}
```
#### func (*Ed25519Verifier) Verify
```go
func (v *Ed25519Verifier) Verify(data, sig []byte) (err error)
```
#### func (*Ed25519Verifier) VerifyHash
```go
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error)
```
#### type ElgPrivateKey
```go
type ElgPrivateKey [256]byte
```
#### func (ElgPrivateKey) Len
```go
func (elg ElgPrivateKey) Len() int
```
#### func (ElgPrivateKey) NewDecrypter
```go
func (elg ElgPrivateKey) NewDecrypter() (dec Decrypter, err error)
```
#### type ElgPublicKey
```go
type ElgPublicKey [256]byte
```
#### func (ElgPublicKey) Len
```go
func (elg ElgPublicKey) Len() int
```
#### func (ElgPublicKey) NewEncrypter
```go
func (elg ElgPublicKey) NewEncrypter() (enc Encrypter, err error)
```
#### type ElgamalEncryption
```go
type ElgamalEncryption struct {
}
```
#### func (*ElgamalEncryption) Encrypt
```go
func (elg *ElgamalEncryption) Encrypt(data []byte) (enc []byte, err error)
```
#### func (*ElgamalEncryption) EncryptPadding
```go
func (elg *ElgamalEncryption) EncryptPadding(data []byte, zeroPadding bool) (encrypted []byte, err error)
```
#### type Encrypter
```go
type Encrypter interface {
// encrypt a block of data
// return encrypted block or nil and error if an error happened
Encrypt(data []byte) (enc []byte, err error)
}
```
encrypts data
#### type HMACDigest
```go
type HMACDigest [16]byte
```
#### func I2PHMAC
```go
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest)
```
do i2p hmac
#### type HMACKey
```go
type HMACKey [32]byte
```
#### type PrivateEncryptionKey
```go
type PrivateEncryptionKey interface {
// create a new decryption object for this private key to decrypt data encrypted to our public key
// returns decrypter or nil and error if the private key is in a bad format
NewDecrypter() (Decrypter, error)
}
```
#### type PublicEncryptionKey
```go
type PublicEncryptionKey interface {
// create a new encrypter to encrypt data to this public key
NewEncrypter() (Encrypter, error)
// length of this public key in bytes
Len() int
}
```
#### type PublicKey
```go
type PublicKey interface {
Len() int
NewEncrypter() (Encrypter, error)
}
```
#### type RSA2048PrivateKey
```go
type RSA2048PrivateKey [512]byte
```
#### type RSA2048PublicKey
```go
type RSA2048PublicKey [256]byte
```
#### type RSA3072PrivateKey
```go
type RSA3072PrivateKey [786]byte
```
#### type RSA3072PublicKey
```go
type RSA3072PublicKey [384]byte
```
#### type RSA4096PrivateKey
```go
type RSA4096PrivateKey [1024]byte
```
#### type RSA4096PublicKey
```go
type RSA4096PublicKey [512]byte
```
#### type Signer
```go
type Signer interface {
// sign data with our private key by calling SignHash after hashing the data we are given
// return signature or nil signature and error if an error happened
Sign(data []byte) (sig []byte, err error)
// sign hash of data with our private key
// return signature or nil signature and error if an error happened
SignHash(h []byte) (sig []byte, err error)
}
```
type for signing data
#### type SigningPrivateKey
```go
type SigningPrivateKey interface {
// create a new signer to sign data
// return signer or nil and error if key format is invalid
NewSigner() (Signer, error)
// length of this private key
Len() int
// get public key or return nil and error if invalid key data in private key
Public() (SigningPublicKey, error)
// generate a new private key, put it into itself
// returns itself or nil and error if an error occurs
Generate() (SigningPrivateKey, error)
}
```
key for signing data
#### type SigningPublicKey
```go
type SigningPublicKey interface {
// create new Verifier to verify the validity of signatures
// return verifier or nil and error if key format is invalid
NewVerifier() (Verifier, error)
// get the size of this public key
Len() int
}
```
key for verifying data
#### type Tunnel
```go
type Tunnel struct {
}
```
#### func NewTunnelCrypto
```go
func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error)
```
#### func (*Tunnel) Decrypt
```go
func (t *Tunnel) Decrypt(td *TunnelData)
```
#### func (*Tunnel) Encrypt
```go
func (t *Tunnel) Encrypt(td *TunnelData)
```
encrypt tunnel data in place
#### type TunnelData
```go
type TunnelData [1028]byte
```
#### type TunnelIV
```go
type TunnelIV []byte
```
The initialization vector for a tunnel message
#### type TunnelKey
```go
type TunnelKey [32]byte
```
A symetric key for encrypting tunnel messages
#### type Verifier
```go
type Verifier interface {
// verify hashed data with this signing key
// return nil on valid signature otherwise error
VerifyHash(h, sig []byte) error
// verify an unhashed piece of data by hashing it and calling VerifyHash
Verify(data, sig []byte) error
}
```
type for verifying signatures

View File

@@ -2,9 +2,10 @@ package crypto
import ( import (
"crypto/rand" "crypto/rand"
log "github.com/sirupsen/logrus"
"io" "io"
"testing" "testing"
log "github.com/sirupsen/logrus"
) )
func TestDSA(t *testing.T) { func TestDSA(t *testing.T) {

View File

@@ -44,8 +44,10 @@ func createECVerifier(c elliptic.Curve, h crypto.Hash, k []byte) (ev *ECDSAVerif
return return
} }
type ECP256PublicKey [64]byte type (
type ECP256PrivateKey [32]byte ECP256PublicKey [64]byte
ECP256PrivateKey [32]byte
)
func (k ECP256PublicKey) Len() int { func (k ECP256PublicKey) Len() int {
return len(k) return len(k)
@@ -55,8 +57,10 @@ func (k ECP256PublicKey) NewVerifier() (Verifier, error) {
return createECVerifier(elliptic.P256(), crypto.SHA256, k[:]) return createECVerifier(elliptic.P256(), crypto.SHA256, k[:])
} }
type ECP384PublicKey [96]byte type (
type ECP384PrivateKey [48]byte ECP384PublicKey [96]byte
ECP384PrivateKey [48]byte
)
func (k ECP384PublicKey) Len() int { func (k ECP384PublicKey) Len() int {
return len(k) return len(k)
@@ -66,8 +70,10 @@ func (k ECP384PublicKey) NewVerifier() (Verifier, error) {
return createECVerifier(elliptic.P384(), crypto.SHA384, k[:]) return createECVerifier(elliptic.P384(), crypto.SHA384, k[:])
} }
type ECP521PublicKey [132]byte type (
type ECP521PrivateKey [66]byte ECP521PublicKey [132]byte
ECP521PrivateKey [66]byte
)
func (k ECP521PublicKey) Len() int { func (k ECP521PublicKey) Len() int {
return len(k) return len(k)

View File

@@ -30,11 +30,15 @@ var elgp = new(big.Int).SetBytes([]byte{
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
}) })
var one = big.NewInt(1) var (
var elgg = big.NewInt(2) one = big.NewInt(1)
elgg = big.NewInt(2)
)
var ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data") var (
var ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal") ElgDecryptFail = errors.New("failed to decrypt elgamal encrypted data")
ElgEncryptTooBig = errors.New("failed to encrypt data, too big for elgamal")
)
// generate an elgamal key pair // generate an elgamal key pair
func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) { func ElgamalGenerate(priv *elgamal.PrivateKey, rand io.Reader) (err error) {
@@ -184,8 +188,10 @@ func createElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *Elgam
return return
} }
type ElgPublicKey [256]byte type (
type ElgPrivateKey [256]byte ElgPublicKey [256]byte
ElgPrivateKey [256]byte
)
func (elg ElgPublicKey) Len() int { func (elg ElgPublicKey) Len() int {
return len(elg) return len(elg)

View File

@@ -3,10 +3,11 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/openpgp/elgamal"
"io" "io"
"testing" "testing"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/openpgp/elgamal"
) )
func BenchmarkElgGenerate(b *testing.B) { func BenchmarkElgGenerate(b *testing.B) {
@@ -46,7 +47,6 @@ func BenchmarkElgDecrypt(b *testing.B) {
} }
} }
log.Infof("%d fails %d rounds", fails, b.N) log.Infof("%d fails %d rounds", fails, b.N)
} }
func BenchmarkElgEncrypt(b *testing.B) { func BenchmarkElgEncrypt(b *testing.B) {

View File

@@ -8,7 +8,6 @@ type Encrypter interface {
} }
type PublicEncryptionKey interface { type PublicEncryptionKey interface {
// create a new encrypter to encrypt data to this public key // create a new encrypter to encrypt data to this public key
NewEncrypter() (Encrypter, error) NewEncrypter() (Encrypter, error)

View File

@@ -4,11 +4,15 @@ import (
"crypto/md5" "crypto/md5"
) )
const IPAD = byte(0x36) const (
const OPAD = byte(0x5C) IPAD = byte(0x36)
OPAD = byte(0x5C)
)
type HMACKey [32]byte type (
type HMACDigest [16]byte HMACKey [32]byte
HMACDigest [16]byte
)
func (hk HMACKey) xor(p byte) (i []byte) { func (hk HMACKey) xor(p byte) (i []byte) {
i = make([]byte, 64) i = make([]byte, 64)
@@ -25,7 +29,6 @@ func (hk HMACKey) xor(p byte) (i []byte) {
// do i2p hmac // do i2p hmac
func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) { func I2PHMAC(data []byte, k HMACKey) (d HMACDigest) {
buff := make([]byte, 64+len(data)) buff := make([]byte, 64+len(data))
ip := k.xor(IPAD) ip := k.xor(IPAD)
copy(buff, ip) copy(buff, ip)

View File

@@ -1,10 +1,16 @@
package crypto package crypto
type RSA2048PublicKey [256]byte type (
type RSA2048PrivateKey [512]byte RSA2048PublicKey [256]byte
RSA2048PrivateKey [512]byte
)
type RSA3072PublicKey [384]byte type (
type RSA3072PrivateKey [786]byte RSA3072PublicKey [384]byte
RSA3072PrivateKey [786]byte
)
type RSA4096PublicKey [512]byte type (
type RSA4096PrivateKey [1024]byte RSA4096PublicKey [512]byte
RSA4096PrivateKey [1024]byte
)

View File

@@ -4,9 +4,11 @@ import (
"errors" "errors"
) )
var ErrBadSignatureSize = errors.New("bad signature size") var (
var ErrInvalidKeyFormat = errors.New("invalid key format") ErrBadSignatureSize = errors.New("bad signature size")
var ErrInvalidSignature = errors.New("invalid signature") ErrInvalidKeyFormat = errors.New("invalid key format")
ErrInvalidSignature = errors.New("invalid signature")
)
// type for verifying signatures // type for verifying signatures
type Verifier interface { type Verifier interface {

View File

@@ -19,7 +19,6 @@ type Tunnel struct {
} }
func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) { func NewTunnelCrypto(layerKey, ivKey TunnelKey) (t *Tunnel, err error) {
t = new(Tunnel) t = new(Tunnel)
t.layerKey, err = aes.NewCipher(layerKey[:]) t.layerKey, err = aes.NewCipher(layerKey[:])
if err == nil { if err == nil {

View File

@@ -149,8 +149,10 @@ padding :: Data
total length: 222 total length: 222
*/ */
type BuildRequestRecordElGamalAES [528]byte type (
type BuildRequestRecordElGamal [528]byte BuildRequestRecordElGamalAES [528]byte
BuildRequestRecordElGamal [528]byte
)
type BuildRequestRecord struct { type BuildRequestRecord struct {
ReceiveTunnel tunnel.TunnelID ReceiveTunnel tunnel.TunnelID

View File

@@ -14,7 +14,6 @@ func TestReadBuildRequestRecordReceiveTunnelTooLittleData(t *testing.T) {
receive_tunnel, err := readBuildRequestRecordReceiveTunnel([]byte{0x01}) receive_tunnel, err := readBuildRequestRecordReceiveTunnel([]byte{0x01})
assert.Equal(tunnel.TunnelID(0), receive_tunnel) assert.Equal(tunnel.TunnelID(0), receive_tunnel)
assert.Equal(ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA, err) assert.Equal(ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA, err)
} }
func TestReadBuildRequestRecordReceiveTunnelValidData(t *testing.T) { func TestReadBuildRequestRecordReceiveTunnelValidData(t *testing.T) {

View File

@@ -38,8 +38,10 @@ byte 527 :: reply
total length: 528 total length: 528
*/ */
type BuildResponseRecordELGamalAES [528]byte type (
type BuildResponseRecordELGamal [528]byte BuildResponseRecordELGamalAES [528]byte
BuildResponseRecordELGamal [528]byte
)
type BuildResponseRecord struct { type BuildResponseRecord struct {
Hash common.Hash Hash common.Hash

343
lib/i2np/doc.md Normal file
View File

@@ -0,0 +1,343 @@
# i2np
--
import "github.com/go-i2p/go-i2p/lib/i2np"
## Usage
```go
const (
I2NP_MESSAGE_TYPE_DATABASE_STORE = 1
I2NP_MESSAGE_TYPE_DATABASE_LOOKUP = 2
I2NP_MESSAGE_TYPE_DATABASE_SEARCH_REPLY = 3
I2NP_MESSAGE_TYPE_DELIVERY_STATUS = 10
I2NP_MESSAGE_TYPE_GARLIC = 11
I2NP_MESSAGE_TYPE_TUNNEL_DATA = 18
I2NP_MESSAGE_TYPE_TUNNEL_GATEWAY = 19
I2NP_MESSAGE_TYPE_DATA = 20
I2NP_MESSAGE_TYPE_TUNNEL_BUILD = 21
I2NP_MESSAGE_TYPE_TUNNEL_BUILD_REPLY = 22
I2NP_MESSAGE_TYPE_VARIABLE_TUNNEL_BUILD = 23
I2NP_MESSAGE_TYPE_VARIABLE_TUNNEL_BUILD_REPLY = 24
)
```
```go
var ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA = errors.New("not enough i2np build request record data")
```
```go
var ERR_I2NP_NOT_ENOUGH_DATA = errors.New("not enough i2np header data")
```
#### func ReadI2NPNTCPData
```go
func ReadI2NPNTCPData(data []byte, size int) ([]byte, error)
```
#### func ReadI2NPNTCPMessageChecksum
```go
func ReadI2NPNTCPMessageChecksum(data []byte) (int, error)
```
#### func ReadI2NPNTCPMessageExpiration
```go
func ReadI2NPNTCPMessageExpiration(data []byte) (datalib.Date, error)
```
#### func ReadI2NPNTCPMessageID
```go
func ReadI2NPNTCPMessageID(data []byte) (int, error)
```
#### func ReadI2NPNTCPMessageSize
```go
func ReadI2NPNTCPMessageSize(data []byte) (int, error)
```
#### func ReadI2NPSSUMessageExpiration
```go
func ReadI2NPSSUMessageExpiration(data []byte) (datalib.Date, error)
```
#### func ReadI2NPType
```go
func ReadI2NPType(data []byte) (int, error)
```
#### type BuildRequestRecord
```go
type BuildRequestRecord struct {
ReceiveTunnel tunnel.TunnelID
OurIdent common.Hash
NextTunnel tunnel.TunnelID
NextIdent common.Hash
LayerKey session_key.SessionKey
IVKey session_key.SessionKey
ReplyKey session_key.SessionKey
ReplyIV [16]byte
Flag int
RequestTime time.Time
SendMessageID int
Padding [29]byte
}
```
#### func ReadBuildRequestRecord
```go
func ReadBuildRequestRecord(data []byte) (BuildRequestRecord, error)
```
#### type BuildRequestRecordElGamal
```go
type BuildRequestRecordElGamal [528]byte
```
#### type BuildRequestRecordElGamalAES
```go
type BuildRequestRecordElGamalAES [528]byte
```
#### type BuildResponseRecord
```go
type BuildResponseRecord struct {
Hash common.Hash
Padding [495]byte
Reply byte
}
```
#### type BuildResponseRecordELGamal
```go
type BuildResponseRecordELGamal [528]byte
```
#### type BuildResponseRecordELGamalAES
```go
type BuildResponseRecordELGamalAES [528]byte
```
#### type Data
```go
type Data struct {
Length int
Data []byte
}
```
#### type DatabaseLookup
```go
type DatabaseLookup struct {
Key common.Hash
From common.Hash
Flags byte
ReplyTunnelID [4]byte
Size int
ExcludedPeers []common.Hash
ReplyKey session_key.SessionKey
ReplyTags []session_tag.SessionTag
}
```
#### type DatabaseSearchReply
```go
type DatabaseSearchReply struct {
Key common.Hash
Count int
PeerHashes []common.Hash
From common.Hash
}
```
#### type DatabaseStore
```go
type DatabaseStore struct {
Key common.Hash
Type byte
ReplyToken [4]byte
ReplyTunnelID [4]byte
ReplyGateway common.Hash
Data []byte
}
```
#### type DeliveryStatus
```go
type DeliveryStatus struct {
MessageID int
Timestamp time.Time
}
```
#### type Garlic
```go
type Garlic struct {
Count int
Cloves []GarlicClove
Certificate certificate.Certificate
MessageID int
Expiration time.Time
}
```
#### type GarlicClove
```go
type GarlicClove struct {
DeliveryInstructions GarlicCloveDeliveryInstructions
I2NPMessage I2NPMessage
CloveID int
Expiration time.Time
Certificate certificate.Certificate
}
```
#### type GarlicCloveDeliveryInstructions
```go
type GarlicCloveDeliveryInstructions struct {
Flag byte
SessionKey session_key.SessionKey
Hash common.Hash
TunnelID tunnel.TunnelID
Delay int
}
```
#### type GarlicElGamal
```go
type GarlicElGamal []byte
```
#### type I2NPMessage
```go
type I2NPMessage []byte
```
#### type I2NPNTCPHeader
```go
type I2NPNTCPHeader struct {
Type int
MessageID int
Expiration time.Time
Size int
Checksum int
Data []byte
}
```
#### func ReadI2NPNTCPHeader
```go
func ReadI2NPNTCPHeader(data []byte) (I2NPNTCPHeader, error)
```
Read an entire I2NP message and return the parsed header with embedded encrypted
data
#### type I2NPSSUHeader
```go
type I2NPSSUHeader struct {
Type int
Expiration time.Time
}
```
#### func ReadI2NPSSUHeader
```go
func ReadI2NPSSUHeader(data []byte) (I2NPSSUHeader, error)
```
#### type TunnelBuild
```go
type TunnelBuild [8]BuildRequestRecord
```
#### type TunnelBuildReply
```go
type TunnelBuildReply [8]BuildResponseRecord
```
#### type TunnelData
```go
type TunnelData [1028]byte
```
#### type TunnelGatway
```go
type TunnelGatway struct {
TunnelID tunnel.TunnelID
Length int
Data []byte
}
```
#### type VariableTunnelBuild
```go
type VariableTunnelBuild struct {
Count int
BuildRequestRecords []BuildRequestRecord
}
```
#### type VariableTunnelBuildReply
```go
type VariableTunnelBuildReply struct {
Count int
BuildResponseRecords []BuildResponseRecord
}
```

View File

@@ -0,0 +1,12 @@
# exportable
--
import "github.com/go-i2p/go-i2p/lib/i2np/fuzz/header"
## Usage
#### func Fuzz
```go
func Fuzz(data []byte) int
```

182
lib/netdb/doc.md Normal file
View File

@@ -0,0 +1,182 @@
# netdb
--
import "github.com/go-i2p/go-i2p/lib/netdb"
## Usage
```go
const CacheFileName = "sizecache.txt"
```
name of file to hold precomputed size of netdb
#### type Entry
```go
type Entry struct {
*router_info.RouterInfo
*lease_set.LeaseSet
}
```
netdb entry wraps a router info and provides serialization
#### func (*Entry) ReadFrom
```go
func (e *Entry) ReadFrom(r io.Reader) (err error)
```
#### func (*Entry) WriteTo
```go
func (e *Entry) WriteTo(w io.Writer) (err error)
```
#### type NetworkDatabase
```go
type NetworkDatabase interface {
// obtain a RouterInfo by its hash locally
// return a RouterInfo if we found it locally
// return nil if the RouterInfo cannot be found locally
GetRouterInfo(hash common.Hash) router_info.RouterInfo
// store a router info locally
StoreRouterInfo(ri router_info.RouterInfo)
// try obtaining more peers with a bootstrap instance until we get minRouters number of router infos
// returns error if bootstrap.GetPeers returns an error otherwise returns nil
Reseed(b bootstrap.Bootstrap, minRouters int) error
// return how many router infos we have
Size() int
// Recaculate size of netdb from backend
RecalculateSize() error
// ensure underlying resources exist , i.e. directories, files, configs
Ensure() error
}
```
i2p network database, storage of i2p RouterInfos
#### type Resolver
```go
type Resolver interface {
// resolve a router info by hash
// return a chan that yields the found RouterInfo or nil if it could not be found after timeout
Lookup(hash common.Hash, timeout time.Duration) chan router_info.RouterInfo
}
```
resolves unknown RouterInfos given the hash of their RouterIdentity
#### func KademliaResolver
```go
func KademliaResolver(netDb NetworkDatabase, pool *tunnel.Pool) (r Resolver)
```
create a new resolver that stores result into a NetworkDatabase and uses a
tunnel pool for the lookup
#### type StdNetDB
```go
type StdNetDB struct {
DB string
RouterInfos map[common.Hash]Entry
LeaseSets map[common.Hash]Entry
}
```
standard network database implementation using local filesystem skiplist
#### func NewStdNetDB
```go
func NewStdNetDB(db string) StdNetDB
```
#### func (*StdNetDB) CheckFilePathValid
```go
func (db *StdNetDB) CheckFilePathValid(fpath string) bool
```
#### func (*StdNetDB) Create
```go
func (db *StdNetDB) Create() (err error)
```
create base network database directory
#### func (*StdNetDB) Ensure
```go
func (db *StdNetDB) Ensure() (err error)
```
ensure that the network database exists
#### func (*StdNetDB) Exists
```go
func (db *StdNetDB) Exists() bool
```
return true if the network db directory exists and is writable
#### func (*StdNetDB) GetRouterInfo
```go
func (db *StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.RouterInfo)
```
#### func (*StdNetDB) Path
```go
func (db *StdNetDB) Path() string
```
get netdb path
#### func (*StdNetDB) RecalculateSize
```go
func (db *StdNetDB) RecalculateSize() (err error)
```
recalculateSize recalculates cached size of netdb
#### func (*StdNetDB) Reseed
```go
func (db *StdNetDB) Reseed(b bootstrap.Bootstrap, minRouters int) (err error)
```
reseed if we have less than minRouters known routers returns error if reseed
failed
#### func (*StdNetDB) Save
```go
func (db *StdNetDB) Save() (err error)
```
#### func (*StdNetDB) SaveEntry
```go
func (db *StdNetDB) SaveEntry(e *Entry) (err error)
```
#### func (*StdNetDB) Size
```go
func (db *StdNetDB) Size() (routers int)
```
return how many routers we know about in our network database
#### func (*StdNetDB) SkiplistFile
```go
func (db *StdNetDB) SkiplistFile(hash common.Hash) (fpath string)
```
get the skiplist file that a RouterInfo with this hash would go in

View File

@@ -3,13 +3,15 @@ package netdb
import ( import (
"io" "io"
"github.com/go-i2p/go-i2p/lib/common/lease_set"
"github.com/go-i2p/go-i2p/lib/common/router_info" "github.com/go-i2p/go-i2p/lib/common/router_info"
) )
// netdb entry // netdb entry
// wraps a router info and provides serialization // wraps a router info and provides serialization
type Entry struct { type Entry struct {
ri router_info.RouterInfo *router_info.RouterInfo
*lease_set.LeaseSet
} }
func (e *Entry) WriteTo(w io.Writer) (err error) { func (e *Entry) WriteTo(w io.Writer) (err error) {

27
lib/netdb/reseed/doc.md Normal file
View File

@@ -0,0 +1,27 @@
# reseed
--
import "github.com/go-i2p/go-i2p/lib/netdb/reseed"
## Usage
```go
const (
I2pUserAgent = "Wget/1.11.4"
)
```
#### type Reseed
```go
type Reseed struct {
net.Dialer
}
```
#### func (Reseed) SingleReseed
```go
func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error)
```

View File

@@ -0,0 +1,94 @@
package reseed
import (
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"github.com/eyedeekay/go-unzip/pkg/unzip"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/config"
"github.com/go-i2p/go-i2p/lib/su3"
)
const (
I2pUserAgent = "Wget/1.11.4"
)
type Reseed struct {
net.Dialer
}
func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) {
transport := http.Transport{
DialContext: r.DialContext,
}
client := http.Client{
Transport: &transport,
}
URL, err := url.Parse(uri)
if err != nil {
return nil, err
}
header := http.Header{}
header.Add("user-agent", "Wget/1.11.4")
request := http.Request{
URL: URL,
Header: header,
}
response, err := client.Do(&request)
if err != nil {
return nil, err
}
su3file, err := su3.Read(response.Body)
if err != nil {
return nil, err
}
if su3file.FileType == su3.ZIP {
if su3file.ContentType == su3.RESEED {
if err == nil {
content, err := io.ReadAll(su3file.Content(""))
if err == nil {
signature, err := io.ReadAll(su3file.Signature())
if err != nil {
return nil, err
}
log.Println("warning: this doesn't validate the signature yet", signature)
}
zip := filepath.Join(config.RouterConfigProperties.NetDb.Path, "reseed.zip")
err = os.WriteFile(zip, content, 0o644)
if err != nil {
return nil, err
}
// content is a zip file, unzip it and get the files
files, err := unzip.New().Extract(zip, config.RouterConfigProperties.NetDb.Path)
if err != nil {
return nil, err
}
if len(files) <= 0 {
return nil, fmt.Errorf("error: reseed appears to have no content")
}
var ris []router_info.RouterInfo
for _, f := range files {
riB, err := os.ReadFile(f)
if err != nil {
continue
}
ri, _, err := router_info.ReadRouterInfo(riB)
if err != nil {
continue
}
ris = append(ris, ri)
}
err = os.Remove(zip)
return ris, err
}
}
}
return nil, fmt.Errorf("error: undefined reseed error")
}

View File

@@ -11,6 +11,7 @@ import (
"strings" "strings"
"github.com/go-i2p/go-i2p/lib/bootstrap" "github.com/go-i2p/go-i2p/lib/bootstrap"
"github.com/go-i2p/go-i2p/lib/common/base32"
"github.com/go-i2p/go-i2p/lib/common/base64" "github.com/go-i2p/go-i2p/lib/common/base64"
common "github.com/go-i2p/go-i2p/lib/common/data" common "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/router_info" "github.com/go-i2p/go-i2p/lib/common/router_info"
@@ -19,43 +20,66 @@ import (
) )
// standard network database implementation using local filesystem skiplist // standard network database implementation using local filesystem skiplist
type StdNetDB string type StdNetDB struct {
DB string
RouterInfos map[common.Hash]Entry
LeaseSets map[common.Hash]Entry
}
func (db StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.RouterInfo) { func NewStdNetDB(db string) StdNetDB {
fname := db.SkiplistFile(hash) return StdNetDB{
f, err := os.Open(fname) DB: db,
if err != nil { RouterInfos: make(map[common.Hash]Entry),
return nil LeaseSets: make(map[common.Hash]Entry),
} }
}
func (db *StdNetDB) GetRouterInfo(hash common.Hash) (chnl chan router_info.RouterInfo) {
if ri, ok := db.RouterInfos[hash]; ok {
chnl <- *ri.RouterInfo
return
}
fname := db.SkiplistFile(hash)
buff := new(bytes.Buffer) buff := new(bytes.Buffer)
_, err = io.Copy(buff, f) if f, err := os.Open(fname); err != nil {
f.Close() return nil
} else {
if _, err := io.Copy(buff, f); err != nil {
return nil
}
defer f.Close()
}
chnl = make(chan router_info.RouterInfo) chnl = make(chan router_info.RouterInfo)
ri, _, err := router_info.ReadRouterInfo(buff.Bytes()) ri, _, err := router_info.ReadRouterInfo(buff.Bytes())
if err == nil { if err == nil {
if _, ok := db.RouterInfos[hash]; !ok {
db.RouterInfos[hash] = Entry{
RouterInfo: &ri,
}
}
chnl <- ri chnl <- ri
} }
return return
} }
// get the skiplist file that a RouterInfo with this hash would go in // get the skiplist file that a RouterInfo with this hash would go in
func (db StdNetDB) SkiplistFile(hash common.Hash) (fpath string) { func (db *StdNetDB) SkiplistFile(hash common.Hash) (fpath string) {
fname := base64.EncodeToString(hash[:]) fname := base64.EncodeToString(hash[:])
fpath = filepath.Join(db.Path(), fmt.Sprintf("r%c", fname[0]), fmt.Sprintf("routerInfo-%s.dat", fname)) fpath = filepath.Join(db.Path(), fmt.Sprintf("r%c", fname[0]), fmt.Sprintf("routerInfo-%s.dat", fname))
return return
} }
// get netdb path // get netdb path
func (db StdNetDB) Path() string { func (db *StdNetDB) Path() string {
return string(db) return string(db.DB)
} }
// return how many routers we know about in our network database // return how many routers we know about in our network database
func (db StdNetDB) Size() (routers int) { func (db *StdNetDB) Size() (routers int) {
// TODO: implement this // TODO: implement this
var err error var err error
var data []byte var data []byte
if !util.CheckFileExists(db.cacheFilePath()) { if !util.CheckFileExists(db.cacheFilePath()) || util.CheckFileAge(db.cacheFilePath(), 2) || len(db.RouterInfos) == 0 {
// regenerate // regenerate
err = db.RecalculateSize() err = db.RecalculateSize()
if err != nil { if err != nil {
@@ -74,33 +98,63 @@ func (db StdNetDB) Size() (routers int) {
const CacheFileName = "sizecache.txt" const CacheFileName = "sizecache.txt"
// get filepath for storing netdb info cache // get filepath for storing netdb info cache
func (db StdNetDB) cacheFilePath() string { func (db *StdNetDB) cacheFilePath() string {
return filepath.Join(db.Path(), CacheFileName) return filepath.Join(db.Path(), CacheFileName)
} }
func (db StdNetDB) CheckFilePathValid(fpath string) bool { func (db *StdNetDB) CheckFilePathValid(fpath string) bool {
// TODO: make this better // TODO: make this better
return strings.HasSuffix(fpath, ".dat") return strings.HasSuffix(fpath, ".dat")
} }
// recalculateSize recalculates cached size of netdb // recalculateSize recalculates cached size of netdb
func (db StdNetDB) RecalculateSize() (err error) { func (db *StdNetDB) RecalculateSize() (err error) {
fpath := db.cacheFilePath()
count := 0 count := 0
err = filepath.Walk(fpath, func(fname string, info os.FileInfo, err error) error { err = filepath.Walk(db.Path(), func(fname string, info os.FileInfo, err error) error {
if info.IsDir() { if info.IsDir() {
if !strings.HasPrefix(fname, db.Path()) {
if db.Path() == fname {
log.Info("path==name time to exit")
return nil
}
log.Info("Outside of netDb dir time to exit", db.Path(), " ", fname)
return err
}
return err return err
} }
if db.CheckFilePathValid(fname) { if db.CheckFilePathValid(fname) {
// TODO: make sure it's in a skiplist directory log.Println("Reading in file:", fname)
b, err := os.ReadFile(fname)
if err != nil {
return err
}
ri, _, err := router_info.ReadRouterInfo(b)
if err != nil {
return err
}
ih := ri.IdentHash().Bytes()
log.Printf("Read in IdentHash: %s", base32.EncodeToString(ih[:]))
for _, addr := range ri.RouterAddresses() {
log.Println(string(addr.Bytes()))
}
if ent, ok := db.RouterInfos[ih]; !ok {
db.RouterInfos[ri.IdentHash()] = Entry{
RouterInfo: &ri,
}
} else {
log.Println("entry previously found in table", ent, fname)
}
ri = router_info.RouterInfo{}
count++ count++
} else {
log.Println("Invalid path error")
} }
return err return err
}) })
if err == nil { if err == nil {
str := fmt.Sprintf("%d", count) str := fmt.Sprintf("%d", count)
var f *os.File var f *os.File
f, err = os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0600) f, err = os.OpenFile(db.cacheFilePath(), os.O_CREATE|os.O_WRONLY, 0o600)
if err == nil { if err == nil {
_, err = io.WriteString(f, str) _, err = io.WriteString(f, str)
f.Close() f.Close()
@@ -110,7 +164,7 @@ func (db StdNetDB) RecalculateSize() (err error) {
} }
// return true if the network db directory exists and is writable // return true if the network db directory exists and is writable
func (db StdNetDB) Exists() bool { func (db *StdNetDB) Exists() bool {
p := db.Path() p := db.Path()
// check root directory // check root directory
_, err := os.Stat(p) _, err := os.Stat(p)
@@ -125,12 +179,11 @@ func (db StdNetDB) Exists() bool {
return err == nil return err == nil
} }
func (db StdNetDB) SaveEntry(e *Entry) (err error) { func (db *StdNetDB) SaveEntry(e *Entry) (err error) {
var f io.WriteCloser var f io.WriteCloser
var h common.Hash h := e.RouterInfo.IdentHash()
h = e.ri.IdentHash() // if err == nil {
//if err == nil { f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0o700)
f, err = os.OpenFile(db.SkiplistFile(h), os.O_WRONLY|os.O_CREATE, 0700)
if err == nil { if err == nil {
err = e.WriteTo(f) err = e.WriteTo(f)
f.Close() f.Close()
@@ -142,14 +195,27 @@ func (db StdNetDB) SaveEntry(e *Entry) (err error) {
return return
} }
func (db *StdNetDB) Save() (err error) {
for _, dbe := range db.RouterInfos {
if e := db.SaveEntry(&dbe); e != nil {
err = e
// TODO: log this
}
}
return
}
// reseed if we have less than minRouters known routers // reseed if we have less than minRouters known routers
// returns error if reseed failed // returns error if reseed failed
func (db StdNetDB) Reseed(b bootstrap.Bootstrap, minRouters int) (err error) { func (db *StdNetDB) Reseed(b bootstrap.Bootstrap, minRouters int) (err error) {
if db.Size() > minRouters {
return nil
}
return return
} }
// ensure that the network database exists // ensure that the network database exists
func (db StdNetDB) Ensure() (err error) { func (db *StdNetDB) Ensure() (err error) {
if !db.Exists() { if !db.Exists() {
err = db.Create() err = db.Create()
} }
@@ -157,8 +223,8 @@ func (db StdNetDB) Ensure() (err error) {
} }
// create base network database directory // create base network database directory
func (db StdNetDB) Create() (err error) { func (db *StdNetDB) Create() (err error) {
mode := os.FileMode(0700) mode := os.FileMode(0o700)
p := db.Path() p := db.Path()
log.Infof("Create network database in %s", p) log.Infof("Create network database in %s", p)

58
lib/router/doc.md Normal file
View File

@@ -0,0 +1,58 @@
# router
--
import "github.com/go-i2p/go-i2p/lib/router"
## Usage
#### type Router
```go
type Router struct {
}
```
i2p router type
#### func CreateRouter
```go
func CreateRouter() (r *Router, err error)
```
create router with default configuration
#### func FromConfig
```go
func FromConfig(c *config.RouterConfig) (r *Router, err error)
```
create router from configuration
#### func (*Router) Close
```go
func (r *Router) Close() error
```
Close closes any internal state and finallizes router resources so that nothing
can start up again
#### func (*Router) Start
```go
func (r *Router) Start()
```
Start starts router mainloop
#### func (*Router) Stop
```go
func (r *Router) Stop()
```
Stop starts stopping internal state of router
#### func (*Router) Wait
```go
func (r *Router) Wait()
```
Wait blocks until router is fully stopped

View File

@@ -1,10 +1,11 @@
package router package router
import ( import (
"time"
"github.com/go-i2p/go-i2p/lib/config" "github.com/go-i2p/go-i2p/lib/config"
"github.com/go-i2p/go-i2p/lib/netdb" "github.com/go-i2p/go-i2p/lib/netdb"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"time"
) )
// i2p router type // i2p router type
@@ -17,7 +18,7 @@ type Router struct {
// create router with default configuration // create router with default configuration
func CreateRouter() (r *Router, err error) { func CreateRouter() (r *Router, err error) {
cfg := config.DefaultRouterConfig cfg := config.RouterConfigProperties
r, err = FromConfig(cfg) r, err = FromConfig(cfg)
return return
} }
@@ -61,22 +62,28 @@ func (r *Router) Start() {
// run i2p router mainloop // run i2p router mainloop
func (r *Router) mainloop() { func (r *Router) mainloop() {
r.ndb = netdb.StdNetDB(r.cfg.NetDb.Path) r.ndb = netdb.NewStdNetDB(r.cfg.NetDb.Path)
// make sure the netdb is ready // make sure the netdb is ready
err := r.ndb.Ensure() var e error
if err == nil { if err := r.ndb.Ensure(); err != nil {
e = err
}
if sz := r.ndb.Size(); sz >= 0 {
log.Info("NetDB Size:", sz)
}
if e == nil {
// netdb ready // netdb ready
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Router) mainloop", "at": "(Router) mainloop",
}).Info("Router ready") }).Info("Router ready")
for err == nil { for e == nil {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
} else { } else {
// netdb failed // netdb failed
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(Router) mainloop", "at": "(Router) mainloop",
"reason": err.Error(), "reason": e.Error(),
}).Error("Netdb Startup failed") }).Error("Netdb Startup failed")
r.Stop() r.Stop()
} }

189
lib/su3/doc.md Normal file
View File

@@ -0,0 +1,189 @@
# su3
--
import "github.com/go-i2p/go-i2p/lib/su3"
Package su3 implements reading the SU3 file format.
SU3 files provide content that is signed by a known identity. They are used to
distribute many types of data, including reseed files, plugins, blocklists, and
more.
See: https://geti2p.net/spec/updates#su3-file-specification
The Read() function takes an io.Reader, and it returns a *SU3. The *SU3 contains
the SU3 file metadata, such as the type of the content and the signer ID. In
order to get the file contents, one must pass in the public key associated with
the file's signer, so that the signature can be validated. The content can still
be read without passing in the key, but after returning the full 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.
}
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))
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.
}
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 content
bytes will be thrown away. If you then attempt to read the content, you will get
an error. For clarification, see TestReadSignatureFirst.
## Usage
```go
var (
ErrMissingMagicBytes = errors.New("missing magic bytes")
ErrMissingUnusedByte6 = errors.New("missing unused byte 6")
ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version")
ErrMissingSignatureType = errors.New("missing or invalid signature type")
ErrUnsupportedSignatureType = errors.New("unsupported signature type")
ErrMissingSignatureLength = errors.New("missing signature length")
ErrMissingUnusedByte12 = errors.New("missing unused byte 12")
ErrMissingVersionLength = errors.New("missing version length")
ErrVersionTooShort = errors.New("version length too short")
ErrMissingUnusedByte14 = errors.New("missing unused byte 14")
ErrMissingSignerIDLength = errors.New("missing signer ID length")
ErrMissingContentLength = errors.New("missing content length")
ErrMissingUnusedByte24 = errors.New("missing unused byte 24")
ErrMissingFileType = errors.New("missing or invalid file type")
ErrMissingUnusedByte26 = errors.New("missing unused byte 26")
ErrMissingContentType = errors.New("missing or invalid content type")
ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39")
ErrMissingVersion = errors.New("missing version")
ErrMissingSignerID = errors.New("missing signer ID")
ErrMissingContent = errors.New("missing content")
ErrMissingSignature = errors.New("missing signature")
ErrInvalidPublicKey = errors.New("invalid public key")
ErrInvalidSignature = errors.New("invalid signature")
)
```
#### type ContentType
```go
type ContentType string
```
```go
const (
UNKNOWN ContentType = "unknown"
ROUTER_UPDATE ContentType = "router_update"
PLUGIN ContentType = "plugin"
RESEED ContentType = "reseed"
NEWS ContentType = "news"
BLOCKLIST ContentType = "blocklist"
)
```
#### type FileType
```go
type FileType string
```
```go
const (
ZIP FileType = "zip"
XML FileType = "xml"
HTML FileType = "html"
XML_GZIP FileType = "xml.gz"
TXT_GZIP FileType = "txt.gz"
DMG FileType = "dmg"
EXE FileType = "exe"
)
```
#### type SU3
```go
type SU3 struct {
SignatureType SignatureType
SignatureLength uint16
ContentLength uint64
FileType FileType
ContentType ContentType
Version string
SignerID string
}
```
#### func Read
```go
func Read(reader io.Reader) (su3 *SU3, err error)
```
#### func (*SU3) Content
```go
func (su3 *SU3) Content(publicKey interface{}) io.Reader
```
#### func (*SU3) Signature
```go
func (su3 *SU3) Signature() io.Reader
```
#### type SignatureType
```go
type SignatureType string
```
```go
const (
DSA_SHA1 SignatureType = "DSA-SHA1"
ECDSA_SHA256_P256 SignatureType = "ECDSA-SHA256-P256"
ECDSA_SHA384_P384 SignatureType = "ECDSA-SHA384-P384"
ECDSA_SHA512_P521 SignatureType = "ECDSA-SHA512-P521"
RSA_SHA256_2048 SignatureType = "RSA-SHA256-2048"
RSA_SHA384_3072 SignatureType = "RSA-SHA384-3072"
RSA_SHA512_4096 SignatureType = "RSA-SHA512-4096"
EdDSA_SHA512_Ed25519ph SignatureType = "EdDSA-SHA512-Ed25519ph"
)
```

View File

@@ -146,29 +146,31 @@ var contentTypes = map[byte]ContentType{
0x05: BLOCKLIST, 0x05: BLOCKLIST,
} }
var ErrMissingMagicBytes = errors.New("missing magic bytes") var (
var ErrMissingUnusedByte6 = errors.New("missing unused byte 6") ErrMissingMagicBytes = errors.New("missing magic bytes")
var ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version") ErrMissingUnusedByte6 = errors.New("missing unused byte 6")
var ErrMissingSignatureType = errors.New("missing or invalid signature type") ErrMissingFileFormatVersion = errors.New("missing or incorrect file format version")
var ErrUnsupportedSignatureType = errors.New("unsupported signature type") ErrMissingSignatureType = errors.New("missing or invalid signature type")
var ErrMissingSignatureLength = errors.New("missing signature length") ErrUnsupportedSignatureType = errors.New("unsupported signature type")
var ErrMissingUnusedByte12 = errors.New("missing unused byte 12") ErrMissingSignatureLength = errors.New("missing signature length")
var ErrMissingVersionLength = errors.New("missing version length") ErrMissingUnusedByte12 = errors.New("missing unused byte 12")
var ErrVersionTooShort = errors.New("version length too short") ErrMissingVersionLength = errors.New("missing version length")
var ErrMissingUnusedByte14 = errors.New("missing unused byte 14") ErrVersionTooShort = errors.New("version length too short")
var ErrMissingSignerIDLength = errors.New("missing signer ID length") ErrMissingUnusedByte14 = errors.New("missing unused byte 14")
var ErrMissingContentLength = errors.New("missing content length") ErrMissingSignerIDLength = errors.New("missing signer ID length")
var ErrMissingUnusedByte24 = errors.New("missing unused byte 24") ErrMissingContentLength = errors.New("missing content length")
var ErrMissingFileType = errors.New("missing or invalid file type") ErrMissingUnusedByte24 = errors.New("missing unused byte 24")
var ErrMissingUnusedByte26 = errors.New("missing unused byte 26") ErrMissingFileType = errors.New("missing or invalid file type")
var ErrMissingContentType = errors.New("missing or invalid content type") ErrMissingUnusedByte26 = errors.New("missing unused byte 26")
var ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39") ErrMissingContentType = errors.New("missing or invalid content type")
var ErrMissingVersion = errors.New("missing version") ErrMissingUnusedBytes28To39 = errors.New("missing unused bytes 28-39")
var ErrMissingSignerID = errors.New("missing signer ID") ErrMissingVersion = errors.New("missing version")
var ErrMissingContent = errors.New("missing content") ErrMissingSignerID = errors.New("missing signer ID")
var ErrMissingSignature = errors.New("missing signature") ErrMissingContent = errors.New("missing content")
var ErrInvalidPublicKey = errors.New("invalid public key") ErrMissingSignature = errors.New("missing signature")
var ErrInvalidSignature = errors.New("invalid signature") ErrInvalidPublicKey = errors.New("invalid public key")
ErrInvalidSignature = errors.New("invalid signature")
)
const magicBytes = "I2Psu3" const magicBytes = "I2Psu3"

View File

@@ -9,11 +9,12 @@ import (
"encoding/binary" "encoding/binary"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"github.com/stretchr/testify/assert"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func fileReader(t *testing.T, filename string) io.Reader { func fileReader(t *testing.T, filename string) io.Reader {
@@ -60,11 +61,13 @@ func fileRSAPubKey(t *testing.T, filename string) *rsa.PublicKey {
} }
// This fake data is generated in TestMain. // This fake data is generated in TestMain.
var aliceFakeKey *rsa.PrivateKey var (
var bobFakeKey *rsa.PrivateKey aliceFakeKey *rsa.PrivateKey
var aliceContent []byte bobFakeKey *rsa.PrivateKey
var aliceSignature []byte aliceContent []byte
var aliceSU3 []byte aliceSignature []byte
aliceSU3 []byte
)
func TestRead(t *testing.T) { func TestRead(t *testing.T) {
tests := []struct { tests := []struct {

122
lib/transport/doc.md Normal file
View File

@@ -0,0 +1,122 @@
# transport
--
import "github.com/go-i2p/go-i2p/lib/transport"
*
i2np messages transports
## Usage
```go
var ErrNoTransportAvailable = errors.New("no transports available")
```
error for when we have no transports available to use
#### type Transport
```go
type Transport interface {
// Accept accepts an incoming session.
Accept() (net.Conn, error)
// Addr returns an
Addr() net.Addr
// 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
SetIdentity(ident router_identity.RouterIdentity) error
// Obtain a transport session with a router given its RouterInfo.
// If a session with this router is NOT already made attempt to create one and block until made or until an error happens
// returns an established TransportSession and nil on success
// returns nil and an error on error
GetSession(routerInfo router_info.RouterInfo) (TransportSession, error)
// return true if a routerInfo is compatable with this transport
Compatable(routerInfo router_info.RouterInfo) bool
// close the transport cleanly
// blocks until done
// returns an error if one happens
Close() error
// get the name of this tranport as a string
Name() string
}
```
#### type TransportMuxer
```go
type TransportMuxer struct {
}
```
muxes multiple transports into 1 Transport implements transport.Transport
#### func Mux
```go
func Mux(t ...Transport) (tmux *TransportMuxer)
```
mux a bunch of transports together
#### func (*TransportMuxer) Close
```go
func (tmux *TransportMuxer) Close() (err error)
```
close every transport that this transport muxer has
#### func (*TransportMuxer) Compatable
```go
func (tmux *TransportMuxer) Compatable(routerInfo router_info.RouterInfo) (compat bool)
```
is there a transport that we mux that is compatable with this router info?
#### func (*TransportMuxer) GetSession
```go
func (tmux *TransportMuxer) GetSession(routerInfo router_info.RouterInfo) (s TransportSession, err error)
```
get a transport session given a router info return session and nil if successful
return nil and ErrNoTransportAvailable if we failed to get a session
#### func (*TransportMuxer) Name
```go
func (tmux *TransportMuxer) Name() string
```
the name of this transport with the names of all the ones that we mux
#### func (*TransportMuxer) SetIdentity
```go
func (tmux *TransportMuxer) SetIdentity(ident router_identity.RouterIdentity) (err error)
```
set the identity for every transport
#### type TransportSession
```go
type TransportSession interface {
// queue an i2np message to be sent over the session
// will block as long as the send queue is full
// does not block if the queue is not full
QueueSendI2NP(msg i2np.I2NPMessage)
// return how many i2np messages are not completely sent yet
SendQueueSize() int
// blocking read the next fully recv'd i2np message from this session
ReadNextI2NP() (i2np.I2NPMessage, error)
// close the session cleanly
// returns any errors that happen while closing the session
Close() error
}
```
a session between 2 routers for tranmitting i2np messages securly

View File

@@ -0,0 +1,68 @@
# ntcp
--
import "github.com/go-i2p/go-i2p/lib/transport/messages"
## Usage
```go
const (
MessageTypeSessionRequest = 0x00
MessageTypeSessionCreated = 0x01
MessageTypeSessionConfirmed = 0x02
MessageTypeData = 0x03
)
```
#### type Message
```go
type Message interface {
// Type returns the message type
Type() MessageType
// Payload returns the message payload
Payload() []byte
// PayloadSize returns the message payload size
PayloadSize() int
}
```
#### type MessageType
```go
type MessageType uint8
```
#### type SessionRequest
```go
type SessionRequest struct {
XContent []byte // 32-byte X value
Padding []byte // padding of message 1
}
```
#### func (*SessionRequest) Payload
```go
func (sr *SessionRequest) Payload() []byte
```
Payload returns the message payload
#### func (*SessionRequest) PayloadSize
```go
func (sr *SessionRequest) PayloadSize() int
```
PayloadSize returns the message payload size
#### func (*SessionRequest) Type
```go
func (sr *SessionRequest) Type() MessageType
```
Type returns the message type

View File

@@ -46,10 +46,12 @@ package ntcp
type MessageType uint8 type MessageType uint8
const MessageTypeSessionRequest = 0x00 const (
const MessageTypeSessionCreated = 0x01 MessageTypeSessionRequest = 0x00
const MessageTypeSessionConfirmed = 0x02 MessageTypeSessionCreated = 0x01
const MessageTypeData = 0x03 MessageTypeSessionConfirmed = 0x02
MessageTypeData = 0x03
)
type Message interface { type Message interface {
// Type returns the message type // Type returns the message type

View File

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

View File

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

270
lib/transport/noise/doc.md Normal file
View File

@@ -0,0 +1,270 @@
# noise
--
import "github.com/go-i2p/go-i2p/lib/transport/noise"
## Usage
```go
const FlushLimit = 640 * 1024
```
#### type Noise
```go
type Noise struct {
noise.Config
router_address.RouterAddress // always the local addr
*noise.HandshakeState
sync.Mutex
HandshakeStateResponsibility bool
}
```
wrapper around flynn/noise with just enough options exposed to enable
configuring NTCP2 possible and/or relatively intuitive
#### func NewNoise
```go
func NewNoise(ra router_address.RouterAddress) (ns *Noise, err error)
```
#### func (*Noise) Addr
```go
func (ns *Noise) Addr() net.Addr
```
#### func (*Noise) DialNoise
```go
func (ns *Noise) DialNoise(addr router_address.RouterAddress) (conn net.Conn, err error)
```
#### func (*Noise) ListenNoise
```go
func (ns *Noise) ListenNoise() (list NoiseListener, err error)
```
#### func (*Noise) LocalAddr
```go
func (ns *Noise) LocalAddr() net.Addr
```
#### type NoiseConn
```go
type NoiseConn struct {
*Noise
net.Conn
}
```
#### func (*NoiseConn) Close
```go
func (nc *NoiseConn) Close() error
```
Close implements net.Conn.
#### func (*NoiseConn) Frame
```go
func (nc *NoiseConn) Frame(header, body []byte) (err error)
```
#### func (*NoiseConn) HandshakeStateCreate
```go
func (nc *NoiseConn) HandshakeStateCreate(out, payload []byte) (by []byte, err error)
```
#### func (*NoiseConn) HandshakeStateRead
```go
func (nc *NoiseConn) HandshakeStateRead() (err error)
```
HandshakeStateRead reads a handshake's state off the socket for storage in the
NoiseConn.HandshakeState
#### func (*NoiseConn) LocalAddr
```go
func (nc *NoiseConn) LocalAddr() net.Addr
```
LocalAddr implements net.Conn.
#### func (*NoiseConn) Read
```go
func (nc *NoiseConn) Read(b []byte) (n int, err error)
```
Read implements net.Conn.
#### func (*NoiseConn) ReadMsg
```go
func (nc *NoiseConn) ReadMsg(b []byte) (by []byte, err error)
```
#### func (*NoiseConn) RemoteAddr
```go
func (nc *NoiseConn) RemoteAddr() net.Addr
```
RemoteAddr implements net.Conn.
#### func (*NoiseConn) SetCipherStates
```go
func (nc *NoiseConn) SetCipherStates(cs1, cs2 *noise.CipherState)
```
#### func (*NoiseConn) SetDeadline
```go
func (nc *NoiseConn) SetDeadline(t time.Time) error
```
SetDeadline implements net.Conn.
#### func (*NoiseConn) SetReadDeadline
```go
func (nc *NoiseConn) SetReadDeadline(t time.Time) error
```
SetReadDeadline implements net.Conn.
#### func (*NoiseConn) SetWriteDeadline
```go
func (nc *NoiseConn) SetWriteDeadline(t time.Time) error
```
SetWriteDeadline implements net.Conn.
#### func (*NoiseConn) Write
```go
func (nc *NoiseConn) Write(b []byte) (n int, err error)
```
Write implements net.Conn.
#### type NoiseListener
```go
type NoiseListener struct {
*Noise
net.Listener
}
```
#### func (*NoiseListener) Accept
```go
func (ns *NoiseListener) Accept() (net.Conn, error)
```
Accept implements net.Listener.
#### func (*NoiseListener) Addr
```go
func (ns *NoiseListener) Addr() net.Addr
```
Addr implements net.Listener.
#### func (*NoiseListener) Close
```go
func (ns *NoiseListener) Close() error
```
Close implements net.Listener.
#### type NoisePacketConn
```go
type NoisePacketConn struct {
*Noise
// this is always a actually a PacketConn
net.Conn
}
```
#### func (*NoisePacketConn) Close
```go
func (n *NoisePacketConn) Close() error
```
Close implements net.PacketConn. Subtle: this method shadows the method
(Conn).Close of NoisePacketConn.Conn.
#### func (*NoisePacketConn) LocalAddr
```go
func (n *NoisePacketConn) LocalAddr() net.Addr
```
LocalAddr implements net.PacketConn.
#### func (*NoisePacketConn) Read
```go
func (*NoisePacketConn) Read(b []byte) (n int, err error)
```
Read implements net.Conn.
#### func (*NoisePacketConn) ReadFrom
```go
func (*NoisePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error)
```
ReadFrom implements net.PacketConn.
#### func (*NoisePacketConn) RemoteAddr
```go
func (n *NoisePacketConn) RemoteAddr() net.Addr
```
RemoteAddr implements net.Conn.
#### func (*NoisePacketConn) SetDeadline
```go
func (n *NoisePacketConn) SetDeadline(t time.Time) error
```
SetDeadline implements net.PacketConn. Subtle: this method shadows the method
(PacketConn).SetDeadline of NoisePacketConn.PacketConn.
#### func (*NoisePacketConn) SetReadDeadline
```go
func (n *NoisePacketConn) SetReadDeadline(t time.Time) error
```
SetReadDeadline implements net.PacketConn. Subtle: this method shadows the
method (PacketConn).SetReadDeadline of NoisePacketConn.PacketConn.
#### func (*NoisePacketConn) SetWriteDeadline
```go
func (n *NoisePacketConn) SetWriteDeadline(t time.Time) error
```
SetWriteDeadline implements net.PacketConn. Subtle: this method shadows the
method (PacketConn).SetWriteDeadline of NoisePacketConn.PacketConn.
#### func (*NoisePacketConn) Write
```go
func (*NoisePacketConn) Write(b []byte) (n int, err error)
```
Write implements net.Conn.
#### func (*NoisePacketConn) WriteTo
```go
func (*NoisePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error)
```
WriteTo implements net.PacketConn.

View File

@@ -1,41 +0,0 @@
package noise
import (
"sync"
"github.com/go-i2p/go-i2p/lib/common/router_info"
)
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {
c.Mutex.Lock()
defer c.Mutex.Unlock()
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)
c.Mutex.Unlock()
session.(*NoiseSession).Mutex.Lock()
defer session.(*NoiseSession).Mutex.Unlock()
c.Mutex.Lock()
// if c.config.isClient {
if err := session.(*NoiseSession).RunClientHandshake(); err != nil {
return err
}
// Wake any other goroutines that are waiting for this handshake to
// complete.
session.(*NoiseSession).Cond.Broadcast()
session.(*NoiseSession).Cond = nil
return nil
}

View File

@@ -0,0 +1,154 @@
package noise
import (
"fmt"
"log"
"net"
"strconv"
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/common/router_address"
"github.com/go-i2p/go-i2p/lib/common/router_info"
)
// wrapper around flynn/noise with just enough options exposed to enable configuring NTCP2
// possible and/or relatively intuitive
type Noise struct {
noise.Config
router_info.RouterInfo // always the local
*noise.HandshakeState
HandshakeStateResponsibility bool
handshakeHash []byte
send, recv *noise.CipherState
readMsgBuf []byte
writeMsgBuf []byte
readBuf []byte
}
var (
ex_ns net.Conn = &NoiseConn{}
ex_ns_l net.Listener = &NoiseListener{}
ex_ns_u net.PacketConn = &NoisePacketConn{}
)
// NewNoise creates a new Noise-based transport with only the config for our side of the connection.
// It accepts a RouterInfo which should always be our own RouterInfo.
func NewNoise(ri router_info.RouterInfo) (ns *Noise, err error) {
ns = &Noise{}
ns.RouterInfo = ri
// sk, err := ra.StaticKey()
if err != nil {
return nil, err
}
ns.Config = noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
Pattern: noise.HandshakeXK,
// StaticKeypair: ,
// StaticKeypair: ,
// EphemeralKeypair: ,
}
return
}
func (ns *Noise) LocalAddr() net.Addr {
return &ns.RouterInfo
}
func (ns *Noise) Addr() net.Addr {
return ns.LocalAddr()
}
// MatchAddr finds a transport suitable for an incoming RouterAddress
func (ns *Noise) MatchAddr(addr net.Addr) (*router_address.RouterAddress, error) {
for index, address := range ns.RouterInfo.RouterAddresses() {
log.Println("index", index, "address", address)
if addr.Network() == address.Network() {
return address, nil
}
}
return nil, fmt.Errorf("no suitable address found for type %s from %s", addr.Network(), addr.String())
}
func dialWrapper(network, address string) (net.Conn, error) {
switch network {
case "SSU24":
return net.Dial("udp4", address)
case "SSU26":
return net.Dial("udp6", address)
case "NTCP2":
return net.Dial("tcp", address)
case "NTCP24":
return net.Dial("tcp4", address)
case "NTCP26":
return net.Dial("tcp6", address)
case "NTCP4":
return net.Dial("tcp4", address)
case "NTCP6":
return net.Dial("tcp6", address)
default:
return nil, fmt.Errorf("unknown transport, cannot dial %s", network)
}
}
func (ns Noise) DialNoise(addr router_address.RouterAddress) (net.Conn, error) {
cfg := ns
cfg.Initiator = false
network := addr.Network()
host, err := addr.Host()
if err != nil {
return nil, fmt.Errorf("host error: %s", err)
}
port, err := addr.Port()
if err != nil {
return nil, fmt.Errorf("port error: %s", err)
}
raddr := net.JoinHostPort(host.String(), port)
var netConn net.Conn
netConn, err = dialWrapper(network, raddr)
if err != nil {
return nil, fmt.Errorf("dial error: %s", err)
}
cfg.HandshakeState, err = noise.NewHandshakeState(cfg.Config)
if err != nil {
return nil, fmt.Errorf("handshake state initialization error: %s", err)
}
laddr, err := ns.MatchAddr(&addr)
if err != nil {
return nil, fmt.Errorf("transport mismatch error %s", err)
}
// cfg.Config.PeerEphemeral, err = AESDeObfuscateEphemeralKeys()
return &NoiseConn{
Noise: cfg,
Conn: netConn,
raddr: addr,
laddr: *laddr,
}, nil
}
func (ns Noise) ListenNoise(addr router_address.RouterAddress) (list NoiseListener, err error) {
cfg := ns
cfg.Initiator = false
network := "tcp"
host, err := addr.Host()
if err != nil {
return
}
port, err := addr.Port()
if err != nil {
return
}
portNum, _ := strconv.Atoi(port)
port = strconv.Itoa(portNum + 1)
hostip := net.JoinHostPort(host.String(), port)
listener, err := net.Listen(network, hostip)
if err != nil {
return
}
return NoiseListener{
Noise: cfg,
Listener: listener,
}, nil
}

View File

@@ -0,0 +1,138 @@
package noise
import (
"net"
"sync"
"time"
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/common/router_address"
)
const FlushLimit = 640 * 1024
type NoiseConn struct {
Noise
net.Conn
sync.Mutex
laddr, raddr router_address.RouterAddress
lock bool
}
func (ns *NoiseConn) unlockMutex() {
if ns.lock {
ns.lock = false
ns.Mutex.Unlock()
}
}
func (ns *NoiseConn) lockMutex() {
if !ns.lock {
ns.lock = true
ns.Mutex.Lock()
}
}
// Close implements net.Conn.
func (nc *NoiseConn) Close() error {
return nc.Conn.Close()
}
// LocalAddr implements net.Conn.
func (nc *NoiseConn) LocalAddr() net.Addr {
return &nc.laddr
}
// Write implements net.Conn.
func (nc *NoiseConn) Write(b []byte) (n int, err error) {
nc.lockMutex()
if nc.HandshakeState != nil {
defer nc.unlockMutex()
for nc.HandshakeState != nil && len(b) > 0 {
if !nc.Initiator {
// If we're the initiator, then we set that in advance and we already know.
// If not, we need to read the handshake state first.
err = nc.HandshakeStateRead()
if err != nil {
return n, err
}
}
// if the HandshakeState is not populated here we are the initiator.
// we could(should? shouldn't?) check both but for now I'm sticking with what
// NoiseConn does
if nc.HandshakeState != nil {
// choose either the length of b or the maximum length of a message
l := min(noise.MaxMsgLen, len(b))
// update the HandshakeState using l number of bytes to the write message buffer
nc.writeMsgBuf, err = nc.HandshakeStateCreate(nc.writeMsgBuf[:0], b[:l])
if err != nil {
return n, err
}
// write the message buffer to the socket
_, err = nc.Conn.Write(nc.writeMsgBuf)
if err != nil {
return n, err
}
n += l
b = b[l:]
}
}
}
nc.unlockMutex()
// zero-out the write buffer
nc.writeMsgBuf = nc.writeMsgBuf[:0]
for len(b) > 0 {
outlen := len(nc.writeMsgBuf)
l := min(noise.MaxMsgLen, len(b))
nc.writeMsgBuf, err = nc.send.Encrypt(append(nc.writeMsgBuf, make([]byte, 4)...), nil, b[:l])
if err != nil {
return n, err
}
err = nc.Frame(nc.writeMsgBuf[outlen:], nc.writeMsgBuf[outlen+4:])
if err != nil {
return n, err
}
n += l
b = b[l:]
if len(nc.writeMsgBuf) > FlushLimit {
_, err = nc.Conn.Write(nc.writeMsgBuf)
if err != nil {
return n, err
}
nc.writeMsgBuf = nc.writeMsgBuf[:0]
}
}
if len(nc.writeMsgBuf) > 0 {
_, err = nc.Conn.Write(nc.writeMsgBuf)
if err != nil {
return n, err
}
nc.writeMsgBuf = nc.writeMsgBuf[:0]
}
return n, nil
}
// Read implements net.Conn.
func (nc *NoiseConn) Read(b []byte) (n int, err error) {
panic("unimplemented")
}
// RemoteAddr implements net.Conn.
func (nc *NoiseConn) RemoteAddr() net.Addr {
panic("unimplemented")
}
// SetDeadline implements net.Conn.
func (nc *NoiseConn) SetDeadline(t time.Time) error {
panic("unimplemented")
}
// SetReadDeadline implements net.Conn.
func (nc *NoiseConn) SetReadDeadline(t time.Time) error {
panic("unimplemented")
}
// SetWriteDeadline implements net.Conn.
func (nc *NoiseConn) SetWriteDeadline(t time.Time) error {
panic("unimplemented")
}

View File

@@ -0,0 +1,63 @@
package noise
import "github.com/flynn/noise"
// HandshakeStateRead reads a handshake's state off the socket for storage in the
// NoiseConn.HandshakeState
func (nc *NoiseConn) HandshakeStateRead() (err error) {
nc.readMsgBuf, err = nc.ReadMsg(nc.readMsgBuf[:0])
if err != nil {
return err
}
var cs1, cs2 *noise.CipherState
nc.readBuf, cs1, cs2, err = nc.HandshakeState.ReadMessage(nc.readBuf, nc.readMsgBuf)
if err != nil {
return err
}
nc.SetCipherStates(cs1, cs2)
nc.HandshakeStateResponsibility = true
//if nc.rfmValidate != nil {
//err = nc.rfmValidate(nc.Conn.RemoteAddr(), nc.readMsgBuf)
//nc.rfmValidate = nil
//return err
//}
return nil
}
func (nc *NoiseConn) HandshakeStateCreate(out, payload []byte) (by []byte, err error) {
var cs1, cs2 *noise.CipherState
outlen := len(out)
out, cs1, cs2, err = nc.HandshakeState.WriteMessage(append(out, make([]byte, 4)...), payload)
if err != nil {
return nil, err
}
//if nc.rfmValidate != nil {
// only applies to responders, not initiators.
//nc.rfmValidate = nil
//}
nc.SetCipherStates(cs1, cs2)
nc.HandshakeStateResponsibility = false
// nc.readBarrier.Release()
return out, nc.Frame(out[outlen:], out[outlen+4:])
}
func (nc *NoiseConn) Frame(header, body []byte) (err error) {
return
}
func (nc *NoiseConn) ReadMsg(b []byte) (by []byte, err error) {
return
}
func (nc *NoiseConn) SetCipherStates(cs1, cs2 *noise.CipherState) {
if nc.Initiator {
nc.send, nc.recv = cs1, cs2
} else {
nc.send, nc.recv = cs2, cs1
}
if nc.send != nil {
// nc.readBarrier.Release()
nc.handshakeHash = nc.HandshakeState.ChannelBinding()
nc.HandshakeState = nil
}
}

View File

@@ -0,0 +1,44 @@
package noise
import (
"net"
"sync"
"github.com/flynn/noise"
)
type NoiseListener struct {
Noise
net.Listener
sync.Mutex
lock bool
}
// Addr implements net.Listener.
func (ns *NoiseListener) Addr() net.Addr {
return ns.Noise.Addr()
}
// Close implements net.Listener.
func (ns *NoiseListener) Close() error {
return ns.Listener.Close()
}
// Accept implements net.Listener.
func (ns *NoiseListener) Accept() (net.Conn, error) {
cfg := ns.Noise
cfg.Initiator = false
accept, err := ns.Listener.Accept()
if err != nil {
return nil, err
}
hs, err := noise.NewHandshakeState(ns.Config)
if err != nil {
return nil, err
}
cfg.HandshakeState = hs
return &NoiseConn{
Noise: cfg,
Conn: accept,
}, nil
}

View File

@@ -0,0 +1,40 @@
package noise
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/common/router_address"
log "github.com/sirupsen/logrus"
)
// Noise obfuscation functions used in I2P NTCP2 and SSU2 Handshakes,
// including obfuscating the ephemeral keys with a known key and IV found
// in the netDb.
func AESDeObfuscateEphemeralKeys(cipherText string, config noise.Config, bob router_address.RouterAddress) ([]byte, error) {
bobsStaticKey, err := bob.StaticKey()
if err != nil {
return nil, err
}
bobsInitializatonVector, err := bob.InitializationVector()
if err != nil {
return nil, err
}
log.WithFields(
log.Fields{
"at": "(noise) AESObfuscateEphemeralKeys",
}).Debugf("getting ready to deobfuscate our bob's ephemeral keys with bob's static key %s and IV %s", bobsStaticKey, bobsInitializatonVector)
deobfuscate, err := hex.DecodeString(cipherText)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(bobsStaticKey[:])
if err != nil {
return nil, err
}
mode := cipher.NewCBCDecrypter(block, bobsInitializatonVector[:])
mode.CryptBlocks([]byte(deobfuscate), []byte(deobfuscate))
return deobfuscate, nil
}

View File

@@ -0,0 +1,66 @@
package noise
import (
"net"
"time"
)
type NoisePacketConn struct {
*Noise
// this is always a actually a PacketConn
net.Conn
}
// Read implements net.Conn.
func (*NoisePacketConn) Read(b []byte) (n int, err error) {
panic("unimplemented")
}
// RemoteAddr implements net.Conn.
func (n *NoisePacketConn) RemoteAddr() net.Addr {
panic("unimplemented")
}
// Write implements net.Conn.
func (*NoisePacketConn) Write(b []byte) (n int, err error) {
panic("unimplemented")
}
// Close implements net.PacketConn.
// Subtle: this method shadows the method (Conn).Close of NoisePacketConn.Conn.
func (n *NoisePacketConn) Close() error {
return n.Conn.Close()
}
// LocalAddr implements net.PacketConn.
func (n *NoisePacketConn) LocalAddr() net.Addr {
return &n.Noise.RouterInfo
}
// ReadFrom implements net.PacketConn.
func (*NoisePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
panic("unimplemented")
}
// SetDeadline implements net.PacketConn.
// Subtle: this method shadows the method (PacketConn).SetDeadline of NoisePacketConn.PacketConn.
func (n *NoisePacketConn) SetDeadline(t time.Time) error {
panic("unimplemented")
}
// SetReadDeadline implements net.PacketConn.
// Subtle: this method shadows the method (PacketConn).SetReadDeadline of NoisePacketConn.PacketConn.
func (n *NoisePacketConn) SetReadDeadline(t time.Time) error {
panic("unimplemented")
}
// SetWriteDeadline implements net.PacketConn.
// Subtle: this method shadows the method (PacketConn).SetWriteDeadline of NoisePacketConn.PacketConn.
func (n *NoisePacketConn) SetWriteDeadline(t time.Time) error {
panic("unimplemented")
}
// WriteTo implements net.PacketConn.
func (*NoisePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
panic("unimplemented")
}

View File

@@ -0,0 +1,13 @@
package noise
import (
"testing"
)
func TestServer(t *testing.T) {
}
func TestEstablishment(t *testing.T) {
}

View File

@@ -1,85 +0,0 @@
package noise
import (
"bytes"
"net"
"sync"
"time"
cb "github.com/emirpasic/gods/queues/circularbuffer"
"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
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")
}
// SetDeadline implements net.Conn
func (*NoiseSession) SetDeadline(t time.Time) error {
panic("unimplemented")
}
// SetReadDeadline implements net.Conn
func (*NoiseSession) SetReadDeadline(t time.Time) error {
panic("unimplemented")
}
// SetWriteDeadline implements net.Conn
func (*NoiseSession) SetWriteDeadline(t time.Time) error {
panic("unimplemented")
}
var exampleNoiseSession transport.TransportSession = &NoiseSession{}
var ExampleNoiseSession net.Conn = exampleNoiseSession.(*NoiseSession)
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()
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
}

View File

@@ -1,96 +0,0 @@
package noise
/**
* NoiseTransport is an unused transport which is used only for testing the
* transport interfaces. I2P adds obfuscation to NOISE with the NTCP2 protocol
* which is one of the transports which we use in practice.
**/
import (
"errors"
"net"
"sync"
"github.com/flynn/noise"
"github.com/go-i2p/go-i2p/lib/common/data"
"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"
)
type NoiseTransport struct {
*noise.CipherState
router_identity.RouterIdentity
sync.Mutex
Listener net.Listener
peerConnections map[data.Hash]transport.TransportSession
}
var exampleNoiseTransport transport.Transport = &NoiseTransport{}
// ExampleNoiseListener is not a real Noise Listener, do not use it.
// It is exported so that it can be confirmed that the transport
// implements net.Listener
var ExampleNoiseListener net.Listener = exampleNoiseTransport
func (noopt *NoiseTransport) Accept() (net.Conn, error) {
return noopt.Listener.Accept()
}
func (noopt *NoiseTransport) Addr() net.Addr {
return noopt.Listener.Addr()
}
func (noopt *NoiseTransport) Name() string {
return "noise"
}
// 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 {
noopt.RouterIdentity = ident
return nil
}
// Obtain a transport session with a router given its RouterInfo.
// If a session with this router is NOT already made attempt to create one and block until made or until an error happens
// returns an established TransportSession and nil on success
// returns nil and an error on error
func (noopt *NoiseTransport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
hash := routerInfo.IdentHash()
if len(hash) == 0 {
return nil, errors.New("NoiseTransport: GetSession: RouterInfo has no IdentityHash")
}
if t, ok := noopt.peerConnections[hash]; ok == true {
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
}
}
return nil, err
}
// 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
}
// close the transport cleanly
// blocks until done
// returns an error if one happens
func (noopt *NoiseTransport) Close() error {
return nil
}
func NewNoiseTransport(netSocket net.Listener) *NoiseTransport {
return &NoiseTransport{
peerConnections: make(map[data.Hash]transport.TransportSession),
Listener: netSocket,
}
}

View File

@@ -1,16 +0,0 @@
package noise
import (
"net"
"testing"
)
func TestTransport(t *testing.T) {
ln, err := net.Listen("tcp", ":42069")
if err != nil {
t.Error(err)
}
nt := NewNoiseTransport(ln)
t.Log(nt.Name())
}

30
lib/transport/ntcp/doc.md Normal file
View File

@@ -0,0 +1,30 @@
# ntcp
--
import "github.com/go-i2p/go-i2p/lib/transport/ntcp"
## Usage
```go
const (
NTCP_PROTOCOL_VERSION = 2
NTCP_PROTOCOL_NAME = "NTCP2"
NTCP_MESSAGE_MAX_SIZE = 65537
)
```
#### type Session
```go
type Session struct{}
```
Session implements TransportSession An established transport session
#### type Transport
```go
type Transport struct{}
```
Transport is an ntcp transport implementing transport.Transport interface

View File

@@ -2,5 +2,4 @@ package ntcp
// Session implements TransportSession // Session implements TransportSession
// An established transport session // An established transport session
type Session struct { type Session struct{}
}

View File

@@ -11,5 +11,4 @@ const (
) )
// Transport is an ntcp transport implementing transport.Transport interface // Transport is an ntcp transport implementing transport.Transport interface
type Transport struct { type Transport struct{}
}

7
lib/transport/ssu/doc.md Normal file
View File

@@ -0,0 +1,7 @@
# ssu
--
import "github.com/go-i2p/go-i2p/lib/transport/ssu"
i2p ssu transport implementation
## Usage

View File

@@ -708,6 +708,7 @@ func maybeAppendDelay(di_flag DeliveryInstructions, data, current []byte) (now [
} }
return return
} }
func maybeAppendMessageID(di_flag DeliveryInstructions, di_type int, data, current []byte) (now []byte, err error) { func maybeAppendMessageID(di_flag DeliveryInstructions, di_type int, data, current []byte) (now []byte, err error) {
if di_type == FIRST_FRAGMENT { if di_type == FIRST_FRAGMENT {
if fragmented, _ := di_flag.Fragmented(); fragmented { if fragmented, _ := di_flag.Fragmented(); fragmented {

259
lib/tunnel/doc.md Normal file
View File

@@ -0,0 +1,259 @@
# tunnel
--
import "github.com/go-i2p/go-i2p/lib/tunnel"
i2p garlic tunnel implementation
## Usage
```go
const (
DT_LOCAL = iota
DT_TUNNEL
DT_ROUTER
DT_UNUSED
)
```
```go
const (
FIRST_FRAGMENT = iota
FOLLOW_ON_FRAGMENT
)
```
```go
const (
FLAG_SIZE = 1
TUNNEL_ID_SIZE = 4
HASH_SIZE = 32
DELAY_SIZE = 1
MESSAGE_ID_SIZE = 4
EXTENDED_OPTIONS_MIN_SIZE = 2
SIZE_FIELD_SIZE = 2
)
```
#### type DecryptedTunnelMessage
```go
type DecryptedTunnelMessage [1028]byte
```
#### func (DecryptedTunnelMessage) Checksum
```go
func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelIV
```
#### func (DecryptedTunnelMessage) DeliveryInstructionsWithFragments
```go
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment
```
Returns a slice of DeliveryInstructionWithFragment structures, which all of the
Delivery Instructions in the tunnel message and their corresponding
MessageFragment structures.
#### func (DecryptedTunnelMessage) ID
```go
func (decrypted_tunnel_message DecryptedTunnelMessage) ID() TunnelID
```
#### func (DecryptedTunnelMessage) IV
```go
func (decrypted_tunnel_message DecryptedTunnelMessage) IV() crypto.TunnelIV
```
#### type DelayFactor
```go
type DelayFactor byte
```
#### type DeliveryInstructions
```go
type DeliveryInstructions []byte
```
#### func (DeliveryInstructions) Delay
```go
func (delivery_instructions DeliveryInstructions) Delay() (delay_factor DelayFactor, err error)
```
Return the DelayFactor if present and any errors encountered parsing the
DeliveryInstructions.
#### func (DeliveryInstructions) DeliveryType
```go
func (delivery_instructions DeliveryInstructions) DeliveryType() (byte, error)
```
Return the delivery type for these DeliveryInstructions, can be of type
DT_LOCAL, DT_TUNNEL, DT_ROUTER, or DT_UNUSED.
#### func (DeliveryInstructions) ExtendedOptions
```go
func (delivery_instructions DeliveryInstructions) ExtendedOptions() (data []byte, err error)
```
Return the Extended Options data if present, or an error if not present.
Extended Options in unimplemented in the Java router and the presence of
extended options will generate a warning.
#### func (DeliveryInstructions) FragmentNumber
```go
func (delivery_instructions DeliveryInstructions) FragmentNumber() (int, error)
```
Read the integer stored in the 6-1 bits of a FOLLOW_ON_FRAGMENT's flag,
indicating the fragment number.
#### func (DeliveryInstructions) FragmentSize
```go
func (delivery_instructions DeliveryInstructions) FragmentSize() (frag_size uint16, err error)
```
Return the size of the associated I2NP fragment and an error if the data is
unavailable.
#### func (DeliveryInstructions) Fragmented
```go
func (delivery_instructions DeliveryInstructions) Fragmented() (bool, error)
```
Returns true if the Delivery Instructions are fragmented or false if the
following data contains the entire message
#### func (DeliveryInstructions) HasDelay
```go
func (delivery_instructions DeliveryInstructions) HasDelay() (bool, error)
```
Check if the delay bit is set. This feature in unimplemented in the Java router.
#### func (DeliveryInstructions) HasExtendedOptions
```go
func (delivery_instructions DeliveryInstructions) HasExtendedOptions() (bool, error)
```
Check if the extended options bit is set. This feature in unimplemented in the
Java router.
#### func (DeliveryInstructions) HasHash
```go
func (delivery_instructions DeliveryInstructions) HasHash() (bool, error)
```
#### func (DeliveryInstructions) HasTunnelID
```go
func (delivery_instructions DeliveryInstructions) HasTunnelID() (bool, error)
```
Check if the DeliveryInstructions is of type DT_TUNNEL.
#### func (DeliveryInstructions) Hash
```go
func (delivery_instructions DeliveryInstructions) Hash() (hash common.Hash, err error)
```
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.
#### func (DeliveryInstructions) LastFollowOnFragment
```go
func (delivery_instructions DeliveryInstructions) LastFollowOnFragment() (bool, error)
```
Read the value of the 0 bit of a FOLLOW_ON_FRAGMENT, which is set to 1 to
indicate the last fragment.
#### func (DeliveryInstructions) MessageID
```go
func (delivery_instructions DeliveryInstructions) MessageID() (msgid uint32, err error)
```
Return the I2NP Message ID or 0 and an error if the data is not available for
this DeliveryInstructions.
#### func (DeliveryInstructions) TunnelID
```go
func (delivery_instructions DeliveryInstructions) TunnelID() (tunnel_id uint32, err error)
```
Return the tunnel ID in this DeliveryInstructions or 0 and an error if the
DeliveryInstructions are not of type DT_TUNNEL.
#### func (DeliveryInstructions) Type
```go
func (delivery_instructions DeliveryInstructions) Type() (int, error)
```
Return if the DeliveryInstructions are of type FIRST_FRAGMENT or
FOLLOW_ON_FRAGMENT.
#### type DeliveryInstructionsWithFragment
```go
type DeliveryInstructionsWithFragment struct {
DeliveryInstructions DeliveryInstructions
MessageFragment []byte
}
```
#### type EncryptedTunnelMessage
```go
type EncryptedTunnelMessage crypto.TunnelData
```
#### func (EncryptedTunnelMessage) Data
```go
func (tm EncryptedTunnelMessage) Data() crypto.TunnelIV
```
#### func (EncryptedTunnelMessage) ID
```go
func (tm EncryptedTunnelMessage) ID() (tid TunnelID)
```
#### func (EncryptedTunnelMessage) IV
```go
func (tm EncryptedTunnelMessage) IV() crypto.TunnelIV
```
#### type Participant
```go
type Participant struct {
}
```
#### type Pool
```go
type Pool struct{}
```
a pool of tunnels which we have created
#### type TunnelID
```go
type TunnelID uint32
```

View File

@@ -2,6 +2,7 @@ package tunnel
import ( import (
"encoding/binary" "encoding/binary"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )

Some files were not shown because too many files have changed in this diff Show More