47 Commits

Author SHA1 Message Date
Haris Khan
ddba94d6ae remove printing 2024-11-15 22:48:57 -05:00
Haris Khan
767b91df49 clean up temp dirs 2024-11-15 22:47:36 -05:00
Haris Khan
1292098cf0 Merge remote-tracking branch 'origin/10k' into 10k 2024-11-15 22:45:04 -05:00
eyedeekay
24bc4c3c17 Implemented ed25519 SPK's 2024-11-15 22:29:42 -05:00
Haris Khan
81eb270351 !WIP! - 10k test 2024-11-15 22:06:23 -05:00
eyedeekay
b6f197cf92 This is not correct yet, work on key_certificate.go lines 216-245 2024-11-15 17:35:44 -05:00
eyedeekay
c10d98a3b2 export DEBUG_I2P=debug in Makefile so that extended logs show up in the tests 2024-11-15 16:52:37 -05:00
Haris Khan
6d16ca5f87 debugging info to investigate 2024-11-15 14:43:36 -05:00
Haris Khan
003d6c9ab8 !WIP! - 10k test 2024-11-15 13:53:44 -05:00
Haris Khan
015c4b23e2 pass sigType to NewRouterInfo 2024-11-15 11:49:10 -05:00
Haris Khan
e29c3c7abb formatting + implemented GetSignatureTypeFromCertificate 2024-11-15 11:31:29 -05:00
Haris Khan
6f6291a9f6 bounds checking 2024-11-15 11:31:10 -05:00
Haris Khan
767864d457 corrected order in Bytes() 2024-11-15 11:30:59 -05:00
Haris Khan
0a98236d85 adjusted test 2024-11-15 11:30:40 -05:00
Haris Khan
c1fa63f6ec added sigtype 2024-11-15 11:30:34 -05:00
Haris Khan
a75c275b4c Corrected Bytes()
-TODO: add logging
2024-11-15 11:30:11 -05:00
Haris Khan
d40b3e0cd3 added sig types 2024-11-15 11:14:05 -05:00
Haris Khan
2ee2d77d7c check if data slice is empty 2024-11-15 11:01:06 -05:00
eyedeekay
271cf56ded Fixes the padding generation but the reader still thinks something's wrong 2024-11-10 19:29:07 -05:00
eyedeekay
a29fa0bc03 Output the rest of the key certificate, that would probably help... 2024-11-10 17:15:56 -05:00
eyedeekay
63c48dd3b7 log the actual bytes in the test for now, make sure they're really there 2024-11-09 13:41:19 -05:00
eyedeekay
8bec47efd2 log the actual bytes in the test for now, make sure they're really there 2024-11-09 13:39:38 -05:00
eyedeekay
69a50e2035 Try adding a dummy address, change logging to show where not enough data was provided 2024-11-09 13:33:23 -05:00
eyedeekay
8319444890 Try adding a dummy address, change logging to show where not enough data was provided 2024-11-09 13:31:24 -05:00
eyedeekay
b378661e0e Fix LS test, update Noise Subsystem on README.md 2024-11-09 12:33:53 -05:00
Haris Khan
f4086e5f68 !WIP! - Router Info 2024-11-09 11:13:48 -05:00
Haris Khan
877fc707c4 !WIP! - Router Info 2024-11-09 01:04:44 -05:00
Haris Khan
98d05e27c8 !WIP! - Router Info 2024-11-09 00:53:17 -05:00
eyedeekay
4020db8a19 Refactor: Certificate Constructor: 2024-11-04 19:19:03 -05:00
eyedeekay
67a02f5d69 Noise: Refactor, remove unused fields 2024-11-04 18:26:17 -05:00
eyedeekay
ca1280231c Tidy 2024-11-04 15:25:54 -05:00
eyedeekay
02b309df43 Refactor: move HandshakeState to own struct in preparation for NTCP2 mods 2024-11-04 15:20:56 -05:00
eyedeekay
a5b3c3f194 NTCP2: Stub out NTCP2 and explain the task at hand, SSU2: Explain the plan 2024-11-04 00:24:08 -05:00
eyedeekay
0aa7a5554b Merge branch 'master' of github.com:go-i2p/go-i2p 2024-11-03 23:59:13 -05:00
eyedeekay
266a1b71d6 Cleanup: Move obfs.go to own package to avoid import cycle noise->ntcp. I probably should have caught that in review. 2024-11-03 23:58:49 -05:00
idk
d32f2e78ab Merge pull request #21 from hkh4n/config
move base dir from ~/go-i2p to ~/.go-i2p & other changes
2024-11-04 04:51:24 +00:00
idk
9e806bc32e Merge branch 'master' into config 2024-11-03 22:25:05 +00:00
idk
c52112a36f Merge pull request #22 from hkh4n/refactor
go mod tidy & fixed condition that was always true
2024-11-03 22:23:15 +00:00
eyedeekay
db0fd9f7e9 Management: rm PASTA.md 2024-11-03 15:53:23 -05:00
eyedeekay
3ab258cde6 Management: add ROADMAP.md 2024-11-03 15:53:13 -05:00
Haris Khan
20b9bbd8e4 go mod tidy & fixed condition that was always true 2024-11-03 01:52:48 -05:00
Haris Khan
1fa520613c replace deprecated function (ioutil -> os) 2024-11-03 00:14:45 -04:00
Haris Khan
fb99b98a7e minor typo fix 2024-11-02 21:37:56 -04:00
Haris Khan
d6b8cd9d4d go mod tidy 2024-11-02 21:37:29 -04:00
Haris Khan
92e4656774 move from ~/go-i2p to ~/.go-i2p 2024-11-02 21:37:23 -04:00
Haris Khan
5f2bfb8d9d gofumpt adjustment 2024-11-02 21:36:55 -04:00
idk
9494c226a6 Merge pull request #19 from go-i2p/noise-experimental
Noise Subsystem
2024-11-02 02:59:43 +00:00
72 changed files with 1654 additions and 536 deletions

View File

@@ -3,6 +3,7 @@ RELEASE_VERSION=${RELEASE_TAG}
RELEASE_DESCRIPTION=`cat PASTA.md`
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
CGO_ENABLED=0
export DEBUG_I2P=debug
ifdef GOROOT
GO = $(GOROOT)/bin/go

View File

@@ -1,18 +0,0 @@
At long last... something useful
================================
It's been 2 years of me mostly not having time to work on go-i2p itself since my last update.
However, after much waiting, this library is actually **useful** for something.
It is now being used in the `reseed-tools` application to examine RouterInfos prior to including them in reseed bundles.
Routers that self-report as unreachable or congested will be excluded from future reseed bundles.
Additionally, routers that self-report an old version will be excluded from reseed bundles.
This should help new users build better connections faster with the existing, working router implementations.
This is not a working release of a go-i2p router
------------------------------------------------
It is a numbered version of the go-i2p library, which is pre-release, expressly for use in the `reseed-tools` application.
The common library works, and so do some of the cryptographic primitives, however the API is unstable and the software itself is certain to have serious bugs outside of a few well-tested areas.
If you're using it for something other than parsing and analyzing RouterInfos and LeaseSets, you'll probably encounter bugs.
Please report them to the https://github.com/go-i2p/go-i2p
Use any part of it at your own risk.

View File

@@ -41,7 +41,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Elligator2
- [ ] HKDF
- [ ] HMAC
- [/] Noise subsystem
- [X] Noise subsystem
- End-to-End Crypto
- [ ] Garlic messages
- [ ] ElGamal/AES+SessionTag
@@ -111,7 +111,7 @@ export DEBUG_I2P=warn
export DEBUG_I2P=error
```
If I2P_DEBUG is set to an unrecognized variable, it will fall back to "debug".
If DEBUG_I2P is set to an unrecognized variable, it will fall back to "debug".
## Contributing

41
ROADMAP.md Normal file
View File

@@ -0,0 +1,41 @@
# go-i2p Implementation Roadmap
## Transport Layer (NTCP2)
- Build on existing lib/transport/noise implementation
- Core NTCP2 components:
* Session handshake using noise protocol
* Connection management
* I2NP message transport
## Reseed System
- SU3 file format implementation:
* Format parsing and validation(Much of this work is done in reseed-tools, may need to be moved here)
* Signature verification system(Much of this work is done in reseed-tools, may need to be moved here)
- Local reseed functionality:
* File-based reseed operations
- Self-signed/Package-pinned X.509 certificate handling for reseed validation
## NetDb and Database Store
- Database Store message handling:
* Message structure implementation
* Message handling implementation
- NetDb core implementation:
* RouterInfo management
* LeaseSet management
* Lookup system
* Storage interface
* Peer selection logic?(Maybe do something very basic for now like i2pd used to do, and then improve it later, the important part will be interface design at first)
## Tunnel Implementation
- Tunnel cryptography:
* Key generation and management
* Layered encryption scheme
- Message processing:
* Build request/response handling
* Gateway implementation
* Message forwarding logic
Notes:
- Excluding legacy protocols (SSU1, NTCP1, elgamal, DSA)
- Leveraging existing noise protocol implementation
- SSU2 is not on this roadmap but is fair game for implementation as soon as NTCP2 is done. We're focused on NTCP2 to get this thing sending I2NP messages.

View File

@@ -1,15 +1,15 @@
test-crypto-aes-all: test-crypto-aes-core test-crypto-aes-validation test-crypto-aes-padding
test-crypto-aes-core:
go test -v ./lib/crypto -run TestAESEncryptDecrypt
$(GO) test -v ./lib/crypto -run TestAESEncryptDecrypt
test-crypto-aes-validation:
go test -v ./lib/crypto -run TestAESEncryptInvalidKey
go test -v ./lib/crypto -run TestAESDecryptInvalidInput
$(GO) test -v ./lib/crypto -run TestAESEncryptInvalidKey
$(GO) test -v ./lib/crypto -run TestAESDecryptInvalidInput
test-crypto-aes-padding:
go test -v ./lib/crypto -run TestPKCS7PadUnpad
go test -v ./lib/crypto -run TestPKCS7UnpadInvalidInput
$(GO) test -v ./lib/crypto -run TestPKCS7PadUnpad
$(GO) test -v ./lib/crypto -run TestPKCS7UnpadInvalidInput
.PHONY: test-crypto-aes-all \
test-crypto-aes-core \

View File

@@ -1,4 +1,4 @@
test-base32-encode-decode-not-mangled:
go test -v ./lib/common/base32 -run TestEncodeDecodeNotMangled
$(GO) test -v ./lib/common/base32 -run TestEncodeDecodeNotMangled
.PHONY: test-base32-encode-decode-not-mangled

View File

@@ -1,4 +1,4 @@
test-base64-encode-decode-not-mangled:
go test -v ./lib/common/base64 -run TestEncodeDecodeNotMangled
$(GO) test -v ./lib/common/base64 -run TestEncodeDecodeNotMangled
.PHONY: test-base64-encode-decode-not-mangled

View File

@@ -1,22 +1,22 @@
test-build-request-all: test-build-request-receive test-build-request-ident test-build-request-components
test-build-request-receive:
go test -v ./lib/i2np -run TestReadBuildRequestRecordReceiveTunnel
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordReceiveTunnel
test-build-request-ident:
go test -v ./lib/i2np -run TestReadBuildRequestRecordOurIdent
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordOurIdent
test-build-request-components:
go test -v ./lib/i2np -run TestReadBuildRequestRecordNextTunnel
go test -v ./lib/i2np -run TestReadBuildRequestRecordNextIdent
go test -v ./lib/i2np -run TestReadBuildRequestRecordLayerKey
go test -v ./lib/i2np -run TestReadBuildRequestRecordIVKey
go test -v ./lib/i2np -run TestReadBuildRequestRecordReplyKey
go test -v ./lib/i2np -run TestReadBuildRequestRecordReplyIV
go test -v ./lib/i2np -run TestReadBuildRequestRecordFlag
go test -v ./lib/i2np -run TestReadBuildRequestRecordRequestTime
go test -v ./lib/i2np -run TestReadBuildRequestRecordSendMessageID
go test -v ./lib/i2np -run TestReadBuildRequestRecordPadding
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordNextTunnel
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordNextIdent
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordLayerKey
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordIVKey
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordReplyKey
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordReplyIV
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordFlag
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordRequestTime
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordSendMessageID
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordPadding
.PHONY: test-build-request-all \
test-build-request-receive \

View File

@@ -2,46 +2,46 @@
test-cert-all: test-cert-type test-cert-length test-cert-data test-cert-read test-cert-length-correct test-cert-length-too-short test-cert-length-data-short test-cert-data-correct test-cert-data-too-long test-cert-data-too-short test-cert-read-correct test-cert-read-short test-cert-read-remainder test-cert-read-invalid
test-cert-type:
go test -v ./lib/common/certificate -run TestCertificateTypeIsFirstByte
$(GO) test -v ./lib/common/certificate -run TestCertificateTypeIsFirstByte
test-cert-length:
go test -v ./lib/common/certificate -run TestCertificateLength
$(GO) test -v ./lib/common/certificate -run TestCertificateLength
test-cert-data:
go test -v ./lib/common/certificate -run TestCertificateData
$(GO) test -v ./lib/common/certificate -run TestCertificateData
test-cert-read:
go test -v ./lib/common/certificate -run TestReadCertificate
$(GO) test -v ./lib/common/certificate -run TestReadCertificate
test-cert-length-correct:
go test -v ./lib/common/certificate -run TestCertificateLengthCorrect
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthCorrect
test-cert-length-too-short:
go test -v ./lib/common/certificate -run TestCertificateLengthErrWhenTooShort
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthErrWhenTooShort
test-cert-length-data-short:
go test -v ./lib/common/certificate -run TestCertificateLengthErrWhenDataTooShort
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthErrWhenDataTooShort
test-cert-data-correct:
go test -v ./lib/common/certificate -run TestCertificateDataWhenCorrectSize
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenCorrectSize
test-cert-data-too-long:
go test -v ./lib/common/certificate -run TestCertificateDataWhenTooLong
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenTooLong
test-cert-data-too-short:
go test -v ./lib/common/certificate -run TestCertificateDataWhenTooShort
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenTooShort
test-cert-read-correct:
go test -v ./lib/common/certificate -run TestReadCertificateWithCorrectData
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithCorrectData
test-cert-read-short:
go test -v ./lib/common/certificate -run TestReadCertificateWithDataTooShort
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithDataTooShort
test-cert-read-remainder:
go test -v ./lib/common/certificate -run TestReadCertificateWithRemainder
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithRemainder
test-cert-read-invalid:
go test -v ./lib/common/certificate -run TestReadCertificateWithInvalidLength
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithInvalidLength
# Declare all targets as PHONY
.PHONY: test-cert-all \

View File

@@ -1,2 +1,2 @@
test-date-time-from-milliseconds:
go test -v ./lib/common/data -run TestTimeFromMilliseconds
$(GO) test -v ./lib/common/data -run TestTimeFromMilliseconds

View File

@@ -1,17 +1,17 @@
test-crypto-dsa-all: test-crypto-dsa test-crypto-dsa-benchmarks
test-crypto-dsa:
go test -v ./lib/crypto -run TestDSA
$(GO) test -v ./lib/crypto -run TestDSA
test-crypto-dsa-benchmarks:
go test -v ./lib/crypto -bench=DSA -run=^$
$(GO) test -v ./lib/crypto -bench=DSA -run=^$
# Individual benchmarks
test-crypto-dsa-bench-generate:
go test -v ./lib/crypto -bench=DSAGenerate -run=^$
$(GO) test -v ./lib/crypto -bench=DSAGenerate -run=^$
test-crypto-dsa-bench-sign-verify:
go test -v ./lib/crypto -bench=DSASignVerify -run=^$
$(GO) test -v ./lib/crypto -bench=DSASignVerify -run=^$
.PHONY: test-crypto-dsa-all \
test-crypto-dsa \

View File

@@ -1,7 +1,7 @@
test-crypto-ed25519-all: test-crypto-ed25519
test-crypto-ed25519:
go test -v ./lib/crypto -run TestEd25519
$(GO) test -v ./lib/crypto -run TestEd25519
.PHONY: test-crypto-ed25519-all \
test-crypto-ed25519

View File

@@ -1,20 +1,20 @@
test-crypto-elg-all: test-crypto-elg test-crypto-elg-benchmarks
test-crypto-elg:
go test -v ./lib/crypto -run TestElg
$(GO) test -v ./lib/crypto -run TestElg
test-crypto-elg-benchmarks:
go test -v ./lib/crypto -bench=Elg -run=^$
$(GO) test -v ./lib/crypto -bench=Elg -run=^$
# Individual benchmarks
test-crypto-elg-bench-generate:
go test -v ./lib/crypto -bench=ElgGenerate -run=^$
$(GO) test -v ./lib/crypto -bench=ElgGenerate -run=^$
test-crypto-elg-bench-encrypt:
go test -v ./lib/crypto -bench=ElgEncrypt -run=^$
$(GO) test -v ./lib/crypto -bench=ElgEncrypt -run=^$
test-crypto-elg-bench-decrypt:
go test -v ./lib/crypto -bench=ElgDecrypt -run=^$
$(GO) test -v ./lib/crypto -bench=ElgDecrypt -run=^$
.PHONY: test-crypto-elg-all \
test-crypto-elg \

View File

@@ -2,24 +2,24 @@
test-i2np-header-all: test-i2np-type test-i2np-message test-i2np-expiration test-i2np-ntcp-components test-i2np-data test-i2np-regression
test-i2np-type:
go test -v ./lib/i2np -run TestReadI2NPTypeWith
$(GO) test -v ./lib/i2np -run TestReadI2NPTypeWith
test-i2np-message:
go test -v ./lib/i2np -run TestReadI2NPNTCPMessageID
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPMessageID
test-i2np-expiration:
go test -v ./lib/i2np -run TestReadI2NPNTCPMessageExpiration
go test -v ./lib/i2np -run TestReadI2NPSSUMessageExpiration
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPMessageExpiration
$(GO) test -v ./lib/i2np -run TestReadI2NPSSUMessageExpiration
test-i2np-ntcp-components:
go test -v ./lib/i2np -run TestReadI2NPNTCPMessageSize
go test -v ./lib/i2np -run TestReadI2NPNTCPMessageChecksum
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPMessageSize
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPMessageChecksum
test-i2np-data:
go test -v ./lib/i2np -run TestReadI2NPNTCPData
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPData
test-i2np-regression:
go test -v ./lib/i2np -run TestCrasherRegression123781
$(GO) test -v ./lib/i2np -run TestCrasherRegression123781
.PHONY: test-i2np-header-all \
test-i2np-type \

View File

@@ -1,7 +1,7 @@
test-crypto-hmac-all: test-crypto-hmac
test-crypto-hmac:
go test -v ./lib/crypto -run Test_I2PHMAC
$(GO) test -v ./lib/crypto -run Test_I2PHMAC
.PHONY: test-crypto-hmac-all \
test-crypto-hmac

View File

@@ -1,13 +1,13 @@
test-integer-all: test-integer-big-endian test-integer-one-byte test-integer-zero
test-integer-big-endian:
go test -v ./lib/common/integer -run TestIntegerBigEndian
$(GO) test -v ./lib/common/integer -run TestIntegerBigEndian
test-integer-one-byte:
go test -v ./lib/common/integer -run TestWorksWithOneByte
$(GO) test -v ./lib/common/integer -run TestWorksWithOneByte
test-integer-zero:
go test -v ./lib/common/integer -run TestIsZeroWithNoData
$(GO) test -v ./lib/common/integer -run TestIsZeroWithNoData
.PHONY: test-integer-all \
test-integer-big-endian \

View File

@@ -1,21 +1,21 @@
test-key-cert-all: test-key-cert-signing test-key-cert-public test-key-cert-construct
test-key-cert-signing:
go test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReturnsCorrectInteger
go test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReportsWhenDataTooSmall
go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyReportsWhenDataTooSmall
go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithDSASHA1
go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP256
go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP384
go test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP521
$(GO) test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReturnsCorrectInteger
$(GO) test -v ./lib/common/key_certificate -run TestSingingPublicKeyTypeReportsWhenDataTooSmall
$(GO) test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyReportsWhenDataTooSmall
$(GO) test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithDSASHA1
$(GO) test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP256
$(GO) test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP384
$(GO) test -v ./lib/common/key_certificate -run TestConstructSigningPublicKeyWithP521
test-key-cert-public:
go test -v ./lib/common/key_certificate -run TestPublicKeyTypeReturnsCorrectInteger
go test -v ./lib/common/key_certificate -run TestPublicKeyTypeReportsWhenDataTooSmall
$(GO) test -v ./lib/common/key_certificate -run TestPublicKeyTypeReturnsCorrectInteger
$(GO) test -v ./lib/common/key_certificate -run TestPublicKeyTypeReportsWhenDataTooSmall
test-key-cert-construct:
go test -v ./lib/common/key_certificate -run TestConstructPublicKeyReportsWhenDataTooSmall
go test -v ./lib/common/key_certificate -run TestConstructPublicKeyReturnsCorrectDataWithElg
$(GO) test -v ./lib/common/key_certificate -run TestConstructPublicKeyReportsWhenDataTooSmall
$(GO) test -v ./lib/common/key_certificate -run TestConstructPublicKeyReturnsCorrectDataWithElg
.PHONY: test-key-cert-all \
test-key-cert-signing \

View File

@@ -1,27 +1,27 @@
test-keys-cert-all: test-keys-cert-certificate test-keys-cert-public test-keys-cert-signing test-keys-cert-creation
test-keys-cert-certificate:
go test -v ./lib/common/keys_and_cert -run TestCertificateWithValidData
$(GO) test -v ./lib/common/keys_and_cert -run TestCertificateWithValidData
test-keys-cert-public:
go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadData
go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadCertificate
go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithNullCertificate
go test -v ./lib/common/keys_and_cert -run TestPublicKeyWithKeyCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadData
$(GO) test -v ./lib/common/keys_and_cert -run TestPublicKeyWithBadCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestPublicKeyWithNullCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestPublicKeyWithKeyCertificate
test-keys-cert-signing:
go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadData
go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadCertificate
go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithNullCertificate
go test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithKeyCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadData
$(GO) test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithBadCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithNullCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestSigningPublicKeyWithKeyCertificate
test-keys-cert-creation:
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingData
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingCertData
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificate
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificate
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificateAndRemainder
go test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingData
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithMissingCertData
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificate
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithCertificateAndRemainder
$(GO) test -v ./lib/common/keys_and_cert -run TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder
.PHONY: test-keys-cert-all \
test-keys-cert-certificate \

View File

@@ -1,20 +1,20 @@
test-lease-set-all: test-lease-set-basic test-lease-set-leases test-lease-set-expiration
test-lease-set-basic:
go test -v ./lib/common/lease_set -run TestDestinationIsCorrect
go test -v ./lib/common/lease_set -run TestPublicKeyIsCorrect
go test -v ./lib/common/lease_set -run TestSigningKeyIsCorrect
go test -v ./lib/common/lease_set -run TestSignatureIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestDestinationIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestPublicKeyIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestSigningKeyIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestSignatureIsCorrect
test-lease-set-leases:
go test -v ./lib/common/lease_set -run TestLeaseCountCorrect
go test -v ./lib/common/lease_set -run TestLeaseCountCorrectWithMultiple
go test -v ./lib/common/lease_set -run TestLeaseCountErrorWithTooMany
go test -v ./lib/common/lease_set -run TestLeasesHaveCorrectData
$(GO) test -v ./lib/common/lease_set -run TestLeaseCountCorrect
$(GO) test -v ./lib/common/lease_set -run TestLeaseCountCorrectWithMultiple
$(GO) test -v ./lib/common/lease_set -run TestLeaseCountErrorWithTooMany
$(GO) test -v ./lib/common/lease_set -run TestLeasesHaveCorrectData
test-lease-set-expiration:
go test -v ./lib/common/lease_set -run TestNewestExpirationIsCorrect
go test -v ./lib/common/lease_set -run TestOldestExpirationIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestNewestExpirationIsCorrect
$(GO) test -v ./lib/common/lease_set -run TestOldestExpirationIsCorrect
.PHONY: test-lease-set-all \
test-lease-set-basic \

View File

@@ -1,25 +1,25 @@
test-mapping-all: test-mapping-values test-mapping-duplicates test-mapping-conversion test-mapping-utils
test-mapping-values:
go test -v ./lib/common/data -run TestValuesExclusesPairWithBadData
go test -v ./lib/common/data -run TestValuesWarnsMissingData
go test -v ./lib/common/data -run TestValuesWarnsExtraData
go test -v ./lib/common/data -run TestValuesEnforcesEqualDelimitor
go test -v ./lib/common/data -run TestValuesEnforcedSemicolonDelimitor
go test -v ./lib/common/data -run TestValuesReturnsValues
$(GO) test -v ./lib/common/data -run TestValuesExclusesPairWithBadData
$(GO) test -v ./lib/common/data -run TestValuesWarnsMissingData
$(GO) test -v ./lib/common/data -run TestValuesWarnsExtraData
$(GO) test -v ./lib/common/data -run TestValuesEnforcesEqualDelimitor
$(GO) test -v ./lib/common/data -run TestValuesEnforcedSemicolonDelimitor
$(GO) test -v ./lib/common/data -run TestValuesReturnsValues
test-mapping-duplicates:
go test -v ./lib/common/data -run TestHasDuplicateKeysTrueWhenDuplicates
go test -v ./lib/common/data -run TestHasDuplicateKeysFalseWithoutDuplicates
go test -v ./lib/common/data -run TestReadMappingHasDuplicateKeys
$(GO) test -v ./lib/common/data -run TestHasDuplicateKeysTrueWhenDuplicates
$(GO) test -v ./lib/common/data -run TestHasDuplicateKeysFalseWithoutDuplicates
$(GO) test -v ./lib/common/data -run TestReadMappingHasDuplicateKeys
test-mapping-conversion:
go test -v ./lib/common/data -run TestGoMapToMappingProducesCorrectMapping
go test -v ./lib/common/data -run TestFullGoMapToMappingProducesCorrectMapping
$(GO) test -v ./lib/common/data -run TestGoMapToMappingProducesCorrectMapping
$(GO) test -v ./lib/common/data -run TestFullGoMapToMappingProducesCorrectMapping
test-mapping-utils:
go test -v ./lib/common/data -run TestStopValueRead
go test -v ./lib/common/data -run TestBeginsWith
$(GO) test -v ./lib/common/data -run TestStopValueRead
$(GO) test -v ./lib/common/data -run TestBeginsWith
.PHONY: test-mapping-all \
test-mapping-values \

View File

@@ -1,2 +1,2 @@
test-mapping-values-order:
go test -v ./lib/common/data -run TestMappingOrderSortsValuesThenKeys
$(GO) test -v ./lib/common/data -run TestMappingOrderSortsValuesThenKeys

View File

@@ -1,16 +1,16 @@
test-noise-transport-all: test-noise-packet-encryption test-noise-transport-connection test-noise-packet-obfuscation test-noise-packet-obfuscation-func
test-noise-packet-encryption:
go test -v ./lib/transport/noise -run TestEncryptDecryptPacketOffline
$(GO) test -v ./lib/transport/noise -run TestEncryptDecryptPacketOffline
test-noise-transport-connection:
go test -v ./lib/transport/noise -run TestTransport
$(GO) test -v ./lib/transport/noise -run TestTransport
test-noise-packet-obfuscation:
go test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOffline
$(GO) test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOffline
test-noise-packet-obfuscation-func:
go test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOfflineWithFunc
$(GO) test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOfflineWithFunc
.PHONY: test-noise-transport-all \
test-noise-packet-encryption \

View File

@@ -1,17 +1,17 @@
test-router-address-all: test-router-address-validation test-router-address-functionality test-router-address-fuzz
test-router-address-validation:
go test -v ./lib/common/router_address -run TestCheckValidReportsEmptySlice
go test -v ./lib/common/router_address -run TestCheckRouterAddressValidReportsDataMissing
go test -v ./lib/common/router_address -run TestCheckRouterAddressValidNoErrWithValidData
$(GO) test -v ./lib/common/router_address -run TestCheckValidReportsEmptySlice
$(GO) test -v ./lib/common/router_address -run TestCheckRouterAddressValidReportsDataMissing
$(GO) test -v ./lib/common/router_address -run TestCheckRouterAddressValidNoErrWithValidData
test-router-address-functionality:
go test -v ./lib/common/router_address -run TestRouterAddressCostReturnsFirstByte
go test -v ./lib/common/router_address -run TestRouterAddressExpirationReturnsCorrectData
go test -v ./lib/common/router_address -run TestReadRouterAddressReturnsCorrectRemainderWithoutError
$(GO) test -v ./lib/common/router_address -run TestRouterAddressCostReturnsFirstByte
$(GO) test -v ./lib/common/router_address -run TestRouterAddressExpirationReturnsCorrectData
$(GO) test -v ./lib/common/router_address -run TestReadRouterAddressReturnsCorrectRemainderWithoutError
test-router-address-fuzz:
go test -v ./lib/common/router_address -run TestCorrectsFuzzCrasher1
$(GO) test -v ./lib/common/router_address -run TestCorrectsFuzzCrasher1
.PHONY: test-router-address-all \
test-router-address-validation \

View File

@@ -1,23 +1,23 @@
test-router-info-all: test-router-info-published test-router-info-addresses test-router-info-identity test-router-info-misc
test-router-info-published:
go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectDate
go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithPartialDate
go test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithInvalidData
$(GO) test -v ./lib/common/router_info -run TestPublishedReturnsCorrectDate
$(GO) test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithPartialDate
$(GO) test -v ./lib/common/router_info -run TestPublishedReturnsCorrectErrorWithInvalidData
test-router-info-addresses:
go test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectCount
go test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectErrorWithInvalidData
go test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddresses
go test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddressesWithMultiple
$(GO) test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectCount
$(GO) test -v ./lib/common/router_info -run TestRouterAddressCountReturnsCorrectErrorWithInvalidData
$(GO) test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddresses
$(GO) test -v ./lib/common/router_info -run TestRouterAddressesReturnsAddressesWithMultiple
test-router-info-identity:
go test -v ./lib/common/router_info -run TestRouterIdentityIsCorrect
$(GO) test -v ./lib/common/router_info -run TestRouterIdentityIsCorrect
test-router-info-misc:
go test -v ./lib/common/router_info -run TestPeerSizeIsZero
go test -v ./lib/common/router_info -run TestOptionsAreCorrect
go test -v ./lib/common/router_info -run TestSignatureIsCorrectSize
$(GO) test -v ./lib/common/router_info -run TestPeerSizeIsZero
$(GO) test -v ./lib/common/router_info -run TestOptionsAreCorrect
$(GO) test -v ./lib/common/router_info -run TestSignatureIsCorrectSize
.PHONY: test-router-info-all \
test-router-info-published \

View File

@@ -1,24 +1,24 @@
test-string-all: test-string-length test-string-data test-string-conversion test-string-read
test-string-length:
go test -v ./lib/common/data -run TestStringReportsCorrectLength
go test -v ./lib/common/data -run TestI2PStringReportsLengthZeroError
go test -v ./lib/common/data -run TestI2PStringReportsExtraDataError
go test -v ./lib/common/data -run TestI2PStringDataReportsLengthZeroError
$(GO) test -v ./lib/common/data -run TestStringReportsCorrectLength
$(GO) test -v ./lib/common/data -run TestI2PStringReportsLengthZeroError
$(GO) test -v ./lib/common/data -run TestI2PStringReportsExtraDataError
$(GO) test -v ./lib/common/data -run TestI2PStringDataReportsLengthZeroError
test-string-data:
go test -v ./lib/common/data -run TestI2PStringDataReportsExtraDataError
go test -v ./lib/common/data -run TestI2PStringDataEmptyWhenZeroLength
go test -v ./lib/common/data -run TestI2PStringDataErrorWhenNonZeroLengthOnly
$(GO) test -v ./lib/common/data -run TestI2PStringDataReportsExtraDataError
$(GO) test -v ./lib/common/data -run TestI2PStringDataEmptyWhenZeroLength
$(GO) test -v ./lib/common/data -run TestI2PStringDataErrorWhenNonZeroLengthOnly
test-string-conversion:
go test -v ./lib/common/data -run TestToI2PI2PStringFormatsCorrectly
go test -v ./lib/common/data -run TestToI2PStringReportsOverflows
$(GO) test -v ./lib/common/data -run TestToI2PI2PStringFormatsCorrectly
$(GO) test -v ./lib/common/data -run TestToI2PStringReportsOverflows
test-string-read:
go test -v ./lib/common/data -run TestReadStringReadsLength
go test -v ./lib/common/data -run TestReadI2PStringErrWhenEmptySlice
go test -v ./lib/common/data -run TestReadI2PStringErrWhenDataTooShort
$(GO) test -v ./lib/common/data -run TestReadStringReadsLength
$(GO) test -v ./lib/common/data -run TestReadI2PStringErrWhenEmptySlice
$(GO) test -v ./lib/common/data -run TestReadI2PStringErrWhenDataTooShort
.PHONY: test-string-all \
test-string-length \

View File

@@ -1,10 +1,10 @@
test-su3-all: test-su3-read test-su3-signature
test-su3-read:
go test -v ./lib/su3 -run TestRead
$(GO) test -v ./lib/su3 -run TestRead
test-su3-signature:
go test -v ./lib/su3 -run TestReadSignatureFirst
$(GO) test -v ./lib/su3 -run TestReadSignatureFirst
.PHONY: test-su3-all \
test-su3-read \

View File

@@ -2,18 +2,18 @@ test-tunnel-all: test-tunnel-delivery-instructions test-tunnel-message
# Tests from delivery_test.go
test-tunnel-delivery-instructions:
go test -v ./lib/tunnel -run TestReadDeliveryInstructions
$(GO) test -v ./lib/tunnel -run TestReadDeliveryInstructions
# Tests from message_test.go
test-tunnel-message: test-tunnel-message-padding test-tunnel-message-fragments
test-tunnel-message-padding:
go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithNoPadding
go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithSomePadding
go test -v ./lib/tunnel -run TestDeliveryInstructionDataWithOnlyPadding
$(GO) test -v ./lib/tunnel -run TestDeliveryInstructionDataWithNoPadding
$(GO) test -v ./lib/tunnel -run TestDeliveryInstructionDataWithSomePadding
$(GO) test -v ./lib/tunnel -run TestDeliveryInstructionDataWithOnlyPadding
test-tunnel-message-fragments:
go test -v ./lib/tunnel -run TestDeliveryInstructionsWithFragments
$(GO) test -v ./lib/tunnel -run TestDeliveryInstructionsWithFragments
.PHONY: test-tunnel-all \
test-tunnel-delivery-instructions \

13
go.mod
View File

@@ -3,14 +3,17 @@ module github.com/go-i2p/go-i2p
go 1.23.1
require (
github.com/emirpasic/gods v1.18.1
github.com/beevik/ntp v1.4.3
github.com/emirpasic/gods v1.18.1
github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e
github.com/flynn/noise v1.1.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
go.step.sm/crypto v0.53.0
golang.org/x/crypto v0.27.0
gopkg.in/yaml.v3 v3.0.1
)
require (
@@ -28,19 +31,13 @@ require (
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
gopkg.in/ini.v1 v1.67.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
)

20
go.sum
View File

@@ -1,10 +1,9 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -14,27 +13,34 @@ github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e h1:NMjWYVkgcQHG
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/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
@@ -79,8 +85,8 @@ golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt7
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=

View File

@@ -3,6 +3,8 @@
package certificate
import (
"encoding/binary"
"errors"
"fmt"
"github.com/sirupsen/logrus"
@@ -143,9 +145,9 @@ func (c *Certificate) Data() (data []byte) {
return
}
// NewCertificate creates a new Certficiate from []byte
// readCertificate creates a new Certficiate from []byte
// returns err if the certificate is too short or if the payload doesn't match specified length.
func NewCertificate(data []byte) (certificate Certificate, err error) {
func readCertificate(data []byte) (certificate Certificate, err error) {
certificate = Certificate{}
switch len(data) {
case 0:
@@ -171,14 +173,14 @@ func NewCertificate(data []byte) (certificate Certificate, err error) {
default:
certificate.kind = Integer(data[0:1])
certificate.len = Integer(data[1:3])
payleng := len(data) - CERT_MIN_SIZE
payloadLength := len(data) - CERT_MIN_SIZE
certificate.payload = data[CERT_MIN_SIZE:]
if certificate.len.Int() > len(data)-CERT_MIN_SIZE {
err = fmt.Errorf("certificate parsing warning: certificate data is shorter than specified by length")
log.WithFields(logrus.Fields{
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": certificate.len.Int(),
"certificate_payload_length": payleng,
"certificate_payload_length": payloadLength,
"data_bytes:": string(data),
"kind_bytes": data[0:1],
"len_bytes": data[1:3],
@@ -197,7 +199,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.
// returns err if the certificate could not be read.
func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) {
certificate, err = NewCertificate(data)
certificate, err = readCertificate(data)
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
log.Warn("Certificate data longer than specified length")
err = nil
@@ -208,3 +210,53 @@ func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, er
}).Debug("Read certificate and extracted remainder")
return
}
// NewCertificate creates a new Certificate with default NULL type
func NewCertificate() *Certificate {
return &Certificate{
kind: Integer([]byte{CERT_NULL}),
len: Integer([]byte{0}),
payload: make([]byte, 0),
}
}
// NewCertificateWithType creates a new Certificate with specified type and payload
func NewCertificateWithType(certType uint8, payload []byte) (*Certificate, error) {
// Validate certificate type
switch certType {
case CERT_NULL, CERT_HASHCASH, CERT_HIDDEN, CERT_SIGNED, CERT_MULTIPLE, CERT_KEY:
// Valid type
default:
return nil, fmt.Errorf("invalid certificate type: %d", certType)
}
// For NULL certificates, payload should be empty
if certType == CERT_NULL && len(payload) > 0 {
return nil, errors.New("NULL certificates must have empty payload")
}
length, _ := NewIntegerFromInt(len(payload), 2)
cert := &Certificate{
kind: Integer([]byte{certType}),
len: *length,
payload: make([]byte, len(payload)),
}
// Copy payload if present
if len(payload) > 0 {
copy(cert.payload, payload)
}
return cert, nil
}
func GetSignatureTypeFromCertificate(cert Certificate) (int, error) {
if cert.Type() != CERT_KEY {
return 0, fmt.Errorf("unexpected certificate type: %d", cert.Type)
}
if len(cert.payload) < 2 {
return 0, fmt.Errorf("certificate payload too short to contain signature type")
}
sigType := int(binary.BigEndian.Uint16(cert.payload[0:2]))
return sigType, nil
}

View File

@@ -10,7 +10,7 @@ func TestCertificateTypeIsFirstByte(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x00}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_type := certificate.Type()
assert.Equal(cert_type, 3, "certificate.Type() should be the first bytes in a certificate")
@@ -21,7 +21,7 @@ func TestCertificateLengthCorrect(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes")
@@ -45,7 +45,7 @@ func TestCertificateLengthErrWhenDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was actually missing")
@@ -58,7 +58,7 @@ func TestCertificateDataWhenCorrectSize(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x01, 0xaa}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
assert.Nil(err, "certificate.Data() returned error with valid data")
@@ -85,7 +85,7 @@ func TestCertificateDataWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
if assert.NotNil(err) {

View File

@@ -134,6 +134,11 @@ func ToI2PString(data string) (str I2PString, err error) {
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
if len(data) == 0 {
err = errors.New("data slice is empty")
log.WithError(err).Error("Passed data with len == 0")
return
}
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Reading I2PString from bytes")
@@ -143,6 +148,11 @@ func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
return
}
data_len := length.Int() + 1
if data_len > len(data) {
err = fmt.Errorf("I2PString length %d exceeds available data %d", data_len-1, len(data)-1)
log.WithError(err).Error("Failed to read I2PString")
return
}
str = data[:data_len]
remainder = data[data_len:]
l, err := str.Length()

View File

@@ -38,7 +38,8 @@ type Destination struct {
func (destination Destination) Base32Address() (str string) {
log.Debug("Generating Base32 address for Destination")
dest := destination.KeysAndCert.KeyCertificate.Bytes()
cert := destination.KeysAndCert.Certificate()
dest := cert.Bytes()
hash := crypto.SHA256(dest)
str = strings.Trim(base32.EncodeToString(hash[:]), "=")
str = str + ".b32.i2p"
@@ -54,7 +55,8 @@ func (destination Destination) Base32Address() (str string) {
func (destination Destination) Base64() string {
log.Debug("Generating Base64 address for Destination")
dest := destination.KeysAndCert.KeyCertificate.Bytes()
cert := destination.KeysAndCert.Certificate()
dest := cert.Bytes()
base64Address := base64.EncodeToString(dest)
log.WithFields(logrus.Fields{

View File

@@ -5,7 +5,7 @@ import common "github.com/go-i2p/go-i2p/lib/common/router_identity"
func Fuzz(data []byte) int {
router_identity, _, _ := common.ReadRouterIdentity(data)
router_identity.Certificate()
router_identity.PublicKey()
router_identity.SigningPublicKey()
//router_identity.publicKey()
//router_identity.signingPublicKey()
return 0
}

View File

@@ -66,7 +66,7 @@ const (
KEYCERT_MIN_SIZE = 7
)
// SigningPublicKey sizes for Signing Key Types
// signingPublicKey sizes for Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
@@ -79,7 +79,7 @@ const (
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
// PublicKey sizes for Public Key Types
// publicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
@@ -106,34 +106,34 @@ func (key_certificate KeyCertificate) Data() ([]byte, error) {
data := key_certificate.Certificate.RawBytes()
log.WithFields(logrus.Fields{
"data_length": len(data),
}).Debug("Retrieved raw data from KeyCertificate")
}).Debug("Retrieved raw data from keyCertificate")
return key_certificate.Certificate.RawBytes(), nil
}
// SigningPublicKeyType returns the SigningPublicKey type as a Go integer.
// SigningPublicKeyType returns the signingPublicKey type as a Go integer.
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) {
signing_pubkey_type = key_certificate.spkType.Int()
log.WithFields(logrus.Fields{
"signing_pubkey_type": signing_pubkey_type,
}).Debug("Retrieved SigningPublicKey type")
}).Debug("Retrieved signingPublicKey type")
return key_certificate.spkType.Int()
}
// PublicKeyType returns the PublicKey type as a Go integer.
// PublicKeyType returns the publicKey type as a Go integer.
func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) {
pubkey_type = key_certificate.cpkType.Int()
log.WithFields(logrus.Fields{
"pubkey_type": pubkey_type,
}).Debug("Retrieved PublicKey type")
}).Debug("Retrieved publicKey type")
return key_certificate.cpkType.Int()
}
// ConstructPublicKey returns a PublicKey constructed using any excess data that may be stored in the KeyCertififcate.
// ConstructPublicKey returns a publicKey constructed using any excess data that may be stored in the KeyCertififcate.
// Returns enr errors encountered while parsing.
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Constructing PublicKey from KeyCertificate")
}).Debug("Constructing publicKey from keyCertificate")
key_type := key_certificate.PublicKeyType()
if err != nil {
return
@@ -141,7 +141,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
data_len := len(data)
if data_len < key_certificate.CryptoSize() {
log.WithFields(logrus.Fields{
"at": "(KeyCertificate) ConstructPublicKey",
"at": "(keyCertificate) ConstructPublicKey",
"data_len": data_len,
"required_len": KEYCERT_PUBKEY_SIZE,
"reason": "not enough data",
@@ -174,15 +174,15 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Constructing SigningPublicKey from KeyCertificate")
signing_key_type := key_certificate.PublicKeyType()
}).Debug("Constructing signingPublicKey from keyCertificate")
signing_key_type := key_certificate.SigningPublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < key_certificate.SignatureSize() {
log.WithFields(logrus.Fields{
"at": "(KeyCertificate) ConstructSigningPublicKey",
"at": "(keyCertificate) ConstructSigningPublicKey",
"data_len": data_len,
"required_len": KEYCERT_SPK_SIZE,
"reason": "not enough data",
@@ -197,57 +197,60 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
signing_public_key = dsa_key
log.Debug("Constructed DSAPublicKey")
case KEYCERT_SIGN_P256:
var ec_key crypto.ECP256PublicKey
copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_key
log.Debug("Constructed ECP256PublicKey")
var ec_p256_key crypto.ECP256PublicKey
copy(ec_p256_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p256_key
log.Debug("Constructed P256PublicKey")
case KEYCERT_SIGN_P384:
var ec_key crypto.ECP384PublicKey
copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_key
log.Debug("Constructed ECP384PublicKey")
var ec_p384_key crypto.ECP384PublicKey
copy(ec_p384_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p384_key
log.Debug("Constructed P384PublicKey")
case KEYCERT_SIGN_P521:
var ec_key crypto.ECP521PublicKey
extra := KEYCERT_SIGN_P521_SIZE - KEYCERT_SPK_SIZE
copy(ec_key[:], data)
copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra])
signing_public_key = ec_key
log.Debug("Constructed ECP521PublicKey")
/*var ec_p521_key crypto.ECP521PublicKey
copy(ec_p521_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P521_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p521_key
log.Debug("Constructed P521PublicKey")*/
panic("unimplemented P521SigningPublicKey")
case KEYCERT_SIGN_RSA2048:
// var rsa_key crypto.RSA2048PublicKey
// extra := KEYCERT_SIGN_RSA2048_SIZE - 128
// copy(rsa_key[:], data)
// copy(rsa_key[128:], key_certificate[4:4+extra])
// signing_public_key = rsa_key
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Signing key type KEYCERT_SIGN_RSA2048 not implemented")
/*var rsa2048_key crypto.RSA2048PublicKey
copy(rsa2048_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA2048_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa2048_key
log.Debug("Constructed RSA2048PublicKey")*/
panic("unimplemented RSA2048SigningPublicKey")
case KEYCERT_SIGN_RSA3072:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Signing key type KEYCERT_SIGN_RSA3072 not implemented")
/*var rsa3072_key crypto.RSA3072PublicKey
copy(rsa3072_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA3072_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa3072_key
log.Debug("Constructed RSA3072PublicKey")*/
panic("unimplemented RSA3072SigningPublicKey")
case KEYCERT_SIGN_RSA4096:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Signing key type KEYCERT_SIGN_RSA4096 not implemented")
/*var rsa4096_key crypto.RSA4096PublicKey
copy(rsa4096_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA4096_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa4096_key
log.Debug("Constructed RSA4096PublicKey")*/
panic("unimplemented RSA4096SigningPublicKey")
case KEYCERT_SIGN_ED25519:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Signing key type KEYCERT_SIGN_ED25519 not implemented")
var ed25519_key crypto.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519_key
log.Debug("Constructed Ed25519PublicKey")
case KEYCERT_SIGN_ED25519PH:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Signing key type KEYCERT_SIGN_ED25519PH not implemented")
var ed25519ph_key crypto.Ed25519PublicKey
copy(ed25519ph_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519PH_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519ph_key
log.Debug("Constructed Ed25519PHPublicKey")
default:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Unknown signing key type")
panic(err)
}
return
}
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
// SignatureSize return the size of a Signature corresponding to the Key Certificate's signingPublicKey type.
func (key_certificate KeyCertificate) SignatureSize() (size int) {
sizes := map[int]int{
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
@@ -269,7 +272,7 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) {
return sizes[int(key_type)]
}
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type.
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's publicKey type.
func (key_certificate KeyCertificate) CryptoSize() (size int) {
sizes := map[int]int{
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
@@ -293,7 +296,7 @@ func (key_certificate KeyCertificate) CryptoSize() (size int) {
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
log.WithFields(logrus.Fields{
"input_length": len(bytes),
}).Debug("Creating new KeyCertificate")
}).Debug("Creating new keyCertificate")
var certificate Certificate
certificate, remainder, err = ReadCertificate(bytes)
@@ -302,9 +305,9 @@ func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder
return
}
if len(bytes) < KEYCERT_MIN_SIZE {
log.WithError(err).Error("keyCertificate data too short")
err = errors.New("error parsing key certificate: not enough data")
remainder = bytes[KEYCERT_MIN_SIZE:]
log.WithError(err).Error("KeyCertificate data too short")
}
key_certificate = &KeyCertificate{
Certificate: certificate,
@@ -320,20 +323,20 @@ func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder
"spk_type": key_certificate.spkType.Int(),
"cpk_type": key_certificate.cpkType.Int(),
"remainder_length": len(remainder),
}).Debug("Successfully created new KeyCertificate")
}).Debug("Successfully created new keyCertificate")
return
}
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate {
log.Debug("Creating KeyCertificate from Certificate")
log.Debug("Creating keyCertificate from Certificate")
// k, _, _ := NewKeyCertificate(certificate.RawBytes())
k, _, err := NewKeyCertificate(certificate.RawBytes())
if err != nil {
log.WithError(err).Error("Failed to create KeyCertificate from Certificate")
log.WithError(err).Error("Failed to create keyCertificate from Certificate")
} else {
log.Debug("Successfully created KeyCertificate from Certificate")
log.Debug("Successfully created keyCertificate from Certificate")
}
return k
}

View File

@@ -35,7 +35,7 @@ func TestPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03})
pk_type := key_cert.PublicKeyType()
assert.Nil(err, "PublicKey() returned error with valid data")
assert.Nil(err, "publicKey() returned error with valid data")
assert.Equal(pk_type, KEYCERT_SIGN_P521, "PublicKeyType() did not return correct typec")
}
@@ -94,7 +94,7 @@ func TestConstructSigningPublicKeyWithDSASHA1(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with DSA SHA1 returned error with valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_DSA_SHA1_SIZE, "ConstructSigningPublicKey() with DSA SHA1 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_DSA_SHA1_SIZE, "ConstructSigningPublicKey() with DSA SHA1 returned incorrect signingPublicKey length")
}
func TestConstructSigningPublicKeyWithP256(t *testing.T) {
@@ -105,7 +105,7 @@ func TestConstructSigningPublicKeyWithP256(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with P256 returned err on valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_P256_SIZE, "ConstructSigningPublicKey() with P256 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_P256_SIZE, "ConstructSigningPublicKey() with P256 returned incorrect signingPublicKey length")
}
func TestConstructSigningPublicKeyWithP384(t *testing.T) {
@@ -116,7 +116,7 @@ func TestConstructSigningPublicKeyWithP384(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with P384 returned err on valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_P384_SIZE, "ConstructSigningPublicKey() with P384 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_P384_SIZE, "ConstructSigningPublicKey() with P384 returned incorrect signingPublicKey length")
}
func TestConstructSigningPublicKeyWithP521(t *testing.T) {
@@ -127,5 +127,5 @@ func TestConstructSigningPublicKeyWithP521(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with P521 returned err on valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_P521_SIZE, "ConstructSigningPublicKey() with P521 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_P521_SIZE, "ConstructSigningPublicKey() with P521 returned incorrect signingPublicKey length")
}

View File

@@ -2,6 +2,7 @@
package keys_and_cert
import (
"crypto/rand"
"errors"
"github.com/go-i2p/go-i2p/lib/util/logger"
@@ -30,7 +31,7 @@ Description
An encryption public key, a signing public key, and a certificate, used as either a RouterIdentity or a Destination.
Contents
A PublicKey followed by a SigningPublicKey and then a Certificate.
A publicKey followed by a signingPublicKey and then a Certificate.
+----+----+----+----+----+----+----+----+
| public_key |
@@ -55,14 +56,14 @@ A PublicKey followed by a SigningPublicKey and then a Certificate.
| certificate |
+----+----+----+-//
public_key :: PublicKey (partial or full)
public_key :: publicKey (partial or full)
length -> 256 bytes or as specified in key certificate
padding :: random data
length -> 0 bytes or as specified in key certificate
padding length + signing_key length == 128 bytes
signing__key :: SigningPublicKey (partial or full)
signing__key :: signingPublicKey (partial or full)
length -> 128 bytes or as specified in key certificate
padding length + signing_key length == 128 bytes
@@ -76,34 +77,41 @@ total length: 387+ bytes
//
// https://geti2p.net/spec/common-structures#keysandcert
type KeysAndCert struct {
KeyCertificate *KeyCertificate
keyCertificate *KeyCertificate
publicKey crypto.PublicKey
padding []byte
Padding []byte
signingPublicKey crypto.SigningPublicKey
}
// 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 {
bytes := keys_and_cert.KeyCertificate.Bytes()
bytes := keys_and_cert.publicKey.Bytes()
bytes = append(bytes, keys_and_cert.Padding...)
bytes = append(bytes, keys_and_cert.signingPublicKey.Bytes()...)
bytes = append(bytes, keys_and_cert.keyCertificate.Bytes()...)
log.WithFields(logrus.Fields{
"bytes_length": len(bytes),
"pk_bytes_length": len(keys_and_cert.publicKey.Bytes()),
"padding_bytes_length": len(keys_and_cert.Padding),
"spk_bytes_length": len(keys_and_cert.signingPublicKey.Bytes()),
"cert_bytes_length": len(keys_and_cert.keyCertificate.Bytes()),
}).Debug("Retrieved bytes from KeysAndCert")
return 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) {
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) {
return keys_and_cert.signingPublicKey
}
// Certfificate returns the certificate.
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) {
return keys_and_cert.KeyCertificate.Certificate
return keys_and_cert.keyCertificate.Certificate
}
// ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
@@ -123,7 +131,7 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
keys_and_cert.keyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
return
} else if data_len < KEYS_AND_CERT_DATA_SIZE {
log.WithFields(logrus.Fields{
@@ -135,33 +143,110 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte,
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
return
}
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
keys_and_cert.keyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
if err != nil {
log.WithError(err).Error("Failed to create KeyCertificate")
log.WithError(err).Error("Failed to create keyCertificate")
return
}
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same.
// a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE
// and KEYS_AND_CERT_SPK_SIZE constants in the future.
keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
keys_and_cert.publicKey, err = keys_and_cert.keyCertificate.ConstructPublicKey(data[:keys_and_cert.keyCertificate.CryptoSize()])
if err != nil {
log.WithError(err).Error("Failed to construct PublicKey")
log.WithError(err).Error("Failed to construct publicKey")
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 {
log.WithError(err).Error("Failed to construct SigningPublicKey")
log.WithError(err).Error("Failed to construct signingPublicKey")
return
}
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
log.WithFields(logrus.Fields{
"public_key_type": keys_and_cert.KeyCertificate.PublicKeyType(),
"signing_public_key_type": keys_and_cert.KeyCertificate.SigningPublicKeyType(),
"public_key_type": keys_and_cert.keyCertificate.PublicKeyType(),
"signing_public_key_type": keys_and_cert.keyCertificate.SigningPublicKeyType(),
"padding_length": len(padding),
"remainder_length": len(remainder),
}).Debug("Successfully read KeysAndCert")
return
}
// NewKeysAndCert creates a new KeysAndCert instance with the provided parameters.
// It validates the sizes of the provided keys and padding before assembling the struct.
func NewKeysAndCert(
keyCertificate *KeyCertificate,
publicKey crypto.PublicKey,
padding []byte,
signingPublicKey crypto.SigningPublicKey,
) (*KeysAndCert, error) {
log.Debug("Creating new KeysAndCert with provided parameters")
// 1. Validate keyCertificate
if keyCertificate == nil {
log.Error("KeyCertificate is nil")
return nil, errors.New("KeyCertificate cannot be nil")
}
// 2. Validate publicKey size
if publicKey.Len() != KEYS_AND_CERT_PUBKEY_SIZE {
log.WithFields(logrus.Fields{
"expected_size": KEYS_AND_CERT_PUBKEY_SIZE,
"actual_size": publicKey.Len(),
}).Error("Invalid publicKey size")
return nil, errors.New("publicKey has an invalid size")
}
/*
// 3. Validate signingPublicKey size
if signingPublicKey.Len() != KEYS_AND_CERT_SPK_SIZE {
log.WithFields(logrus.Fields{
"expected_size": KEYS_AND_CERT_SPK_SIZE,
"actual_size": signingPublicKey.Len(),
}).Error("Invalid signingPublicKey size")
return nil, errors.New("signingPublicKey has an invalid size")
}
*/
// 4. Validate padding size
publicKeyLength := publicKey.Len()
signingPublicKeyLength := signingPublicKey.Len()
totalKeysSize := publicKeyLength + signingPublicKeyLength
expectedPaddingSize := KEYS_AND_CERT_DATA_SIZE - totalKeysSize
if len(padding) != expectedPaddingSize {
log.WithFields(logrus.Fields{
"expected_size": expectedPaddingSize,
"actual_size": len(padding),
}).Warn("Invalid padding size")
// generate some random padding and continue
padding = make([]byte, expectedPaddingSize)
_, err := rand.Read(padding)
if err != nil {
log.WithError(err).Error("Failed to generate random padding")
return nil, err
}
log.WithFields(logrus.Fields{
"expected_size": expectedPaddingSize,
"actual_size": len(padding),
}).Warn("Generated random padding")
}
// 5. Assemble KeysAndCert
keysAndCert := &KeysAndCert{
keyCertificate: keyCertificate,
publicKey: publicKey,
Padding: padding,
signingPublicKey: signingPublicKey,
}
log.WithFields(logrus.Fields{
"public_key_length": publicKey.Len(),
"signing_public_key_length": signingPublicKey.Len(),
"padding_length": len(padding),
}).Debug("Successfully created KeysAndCert")
return keysAndCert, nil
}

View File

@@ -32,13 +32,13 @@ Accurate for version 0.9.49
Description
Contains all of the currently authorized Leases for a particular Destination, the
PublicKey to which garlic messages can be encrypted, and then the SigningPublicKey
publicKey to which garlic messages can be encrypted, and then the signingPublicKey
that can be used to revoke this particular version of the structure. The LeaseSet is one
of the two structures stored in the network database (the other being RouterInfo), and
is kered under the SHA256 of the contained Destination.
Contents
Destination, followed by a PublicKey for encryption, then a SigningPublicKey which
Destination, followed by a publicKey for encryption, then a signingPublicKey which
can be used to revoke this version of the LeaseSet, then a 1 byte Integer specifying how
many Lease structures are in the set, followed by the actual Lease structures and
finally a Signature of the previous bytes signed by the Destination's SigningPrivateKey.
@@ -100,10 +100,10 @@ finally a Signature of the previous bytes signed by the Destination's SigningPri
destination :: Destination
length -> >= 387 bytes
encryption_key :: PublicKey
encryption_key :: publicKey
length -> 256 bytes
signing_key :: SigningPublicKey
signing_key :: signingPublicKey
length -> 128 bytes or as specified in destination's key certificate
num :: Integer
@@ -157,7 +157,7 @@ func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error
remainder_len := len(remainder)
if remainder_len < LEASE_SET_PUBKEY_SIZE {
log.WithFields(logrus.Fields{
"at": "(LeaseSet) PublicKey",
"at": "(LeaseSet) publicKey",
"data_len": remainder_len,
"required_len": LEASE_SET_PUBKEY_SIZE,
"reason": "not enough data",
@@ -167,7 +167,7 @@ func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error
return
}
copy(public_key[:], remainder[:LEASE_SET_PUBKEY_SIZE])
log.Debug("Successfully retrieved PublicKey from LeaseSet")
log.Debug("Successfully retrieved publicKey from LeaseSet")
return
}
@@ -200,11 +200,11 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
}
if cert_len == 0 {
// No Certificate is present, return the LEASE_SET_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
// signingPublicKey space as legacy DSA SHA1 signingPublicKey.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE])
signing_public_key = dsa_pk
log.Debug("Retrieved legacy DSA SHA1 SigningPublicKey")
log.Debug("Retrieved legacy DSA SHA1 signingPublicKey")
} else {
// A Certificate is present in this LeaseSet's Destination
cert_type := cert.Type()
@@ -216,17 +216,17 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
lease_set[offset : offset+LEASE_SET_SPK_SIZE],
)
if err != nil {
log.WithError(err).Error("Failed to construct SigningPublicKey from KeyCertificate")
log.WithError(err).Error("Failed to construct signingPublicKey from keyCertificate")
} else {
log.Debug("Retrieved SigningPublicKey from KeyCertificate")
log.Debug("Retrieved signingPublicKey from keyCertificate")
}
} else {
// No Certificate is present, return the LEASE_SET_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
// signingPublicKey space as legacy DSA SHA1 signingPublicKey.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE])
signing_public_key = dsa_pk
log.Debug("Retrieved legacy DSA SHA1 SigningPublicKey (Certificate present but not Key Certificate)")
log.Debug("Retrieved legacy DSA SHA1 signingPublicKey (Certificate present but not Key Certificate)")
}
}
return
@@ -358,7 +358,7 @@ func (lease_set LeaseSet) Verify() error {
//data := lease_set[:data_end]
//spk, _ := lease_set.
// Destination().
// SigningPublicKey()
// signingPublicKey()
//verifier, err := spk.NewVerifier()
//if err != nil {
// return err

View File

@@ -61,7 +61,7 @@ func buildSignature(size int) []byte {
func buildFullLeaseSet(n int) LeaseSet {
lease_set_data := make([]byte, 0)
lease_set_data = append(lease_set_data, buildDestination().KeysAndCert.KeyCertificate.RawBytes()...)
lease_set_data = append(lease_set_data, buildDestination().KeysAndCert.Bytes()...)
lease_set_data = append(lease_set_data, buildPublicKey()...)
lease_set_data = append(lease_set_data, buildSigningKey()...)
lease_set_data = append(lease_set_data, byte(n))

View File

@@ -2,11 +2,13 @@
package router_address
import (
"encoding/binary"
"errors"
"fmt"
"net"
"strconv"
"strings"
"time"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/sirupsen/logrus"
@@ -152,14 +154,7 @@ func (router_address RouterAddress) Bytes() []byte {
bytes := make([]byte, 0)
bytes = append(bytes, router_address.TransportCost.Bytes()...)
bytes = append(bytes, router_address.ExpirationDate.Bytes()...)
strData, err := router_address.TransportType.Data()
if err != nil {
log.WithFields(logrus.Fields{
"error": err,
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
} else {
bytes = append(bytes, strData...)
}
bytes = append(bytes, router_address.TransportType...)
bytes = append(bytes, router_address.TransportOptions.Data()...)
log.WithField("bytes_length", len(bytes)).Debug("Converted RouterAddress to bytes")
return bytes
@@ -359,3 +354,57 @@ func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []b
}
return
}
// NewRouterAddress creates a new RouterAddress with the provided parameters.
// Returns a pointer to RouterAddress.
func NewRouterAddress(cost uint8, expiration time.Time, transportType string, options map[string]string) (*RouterAddress, error) {
log.Debug("Creating new RouterAddress")
// Create TransportCost as an Integer (1 byte)
transportCost, err := NewIntegerFromInt(int(cost), 1)
if err != nil {
log.WithError(err).Error("Failed to create TransportCost Integer")
return nil, err
}
// Create ExpirationDate as a Date
millis := expiration.UnixNano() / int64(time.Millisecond)
dateBytes := make([]byte, DATE_SIZE)
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
expirationDate, _, err := NewDate(dateBytes)
if err != nil {
log.WithError(err).Error("Failed to create ExpirationDate")
return nil, err
}
// Create TransportType as an I2PString
transportTypeStr, err := ToI2PString(transportType)
if err != nil {
log.WithError(err).Error("Failed to create TransportType I2PString")
return nil, err
}
// Create TransportOptions as a Mapping
transportOptions, err := GoMapToMapping(options)
if err != nil {
log.WithError(err).Error("Failed to create TransportOptions Mapping")
return nil, err
}
// Create RouterAddress
ra := &RouterAddress{
TransportCost: transportCost,
ExpirationDate: expirationDate,
TransportType: transportTypeStr,
TransportOptions: transportOptions,
}
log.WithFields(logrus.Fields{
"cost": cost,
"expiration": expiration,
"transportType": transportType,
"options": options,
}).Debug("Successfully created new RouterAddress")
return ra, nil
}

View File

@@ -2,7 +2,10 @@
package router_identity
import (
"github.com/go-i2p/go-i2p/lib/common/certificate"
"github.com/go-i2p/go-i2p/lib/common/key_certificate"
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
"github.com/go-i2p/go-i2p/lib/crypto"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/sirupsen/logrus"
)
@@ -47,3 +50,30 @@ func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder
}).Debug("Successfully read RouterIdentity")
return
}
func NewRouterIdentity(publicKey crypto.PublicKey, signingPublicKey crypto.SigningPublicKey, cert certificate.Certificate, padding []byte) (*RouterIdentity, error) {
log.Debug("Creating new RouterIdentity")
// Step 1: Create keyCertificate from the provided certificate.
// Assuming NewKeyCertificate is a constructor that takes a Certificate and returns a keyCertificate.
keyCert := key_certificate.KeyCertificateFromCertificate(cert)
// Step 2: Create KeysAndCert instance.
keysAndCert, err := NewKeysAndCert(keyCert, publicKey, padding, signingPublicKey)
if err != nil {
log.WithError(err).Error("NewKeysAndCert failed.")
}
// Step 3: Initialize RouterIdentity with KeysAndCert.
routerIdentity := RouterIdentity{
KeysAndCert: *keysAndCert,
}
log.WithFields(logrus.Fields{
"public_key_type": keyCert.PublicKeyType(),
"signing_public_key_type": keyCert.SigningPublicKeyType(),
"padding_length": len(padding),
}).Debug("Successfully created RouterIdentity")
return &routerIdentity, nil
}

View File

@@ -0,0 +1,194 @@
package router_info
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func consolidateNetDb(sourcePath string, destPath string) error {
// Create destination directory if it doesn't exist
if err := os.MkdirAll(destPath, 0755); err != nil {
return fmt.Errorf("failed to create destination directory: %v", err)
}
// Walk through all subdirectories
return filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("error accessing path %q: %v", path, err)
}
// Skip if it's a directory
if info.IsDir() {
return nil
}
// Check if this is a routerInfo file
if strings.HasPrefix(info.Name(), "routerInfo-") && strings.HasSuffix(info.Name(), ".dat") {
// Create source file path
srcFile := path
// Create destination file path
dstFile := filepath.Join(destPath, info.Name())
// Copy the file
if err := copyFile(srcFile, dstFile); err != nil {
return fmt.Errorf("failed to copy %s: %v", info.Name(), err)
}
}
return nil
})
}
func copyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
return err
}
func consolidateAllNetDbs(tempDir string) error {
// Common paths for I2P and I2Pd netDb
i2pPath := filepath.Join(os.Getenv("HOME"), ".i2p/netDb")
i2pdPath := filepath.Join(os.Getenv("HOME"), ".i2pd/netDb")
// Create the temp directory
if err := os.MkdirAll(tempDir, 0755); err != nil {
return fmt.Errorf("failed to create temp directory: %v", err)
}
// Try to consolidate I2P netDb
if _, err := os.Stat(i2pPath); err == nil {
if err := consolidateNetDb(i2pPath, tempDir); err != nil {
fmt.Printf("Warning: Error processing I2P netDb: %v\n", err)
}
}
// Try to consolidate I2Pd netDb
if _, err := os.Stat(i2pdPath); err == nil {
if err := consolidateNetDb(i2pdPath, tempDir); err != nil {
fmt.Printf("Warning: Error processing I2Pd netDb: %v\n", err)
}
}
return nil
}
func cleanupTempDir(path string) error {
if err := os.RemoveAll(path); err != nil {
return fmt.Errorf("failed to cleanup temporary directory %s: %v", path, err)
}
return nil
}
func createTempNetDbDir() (string, error) {
// Get system's temp directory in a platform-independent way
baseDir := os.TempDir()
// Create unique directory name with timestamp
timestamp := time.Now().Unix()
dirName := fmt.Sprintf("go-i2p-testfiles-%d", timestamp)
// Join paths in a platform-independent way
tempDir := filepath.Join(baseDir, dirName)
// Create the directory with appropriate permissions
err := os.MkdirAll(tempDir, 0755)
if err != nil {
return "", fmt.Errorf("failed to create temporary directory: %v", err)
}
return tempDir, nil
}
func Test10K(t *testing.T) {
i2pPath := filepath.Join(os.Getenv("HOME"), ".i2p/netDb")
i2pdPath := filepath.Join(os.Getenv("HOME"), ".i2pd/netDb")
// Skip if neither directory exists
if _, err := os.Stat(i2pPath); os.IsNotExist(err) {
if _, err := os.Stat(i2pdPath); os.IsNotExist(err) {
t.Skip("Neither .i2p nor .i2pd netDb directories exist, so we will skip.")
}
}
tempDir, err := createTempNetDbDir()
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
//defer cleanupTempDir(tempDir)
if err := consolidateAllNetDbs(tempDir); err != nil {
t.Fatalf("Failed to consolidate netDbs: %v", err)
}
time.Sleep(1 * time.Second)
targetDir, err := createTempNetDbDir()
if err != nil {
panic(err)
}
// Read and process all router info files
files, err := os.ReadDir(tempDir)
if err != nil {
t.Fatalf("Failed to read temp directory: %v", err)
}
for _, file := range files {
if !file.IsDir() && strings.HasPrefix(file.Name(), "routerInfo-") {
// Read the router info file
log.Println("RI LOAD: ", file.Name())
data, err := os.ReadFile(filepath.Join(tempDir, file.Name()))
if err != nil {
t.Logf("Failed to read file %s: %v", file.Name(), err)
continue
}
// Parse the router info
//fmt.Printf("data: %s\n", string(data))
routerInfo, _, err := ReadRouterInfo(data)
if err != nil {
t.Logf("Failed to parse router info from %s: %v", file.Name(), err)
continue
}
// Write the router info to the target directory
routerBytes, err := routerInfo.Bytes()
if err != nil {
t.Logf("Failed to serialize router info %s: %v", file.Name(), err)
continue
}
err = os.WriteFile(filepath.Join(targetDir, file.Name()), routerBytes, 0644)
if err != nil {
t.Logf("Failed to write router info %s: %v", file.Name(), err)
continue
}
}
}
// Cleanup both directories
if err := cleanupTempDir(tempDir); err != nil {
log.WithError(err).Error("Failed to cleanup temp directory")
t.Errorf("Failed to cleanup temp directory: %v", err)
} else {
log.Debug("Successfully cleaned up temp directory")
}
if err := cleanupTempDir(targetDir); err != nil {
log.WithError(err).Error("Failed to cleanup target directory")
t.Errorf("Failed to cleanup target directory: %v", err)
} else {
log.Debug("Successfully cleaned up target directory")
}
}

View File

@@ -2,9 +2,14 @@
package router_info
import (
"encoding/binary"
"errors"
"github.com/go-i2p/go-i2p/lib/common/certificate"
"strconv"
"strings"
"time"
"github.com/go-i2p/go-i2p/lib/crypto"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/sirupsen/logrus"
@@ -120,7 +125,7 @@ type RouterInfo struct {
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
func (router_info RouterInfo) Bytes() (bytes []byte, err error) {
log.Debug("Converting RouterInfo to bytes")
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
bytes = append(bytes, router_info.router_identity.Bytes()...)
bytes = append(bytes, router_info.published.Bytes()...)
bytes = append(bytes, router_info.size.Bytes()...)
for _, router_address := range router_info.addresses {
@@ -133,17 +138,30 @@ func (router_info RouterInfo) Bytes() (bytes []byte, err error) {
return bytes, err
}
// Convert a byte slice into a string like [1, 2, 3] -> "1, 2, 3"
func bytesToString(bytes []byte) string {
str := "["
for i, b := range bytes {
str += strconv.Itoa(int(b))
if i < len(bytes)-1 {
str += ", "
}
}
str += "]"
return str
}
func (router_info RouterInfo) String() string {
log.Debug("Converting RouterInfo to string")
str := "Certificate: " + string(router_info.router_identity.KeysAndCert.Bytes())
str += "Published: " + string(router_info.published.Bytes())
str += "Addresses:" + string(router_info.size.Bytes())
str := "Certificate: " + bytesToString(router_info.router_identity.Bytes()) + "\n"
str += "Published: " + bytesToString(router_info.published.Bytes()) + "\n"
str += "Addresses:" + bytesToString(router_info.size.Bytes()) + "\n"
for index, router_address := range router_info.addresses {
str += "Address " + strconv.Itoa(index) + ": " + router_address.String()
str += "Address " + strconv.Itoa(index) + ": " + router_address.String() + "\n"
}
str += "Peer Size: " + string(router_info.peer_size.Bytes())
str += "Options: " + string(router_info.options.Data())
str += "Signature: " + string([]byte(*router_info.signature))
str += "Peer Size: " + bytesToString(router_info.peer_size.Bytes()) + "\n"
str += "Options: " + bytesToString(router_info.options.Data()) + "\n"
str += "Signature: " + bytesToString([]byte(*router_info.signature)) + "\n"
log.WithField("string_length", len(str)).Debug("Converted RouterInfo to string")
return str
}
@@ -156,7 +174,9 @@ func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
// IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
func (router_info *RouterInfo) IdentHash() Hash {
log.Debug("Calculating IdentHash for RouterInfo")
data, _ := router_info.RouterIdentity().KeyCertificate.Data()
//data, _ := router_info.RouterIdentity().keyCertificate.Data()
cert := router_info.RouterIdentity().KeysAndCert.Certificate()
data := cert.Data()
hash := HashData(data)
log.WithField("hash", hash).Debug("Calculated IdentHash for RouterInfo")
return HashData(data)
@@ -216,7 +236,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
"required_len": ROUTER_INFO_MIN_SIZE,
"reason": "not enough data",
}).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 to read identity")
return
}
info.published, remainder, err = NewDate(remainder)
@@ -227,7 +247,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
"required_len": DATE_SIZE,
"reason": "not enough data",
}).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 to read publish date")
}
info.size, remainder, err = NewInteger(remainder, 1)
if err != nil {
@@ -248,7 +268,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
//"required_len": ROUTER_ADDRESS_SIZE,
"reason": "not enough data",
}).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 to read router addresses")
}
info.addresses = append(info.addresses, &address)
}
@@ -272,7 +292,11 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
}
err = errors.New("error parsing router info: " + estring)
}
info.signature, remainder, err = NewSignature(remainder)
sigType, err := certificate.GetSignatureTypeFromCertificate(info.router_identity.Certificate())
log.WithFields(logrus.Fields{
"sigType": sigType,
}).Debug("Got sigType")
info.signature, remainder, err = NewSignature(remainder, sigType)
if err != nil {
log.WithFields(logrus.Fields{
"at": "(RouterInfo) ReadRouterInfo",
@@ -280,7 +304,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
//"required_len": MAPPING_SIZE,
"reason": "not enough data",
}).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 to read signature")
}
log.WithFields(logrus.Fields{
@@ -293,6 +317,119 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
return
}
// serializeWithoutSignature serializes the RouterInfo up to (but not including) the signature.
func (ri *RouterInfo) serializeWithoutSignature() []byte {
var bytes []byte
// Serialize RouterIdentity
bytes = append(bytes, ri.router_identity.Bytes()...)
// Serialize Published Date
bytes = append(bytes, ri.published.Bytes()...)
// Serialize Size
bytes = append(bytes, ri.size.Bytes()...)
// Serialize Addresses
for _, addr := range ri.addresses {
bytes = append(bytes, addr.Bytes()...)
}
// Serialize PeerSize (always zero)
bytes = append(bytes, ri.peer_size.Bytes()...)
// Serialize Options
bytes = append(bytes, ri.options.Data()...)
return bytes
}
func NewRouterInfo(
routerIdentity *RouterIdentity,
publishedTime time.Time,
addresses []*RouterAddress,
options map[string]string,
signingPrivateKey crypto.SigningPrivateKey,
sigType int,
) (*RouterInfo, error) {
log.Debug("Creating new RouterInfo")
// 1. Create Published Date
millis := publishedTime.UnixNano() / int64(time.Millisecond)
dateBytes := make([]byte, DATE_SIZE)
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
publishedDate, _, err := ReadDate(dateBytes)
if err != nil {
log.WithError(err).Error("Failed to create Published Date")
return nil, err
}
// 2. Create Size Integer
sizeInt, err := NewIntegerFromInt(len(addresses), 1)
if err != nil {
log.WithError(err).Error("Failed to create Size Integer")
return nil, err
}
// 3. Create PeerSize Integer (always 0)
peerSizeInt, err := NewIntegerFromInt(0, 1)
if err != nil {
log.WithError(err).Error("Failed to create PeerSize Integer")
return nil, err
}
// 4. Convert options map to Mapping
mapping, err := GoMapToMapping(options)
if err != nil {
log.WithError(err).Error("Failed to convert options map to Mapping")
return nil, err
}
// 5. Assemble RouterInfo without signature
routerInfo := &RouterInfo{
router_identity: *routerIdentity,
published: &publishedDate,
size: sizeInt,
addresses: addresses,
peer_size: peerSizeInt,
options: mapping,
signature: nil, // To be set after signing
}
// 6. Serialize RouterInfo without signature
dataBytes := routerInfo.serializeWithoutSignature()
// 7. Compute signature over serialized data
signer, err := signingPrivateKey.NewSigner()
if err != nil {
log.WithError(err).Error("Failed to create new signer")
return nil, err
}
signatureBytes, err := signer.Sign(dataBytes)
if err != nil {
log.WithError(err).Error("Failed to sign")
}
// 8. Create Signature struct from signatureBytes
sig, _, err := ReadSignature(signatureBytes, sigType)
if err != nil {
log.WithError(err).Error("Failed to create Signature from signature bytes")
return nil, err
}
// 9. Attach signature to RouterInfo
routerInfo.signature = &sig
log.WithFields(logrus.Fields{
"router_identity": routerIdentity,
"published": publishedDate,
"address_count": len(addresses),
"options": options,
"signature": sig,
}).Debug("Successfully created RouterInfo")
return routerInfo, nil
}
func (router_info *RouterInfo) RouterCapabilities() string {
log.Debug("Retrieving RouterCapabilities")
str, err := ToI2PString("caps")

View File

@@ -0,0 +1,112 @@
package router_info
import (
"bytes"
"crypto/rand"
"encoding/binary"
"github.com/go-i2p/go-i2p/lib/common/signature"
"testing"
"time"
"github.com/go-i2p/go-i2p/lib/common/certificate"
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/router_address"
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/go-i2p/go-i2p/lib/crypto"
"golang.org/x/crypto/openpgp/elgamal"
)
func TestCreateRouterInfo(t *testing.T) {
// Generate signing key pair (Ed25519)
var ed25519_privkey crypto.Ed25519PrivateKey
_, err := (&ed25519_privkey).Generate()
if err != nil {
t.Fatalf("Failed to generate Ed25519 private key: %v\n", err)
}
ed25519_pubkey_raw, err := ed25519_privkey.Public()
if err != nil {
t.Fatalf("Failed to derive Ed25519 public key: %v\n", err)
}
ed25519_pubkey, ok := ed25519_pubkey_raw.(crypto.SigningPublicKey)
if !ok {
t.Fatalf("Failed to get SigningPublicKey from Ed25519 public key")
}
// Generate encryption key pair (ElGamal)
var elgamal_privkey elgamal.PrivateKey
err = crypto.ElgamalGenerate(&elgamal_privkey, rand.Reader)
if err != nil {
t.Fatalf("Failed to generate ElGamal private key: %v\n", err)
}
// Convert elgamal private key to crypto.ElgPrivateKey
var elg_privkey crypto.ElgPrivateKey
xBytes := elgamal_privkey.X.Bytes()
if len(xBytes) > 256 {
t.Fatalf("ElGamal private key X too large")
}
copy(elg_privkey[256-len(xBytes):], xBytes)
// Convert elgamal public key to crypto.ElgPublicKey
var elg_pubkey crypto.ElgPublicKey
yBytes := elgamal_privkey.PublicKey.Y.Bytes()
if len(yBytes) > 256 {
t.Fatalf("ElGamal public key Y too large")
}
copy(elg_pubkey[256-len(yBytes):], yBytes)
// Ensure that elg_pubkey implements crypto.PublicKey interface
var _ crypto.PublicKey = elg_pubkey
// Create KeyCertificate specifying key types
var payload bytes.Buffer
signingPublicKeyType, _ := data.NewIntegerFromInt(7, 2)
cryptoPublicKeyType, _ := data.NewIntegerFromInt(0, 2)
err = binary.Write(&payload, binary.BigEndian, signingPublicKeyType)
if err != nil {
t.Fatalf("Failed to write signing public key type to payload: %v\n", err)
}
err = binary.Write(&payload, binary.BigEndian, cryptoPublicKeyType)
if err != nil {
t.Fatalf("Failed to write crypto public key type to payload: %v\n", err)
}
// Create KeyCertificate specifying key types
cert, err := certificate.NewCertificateWithType(certificate.CERT_KEY, payload.Bytes())
if err != nil {
t.Fatalf("Failed to create new certificate: %v\n", err)
}
// Create RouterIdentity
routerIdentity, err := router_identity.NewRouterIdentity(elg_pubkey, ed25519_pubkey, *cert, nil)
if err != nil {
t.Fatalf("Failed to create router identity: %v\n", err)
}
// create some dummy addresses
options := map[string]string{}
routerAddress, err := router_address.NewRouterAddress(3, <-time.After(1*time.Second), "NTCP2", options)
if err != nil {
t.Fatalf("Failed to create router address: %v\n", err)
}
routerAddresses := []*router_address.RouterAddress{routerAddress}
// create router info
routerInfo, err := NewRouterInfo(routerIdentity, time.Now(), routerAddresses, nil, &ed25519_privkey, signature.SIGNATURE_TYPE_EDDSA_SHA512_ED25519)
if err != nil {
t.Fatalf("Failed to create router info: %v\n", err)
}
t.Run("Serialize and Deserialize RouterInfo", func(t *testing.T) {
routerInfoBytes, err := routerInfo.Bytes()
t.Log(len(routerInfoBytes), routerInfo.String(), routerInfoBytes)
if err != nil {
t.Fatalf("Failed to write RouterInfo to bytes: %v\n", err)
}
_, _, err = ReadRouterInfo(routerInfoBytes)
if err != nil {
t.Fatalf("Failed to read routerInfoBytes: %v\n", err)
}
})
}

View File

@@ -2,6 +2,7 @@
package signature
import (
"fmt"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/sirupsen/logrus"
)
@@ -22,6 +23,19 @@ const (
RedDSA_SHA512_Ed25519_SIZE = 64
)
const (
SIGNATURE_TYPE_DSA_SHA1 = 0
SIGNATURE_TYPE_ECDSA_SHA256_P256 = 1
SIGNATURE_TYPE_ECDSA_SHA384_P384 = 2
SIGNATURE_TYPE_ECDSA_SHA512_P521 = 3
SIGNATURE_TYPE_RSA_SHA256_2048 = 4
SIGNATURE_TYPE_RSA_SHA384_3072 = 5
SIGNATURE_TYPE_RSA_SHA512_4096 = 6
SIGNATURE_TYPE_EDDSA_SHA512_ED25519 = 7
SIGNATURE_TYPE_EDDSA_SHA512_ED25519PH = 8
SIGNATURE_TYPE_REDDSA_SHA512_ED25519 = 11
)
/*
[Signature]
Accurate for version 0.9.49
@@ -39,30 +53,51 @@ DSA_SHA1. As of release 0.9.12, other types may be supported, depending on conte
// https://geti2p.net/spec/common-structures#signature
type Signature []byte
// ReadSignature returns Signature from a []byte.
// ReadSignature returns a Signature from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadSignature(bytes []byte) (info Signature, remainder []byte, err error) {
// TODO: stub
log.Warn("ReadSignature is not implemented")
// Returns an error if there is insufficient data to read the signature.
//
// Since the signature type and length are inferred from context (the type of key used),
// and are not explicitly stated, this function assumes the default signature type (DSA_SHA1)
// with a length of 40 bytes.
//
// If a different signature type is expected based on context, this function should be
// modified accordingly to handle the correct signature length.
func ReadSignature(data []byte, sigType int) (sig Signature, remainder []byte, err error) {
var sigLength int
switch sigType {
case SIGNATURE_TYPE_DSA_SHA1:
sigLength = DSA_SHA1_SIZE
case SIGNATURE_TYPE_EDDSA_SHA512_ED25519:
sigLength = EdDSA_SHA512_Ed25519_SIZE
default:
err = fmt.Errorf("unsupported signature type: %d", sigType)
return
}
if len(data) < sigLength {
err = fmt.Errorf("insufficient data to read signature: need %d bytes, have %d", sigLength, len(data))
log.WithError(err).Error("Failed to read Signature")
return
}
sig = data[:sigLength]
remainder = data[sigLength:]
return
}
// NewSignature creates a new *Signature from []byte using ReadSignature.
// Returns a pointer to Signature unlike ReadSignature.
func NewSignature(data []byte) (session_tag *Signature, remainder []byte, err error) {
func NewSignature(data []byte, sigType int) (signature *Signature, remainder []byte, err error) {
log.WithField("input_length", len(data)).Debug("Creating new Signature")
// sessionTag, remainder, err := ReadSignature(data)
sig, remainder, err := ReadSignature(data)
sig, remainder, err := ReadSignature(data, sigType)
if err != nil {
log.WithError(err).Error("Failed to read Signature")
return nil, remainder, err
}
session_tag = &sig
signature = &sig
log.WithFields(logrus.Fields{
"signature_length": len(sig),
"remainder_length": len(remainder),
}).Debug("Successfully created new Signature")
return
}

View File

@@ -14,8 +14,10 @@ var (
log = logger.GetGoI2PLogger()
)
const GOI2P_BASE_DIR = ".go-i2p"
func InitConfig() {
defaultConfigDir := filepath.Join(os.Getenv("HOME"), ".go-i2p")
defaultConfigDir := filepath.Join(os.Getenv("HOME"), GOI2P_BASE_DIR)
defaultConfigFile := filepath.Join(defaultConfigDir, "config.yaml")
if CfgFile != "" {

View File

@@ -26,11 +26,11 @@ func home() string {
}
func defaultBase() string {
return filepath.Join(home(), "go-i2p", "base")
return filepath.Join(home(), GOI2P_BASE_DIR, "base")
}
func defaultConfig() string {
return filepath.Join(home(), "go-i2p", "config")
return filepath.Join(home(), GOI2P_BASE_DIR, "config")
}
// defaults for router

View File

@@ -95,6 +95,10 @@ type DSAVerifier struct {
type DSAPublicKey [128]byte
func (k DSAPublicKey) Bytes() []byte {
return k[:]
}
// create a new dsa verifier
func (k DSAPublicKey) NewVerifier() (v Verifier, err error) {
log.Debug("Creating new DSA verifier")

View File

@@ -73,6 +73,10 @@ func (k ECP256PublicKey) Len() int {
return len(k)
}
func (k ECP256PublicKey) Bytes() []byte {
return k[:]
}
func (k ECP256PublicKey) NewVerifier() (Verifier, error) {
log.Debug("Creating new P256 ECDSA verifier")
// return createECVerifier(elliptic.P256(), crypto.SHA256, k[:])
@@ -88,6 +92,10 @@ type (
ECP384PrivateKey [48]byte
)
func (k ECP384PublicKey) Bytes() []byte {
return k[:]
}
func (k ECP384PublicKey) Len() int {
return len(k)
}
@@ -107,6 +115,10 @@ type (
ECP521PrivateKey [66]byte
)
func (k ECP521PublicKey) Bytes() []byte {
return k[:]
}
func (k ECP521PublicKey) Len() int {
return len(k)
}

View File

@@ -12,7 +12,10 @@ import (
"github.com/sirupsen/logrus"
)
var Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
var (
Ed25519EncryptTooBig = errors.New("failed to encrypt data, too big for Ed25519")
ErrInvalidPublicKeySize = errors.New("failed to verify: invalid ed25519 public key size")
)
type Ed25519PublicKey []byte
@@ -31,6 +34,10 @@ func (k Ed25519PublicKey) Len() int {
return len(k)
}
func (k Ed25519PublicKey) Bytes() []byte {
return k
}
func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) {
log.WithField("data_length", len(data)).Debug("Creating Ed25519 public key")
if len(data) == 256 {
@@ -44,22 +51,36 @@ func createEd25519PublicKey(data []byte) (k *ed25519.PublicKey) {
return
}
func createEd25519Encryption(pub *ed25519.PublicKey, rand io.Reader) (enc *Ed25519Encryption, err error) {
/*kbytes := make([]byte, 256)
k := new(big.Int)
for err == nil {
_, err = io.ReadFull(rand, kbytes)
k = new(big.Int).SetBytes(kbytes)
k = k.Mod(k, pub.P)
if k.Sign() != 0 {
break
// createEd25519Encryption initializes the Ed25519Encryption struct using the public key.
func createEd25519Encryption(pub *ed25519.PublicKey, randReader io.Reader) (*Ed25519Encryption, error) {
// Define p = 2^255 - 19
p := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 255), big.NewInt(19))
// Validate public key length
if len(*pub) != ed25519.PublicKeySize {
log.WithField("pub_length", len(*pub)).Error("Invalid Ed25519 public key size")
return nil, ErrInvalidPublicKeySize
}
// Convert public key bytes to big.Int
a := new(big.Int).SetBytes(*pub)
// Generate a random scalar b1 in [0, p)
b1, err := rand.Int(randReader, p)
if err != nil {
log.WithError(err).Error("Failed to generate b1 for Ed25519Encryption")
return nil, err
}
if err == nil {
enc = &Ed25519Encryption{}
}*/
log.Warn("createEd25519Encryption is not implemented")
return
// Initialize Ed25519Encryption struct
enc := &Ed25519Encryption{
p: p,
a: a,
b1: b1,
}
log.Debug("Ed25519Encryption created successfully")
return enc, nil
}
type Ed25519Encryption struct {
@@ -109,13 +130,18 @@ func (ed25519 *Ed25519Encryption) EncryptPadding(data []byte, zeroPadding bool)
func (elg Ed25519PublicKey) NewEncrypter() (enc Encrypter, err error) {
log.Debug("Creating new Ed25519 encrypter")
k := createEd25519PublicKey(elg[:])
if k == nil {
return nil, errors.New("invalid public key format")
}
enc, err = createEd25519Encryption(k, rand.Reader)
if err != nil {
log.WithError(err).Error("Failed to create Ed25519 encrypter")
} else {
log.Debug("Ed25519 encrypter created successfully")
return nil, err
}
return
log.Debug("Ed25519 encrypter created successfully")
return enc, nil
}
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) {
@@ -158,6 +184,42 @@ func (v *Ed25519Verifier) Verify(data, sig []byte) (err error) {
type Ed25519PrivateKey ed25519.PrivateKey
func (k Ed25519PrivateKey) NewDecrypter() (Decrypter, error) {
//TODO implement me
panic("implement me")
}
func (k Ed25519PrivateKey) NewSigner() (Signer, error) {
if len(k) != ed25519.PrivateKeySize {
return nil, errors.New("invalid ed25519 private key size")
}
return &Ed25519Signer{k: k}, nil
}
func (k Ed25519PrivateKey) Len() int {
return len(k)
}
func (k *Ed25519PrivateKey) Generate() (SigningPrivateKey, error) {
// Generate a new Ed25519 key pair
_, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
// Assign the generated private key to the receiver
*k = Ed25519PrivateKey(priv)
return k, nil
}
func (k Ed25519PrivateKey) Public() (SigningPublicKey, error) {
if len(k) != ed25519.PrivateKeySize {
return nil, errors.New("invalid ed25519 private key size")
}
// The public key is the first 32 bytes of the private key's seed
pubKey := k[32:]
return Ed25519PublicKey(pubKey), nil
}
type Ed25519Signer struct {
k []byte
}

View File

@@ -237,6 +237,10 @@ func (elg ElgPublicKey) Len() int {
return len(elg)
}
func (elg ElgPublicKey) Bytes() []byte {
return elg[:]
}
func (elg ElgPublicKey) NewEncrypter() (enc Encrypter, err error) {
log.Debug("Creating new ElGamal encrypter")
k := createElgamalPublicKey(elg[:])

View File

@@ -5,12 +5,57 @@ type (
RSA2048PrivateKey [512]byte
)
// Bytes implements SigningPublicKey.
func (r RSA2048PublicKey) Bytes() []byte {
panic("unimplemented")
}
// Len implements SigningPublicKey.
func (r RSA2048PublicKey) Len() int {
panic("unimplemented")
}
// NewVerifier implements SigningPublicKey.
func (r RSA2048PublicKey) NewVerifier() (Verifier, error) {
panic("unimplemented")
}
type (
RSA3072PublicKey [384]byte
RSA3072PrivateKey [786]byte
)
// Bytes implements SigningPublicKey.
func (r RSA3072PublicKey) Bytes() []byte {
panic("unimplemented")
}
// Len implements SigningPublicKey.
func (r RSA3072PublicKey) Len() int {
panic("unimplemented")
}
// NewVerifier implements SigningPublicKey.
func (r RSA3072PublicKey) NewVerifier() (Verifier, error) {
panic("unimplemented")
}
type (
RSA4096PublicKey [512]byte
RSA4096PrivateKey [1024]byte
)
// Bytes implements SigningPublicKey.
func (r RSA4096PublicKey) Bytes() []byte {
panic("unimplemented")
}
// Len implements SigningPublicKey.
func (r RSA4096PublicKey) Len() int {
panic("unimplemented")
}
// NewVerifier implements SigningPublicKey.
func (r RSA4096PublicKey) NewVerifier() (Verifier, error) {
panic("unimplemented")
}

View File

@@ -26,10 +26,11 @@ type SigningPublicKey interface {
NewVerifier() (Verifier, error)
// get the size of this public key
Len() int
Bytes() []byte
}
type PublicKey interface {
Len() int
Bytes() []byte
NewEncrypter() (Encrypter, error)
}

View File

@@ -69,11 +69,11 @@ func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) {
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 {
log.WithError(err).Error("Failed to read SU3 file signature")
return nil, err
}
log.Println("warning: this doesn't validate the signature yet", signature)
@@ -118,10 +118,6 @@ func (r Reseed) SingleReseed(uri string) ([]router_info.RouterInfo, error) {
}
log.WithField("router_info_count", len(ris)).Debug("Successfully processed reseed data")
return ris, err
} else {
log.WithError(err).Error("Failed to read SU3 file signature")
return nil, err
}
}
}
log.Error("Undefined reseed error")

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -103,7 +102,7 @@ func (db *StdNetDB) Size() (routers int) {
log.WithError(err).Panic("Failed to recalculate NetDB size")
}
}
data, err = ioutil.ReadFile(db.cacheFilePath())
data, err = os.ReadFile(db.cacheFilePath())
if err == nil {
routers, err = strconv.Atoi(string(data))
if err != nil {

View File

@@ -53,7 +53,7 @@ func fileRSAPubKey(t *testing.T, filename string) *rsa.PublicKey {
}
var pubKey *rsa.PublicKey
if k, ok := cert.PublicKey.(*rsa.PublicKey); !ok {
t.Fatalf("expected rsa.PublicKey from file %s", filename)
t.Fatalf("expected rsa.publicKey from file %s", filename)
} else {
pubKey = k
}

View File

@@ -9,7 +9,7 @@ import (
"testing"
"github.com/go-i2p/go-i2p/lib/crypto"
"github.com/go-i2p/go-i2p/lib/transport/ntcp"
"github.com/go-i2p/go-i2p/lib/transport/obfs"
"github.com/flynn/noise"
"github.com/stretchr/testify/assert"
@@ -536,7 +536,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) {
}
// Obfuscate Alice's ephemeral public key in message 1
obfuscatedMsg1, err := ntcp.ObfuscateEphemeralKey(msg1, aesKey)
obfuscatedMsg1, err := obfs.ObfuscateEphemeralKey(msg1, aesKey)
if err != nil {
t.Fatalf("Failed to obfuscate message 1: %v", err)
}
@@ -546,7 +546,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) {
// -------------------------------
// Deobfuscate Alice's ephemeral public key in message 1
deobfuscatedMsg1, err := ntcp.DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey)
deobfuscatedMsg1, err := obfs.DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey)
if err != nil {
t.Fatalf("Failed to deobfuscate message 1: %v", err)
}
@@ -574,7 +574,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) {
}
// Obfuscate Bob's ephemeral public key in message 2
obfuscatedMsg2, err := ntcp.ObfuscateEphemeralKey(msg2, aesKey)
obfuscatedMsg2, err := obfs.ObfuscateEphemeralKey(msg2, aesKey)
if err != nil {
t.Fatalf("Failed to obfuscate message 2: %v", err)
}
@@ -584,7 +584,7 @@ func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) {
// -------------------------------
// Deobfuscate Bob's ephemeral public key in message 2
deobfuscatedMsg2, err := ntcp.DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey)
deobfuscatedMsg2, err := obfs.DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey)
if err != nil {
t.Fatalf("Failed to deobfuscate message 2: %v", err)
}

View File

@@ -3,11 +3,79 @@ package noise
import (
"sync"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/flynn/noise"
)
type HandshakeState struct {
mutex sync.Mutex
ephemeral *noise.DHKey
pattern noise.HandshakePattern
handshakeComplete bool
HandKey noise.DHKey
*noise.HandshakeState
}
func NewHandshakeState(staticKey noise.DHKey, isInitiator bool) (*HandshakeState, error) {
hs := &HandshakeState{
pattern: noise.HandshakeXK,
}
config := noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashSHA256),
Pattern: hs.pattern,
Initiator: isInitiator,
StaticKeypair: staticKey,
}
protocol, err := noise.NewHandshakeState(config)
if err != nil {
return nil, err
}
hs.HandshakeState = protocol
return hs, nil
}
// GenerateEphemeral creates the ephemeral keypair that will be used in handshake
// This needs to be separate so NTCP2 can obfuscate it
func (h *HandshakeState) GenerateEphemeral() (*noise.DHKey, error) {
h.mutex.Lock()
defer h.mutex.Unlock()
dhKey, err := noise.DH25519.GenerateKeypair(nil)
if err != nil {
return nil, err
}
h.ephemeral = &dhKey
return &dhKey, nil
}
// SetEphemeral allows setting a potentially modified ephemeral key
// This is needed for NTCP2's obfuscation layer
func (h *HandshakeState) SetEphemeral(key *noise.DHKey) error {
h.mutex.Lock()
defer h.mutex.Unlock()
h.ephemeral = key
return nil
}
func (h *HandshakeState) WriteMessage(payload []byte) ([]byte, *noise.CipherState, *noise.CipherState, error) {
h.mutex.Lock()
defer h.mutex.Unlock()
return h.HandshakeState.WriteMessage(nil, payload)
}
func (h *HandshakeState) ReadMessage(message []byte) ([]byte, *noise.CipherState, *noise.CipherState, error) {
h.mutex.Lock()
defer h.mutex.Unlock()
return h.HandshakeState.ReadMessage(nil, message)
}
var log = logger.GetGoI2PLogger()
func (c *NoiseTransport) Handshake(routerInfo router_info.RouterInfo) error {

View File

@@ -3,61 +3,13 @@ package noise
import (
"bytes"
"crypto/rand"
"encoding/binary"
"errors"
"io"
"github.com/sirupsen/logrus"
"github.com/flynn/noise"
"github.com/sirupsen/logrus"
)
func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
log.Debug("Starting ComposeReceiverHandshakeMessage")
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
log.WithField("rs_length", len(rs)).Error("Invalid remote static key length")
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
log.WithField("pattern", "XK").Debug("Noise pattern set")
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
log.Debug("Using crypto/rand as random source")
} else {
random = bytes.NewBuffer(ePrivate)
log.Debug("Using provided ePrivate as random source")
}
prologue := make([]byte, 2, uint16Size+len(negData))
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
prologue = append(prologue, negData...)
log.WithField("prologue_length", len(prologue)).Debug("Prologue created")
// prologue = append(initString, prologue...)
state, err = noise.NewHandshakeState(noise.Config{
StaticKeypair: s,
Initiator: false,
Pattern: pattern,
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
PeerStatic: rs,
Prologue: prologue,
Random: random,
})
if err != nil {
log.WithError(err).Error("Failed to create new handshake state")
return
}
log.WithField("message_length", len(msg)).Debug("Handshake message composed successfully")
// log.Debug("Handshake state created successfully")
padBuf := make([]byte, 2+len(payload))
copy(padBuf[2:], payload)
msg, _, _, err = state.WriteMessage(msg, padBuf)
return
}
func (c *NoiseSession) RunIncomingHandshake() error {
log.Debug("Starting incoming handshake")
@@ -66,6 +18,9 @@ func (c *NoiseSession) RunIncomingHandshake() error {
log.WithError(err).Error("Failed to compose receiver handshake message")
return err
}
c.HandshakeState = &HandshakeState{
HandshakeState: state,
}
log.WithFields(logrus.Fields{
"negData_length": len(negData),
"msg_length": len(msg),
@@ -86,3 +41,51 @@ func (c *NoiseSession) RunIncomingHandshake() error {
log.Debug("Incoming handshake completed successfully")
return nil
}
func ComposeReceiverHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
log.Debug("Starting ComposeReceiverHandshakeMessage")
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
log.WithField("rs_length", len(rs)).Error("Invalid remote static key length")
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
log.Debug("Using crypto/rand as random source")
} else {
random = bytes.NewBuffer(ePrivate)
}
config := noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashSHA256),
Pattern: pattern,
Initiator: false,
StaticKeypair: s,
Random: random,
}
state, err = noise.NewHandshakeState(config)
if err != nil {
return nil, nil, nil, err
}
// Write message 2, expecting no CipherStates yet
msg, cs0, cs1, err := state.WriteMessage(nil, payload)
if err != nil {
return nil, nil, nil, err
}
// Verify no CipherStates are returned yet
if cs0 != nil || cs1 != nil {
return nil, nil, nil, errors.New("unexpected cipher states in message 2")
}
return negData, msg, state, nil
}

View File

@@ -3,7 +3,6 @@ package noise
import (
"bytes"
"crypto/rand"
"encoding/binary"
"errors"
"io"
@@ -12,56 +11,6 @@ import (
"github.com/flynn/noise"
)
func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
log.Debug("Starting ComposeInitiatorHandshakeMessage")
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
log.WithField("rs_length", len(rs)).Error("Invalid remote static key length")
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
log.WithField("pattern", "XK").Debug("Noise pattern set")
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
log.Debug("Using crypto/rand as random source")
} else {
random = bytes.NewBuffer(ePrivate)
log.Debug("Using provided ePrivate as random source")
}
prologue := make([]byte, 2, uint16Size+len(negData))
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
prologue = append(prologue, negData...)
log.WithField("prologue_length", len(prologue)).Debug("Prologue created")
// prologue = append(initString, prologue...)
state, err = noise.NewHandshakeState(noise.Config{
StaticKeypair: s,
Initiator: true,
Pattern: pattern,
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256),
PeerStatic: rs,
Prologue: prologue,
Random: random,
})
if err != nil {
log.WithError(err).Error("Failed to create new handshake state")
return
}
log.Debug("Handshake state created successfully")
padBuf := make([]byte, 2+len(payload))
copy(padBuf[2:], payload)
msg, _, _, err = state.WriteMessage(msg, padBuf)
if err != nil {
log.WithError(err).Error("Failed to write handshake message")
return
}
log.WithField("message_length", len(msg)).Debug("Handshake message composed successfully")
return
}
func (c *NoiseSession) RunOutgoingHandshake() error {
log.Debug("Starting outgoing handshake")
@@ -74,6 +23,9 @@ func (c *NoiseSession) RunOutgoingHandshake() error {
"negData_length": len(negData),
"msg_length": len(msg),
}).Debug("Initiator handshake message composed")
c.HandshakeState = &HandshakeState{
HandshakeState: state,
}
if _, err = c.Write(negData); err != nil {
log.WithError(err).Error("Failed to write negotiation data")
@@ -92,3 +44,49 @@ func (c *NoiseSession) RunOutgoingHandshake() error {
log.Debug("Outgoing handshake completed successfully")
return nil
}
func ComposeInitiatorHandshakeMessage(s noise.DHKey, rs []byte, payload []byte, ePrivate []byte) (negData, msg []byte, state *noise.HandshakeState, err error) {
log.Debug("Starting ComposeInitiatorHandshakeMessage")
if len(rs) != 0 && len(rs) != noise.DH25519.DHLen() {
return nil, nil, nil, errors.New("only 32 byte curve25519 public keys are supported")
}
negData = make([]byte, 6)
copy(negData, initNegotiationData(nil))
pattern := noise.HandshakeXK
negData[5] = NOISE_PATTERN_XK
var random io.Reader
if len(ePrivate) == 0 {
random = rand.Reader
} else {
random = bytes.NewBuffer(ePrivate)
}
config := noise.Config{
CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherAESGCM, noise.HashSHA256),
Pattern: pattern,
Initiator: true,
StaticKeypair: s,
Random: random,
}
state, err = noise.NewHandshakeState(config)
if err != nil {
return nil, nil, nil, err
}
// Write message, expecting no CipherStates yet since this is message 1
msg, cs0, cs1, err := state.WriteMessage(nil, payload)
if err != nil {
return nil, nil, nil, err
}
// Verify no CipherStates are returned yet
if cs0 != nil || cs1 != nil {
return nil, nil, nil, errors.New("unexpected cipher states in message 1")
}
return negData, msg, state, nil
}

View File

@@ -1,7 +1,6 @@
package noise
import (
"bytes"
"fmt"
"net"
"sync"
@@ -19,18 +18,13 @@ import (
type NoiseSession struct {
router_info.RouterInfo
*noise.CipherState
sync.Mutex
*sync.Cond
*NoiseTransport // The parent transport, which "Dialed" the connection to the peer whith whom we established the session
*HandshakeState
RecvQueue *cb.Queue
SendQueue *cb.Queue
SendKey noise.DHKey
RecvKey noise.DHKey
HandKey noise.DHKey
VerifyCallback VerifyCallbackFunc
handshakeBuffer bytes.Buffer
activeCall int32
handshakeComplete bool
Conn net.Conn
}
@@ -116,15 +110,6 @@ func NewNoiseTransportSession(ri router_info.RouterInfo) (transport.TransportSes
log.WithError(err).Error("Failed to dial address")
return nil, err
}
/*
return &NoiseSession{
SendQueue: cb.New(1024),
RecvQueue: cb.New(1024),
RouterInfo: ri,
Conn: socket,
}, nil
*/
session := &NoiseSession{
SendQueue: cb.New(1024),
RecvQueue: cb.New(1024),

View File

@@ -13,7 +13,6 @@ import (
"github.com/sirupsen/logrus"
"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"
@@ -23,7 +22,6 @@ import (
type NoiseTransport struct {
sync.Mutex
router_identity.RouterIdentity
*noise.CipherState
Listener net.Listener
peerConnections map[data.Hash]transport.TransportSession
}

View File

@@ -1,5 +1,101 @@
package ntcp
// Session implements TransportSession
// An established transport session
type Session struct{}
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/transport/noise"
)
/*
Summary of what needs to be done:
NTCP and SSU2 are both transport protocols based on noise, with additional features designed to prevent p2p traffic from being blocked by firewalls.
These modifications affect how the Noise handshake takes place, in particular:
- Ephemeral keys are transmitted **obfuscated** by encrypting them with the peer's known static public key.
these modifications are simple enough, but for our purposes we also want to be able to re-use as much code as possible.
So, what we need to do is devise a means of adding these modifications to the existing NoiseSession implementation.
We could do this in any number of ways, we could:
1. Implement a custom struct that embeds a NoiseSession and overrides the Compose*HandshakeMessage functions
2. Modify the NoiseSession handshake functions to allow passing an obfuscation and/or padding function as a parameter
3. Modify the NoiseSession implementation to allow replacing the Compose*HandshakeMessage functions with custom ones
4. Refactor the NoiseSession implementation to break Compose*HandshakeMessage out into a separate interface, and implement that interface in a custom struct
Ideally, we're already set up to do #1, but we'll see how it goes.
Now is the right time to make changes if we need to, go-i2p is the only consumer of go-i2p right now, we can make our lives as easy as we want to.
*/
// NTCP2Session extends the base noise.NoiseSession with NTCP2-specific functionality
type NTCP2Session struct {
*noise.NoiseSession
paddingStrategy PaddingStrategy
}
// NewNTCP2Session creates a new NTCP2 session using the existing noise implementation
func NewNTCP2Session(noiseConfig router_info.RouterInfo) (*NTCP2Session, error) {
baseNoiseSession, err := noise.NewNoiseTransportSession(noiseConfig)
if err != nil {
return nil, err
}
return &NTCP2Session{
NoiseSession: baseNoiseSession.(*noise.NoiseSession),
}, nil
}
type PaddingStrategy interface {
AddPadding(message []byte) []byte
RemovePadding(message []byte) []byte
}
// PeerStaticKey is equal to the NTCP2 peer's static public key, found in their router info
func (s *NTCP2Session) peerStaticKey() ([32]byte, error) {
for _, addr := range s.RouterInfo.RouterAddresses() {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NTCP_PROTOCOL_NAME {
return addr.StaticKey()
}
}
return [32]byte{}, fmt.Errorf("Remote static key error")
}
// ObfuscateEphemeral implements NTCP2's key obfuscation using AES-256-CBC
func (s *NTCP2Session) ObfuscateEphemeral(key []byte) ([]byte, error) {
static, err := s.peerStaticKey()
if err != nil {
return nil, err
}
block, err := aes.NewCipher(static[:])
if err != nil {
return nil, err
}
obfuscated := make([]byte, len(key))
iv := make([]byte, aes.BlockSize)
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(obfuscated, key)
return obfuscated, nil
}
// DeobfuscateEphemeral reverses the key obfuscation
func (s *NTCP2Session) DeobfuscateEphemeral(obfuscated []byte) ([]byte, error) {
static, err := s.peerStaticKey()
if err != nil {
return nil, err
}
block, err := aes.NewCipher(static[:])
if err != nil {
return nil, err
}
key := make([]byte, len(obfuscated))
iv := make([]byte, aes.BlockSize)
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(key, obfuscated)
return key, nil
}

View File

@@ -4,11 +4,85 @@ package ntcp
* https://geti2p.net/spec/ntcp2
**/
import (
"fmt"
"net"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/transport"
"github.com/go-i2p/go-i2p/lib/transport/noise"
)
const (
NTCP_PROTOCOL_VERSION = 2
NTCP_PROTOCOL_NAME = "NTCP2"
NTCP_MESSAGE_MAX_SIZE = 65537
)
// Transport is an ntcp transport implementing transport.Transport interface
type Transport struct{}
var exampleNTCPTransport transport.Transport = &Transport{}
// Transport is an ntcp2 transport implementing transport.Transport interface
type Transport struct {
*noise.NoiseTransport
}
func (t *Transport) Name() string {
return NTCP_PROTOCOL_NAME
}
func (t *Transport) Compatible(routerInfo router_info.RouterInfo) bool {
// Check if the router info contains NTCP2 address and capabilities
addresses := routerInfo.RouterAddresses()
for _, addr := range addresses {
transportStyle, err := addr.TransportStyle().Data()
if err != nil {
continue
}
if transportStyle == NTCP_PROTOCOL_NAME {
return true
}
}
return false
}
func (t *Transport) GetSession(routerInfo router_info.RouterInfo) (transport.TransportSession, error) {
// Create new NTCP2 session
session, err := NewNTCP2Session(routerInfo)
if err != nil {
return nil, err
}
// Perform handshake
if err := session.Handshake(routerInfo); err != nil {
return nil, err
}
return session, nil
}
func (t *Transport) Accept() (net.Conn, error) {
conn, err := t.NoiseTransport.Accept()
if err != nil {
return nil, err
}
// check if remote router address contains a compatible transport
// first get the RemoteAddr
remoteAddr := conn.LocalAddr()
// then check if it's a router address
routerAddr, ok := remoteAddr.(*router_info.RouterInfo)
if !ok {
return nil, fmt.Errorf("remote address is not a router address")
}
// then check if it's compatible
if !t.Compatible(*routerAddr) {
return nil, fmt.Errorf("remote router address is not compatible with NTCP2")
}
// Wrap connection with NTCP2 session
session, err := NewNTCP2Session(remoteAddr.(router_info.RouterInfo)) // nil for incoming connections
if err != nil {
conn.Close()
return nil, err
}
return session, nil
}

View File

@@ -1,4 +1,4 @@
package ntcp
package obfs
import (
"fmt"

View File

@@ -1 +1,10 @@
package ssu
/*
Summary of what needs to be done:
In addition to being a modified Noise protocol implementation,
SSU2 also includes peer-testing features and QUIC-inspired features for resuming interrupted sessions.
If we've done our jobs correctly when we get to this point, we will be implementing a net.Conn interface
that can do the peer-testing and session management stuff, and we will **layer** it with our Noise protocol
implementation and the SSU2 modifications.
*/

View File

@@ -1 +1,17 @@
package ssu
/*
Summary of what needs to be done:
NTCP and SSU2 are both transport protocols based on noise, with additional features designed to prevent p2p traffic from being blocked by firewalls.
These modifications affect how the Noise handshake takes place, in particular:
- Ephemeral keys are transmitted **obfuscated** by encrypting them with the peer's known static public key.
these modifications are simple enough, but for our purposes we also want to be able to re-use as much code as possible.
So, what we need to do is devise a means of adding these modifications to the existing NoiseSession implementation.
We could do this in any number of ways, we could:
1. Implement a custom struct that embeds a NoiseSession and overrides the Compose*HandshakeMessage functions
2. Modify the NoiseSession handshake functions to allow passing an obfuscation and/or padding function as a parameter
3. Modify the NoiseSession implementation to allow replacing the Compose*HandshakeMessage functions with custom ones
4. Refactor the NoiseSession implementation to break Compose*HandshakeMessage out into a separate interface, and implement that interface in a custom struct
Ideally, we're already set up to do #1, but we'll see how it goes.
Now is the right time to make changes if we need to, go-i2p is the only consumer of go-i2p right now, we can make our lives as easy as we want to.
*/

View File

@@ -22,6 +22,8 @@ type TransportSession interface {
// close the session cleanly
// returns any errors that happen while closing the session
Close() error
// create a handshake message for the session
// CreateHandshakeMessage() (i2np.I2NPMessage, error)
}
type Transport interface {

View File

@@ -121,9 +121,11 @@ func (rt *RouterTimestamper) TimestampNow() {
go rt.runOnce()
}
}
func (rt *RouterTimestamper) secureRandBool(probability float64) bool {
return rand.Float64() < probability
}
func (rt *RouterTimestamper) performTimeQuery() bool {
rt.updateConfig()
preferIPv6 := checkIPv6Connectivity()
@@ -270,6 +272,7 @@ func (rt *RouterTimestamper) run() {
func (rt *RouterTimestamper) runOnce() {
rt.performTimeQuery()
}
func (rt *RouterTimestamper) queryTime(servers []string, timeout time.Duration, preferIPv6 bool) bool {
found := make([]time.Duration, rt.concurringServers)
var expectedDelta time.Duration

View File

@@ -1,10 +1,11 @@
package sntp
import (
"github.com/beevik/ntp"
"sync"
"testing"
"time"
"github.com/beevik/ntp"
)
type MockNTPClient struct {
@@ -86,6 +87,7 @@ func TestTimestampNow(t *testing.T) {
t.Error("Expected at least one time update, got none")
}
}
func TestTimestampNowWithRealNTP(t *testing.T) {
defaultClient := &DefaultNTPClient{}
timestamper := NewRouterTimestamper(defaultClient)
@@ -140,6 +142,7 @@ func TestTimestampNowWithRealNTP(t *testing.T) {
t.Logf("NTP Servers: %v", timestamper.servers)
t.Logf("Priority Servers: %v", timestamper.priorityServers)
}
func TestWaitForInitialization(t *testing.T) {
defaultClient := &DefaultNTPClient{}
timestamper := NewRouterTimestamper(defaultClient)

View File

@@ -2,8 +2,9 @@ package sntp
import (
"fmt"
"github.com/beevik/ntp"
"time"
"github.com/beevik/ntp"
)
func (rt *RouterTimestamper) validateResponse(response *ntp.Response) bool {

View File

@@ -1,9 +1,10 @@
package sntp
import (
"github.com/beevik/ntp"
"testing"
"time"
"github.com/beevik/ntp"
)
func TestValidateResponse(t *testing.T) {