385 Commits

Author SHA1 Message Date
idk
3142a394aa Merge pull request #31 from go-i2p/ntcp
NTCP2 Handshake Development
2025-03-21 15:48:13 -04:00
f2b6d4bc01 Refactor noise locked read/write, move handshake out to own interface 2025-03-19 22:28:14 -04:00
fa0a42855c move padding 2025-03-19 17:20:33 -04:00
3212cae276 fix tests that failed because of inconsistent usage of crypto API 2025-03-09 14:04:43 -04:00
ad7bac666b Merge branch 'ntcp' of github.com:go-i2p/go-i2p into ntcp 2025-03-09 14:02:42 -04:00
ba0c89d567 fix tests that failed because of inconsistent usage of crypto API 2025-03-09 14:02:10 -04:00
idk
6a64b28bb3 Merge pull request #39 from urgentquest/better-config-file-handling
Better config file handling
2025-03-09 13:52:15 -04:00
9fa714f648 typo 2025-03-05 20:03:31 +00:00
eda403443d Some additional tweaks. Split out actual config handling. Add an auxiliary func to build i2p base directory path 2025-03-05 00:40:43 +00:00
84cc45d3e4 Refactor config handling
- Replace low-level operations like file existance checks, file io with viper calls.
That also allows to get rid of manual config structure initialization.
- Split out UserHome() into itil/home.go to reduce code duplicacy.
- Better error handling and general readbility.
2025-03-04 23:59:38 +00:00
598ee1eb70 Merge branch 'ntcp' of github.com:go-i2p/go-i2p into ntcp 2025-03-02 16:44:43 -05:00
bd6edf446d Fix some tests 2025-03-02 16:43:47 -05:00
idk
94e43f8aa6 Merge pull request #38 from urgentquest/ntcp-go-fix-null-pointer-dereferences
ntcp/session.go: fixes and imrovements
2025-03-02 15:46:45 -05:00
7bdaf6d4ea ntcp/session.go: fixes and imrovements
- Stop using deprecated (and probably
not cryptographically secure) exp/rand, switch to crypto/rand instead
- Reduce code duplicacy by defining `buildAesStaticKey()` method
- Properly handle pointer to `crypto.AESSymmetricKey` struct
to prevent nil pointer dereferences
- go mod tidy
2025-03-01 21:19:53 +00:00
393263294e update CONTRIBUTING.md 2025-02-27 12:53:55 -05:00
55f92bdd8a update CONTRIBUTING.md 2025-02-27 11:17:57 -05:00
8ea238f3dd add template for docs 2025-02-27 10:33:01 -05:00
91d8b30495 Add callgraphs to docs 2025-02-26 21:03:51 -05:00
ea4d126358 Add callgraphs to docs 2025-02-26 20:58:20 -05:00
f46bd95b68 Add callgraphs to docs 2025-02-26 20:52:16 -05:00
35eb66084b add the ability to generate callgraphs 2025-02-26 20:38:46 -05:00
a9289dd4d3 add the ability to generate callgraphs 2025-02-26 20:38:29 -05:00
7f78fdf784 Add new, address generation functions 2025-02-26 19:31:57 -05:00
ae4970b3a9 Switch to oops for error configuration so we can get more info about failures 2025-02-26 19:22:48 -05:00
3d6a08a76b start building NTCP2 addresses 2025-02-26 19:13:05 -05:00
18b2afe828 create and store our own RI with private keys 2025-02-26 14:44:02 -05:00
c6867e0b16 more keystore work 2025-02-25 16:15:18 -05:00
d0b4db769e Work on setting up a routerinfo from a keystore 2025-02-16 15:09:12 -05:00
26a9a00b34 Work on setting up a routerinfo from a keystore 2025-02-16 14:38:06 -05:00
99df4c7ce8 Little more RI private key stuff just to be sure where I think it should go 2025-02-15 22:19:46 -05:00
b95b0c4fa3 start working on basic key storage for own RI private keys 2025-02-15 22:17:32 -05:00
036f9116a5 start working on basic key storage for own RI private keys 2025-02-15 22:16:31 -05:00
idk
d97624282e Merge pull request #35 from satk0/i2np-build-res
Add i2np Build Response Record
2025-02-11 14:12:08 -05:00
46af6d55ef Update upload-artifact in workflow 2025-02-11 13:19:39 +01:00
9591f496eb Add BuildResponseRecord 2025-02-11 13:15:47 +01:00
71fff44d4b Merge branch 'master' of github.com:go-i2p/go-i2p into ntcp 2025-02-10 16:44:55 -05:00
6b2f231c36 spk and cpk reads were reversed 2025-02-10 16:41:59 -05:00
4eeaf915f0 sam and tunnel manager are now freestanding apps 2025-02-09 12:29:17 -05:00
440b9e8118 revise logging around SPK stuff in router_info.go 2025-01-30 15:49:28 -05:00
8bc5ca162a NTCP2: Change noise interface so we get static keys from better places 2024-12-21 22:13:03 -05:00
bd92221d56 Merge branch 'master' of github.com:go-i2p/go-i2p into ntcp 2024-12-21 19:52:28 -05:00
idk
22111a6cb7 Merge pull request #30 from satk0/add-signature-tests
Add signature tests
2024-12-14 00:19:14 +00:00
74d2998e10 Try and reason with the ways of getting local and remote static keys in the transports 2024-12-13 16:59:46 -05:00
0b89baf98b Add signature tests to doc/tests and actions 2024-12-13 22:42:29 +01:00
daac1a59b5 Add more signatures 2024-12-13 18:30:15 +01:00
6f65a7c068 Add signature tests 2024-12-13 15:26:21 +01:00
db91315582 Make the arguments to ComposeInitatorHandshakeMessage comprehensible 2024-12-12 14:55:40 -05:00
idk
5f3a7f2340 Merge pull request #26 from hkh4n/tests
Refactoring tests
2024-12-04 21:18:57 +00:00
8494da07a7 deprecate unused functions, deferring non-working test functions for later 2024-12-04 03:37:31 -05:00
832e0d9114 Ed25519PrivateKey Public() modification 2024-12-04 02:22:54 -05:00
8d56d033ae flux 2024-12-04 01:40:23 -05:00
ad22d3e249 flux 2024-12-04 01:28:13 -05:00
f55788e8ab flux 2024-12-04 01:18:54 -05:00
2a4f4d6186 successful flux 2024-12-04 01:14:38 -05:00
ca1180c57f added cert tests and experimental function NewCertificateDeux 2024-12-04 00:55:53 -05:00
76c3e5f293 WHAT IS HAPPENING RIGHT NOW 2024-12-04 00:02:33 -05:00
91abe52725 flux 2024-12-03 23:22:14 -05:00
a0ad9e0122 flux 2024-12-03 23:12:34 -05:00
b23edc28d1 flux 2024-12-03 23:07:52 -05:00
b547faf286 flux 2024-12-03 21:24:32 -05:00
a145555bb2 flux 2024-12-03 19:27:41 -05:00
280c877d39 Merge branch 'master' of github.com:go-i2p/go-i2p into ntcp 2024-12-01 15:41:24 -05:00
ef4d4658c0 NTCP2: Add CreateSessionRequest to implement handshake 1 message, modify ComposeInitiatorHandshakeMessage to actually send it 2024-12-01 15:27:42 -05:00
15bf28403e exported KeyCertificate 2024-12-01 01:28:38 -05:00
b40c0ab6f9 fixed crypto public key size 2024-12-01 01:13:53 -05:00
b952be5e08 build test (redo) 2024-11-30 18:33:39 -05:00
aafbf74986 revert build test 2024-11-30 18:30:02 -05:00
3cdc5676eb build test 2024-11-30 18:27:54 -05:00
d41efdba0e adjusted tests.yml and Makefile 2024-11-30 17:43:51 -05:00
edc436ac39 Merge branch 'master' into tests
# Conflicts:
#	Makefile
2024-11-30 17:30:47 -05:00
idk
414b489b37 Merge pull request #29 from hkh4n/workflow2
Adjust github workflows
2024-11-30 22:11:49 +00:00
da875738e4 fix typos 2024-11-28 22:46:48 -05:00
2a027ebb6c added lease_set.mk + add to Makefile 2024-11-28 22:44:51 -05:00
d658dee6de correct filename + add to Makefile 2024-11-28 22:43:20 -05:00
8fde3c9400 updated lease_set.mk 2024-11-28 22:40:20 -05:00
9421374384 are tests running? 2024-11-28 20:18:03 -05:00
daad2dcacd dont fail fast on CI 2024-11-28 20:16:10 -05:00
5f8dc3f9a2 matrix x2 2024-11-28 20:14:05 -05:00
9cc2e8f410 matrix 2024-11-28 20:13:21 -05:00
6ac46aa747 Run aggregated tests 2024-11-28 20:07:37 -05:00
5548b865b4 Adjusted makefile
-moved make test-all to just make test
-removed make test-all from tests.yml
2024-11-28 18:42:23 -05:00
55245b2aa7 added more logging 2024-11-26 23:06:21 -05:00
208051f92d strange error: publicKey has invalid size: expected 0, got 256 2024-11-26 23:03:17 -05:00
8a672ca6ca adjust var names 2024-11-26 22:10:53 -05:00
45def9dd0c Merge branch 'master' into tests 2024-11-26 22:08:46 -05:00
cb1da321b9 added tests.yml 2024-11-26 22:02:31 -05:00
d291624436 fixed auto-assign.yml 2024-11-26 22:01:52 -05:00
a58f64566f Destination size 363 -> Fail 2024-11-26 21:28:02 -05:00
891d915bb2 TODO 2024-11-26 20:30:37 -05:00
a0a8704c6c mapping.size = size to fix dereference panic 2024-11-26 20:30:31 -05:00
c68acf848e Corrected ValuesToMapping to order correctly 2024-11-26 19:56:32 -05:00
7a6927cf53 gofumpt 2024-11-26 19:47:17 -05:00
37e11ffee1 adjust generateTestRouterInfo 2024-11-26 15:56:41 -05:00
e15e427f60 return error + uniform naming 2024-11-26 15:56:29 -05:00
f0803a095e tweaks 2024-11-26 15:55:50 -05:00
bf7e88bec1 updated test functions to not panic 2024-11-24 14:34:14 -05:00
065ceeb88f Various changes
-removed outdated test functions (to be replaced later)
-added working experimental ReadKeysAndCert replacement candidate ReadKeysAndCertDeux
-added readCertificateFromEnd
-added constructPublicKey
-exported SpkType and CpkType in KeyCertificate
-added CryptoPublicKeySize() method
-added SigningPublicKeySize() method
2024-11-24 14:25:40 -05:00
ca4a7a13ea experimental functions, tests pass 2024-11-23 23:54:01 -05:00
0b0753cac1 tweaks 2024-11-23 22:48:58 -05:00
40c2c4806c fix padding + fail on invalid padding instead of warn. 2024-11-23 22:45:32 -05:00
9e3c8bcb98 move logger out of go-i2p so we can re-use it without importing the entire module 2024-11-21 17:16:48 -05:00
9b4bf2663d clear artifact 2024-11-21 14:25:39 -05:00
4a6f49d14a NTCP: fix IV functions 2024-11-20 16:02:14 -05:00
5d789973b2 DRY: use obfs library to ofuscate and deobfuscate ephemeral keys 2024-11-20 15:55:07 -05:00
08127861f1 Refactor: Fix constants. 2024-11-20 15:37:44 -05:00
0e6ffd856b Refactor: move Compose* onto the NoiseSession struct. Fix constants. 2024-11-20 15:34:48 -05:00
idk
10daacbc9b Merge pull request #28 from satk0/add-lease-tests
Add lease tests and make names more clear
2024-11-20 17:36:07 +00:00
eeb1e215a5 Add lease tests and make names more clear 2024-11-19 17:31:34 +01:00
08e599e59a create Ed25519PublicKeyFromBytes 2024-11-18 12:34:03 -05:00
30f5565217 .Type -> .Type() 2024-11-18 12:27:55 -05:00
fc3ba17af5 ReadKeysAndCert is not working as expected 2024-11-18 12:25:31 -05:00
631f8d1850 nuked lease_set_test.go -> BROKEN 2024-11-17 23:04:07 -05:00
cc43160bb9 nuked & revived router_info_test.go
-TestRouterInfoCapabilities() fails
-TestRouterInfoVersion() fails
2024-11-17 22:23:31 -05:00
09acf3d23d adjusted router_info2_test.go 2024-11-17 22:04:27 -05:00
cbe4af8459 added AsDestination() 2024-11-17 21:44:32 -05:00
b72ed0a37d remove recovery attempt in mapping 2024-11-17 21:39:31 -05:00
07268df720 CRITICAL: Reverted mapping.go 2024-11-17 21:03:42 -05:00
def8789b77 verification 2024-11-17 14:13:38 -05:00
59c53bc5c1 Added constructors and readers
-NewLeaseSet()
-NewLeaseSetFromBytes()
-ReadLease()
-NewLeaseFromBytes()
2024-11-17 14:00:41 -05:00
ee56e0f40f corrected TestPublicKeyWithBadCertificate that had fault error matching 2024-11-17 13:32:08 -05:00
4e2b55ccbe add new tests to router_info.mk 2024-11-17 13:01:46 -05:00
64d90a157c Fixed array bounds error in handling short input in NewKeyCertificate 2024-11-17 12:55:34 -05:00
3acff32f17 adjusted vars, all tests pass for mapping 2024-11-17 12:36:26 -05:00
362513bbe5 Handle extra bytes beyond mapping length 2024-11-17 12:32:46 -05:00
c9f3227116 added length check to ReadMapping 2024-11-17 12:23:21 -05:00
f0702ffba9 Various changes
-we're dropping errors instead of trying to recover
-revamp TestReadI2PStringErrWhenDataTooShort to reflect drops instead of recoveries
2024-11-17 11:52:47 -05:00
11b9018630 implement uniform errors 2024-11-17 11:26:02 -05:00
f6daa5d9b6 Various changes
-in func (str I2PString) Data(): remove recovery attempts causing tests to fail
-added more universal errors
2024-11-17 11:16:43 -05:00
58d1f0d815 fixed func (str I2PString) Data()
-replace actual length expected by TestI2PStringDataReportsExtraDataError, which is an invalid length
-added note to see if we should trim instead
2024-11-17 10:52:47 -05:00
62ececf102 fixed func(str I2pString) Length()
-Previously incorrectly checked length causing TestI2PStringReportsExtraDataError to fail
2024-11-17 10:35:22 -05:00
idk
1d90db3239 Merge pull request #23 from hkh4n/routerinfo
Routerinfo
2024-11-17 14:28:44 +00:00
idk
f729bda62d Merge branch 'master' into routerinfo 2024-11-16 18:17:10 +00:00
4ad0f97bfe Fail-fast switch for logging Logging, format 2024-11-16 13:15:33 -05:00
idk
e296441f29 Merge branch 'master' into routerinfo 2024-11-16 03:56:57 +00:00
62086c7d04 make fmt 2024-11-15 22:52:17 -05:00
ddba94d6ae remove printing 2024-11-15 22:48:57 -05:00
767b91df49 clean up temp dirs 2024-11-15 22:47:36 -05:00
1292098cf0 Merge remote-tracking branch 'origin/10k' into 10k 2024-11-15 22:45:04 -05:00
24bc4c3c17 Implemented ed25519 SPK's 2024-11-15 22:29:42 -05:00
81eb270351 !WIP! - 10k test 2024-11-15 22:06:23 -05:00
b6f197cf92 This is not correct yet, work on key_certificate.go lines 216-245 2024-11-15 17:35:44 -05:00
c10d98a3b2 export DEBUG_I2P=debug in Makefile so that extended logs show up in the tests 2024-11-15 16:52:37 -05:00
6d16ca5f87 debugging info to investigate 2024-11-15 14:43:36 -05:00
003d6c9ab8 !WIP! - 10k test 2024-11-15 13:53:44 -05:00
015c4b23e2 pass sigType to NewRouterInfo 2024-11-15 11:49:10 -05:00
e29c3c7abb formatting + implemented GetSignatureTypeFromCertificate 2024-11-15 11:31:29 -05:00
6f6291a9f6 bounds checking 2024-11-15 11:31:10 -05:00
767864d457 corrected order in Bytes() 2024-11-15 11:30:59 -05:00
0a98236d85 adjusted test 2024-11-15 11:30:40 -05:00
c1fa63f6ec added sigtype 2024-11-15 11:30:34 -05:00
a75c275b4c Corrected Bytes()
-TODO: add logging
2024-11-15 11:30:11 -05:00
d40b3e0cd3 added sig types 2024-11-15 11:14:05 -05:00
2ee2d77d7c check if data slice is empty 2024-11-15 11:01:06 -05:00
idk
df45c19272 Merge pull request #24 from satk0/fix-key-certificate-tests
Fix key certificate tests
2024-11-14 15:50:16 +00:00
f6894e9064 Fix PubKeyWithP521 test 2024-11-12 23:54:50 +01:00
b36ef65a10 Fix test when data is too small 2024-11-11 23:04:21 +01:00
271cf56ded Fixes the padding generation but the reader still thinks something's wrong 2024-11-10 19:29:07 -05:00
a29fa0bc03 Output the rest of the key certificate, that would probably help... 2024-11-10 17:15:56 -05:00
63c48dd3b7 log the actual bytes in the test for now, make sure they're really there 2024-11-09 13:41:19 -05:00
8bec47efd2 log the actual bytes in the test for now, make sure they're really there 2024-11-09 13:39:38 -05:00
69a50e2035 Try adding a dummy address, change logging to show where not enough data was provided 2024-11-09 13:33:23 -05:00
8319444890 Try adding a dummy address, change logging to show where not enough data was provided 2024-11-09 13:31:24 -05:00
b378661e0e Fix LS test, update Noise Subsystem on README.md 2024-11-09 12:33:53 -05:00
f4086e5f68 !WIP! - Router Info 2024-11-09 11:13:48 -05:00
877fc707c4 !WIP! - Router Info 2024-11-09 01:04:44 -05:00
98d05e27c8 !WIP! - Router Info 2024-11-09 00:53:17 -05:00
8c2b952616 setup auto-assign workflow 2024-11-08 15:01:05 -05:00
4020db8a19 Refactor: Certificate Constructor: 2024-11-04 19:19:03 -05:00
67a02f5d69 Noise: Refactor, remove unused fields 2024-11-04 18:26:17 -05:00
ca1280231c Tidy 2024-11-04 15:25:54 -05:00
02b309df43 Refactor: move HandshakeState to own struct in preparation for NTCP2 mods 2024-11-04 15:20:56 -05:00
a5b3c3f194 NTCP2: Stub out NTCP2 and explain the task at hand, SSU2: Explain the plan 2024-11-04 00:24:08 -05:00
0aa7a5554b Merge branch 'master' of github.com:go-i2p/go-i2p 2024-11-03 23:59:13 -05:00
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
db0fd9f7e9 Management: rm PASTA.md 2024-11-03 15:53:23 -05:00
3ab258cde6 Management: add ROADMAP.md 2024-11-03 15:53:13 -05:00
20b9bbd8e4 go mod tidy & fixed condition that was always true 2024-11-03 01:52:48 -05:00
1fa520613c replace deprecated function (ioutil -> os) 2024-11-03 00:14:45 -04:00
fb99b98a7e minor typo fix 2024-11-02 21:37:56 -04:00
d6b8cd9d4d go mod tidy 2024-11-02 21:37:29 -04:00
92e4656774 move from ~/go-i2p to ~/.go-i2p 2024-11-02 21:37:23 -04:00
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
idk
344edc6d41 Merge branch 'master' into noise-experimental 2024-11-02 02:59:24 +00:00
idk
9eea99b489 Merge pull request #20 from hkh4n/noise-experimental
Polishes
2024-11-01 14:30:25 +00:00
idk
c984f94b90 Merge pull request #9 from hkh4n/sntp-experimental
Implemented mimic implementation of sntp from the original java implementation
2024-11-01 14:28:00 +00:00
a17f0208dd gofumpt adjustment 2024-10-31 10:53:22 -04:00
487815f8f1 tests 2024-10-31 10:50:21 -04:00
24e0baa879 Moved functions
-encryptPacketDeux -> testEncryptPacket in encrdecr_packet_test.go
-decryptPacketDeux -> testDecryptPacket in encrdecr_packet_test.go
2024-10-31 10:45:42 -04:00
a5d2f0de8c lib/transport/noise/doc.md 2024-10-31 00:01:22 -04:00
423f616d53 Info -> Debug 2024-10-30 23:29:46 -04:00
idk
c65048f3c4 Merge pull request #18 from hkh4n/config
Added config
2024-10-30 22:03:24 +00:00
39b683dac8 fixed circular dependency 2024-10-30 11:20:15 -04:00
46883f6457 build fails -> import cycle 2024-10-30 09:31:01 -04:00
4be55062fc Moved config funcs to config.go 2024-10-30 09:22:32 -04:00
12a3fd4623 Added config files + args
-added routerInstance
-added initConfig()
-added updateRouterConfig()
-yaml format
2024-10-30 09:16:22 -04:00
80e539930e Mapping: fix off-by-one. Format: gofumpt 2024-10-28 18:11:54 -04:00
e58d326d89 Move obfuscation functions to lib/transport/ntcp 2024-10-25 21:29:02 -04:00
e6f84c16f6 added experimental functions which factor in packet length
-encryptPacketDeux
-decryptPacketDeux

Added test -> TestEncryptDecryptPacketObfsOfflineWithFunc()

added new functions in aes.go
-EncryptNoPadding
-DecryptNoPadding
2024-10-24 22:57:36 -04:00
971a18de8d added Compatible warning message 2024-10-24 19:23:36 -04:00
833836ae67 added TestEncryptDecryptPacketObfsOffline 2024-10-24 18:58:07 -04:00
3f191db37a implement TODO for Compatible in NoiseTransport 2024-10-24 18:03:20 -04:00
idk
6865bae386 Merge pull request #17 from hkh4n/dirs
create ~/go-i2p and ~/go-i2p/config properly
2024-10-24 20:12:06 +00:00
f0d9f89ed9 Mkdir -> MkdirAll 2024-10-24 14:26:51 -04:00
idk
c149eef1de Merge pull request #15 from hkh4n/makefile
Makefiles for tests + hotfix for logging naming convention
2024-10-23 17:34:06 +00:00
748dc8a66f tweaks 2024-10-23 00:11:46 -04:00
677aac500e fix logger naming collision with other libs 2024-10-23 00:06:06 -04:00
4e06d3d5ed makefiles 2024-10-22 22:31:19 -04:00
5eaa9cf588 log name collision fix 2024-10-22 22:10:14 -04:00
4dbf537e94 log name collision fix 2024-10-22 22:07:39 -04:00
882c018c0c log name collision fix 2024-10-22 22:06:06 -04:00
5432502852 typo correction 2024-10-22 21:43:49 -04:00
idk
0ea5743365 Merge pull request #14 from hkh4n/noise-experimental
gofumpt adjustment
2024-10-22 21:53:24 +00:00
a9dc482bda gofumpt 2024-10-22 17:37:17 -04:00
idk
c31d20fec0 Merge pull request #13 from hkh4n/logging
Logging
2024-10-22 18:55:15 +00:00
647546a374 typo fix 2024-10-22 14:51:17 -04:00
e468520906 Merge branch 'master' into sntp-experimental 2024-10-20 00:09:42 -04:00
ade80e577c added sntp verification
-Leap Indicator
-Stratum level check
-Round-trip Delay
-Clock offset
-simple non-zero time
-Root Dispersion and Root Delay
2024-10-20 00:07:40 -04:00
f45d301868 proposed refactor
-added secureRandBool() and performTimeQuery()
2024-10-19 22:17:10 -04:00
0256908395 CRITICAL FIX, bytesRead -> n.
n wasn't being used before
2024-10-19 17:27:39 -04:00
3c5aa206d1 expanded logging in message.go 2024-10-19 12:32:49 -04:00
a4517cafd7 expanded logging in delivery.go 2024-10-19 12:25:31 -04:00
f4f39ca53c expanded logging in multi.go 2024-10-19 11:18:20 -04:00
220159476a expanded logging in write_session.go 2024-10-19 11:09:37 -04:00
792cd49208 expanded logging in transport.go 2024-10-19 11:03:55 -04:00
68051630c0 expanded logging in session.go 2024-10-19 10:55:30 -04:00
a3340eb40a expanded logging in read_session.go + changed structure in readPacketLocked() 2024-10-19 10:50:13 -04:00
465a7787a9 expanded logging in outgoing_handshake.go 2024-10-19 10:44:08 -04:00
af3bc44dba expanded logging in incoming_handshake.go 2024-10-19 10:39:23 -04:00
f850f482cf expanded logging in handshake.go 2024-10-19 10:30:11 -04:00
3f23376d22 expanded logging in su3.go 2024-10-19 10:19:55 -04:00
aa98589f1c expanded logging in router.go 2024-10-19 09:46:23 -04:00
c31e990995 expanded logging in std.go 2024-10-18 23:06:44 -04:00
8e97eb5f77 expanded logging in reseed.go 2024-10-18 22:54:08 -04:00
be35267079 expanded logging in header.go 2024-10-18 22:47:28 -04:00
013d35b447 expanded logging in build_request_record.go 2024-10-18 22:41:40 -04:00
e8c9dc17a3 expanded logging in tunnel.go 2024-10-18 21:58:50 -04:00
a1d574446b expanded logging in elg.go 2024-10-18 21:54:27 -04:00
8680acc595 expanded logging in ed25519.go 2024-10-18 21:42:07 -04:00
84e3c5accc expanded logging in ecdsa.go 2024-10-18 17:01:42 -04:00
e772fb5ceb expanded logging in dsa.go 2024-10-18 16:56:25 -04:00
a533cd7ce4 expanded logging in curve25519.go 2024-10-18 16:39:28 -04:00
df37d49444 expanded logging to aes.go 2024-10-18 15:10:16 -04:00
4b2600a065 expanded logging to signature.go
-changed sessionTag -> sig
2024-10-18 14:55:30 -04:00
1c4f937002 expanded logging to session_tag.go 2024-10-18 14:51:53 -04:00
5c2b408f65 expanded logging to session_key.go 2024-10-18 14:43:59 -04:00
beb533a09b expanded logging to router_info.go 2024-10-18 14:40:52 -04:00
f022522ad5 expanded logging to router_identity.go 2024-10-18 14:27:41 -04:00
2191c40ac6 expanded logging to router_address.go + gofumpt adjustment 2024-10-18 13:22:36 -04:00
3bca467f28 updated README.md to reflect new logging paradigm. 2024-10-18 12:59:49 -04:00
a2fd65ee32 expanded logging in lease_set.go 2024-10-18 12:55:35 -04:00
b894e8fb17 expanded logging in keys_and_cert.go 2024-10-18 12:41:48 -04:00
93a71c7398 expanded logging in key_certificate.go 2024-10-18 12:27:42 -04:00
b6544ad194 expanded logging in destination.go 2024-10-18 12:16:36 -04:00
a72b61a886 expanded logging in string.go 2024-10-18 12:08:27 -04:00
dda4f90b6f expanded logging in mapping_values.go 2024-10-18 12:00:58 -04:00
1d1d8126c2 adjusted logging in main.go 2024-10-18 11:53:01 -04:00
73db39ae50 expanded logging in mapping.go 2024-10-18 11:52:39 -04:00
53e902f491 expanded logging to date.go 2024-10-18 11:49:10 -04:00
2f2cd2249c expanded logging to certificate.go 2024-10-18 11:48:56 -04:00
4496c11394 added lib/util/logger/log.go 2024-10-17 22:03:46 -04:00
idk
69449a20b5 Merge pull request #12 from hkh4n/crypto2
AES
2024-10-17 23:48:13 +00:00
a7689e801a minor typo 2024-10-06 12:13:04 -04:00
278bdee277 Various changes
-Aes -> AES
-doc.md
2024-10-06 10:48:22 -04:00
684e89c957 minor typo 2024-10-05 10:15:31 -04:00
50fa9fc374 gofumpt adjustment 2024-10-05 09:43:58 -04:00
491b25022e AES
-Revamped encrypt and decrypt to fit with interfaces
-Adjusted test cases for TestPKCS7UnpadInvalidInput()
2024-10-05 09:00:33 -04:00
677a6b354b AES test 2024-10-04 22:37:57 -04:00
9469fd83aa AES 2024-10-04 22:36:32 -04:00
idk
8173ae49e6 Merge pull request #10 from hkh4n/makefile
Added gofumpt check
2024-10-04 03:26:01 +00:00
2f109d5b4d Added gofumpt check 2024-10-03 23:24:12 -04:00
d7378d7b08 more merge conflicts 2024-10-03 22:46:39 -04:00
3a51a1229e more merge conflicts 2024-10-03 22:45:33 -04:00
2b18b2941d resolve merge conflicts in lib/transport/noise 2024-10-03 22:42:00 -04:00
1eb29ec4ab formatting issues only 2024-10-03 22:36:23 -04:00
d900d7faf8 add doc.md files from master 2024-10-03 22:10:55 -04:00
03c9d60ab9 update other non-transport parts of lib 2024-10-03 22:09:16 -04:00
de2caf499e use makefile from Master 2024-10-03 21:58:16 -04:00
284dd7287e use makefile from Master 2024-10-03 21:56:58 -04:00
9f4154ff45 gofmt 2024-10-03 21:55:35 -04:00
08a0d92742 gofmt 2024-10-03 21:52:49 -04:00
524526d946 Bring in crypto stubs from master 2024-10-03 21:41:31 -04:00
09c7d32797 update the common library to the master branch 2024-10-03 21:31:54 -04:00
16961abc96 !WIP!
-added error handling in TestTransport()
-fixed typo to ComposeReceiverHandshakeMessage
-experimental implementation of encryptPacket
-added encrdecr_packet_test.go
2024-10-03 19:45:17 -04:00
8fa355f067 !WIP! router_timestamper 2024-09-29 22:03:30 -04:00
0c7a3f0f22 force static builds for slightly easier debugging 2024-09-09 20:13:20 -04:00
3d535f67a1 Work on curve25519 stuff so I can generate my own routerInfos instead of just sending crap to other people 2024-09-09 20:10:38 -04:00
bba9350506 WOO some of the important fields are actually populated with correct values 2024-08-28 20:47:54 -04:00
cbc0de4e7e Start working on de-obfuscating ephemeral keys from remote peers 2024-08-28 18:32:42 -04:00
310ef07d3c generate godoc locally so I can go over it offline 2024-08-26 16:21:54 -04:00
14fc6fc3a8 Work on noise tools, comment details of handshake stuff 2024-08-25 23:22:21 -04:00
a3ce9d36c6 If string data is shorter than specified by length create a new string based on the content after the first byte 2024-07-08 10:46:16 -04:00
58a43cdfaf Fix string length checks, sortof 2024-07-05 23:12:03 -04:00
15a5ca5daf Try and make noise work and also fix some tests 2024-07-05 18:12:58 -04:00
08a41686b6 Work on noise wrapper. It is now good enough to fail to connect to a remote I2P router in a way which is discernible on that remote router. 2024-07-03 01:19:31 -04:00
8318fd8f57 Work on noise wrapper. It is now good enough to fail to connect to a remote I2P router in a way which is discernible on that remote router. 2024-07-03 01:17:36 -04:00
9c0552e236 Make some netDb loading stuff work so I have RI's to talk to 2024-07-02 16:54:30 -04:00
20b018a708 Make some netDb loading stuff work so I have RI's to talk to 2024-07-02 16:53:57 -04:00
6c62faa49b finish stubbing out noise transport stuff 2024-07-01 21:37:05 -04:00
a7e31b7833 implement more noise stuff 2024-07-01 21:34:09 -04:00
c09161c824 check in beginnings of new cleaned-up noise prototype 2024-07-01 18:50:13 -04:00
aca62174e6 Load RI's into netDb struct for later referencing 2024-06-30 23:14:48 -04:00
bd27f00959 add my unzip fork which fixes the permissions bug 2024-06-29 00:36:11 -04:00
05c4d3d973 add my unzip fork which fixes the permissions bug 2024-06-29 00:25:23 -04:00
40d0ea5ff5 Start making it so I can configure things, so I can configure it to read the netDb I already have and attempt to make a connection. Implement a reseed puller, or at least most of one. 2024-06-29 00:23:55 -04:00
58e8f78c56 Start making it so I can configure things, so I can configure it to read the netDb I already have and attempt to make a connection. Implement a reseed puller, or at least most of one. 2024-06-29 00:23:42 -04:00
ac705dee76 Set up a pre-release 2024-06-25 12:04:18 -04:00
ca0443ae6a Set up a pre-release 2024-06-25 12:03:55 -04:00
94d0d8efb7 Set up a pre-release 2024-06-25 12:03:09 -04:00
8176e126cb Set up a pre-release 2024-06-25 12:02:49 -04:00
992c5537db Set up a pre-release 2024-06-25 12:02:11 -04:00
5ff9f5578e Update notes 2024-06-25 11:57:52 -04:00
889ec939b3 Eliminate superfluous/rules-breaking logging 2024-06-25 11:41:55 -04:00
6e3a5923cd Make MAX_GOOD_VERSION 99(0.9.99) 2024-06-25 09:35:39 -04:00
ce25a2f0fb Add functions to examine caps 2024-06-24 22:26:17 -04:00
ec22860bb5 Add Get function to MappingValues 2024-06-24 22:18:13 -04:00
cefdcd8c14 RI parsing works again with options and caps and everything 2024-06-24 21:18:54 -04:00
d519f7678d make logging clearer 2024-06-23 22:48:15 -04:00
8dfc5ee5b8 Fix some string errors 2024-06-23 22:39:11 -04:00
d8317351cf Write down my TODO thing 2024-06-23 03:41:40 -04:00
ef127d81c1 Work on figuring out why the mapping size disagrees with the bytes 2024-06-23 03:24:57 -04:00
8acfba160f Log some of the errors that came up after I fix the remainder emissions 2024-06-23 02:51:48 -04:00
d93e78d772 Fix how it handles remainders of structures when parsing routerInfos 2024-06-23 01:35:42 -04:00
bdc9ca4c2b Implement some missing ed25519 functions 2024-06-20 17:04:21 -04:00
83f3d11621 Update the roadmap to more accurately reflect the actual state of the code 2024-02-09 15:02:46 -05:00
784f72403b Fix padding, add TODO note, align spk to end of first 384 bytes 2024-02-05 12:41:49 -05:00
664a17e42a Fix construction of keys_and_cert from a stream of bytes 2024-02-05 12:32:33 -05:00
37718c36f8 Fix cert construction in keys_and_cert 2024-02-05 11:47:51 -05:00
b0fcf4bc11 Fix mapping values, remove redundant, unused functions 2024-02-05 10:42:57 -05:00
idk
65febb5dcf Work on organizing this Noise over TCP Socket stuff 2022-12-15 23:52:05 +00:00
idk
116e22f8da Try to figure out how to implement the pieces I'm still missing from the Noise handshake, but I think that I probably need to redo it again anyway 2022-12-12 17:44:43 +00:00
idk
0419665d7b use separate incoming and outgoing queues 2022-11-14 00:10:58 -05:00
idk
dab108c270 Client=>Outgoing 2022-11-13 23:46:57 -05:00
idk
0fcded4c51 check in more noise handshake missing pieces 2022-11-13 22:24:31 -05:00
idk
7d16b0b257 update my notes 2022-10-17 02:16:44 -04:00
idk
a689f26d73 fix merge conflicts 2022-10-17 02:07:11 -04:00
idk
8d631239b7 Implements a mostly-working Noise IK handshake on a socket with multiple subsessions. Does not implement conns or listeners yet. 2022-10-17 02:03:59 -04:00
idk
fdc34b382e Fix some tests so it compiles again 2022-10-16 17:19:38 -04:00
idk
a4ed06e530 update my notes 2022-09-26 12:18:33 -04:00
idk
c6e359f152 Merge pull request #4 from Thuulium/MappingValues/TweakValuesSort
Rework MappingValues Sort
2022-09-20 11:14:51 -04:00
70415b34eb Tweak test message 2022-09-19 19:47:46 -04:00
dbd4c7d346 Allow duplicate keys, add back HasDuplicateKeys 2022-09-19 19:46:46 -04:00
idk
6b5ea57cbd Move my noise transport tests to a branch so I don't mess up the other branch 2022-09-19 14:35:49 -04:00
43c3498389 Rework MappingValues Sort 2022-09-18 20:54:43 -04:00
idk
f90d1d5f42 Merge branch 'tweak-lib/common-godocs' into 'master'
Tweak godocs for lib/common

See merge request idk/go-i2p!4
2022-09-19 00:02:56 +00:00
c8c4196c6f Tweak godocs for lib/common 2022-09-12 04:31:02 -04:00
idk
68a6ed02be Merge branch 'unbreak-mappings' into 'master'
Attempt to fix mappings

See merge request idk/go-i2p!3
2022-09-11 19:13:49 +00:00
53dd3230df Attempt to fix mappings 2022-09-10 15:34:20 -04:00
idk
c3147c3570 Fix most of the router info tests, all errors are now Mapping-related. 2022-08-06 14:16:42 -04:00
idk
76fba3c8ba Merge pull request #3 from apeace/su3
This merges apeace's working SU3 implementation, which is more like idiomatic Go and will be easier to build upon. TODO: We need to write the godoc, we don't want that situation to get out of hand.
2022-08-05 00:55:57 -04:00
0cae80c698 documentation on novg.net reseed file 2022-08-03 16:14:21 -04:00
7deba5f725 when checking su3 signature, hash ALL file contents up to the signature 2022-08-03 16:10:27 -04:00
35983423ed update from PSS -> PKCS1v15 2022-08-02 15:46:06 -04:00
136133e643 add signature test for snowflake plugin 2022-08-02 11:50:02 -04:00
8d39f1512a add su3 test of snowflake plugin 2022-08-02 11:43:54 -04:00
c9b5fa1406 Add a test for verifying i2pgit reseed signature 2022-08-02 11:27:45 -04:00
cdc9998f10 improve su3 tests by only generating fake data once 2022-08-02 09:47:19 -04:00
4c06fcaff0 add su3 documentation on streaming to disk 2022-08-02 09:47:19 -04:00
403ef30119 verify su3 RSA signatures 2022-08-02 09:47:19 -04:00
feef6e6bbf refactor su3 readers to support signature verification 2022-08-02 09:47:19 -04:00
ad7a828d43 documentation on reading su3 from []byte 2022-08-02 09:47:19 -04:00
416cf6546a remove unused config/su3 implementation 2022-08-02 09:47:19 -04:00
9b81a5c6d8 package su3 documentation 2022-08-02 09:47:19 -04:00
940347351e package su3 documentation 2022-08-02 09:47:19 -04:00
726bff974c read SU3 files into io.Readers 2022-08-02 09:47:19 -04:00
74591a96cb read SU3 files into a struct 2022-08-02 09:47:19 -04:00
idk
eb117aa1bd Updates Go Modules and several tests.
Re: the tests, this happens largely because when you can check for errors changes fundamentally
based on whether or not you're just reading some bytes and storing them for later or whether
you're reading them and then immediately trying to store them in some intelligible datastructure.
The old code, before I started refactoring it, sort of split the difference by putting everything
into slices of bytes, but hanging functions off those byte slices to parse intellible structures
on the fly. The tests were largely designed around testing this format. Updating them has been
a menace. It is very difficult to tell which tests are necessary and how the necessary tests need
to be changed. A handful of high-level tests in router_info_test currently won't compile. I think
those are the only remaining broken tests.
2022-08-01 12:50:42 -04:00
idk
88d8d09527 write my notes for this week 2022-07-18 13:31:20 -04:00
idk
83e999992f start putting my copypasta in the repo 2022-07-18 12:48:49 -04:00
idk
a437bab373 Progress on pure-noise transport 2022-07-18 12:32:29 -04:00
idk
2d310fe91a Progress on pure-noise transport 2022-07-18 12:32:16 -04:00
idk
fefbfc4be6 move mapping_values to it's own file 2022-07-14 16:05:48 -04:00
idk
0ec4f55fa9 Check in unchecked-in common library fixes, start implementing transports.
Since I turned out to be implementing parts of Noise which I did not need to implement, I'm taking a different approach, and doing an unmodified Noise transport first and then making our modifications to it. That should reduce what I need to do to message pre-processing mostly, I think.
2022-07-11 23:41:58 -04:00
idk
8bd30d1e23 start pure-noise transport. Move messages to own module 2022-07-11 17:29:01 -04:00
idk
b7768d4d99 Work on Mapping tests, get ready to send Session messages for NTCP2 2022-07-11 10:33:33 -04:00
idk
171f09bba6 move every struct into it's own directory in order to run tests individually. 2022-05-22 19:59:20 -04:00
idk
13b996d0da Factor away byte slices in RouterInfo, KeysAndCert, Mapping, RouterAddress, RouterIdentity. 2022-05-09 20:43:24 -04:00
idk
82f0e86931 refactor Strings, Integers, Dates, Mapping, Certificates and KeyCertificates. The remaining structs will be checked in one-by-one. 2022-05-02 14:24:51 -04:00
idk
f113977419 refactor certs, keycerts 2022-04-27 10:50:10 -04:00
idk
86dc323348 refactor certs, keycerts 2022-04-27 10:48:59 -04:00
idk
a80c9973f9 Merge pull request #1 from eyedeekay/circleci-project-setup
Add .circleci/config.yml
2021-05-11 10:46:52 -07:00
idk
7adf3d7577 Add .circleci/config.yml 2021-05-11 07:34:35 -07:00
301 changed files with 40823 additions and 4638 deletions

26
.circleci/config.yml Normal file
View File

@ -0,0 +1,26 @@
# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1
jobs:
build:
working_directory: ~/repo
docker:
- image: circleci/golang:1.15.8
steps:
- checkout
- restore_cache:
keys:
- go-mod-v4-{{ checksum "go.sum" }}
- run:
name: Install Dependencies
command: go mod download
- save_cache:
key: go-mod-v4-{{ checksum "go.sum" }}
paths:
- "/go/pkg/mod"
- run:
name: Run tests
command: |
mkdir -p /tmp/test-reports
gotestsum --junitfile /tmp/test-reports/unit-tests.xml
- store_test_results:
path: /tmp/test-reports

19
.github/workflows/auto-assign.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Auto Assign
on:
issues:
types: [opened]
pull_request:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: 'Auto-assign issue'
uses: pozil/auto-assign-issue@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
assignees: eyedeekay
numOfAssignee: 1

89
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: Go Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- run: make build
env:
GO: go
CGO_ENABLED: 0
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false # Ensure all matrix jobs run even if some fail
matrix:
test_target:
- "test-string-all"
- "test-mapping-all"
- "test-crypto-aes-all"
- "test-crypto-dsa-all"
- "test-crypto-ed25519-all"
- "test-crypto-elg-all"
- "test-crypto-hmac-all"
- "test-i2np-header-all"
- "test-key-cert-all"
- "test-keys-cert-all"
- "test-lease-set-all"
- "test-noise-transport-all"
- "test-router-address-all"
- "test-router-info-all"
- "test-su3-all"
- "test-tunnel-all"
- "test-base32-encode-decode-not-mangled"
- "test-base64-encode-decode-not-mangled"
- "test-lease-all"
- "test-date-time-from-milliseconds"
- "test-cert-all"
- "test-signatures"
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21' # Adjust this version as needed
- name: Cache Go modules
uses: actions/cache@v3
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install gofumpt
run: go install mvdan.cc/gofumpt@latest
- name: Go mod tidy
run: go mod tidy
- name: Run ${{ matrix.test_target }}
run: make ${{ matrix.test_target }}
env:
GO: go
DEBUG_I2P: debug
CGO_ENABLED: 0
- name: Upload Test Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.test_target }}-logs
path: ./test-logs/${{ matrix.test_target }}.log # Adjust this path as needed

8
.gitignore vendored
View File

@ -5,4 +5,10 @@
*.coverprofile
*exportable-fuzz.zip
go-i2p
*.exe
*.exe
.idea/
router.info
log
*.gv
diff
err

View File

@ -1,20 +1,35 @@
# Contributing
Thanks for taking a look at go-i2p! Please reach out if you have any questions or need help getting started.
Thanks for taking a look at go-i2p! Please reach out if you have any questions or need help getting started. We have an IRC channel on IRC2P: #go-i2p-dev and we're reachable here at github.com/go-i2p also.
## Getting Starting
## Getting Started
Install required dependencies
This example assumes Ubuntu 16.04
This example assumes Ubuntu or Debian based Linux, a reasonably modern version.
The instructions will be similar for other Linux distributions with slightly different package managers and package names.
```sh
go get github.com/hkparker/go-i2p
go get github.com/Sirupsen/logrus
go get github.com/stretchr/testify/assert
# For obtaining, modifying, compiling, and tracking changes to go-i2p, install:
sudo apt-get install golang-go make git
# If you want to generate markdown versions of the godoc locally, also install:
go install github.com/robertkrimen/godocdown/godocdown@master
# If you want to generate call graphs locally, also install:
go install github.com/ofabry/go-callvis@master
```
Fork go-i2p and clone it into your workspace. Make sure you can execute `go test ./...` in the project's root directory. At that point you should have everything you need to start making changes and opening pull requests. If you aren't sure what to work on, take a look at some good [getting started issues](https://github.com/hkparker/go-i2p/issues?q=is%3Aopen+is%3Aissue+label%3A%22start+here%22).
On Windows, one must install the latest versions of Go and Git Bash from their respective sources.
## Set up your workspace:
```sh
github_username=yourusername
cd $(go env GOPATH)
git clone git@github.com:$github_username/go-i2p github.com/go-i2p/go-i2p
github.com/go-i2p/go-i2p
```
Fork go-i2p and clone it into your workspace. Make sure you can execute `go test ./...` in the project's root directory. At that point you should have everything you need to start making changes and opening pull requests.
## I2P Specifications
@ -26,9 +41,17 @@ The I2P community maintains up-to-date [specifications](https://geti2p.net/spec)
## Conventions
#### Errors
We use oops to provide context to the errors we return. Do not use `errors.New` or `fmt.Errorf` when returning errors from functions. Instead, wrap raw errors in oops errors. When an error is recieved, used oops to supplement the log output.
It is OK to use `fmt.Errorf` for declaring custom error types.
#### Logging
Logrus is used for logging across all of go-i2p. All log statements should contain an `at` fields and a `reason` field. Here is a good example from the go-i2p implementation of a LeaseSet:
Logrus is used for logging across all of go-i2p. We have a small extension of logrus at https://github.com/go-i2p/logger which we use to add a "Fail Fast mode." We are mostly converted over to using it.
All log statements should contain an `at` fields and a `reason` field. Here is a good example from the go-i2p implementation of a LeaseSet:
```go
log.WithFields(log.Fields{
@ -56,4 +79,4 @@ func TestRouterAddressCountReturnsCorrectCount(t *testing.T) {
## Pull Requests
Pull requests should pass all tests, test all new behavior, and be correctly formatted by `gofmt` before merge. Feel free to open incomplete pull requests if you are struggling, I will enthusiasticlly help you complete the PR in any way needed.
Pull requests should pass all tests, test all new behavior, and be correctly formatted by `gofumpt -w -s -extra` before merge. Feel free to open incomplete pull requests and ask for help and advice.

View File

@ -1,5 +1,9 @@
RELEASE_TAG=0.0.1
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
@ -13,13 +17,52 @@ else
EXE := $(REPO)/go-i2p
endif
#check for gofumpt
check_gofumpt:
@which gofumpt > /dev/null 2>&1 || (echo "gofumpt is required but not installed. Please install it from https://github.com/mvdan/gofumpt."; exit 1)
build: clean $(EXE)
$(EXE):
$(GO) build -v -o $(EXE)
$(GO) build --tags netgo,osusergo -v -o $(EXE)
test:
$(GO) test ./...
# Include test definitions
-include doc/tests/*.mk
test: test-string-all \
test-mapping-all \
test-crypto-aes-all \
test-crypto-dsa-all \
test-crypto-ed25519-all \
test-crypto-elg-all \
test-crypto-hmac-all \
test-i2np-header-all \
test-key-cert-all \
test-keys-cert-all \
test-lease-set-all \
test-noise-transport-all \
test-router-address-all \
test-router-info-all \
test-su3-all \
test-tunnel-all \
test-base32-encode-decode-not-mangled \
test-base64-encode-decode-not-mangled \
test-lease-all \
test-date-time-from-milliseconds
clean:
$(GO) clean -v
fmt:
find . -name '*.go' -exec gofumpt -w {} \;
info:
echo "GOROOT: ${GOROOT}"
echo "GO: ${GO}"
echo "REPO: ${REPO}"
release:
github-release release -u go-i2p -r go-i2p -n "${RELEASE_VERSION}" -t "${RELEASE_TAG}" -d "${RELEASE_DESCRIPTION}" -p
godoc:
./callgraph.sh

View File

@ -4,7 +4,10 @@ A pure Go implementation of the I2P router.
## Status
go-i2p is in early development.
go-i2p is in early development. The master branch is being refactored and API's are
definitely going to change. If you choose to use any part of this code right now,
please keep up with these changes, as they will not be backward compatible and require
**Fundamentally** changing any code that treats this as a dependency.
### Implemented Features
@ -12,9 +15,7 @@ go-i2p is in early development.
- [ ] Datagrams
- [ ] I2CP
- [ ] Message routing
- [ ] SAM
- [ ] Streaming
- [ ] Tunnel Manager
- Cryptographic primitives
- Signing
- [ ] ECDSA_SHA256_P256
@ -38,7 +39,7 @@ go-i2p is in early development.
- [ ] Elligator2
- [ ] HKDF
- [ ] HMAC
- [ ] Noise subsystem
- [X] Noise subsystem
- End-to-End Crypto
- [ ] Garlic messages
- [ ] ElGamal/AES+SessionTag
@ -47,9 +48,9 @@ go-i2p is in early development.
- [ ] Message parsing
- [ ] Message handling
- NetDB
- [ ] Local storage
- [ ] Persistence to disk
- [ ] Reseeding
- [/] Local storage
- [/] Persistence to disk
- [X] Reseeding
- [ ] Lookups
- [ ] Expiry
- [ ] Exploration
@ -57,12 +58,12 @@ go-i2p is in early development.
- [ ] Floodfill
- [ ] LS2 and Encrypted Leasesets
- Transports
- [ ] Transport manager
- [X] Transport manager
- NTCP2
- [ ] Handshake
- [ ] Session tracking
- [ ] Automatic session creation
- SSU
- SSU2
- [ ] Handshake
- [ ] Session tracking
- [ ] Automatic session creation
@ -75,7 +76,51 @@ go-i2p is in early development.
- [ ] Participating
- [ ] Tunnel Message Crypto
- [ ] Tunnel Message Fragmentation/Reassembly
- Common Data Structures
- [X] Keys and Cert
- [X] Key Certificates
- [X] Certificate
- [X] Lease
- [X] Lease Set
- [X] Router Info
- [X] Router Identity
- [X] Router Address
- [X] Session Key
- [X] Signature Types
- [X] Destination
- [X] Data Types
- [X] Session Tag
## Verbosity ##
Logging can be enabled and configured using the `DEBUG_I2P` environment variable. By default, logging is disabled.
There are three available log levels:
- Debug
```shell
export DEBUG_I2P=debug
```
- Warn
```shell
export DEBUG_I2P=warn
```
- Error
```shell
export DEBUG_I2P=error
```
If DEBUG_I2P is set to an unrecognized variable, it will fall back to "debug".
## Fast-Fail mode ##
Fast-Fail mode can be activated by setting `WARNFAIL_I2P` to any non-empty value. When set, every warning or error is Fatal.
It is unsafe for production use, and intended only for debugging and testing purposes.
```shell
export WARNFAIL_I2P=true
```
If `WARNFAIL_I2P` is set and `DEBUG_I2P` is unset, `DEBUG_I2P` will be set 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.

19
callgraph.sh Executable file
View File

@ -0,0 +1,19 @@
#! /usr/bin/env sh
dirs=$(find lib/ -type d)
for dir in $dirs; do
files=$(find "$dir" -maxdepth 1 -type f -name "*.go")
#echo "Files in $dir: $files"
file=$(echo $files | awk '{print $1}')
if [ -z "$file" ]; then
echo "no go files, skipping"
continue
fi
packageLine=$(grep -E "^package" $file)
package=$(echo $packageLine | awk '{print $2}')
echo "Generating callgraph for $package"
go-callvis -nostd -focus "$package" -group type -format svg -file $dir/$package "github.com/go-i2p/go-i2p/$dir"
git mv -v "$dir/doc.md" "$dir/README.md"
godocdown -template template.md -o "$dir/README.md" "./$dir"
git add -v "$dir/$package.svg" "$dir/README.md"
done

17
doc/tests/aes.mk Normal file
View File

@ -0,0 +1,17 @@
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
test-crypto-aes-validation:
$(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
.PHONY: test-crypto-aes-all \
test-crypto-aes-core \
test-crypto-aes-validation \
test-crypto-aes-padding

4
doc/tests/base32.mk Normal file
View File

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

4
doc/tests/base64.mk Normal file
View File

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

View File

@ -0,0 +1,24 @@
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
test-build-request-ident:
$(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
.PHONY: test-build-request-all \
test-build-request-receive \
test-build-request-ident \
test-build-request-components

119
doc/tests/certificate.mk Normal file
View File

@ -0,0 +1,119 @@
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-new-null-type test-cert-new-null-payload test-cert-new-key-type test-cert-new-invalid-type test-cert-new-payload-too-long test-cert-bytes-serialization test-cert-fields-after-creation test-cert-zero-length-payload test-cert-new-deux test-cert-invalid-payload-length test-cert-excess-bytes test-cert-serialization test-cert-serialization-excess test-cert-serialization-empty test-cert-serialization-max
test-cert-type:
$(GO) test -v ./lib/common/certificate -run TestCertificateTypeIsFirstByte
test-cert-length:
$(GO) test -v ./lib/common/certificate -run TestCertificateLength
test-cert-data:
$(GO) test -v ./lib/common/certificate -run TestCertificateData
test-cert-read:
$(GO) test -v ./lib/common/certificate -run TestReadCertificate
test-cert-length-correct:
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthCorrect
test-cert-length-too-short:
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthErrWhenTooShort
test-cert-length-data-short:
$(GO) test -v ./lib/common/certificate -run TestCertificateLengthErrWhenDataTooShort
test-cert-data-correct:
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenCorrectSize
test-cert-data-too-long:
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenTooLong
test-cert-data-too-short:
$(GO) test -v ./lib/common/certificate -run TestCertificateDataWhenTooShort
test-cert-read-correct:
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithCorrectData
test-cert-read-short:
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithDataTooShort
test-cert-read-remainder:
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithRemainder
test-cert-read-invalid:
$(GO) test -v ./lib/common/certificate -run TestReadCertificateWithInvalidLength
test-cert-new-null-type:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateNullType
test-cert-new-null-payload:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateNullTypeWithPayload
test-cert-new-key-type:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateKeyType
test-cert-new-invalid-type:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateInvalidType
test-cert-new-payload-too-long:
$(GO) test -v ./lib/common/certificate -run TestNewCertificatePayloadTooLong
test-cert-bytes-serialization:
$(GO) test -v ./lib/common/certificate -run TestCertificateBytesSerialization
test-cert-fields-after-creation:
$(GO) test -v ./lib/common/certificate -run TestCertificateFieldsAfterCreation
test-cert-zero-length-payload:
$(GO) test -v ./lib/common/certificate -run TestCertificateWithZeroLengthPayload
test-cert-new-deux:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateDeuxFunction
test-cert-invalid-payload-length:
$(GO) test -v ./lib/common/certificate -run TestNewCertificateWithInvalidPayloadLength
test-cert-excess-bytes:
$(GO) test -v ./lib/common/certificate -run TestCertificateExcessBytes
test-cert-serialization:
$(GO) test -v ./lib/common/certificate -run TestCertificateSerializationDeserialization
test-cert-serialization-excess:
$(GO) test -v ./lib/common/certificate -run TestCertificateSerializationDeserializationWithExcessBytes
test-cert-serialization-empty:
$(GO) test -v ./lib/common/certificate -run TestCertificateSerializationDeserializationEmptyPayload
test-cert-serialization-max:
$(GO) test -v ./lib/common/certificate -run TestCertificateSerializationDeserializationMaxPayload
.PHONY: 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-new-null-type \
test-cert-new-null-payload \
test-cert-new-key-type \
test-cert-new-invalid-type \
test-cert-new-payload-too-long \
test-cert-bytes-serialization \
test-cert-fields-after-creation \
test-cert-zero-length-payload \
test-cert-new-deux \
test-cert-invalid-payload-length \
test-cert-excess-bytes \
test-cert-serialization \
test-cert-serialization-excess \
test-cert-serialization-empty \
test-cert-serialization-max

2
doc/tests/date.mk Normal file
View File

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

20
doc/tests/dsa.mk Normal file
View File

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

7
doc/tests/ed25519.mk Normal file
View File

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

24
doc/tests/elg.mk Normal file
View File

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

48
doc/tests/header.mk Normal file
View File

@ -0,0 +1,48 @@
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-build-request-record test-i2np-build-response-record
test-i2np-type:
$(GO) test -v ./lib/i2np -run TestReadI2NPTypeWith
test-i2np-message:
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPMessageID
test-i2np-expiration:
$(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
test-i2np-data:
$(GO) test -v ./lib/i2np -run TestReadI2NPNTCPData
test-i2np-regression:
$(GO) test -v ./lib/i2np -run TestCrasherRegression123781
test-i2np-build-request-record:
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordReceiveTunnelTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordReceiveTunnelValidData
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordOurIdentTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildRequestRecordOurIdentValidData
test-i2np-build-response-record:
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordHashTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordHashValidData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordRandomDataTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordRandomDataValidData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordReplyTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordReplyValidData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordValidData
.PHONY: 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-build-request-record \
test-i2np-build-response-record

7
doc/tests/hmac.mk Normal file
View File

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

15
doc/tests/integer.mk Normal file
View File

@ -0,0 +1,15 @@
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
test-integer-one-byte:
$(GO) test -v ./lib/common/integer -run TestWorksWithOneByte
test-integer-zero:
$(GO) test -v ./lib/common/integer -run TestIsZeroWithNoData
.PHONY: test-integer-all \
test-integer-big-endian \
test-integer-one-byte \
test-integer-zero

View File

@ -0,0 +1,23 @@
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
test-key-cert-public:
$(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
.PHONY: test-key-cert-all \
test-key-cert-signing \
test-key-cert-public \
test-key-cert-construct

View File

@ -0,0 +1,30 @@
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
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
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
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
.PHONY: test-keys-cert-all \
test-keys-cert-certificate \
test-keys-cert-public \
test-keys-cert-signing \
test-keys-cert-creation

15
doc/tests/lease.mk Normal file
View File

@ -0,0 +1,15 @@
test-lease-all: test-lease-tunnel-gateway test-lease-tunnel-id test-lease-date
test-lease-tunnel-gateway:
$(GO) test -v ./lib/common/lease -run TestTunnelGateway
test-lease-tunnel-id:
$(GO) test -v ./lib/common/lease -run TestTunnelID
test-lease-date:
$(GO) test -v ./lib/common/lease -run TestDate
.PHONY: test-lease-all \
test-lease-tunnel-gateway \
test-lease-tunnel-id \
test-lease-date

26
doc/tests/lease_set.mk Normal file
View File

@ -0,0 +1,26 @@
test-lease-set-all: test-lease-set-creation \
test-lease-set-validation \
test-lease-set-components \
test-lease-set-expirations \
test-lease-set-signature-verification
test-lease-set-creation:
$(GO) test -v ./lib/common/lease_set -run TestLeaseSetCreation
test-lease-set-validation:
$(GO) test -v ./lib/common/lease_set -run TestLeaseSetValidation
test-lease-set-components:
$(GO) test -v ./lib/common/lease_set -run TestLeaseSetComponents
test-lease-set-expirations:
$(GO) test -v ./lib/common/lease_set -run TestExpirations
test-lease-set-signature-verification:
$(GO) test -v ./lib/common/lease_set -run TestSignatureVerification
.PHONY: test-lease-set-all \
test-lease-set-creation \
test-lease-set-validation \
test-lease-set-components \
test-lease-set-expirations \
test-lease-set-signature-verification

28
doc/tests/mapping.mk Normal file
View File

@ -0,0 +1,28 @@
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
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
test-mapping-conversion:
$(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
.PHONY: test-mapping-all \
test-mapping-values \
test-mapping-duplicates \
test-mapping-conversion \
test-mapping-utils

View File

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

19
doc/tests/noise.mk Normal file
View File

@ -0,0 +1,19 @@
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
test-noise-transport-connection:
$(GO) test -v ./lib/transport/noise -run TestTransport
test-noise-packet-obfuscation:
$(GO) test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOffline
test-noise-packet-obfuscation-func:
$(GO) test -v ./lib/transport/noise -run TestEncryptDecryptPacketObfsOfflineWithFunc
.PHONY: test-noise-transport-all \
test-noise-packet-encryption \
test-noise-transport-connection \
test-noise-packet-obfuscation \
test-noise-packet-obfuscation-func

View File

@ -0,0 +1,19 @@
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
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
test-router-address-fuzz:
$(GO) test -v ./lib/common/router_address -run TestCorrectsFuzzCrasher1
.PHONY: test-router-address-all \
test-router-address-validation \
test-router-address-functionality \
test-router-address-fuzz

52
doc/tests/router_info.mk Normal file
View File

@ -0,0 +1,52 @@
test-router-info-all: test-router-info-creation test-router-info-published-date test-router-info-identity test-router-info-addresses test-router-info-serialization test-router-info-signature test-router-info-capabilities test-router-info-version test-router-info-good-version test-router-info-uncongested test-router-info-reachable test-router-info-10k
test-router-info-creation:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoCreation
$(GO) test -v ./lib/common/router_info -run TestCreateRouterInfo
test-router-info-published-date:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoPublishedDate
test-router-info-identity:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoRouterIdentity
test-router-info-addresses:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoAddresses
test-router-info-serialization:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoSerialization
test-router-info-signature:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoSignature
test-router-info-capabilities:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoCapabilities
test-router-info-version:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoVersion
test-router-info-good-version:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoGoodVersion
test-router-info-uncongested:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoUnCongested
test-router-info-reachable:
$(GO) test -v ./lib/common/router_info -run TestRouterInfoReachable
test-router-info-10k:
$(GO) test -v ./lib/common/router_info -run Test10K
.PHONY: test-router-info-all \
test-router-info-creation \
test-router-info-published-date \
test-router-info-identity \
test-router-info-addresses \
test-router-info-serialization \
test-router-info-signature \
test-router-info-capabilities \
test-router-info-version \
test-router-info-good-version \
test-router-info-uncongested \
test-router-info-reachable \
test-router-info-10k

7
doc/tests/signatures.mk Normal file
View File

@ -0,0 +1,7 @@
test-signatures:
$(GO) test -v ./lib/common/signature/ -run TestReadSignatureErrors
$(GO) test -v ./lib/common/signature/ -run TestReadSignature
$(GO) test -v ./lib/common/signature/ -run TestNewSignatureError
$(GO) test -v ./lib/common/signature/ -run TestNewSignature
.PHONY: test-signatures

27
doc/tests/string.mk Normal file
View File

@ -0,0 +1,27 @@
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
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
test-string-conversion:
$(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
.PHONY: test-string-all \
test-string-length \
test-string-data \
test-string-conversion \
test-string-read

11
doc/tests/su3.mk Normal file
View File

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

22
doc/tests/tunnel.mk Normal file
View File

@ -0,0 +1,22 @@
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
# 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
test-tunnel-message-fragments:
$(GO) test -v ./lib/tunnel -run TestDeliveryInstructionsWithFragments
.PHONY: test-tunnel-all \
test-tunnel-delivery-instructions \
test-tunnel-message \
test-tunnel-message-padding \
test-tunnel-message-fragments

49
go.mod
View File

@ -1,9 +1,50 @@
module github.com/go-i2p/go-i2p
go 1.16
go 1.23.3
toolchain go1.23.5
require (
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc
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/go-i2p/logger v0.0.0-20241123010126-3050657e5d0c
github.com/samber/oops v1.16.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
go.step.sm/crypto v0.58.1
golang.org/x/crypto v0.35.0
gopkg.in/yaml.v3 v3.0.1
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/samber/lo v1.49.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

110
go.sum
View File

@ -1,24 +1,110 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
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=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/eyedeekay/go-unzip v0.0.0-20240201194209-560d8225b50e h1:NMjWYVkgcQHGOy0/VxU0TU6smrcoxzj9hwDesx2sB0w=
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.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-i2p/logger v0.0.0-20241123010126-3050657e5d0c h1:VTiECn3dFEmUlZjto+wOwJ7SSJTHPLyNprQMR5HzIMI=
github.com/go-i2p/logger v0.0.0-20241123010126-3050657e5d0c/go.mod h1:te7Zj3g3oMeIl8uBXAgO62UKmZ6m6kHRNg1Mm+X8Hzk=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/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/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/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.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
github.com/magiconair/properties v1.8.9/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/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
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.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/samber/oops v1.16.1 h1:XlKkXsWM5g8hE4C+sEV9n0X282fZn3XabVmAKU2RiHI=
github.com/samber/oops v1.16.1/go.mod h1:8eXgMAJcDXRAijQsFRhfy/EHDOTiSvwkg6khFqFK078=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc h1:+q90ECDSAQirdykUN6sPEiBXBsp8Csjcca8Oy7bgLTA=
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.step.sm/crypto v0.58.1 h1:2PpEYTbytA3el9dW0gh9uJEe/CR/J6wS+x2vWYLG83M=
go.step.sm/crypto v0.58.1/go.mod h1:yluOL5OqY7mXGGQ7JUmAv/6h8T8Ge3yXdlEESWHOqDQ=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
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.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

31
lib/bootstrap/README.md Normal file
View File

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

View File

@ -1,6 +1,6 @@
package bootstrap
import "github.com/go-i2p/go-i2p/lib/common"
import "github.com/go-i2p/go-i2p/lib/common/router_info"
// interface defining a way to bootstrap into the i2p network
type Bootstrap interface {
@ -9,5 +9,5 @@ type Bootstrap interface {
// if n is 0 then try obtaining as many router infos as possible
// returns nil and error if we cannot fetch ANY router infos
// returns a channel that yields 1 slice of router infos containing n or fewer router infos, caller must close channel after use
GetPeers(n int) (chan []common.RouterInfo, error)
GetPeers(n int) (chan []router_info.RouterInfo, error)
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="0pt" height="0pt"
viewBox="0.00 0.00 0.00 0.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 0)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,0 0,0 0,0 0,0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 584 B

View File

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

View File

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

View File

@ -1,18 +1,23 @@
//
// base32 encoding using I2P's alphabet
//
// Package base32 implmenets utilities for encoding and decoding text using I2P's alphabet
package base32
import (
b32 "encoding/base32"
)
var I2PEncoding *b32.Encoding = b32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
// I2PEncodeAlphabet is the base32 encoding used throughout I2P.
// RFC 3548 using lowercase characters.
const I2PEncodeAlphabet = "abcdefghijklmnopqrstuvwxyz234567"
//
// Return a go string of the I2P base32
// encoding of the provided byte slice
//
// I2PEncoding is the standard base32 encoding used through I2P.
var I2PEncoding *b32.Encoding = b32.NewEncoding(I2PEncodeAlphabet)
// EncodeToString encodes []byte to a base32 string using I2PEncoding
func EncodeToString(data []byte) string {
return I2PEncoding.EncodeToString(data)
}
// DecodeString decodes base64 string to []byte I2PEncoding
func DecodeString(data string) ([]byte, error) {
return I2PEncoding.DecodeString(data)
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="0pt" height="0pt"
viewBox="0.00 0.00 0.00 0.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 0)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,0 0,0 0,0 0,0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 584 B

View File

@ -0,0 +1,20 @@
package base32
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeNotMangled(t *testing.T) {
assert := assert.New(t)
// Random pangram
testInput := []byte("How vexingly quick daft zebras jump!")
encodedString := EncodeToString(testInput)
decodedString, err := DecodeString(encodedString)
assert.Nil(err)
assert.ElementsMatch(testInput, decodedString)
}

View File

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

View File

@ -1,30 +1,23 @@
//
// base64 encoding using I2P's alphabet
//
// Package base64 implmenets utilities for encoding and decoding text using I2P's alphabet
package base64
import (
b64 "encoding/base64"
)
// i2p base64 alphabet
const Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"
// I2PEncodeAlphabet is the base64 encoding used throughout I2P.
// RFC 4648 with "/"" replaced with "~", and "+" replaced with "-".
const I2PEncodeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"
// i2p base64 encoding
var I2PEncoding *b64.Encoding = b64.NewEncoding(Alphabet)
// I2PEncoding is the standard base64 encoding used through I2P.
var I2PEncoding *b64.Encoding = b64.NewEncoding(I2PEncodeAlphabet)
//
// Return a go string of the I2P base64
// encoding of the provided byte slice
//
// I2PEncoding is the standard base64 encoding used through I2P.
func EncodeToString(data []byte) string {
return I2PEncoding.EncodeToString(data)
}
//
// decode string using i2p base64 encoding
// returns error if data is malfromed
//
func DecodeFromString(str string) (d []byte, err error) {
// DecodeString decodes base64 string to []byte I2PEncoding
func DecodeString(str string) ([]byte, error) {
return I2PEncoding.DecodeString(str)
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="0pt" height="0pt"
viewBox="0.00 0.00 0.00 0.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 0)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,0 0,0 0,0 0,0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 584 B

View File

@ -0,0 +1,20 @@
package base64
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeNotMangled(t *testing.T) {
assert := assert.New(t)
// Random pangram
testInput := []byte("Glib jocks quiz nymph to vex dwarf.")
encodedString := EncodeToString(testInput)
decodedString, err := DecodeString(encodedString)
assert.Nil(err)
assert.ElementsMatch(testInput, decodedString)
}

View File

@ -1,139 +0,0 @@
package common
/*
I2P Certificate
https://geti2p.net/spec/common-structures#certificate
Accurate for version 0.9.24
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
case 5 -> KEY
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
*/
import (
"errors"
log "github.com/sirupsen/logrus"
)
// Certificate Types
const (
CERT_NULL = iota
CERT_HASHCASH
CERT_HIDDEN
CERT_SIGNED
CERT_MULTIPLE
CERT_KEY
)
// Minimum size of a valid Certificate
const (
CERT_MIN_SIZE = 3
)
type Certificate []byte
//
// Return the Certificate Type specified in the first byte of the Certificate,
// and an error if the certificate is shorter than the minimum certificate size.
//
func (certificate Certificate) Type() (cert_type int, err error) {
cert_len := len(certificate)
if cert_len < CERT_MIN_SIZE {
log.WithFields(log.Fields{
"at": "(Certificate) Type",
"certificate_bytes_length": cert_len,
"reason": "too short (len < CERT_MIN_SIZE)",
}).Error("invalid certificate")
err = errors.New("error parsing certificate length: certificate is too short")
return
}
cert_type = Integer([]byte{certificate[0]})
return
}
//
// Look up the length of the Certificate, reporting errors if the certificate is
// shorter than the minimum certificate size or if the reported length doesn't
// match the provided data.
//
func (certificate Certificate) Length() (length int, err error) {
cert_len := len(certificate)
_, err = certificate.Type()
if err != nil {
return
}
length = Integer(certificate[1:CERT_MIN_SIZE])
inferred_len := length + CERT_MIN_SIZE
if inferred_len > cert_len {
log.WithFields(log.Fields{
"at": "(Certificate) Length",
"certificate_bytes_length": cert_len,
"certificate_length_field": length,
"expected_bytes_length": inferred_len,
"reason": "data shorter than specified",
}).Warn("certificate format warning")
err = errors.New("certificate parsing warning: certificate data is shorter than specified by length")
} else if cert_len > inferred_len {
log.WithFields(log.Fields{
"at": "(Certificate) Length",
"certificate_bytes_length": cert_len,
"certificate_length_field": length,
"expected_bytes_length": inferred_len,
"reason": "data longer than expected",
}).Warn("certificate format warning")
err = errors.New("certificate parsing warning: certificate contains data beyond length")
}
return
}
//
// Return the Certificate data and any errors encountered parsing the Certificate.
//
func (certificate Certificate) Data() (data []byte, err error) {
length, err := certificate.Length()
if err != nil {
switch err.Error() {
case "error parsing certificate length: certificate is too short":
return
case "certificate parsing warning: certificate data is shorter than specified by length":
data = certificate[CERT_MIN_SIZE:]
return
case "certificate parsing warning: certificate contains data beyond length":
data = certificate[CERT_MIN_SIZE : length+CERT_MIN_SIZE]
return
}
}
data = certificate[CERT_MIN_SIZE:]
return
}
//
// Read a Certificate from a slice of bytes, returning any extra data on the end of the slice
// and any errors if a valid Certificate could not be read.
//
func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) {
certificate = Certificate(data)
length, err := certificate.Length()
if err != nil && err.Error() == "certificate parsing warning: certificate contains data beyond length" {
certificate = Certificate(data[:length+CERT_MIN_SIZE])
remainder = data[length+CERT_MIN_SIZE:]
err = nil
}
return
}

View File

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

View File

@ -0,0 +1,290 @@
// Package certificate implements the certificate common-structure of I2P.
package certificate
import (
"encoding/binary"
"fmt"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
// log "github.com/sirupsen/logrus"
"github.com/go-i2p/logger"
. "github.com/go-i2p/go-i2p/lib/common/data"
)
var log = logger.GetGoI2PLogger()
// Certificate Types
const (
CERT_NULL = iota
CERT_HASHCASH
CERT_HIDDEN
CERT_SIGNED
CERT_MULTIPLE
CERT_KEY
)
// CERT_MIN_SIZE is the minimum size of a valid Certificate in []byte
// 1 byte for type
// 2 bytes for payload length
const CERT_MIN_SIZE = 3
/*
[I2P Certificate]
Accurate for version 0.9.49
Description
A certifificate is a container for various receipts of proof of works used throughout the I2P network.
Contents
1 byte Integer specifying certificate type, followed by a 2 byte Integer specifying the size of the certificate playload, then that many bytes.
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
case 5 -> KEY
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
*/
// Certificate is the representation of an I2P Certificate.
//
// https://geti2p.net/spec/common-structures#certificate
type Certificate struct {
kind Integer
len Integer
payload []byte
}
// RawBytes returns the entire certificate in []byte form, includes excess payload data.
func (c *Certificate) RawBytes() []byte {
bytes := c.kind.Bytes()
bytes = append(bytes, c.len.Bytes()...)
bytes = append(bytes, c.payload...)
log.WithFields(logrus.Fields{
"raw_bytes_length": len(bytes),
}).Debug("Generated raw bytes for certificate")
return bytes
}
// ExcessBytes returns the excess bytes in a certificate found after the specified payload length.
func (c *Certificate) ExcessBytes() []byte {
if len(c.payload) >= c.len.Int() {
excess := c.payload[c.len.Int():]
log.WithFields(logrus.Fields{
"excess_bytes_length": len(excess),
}).Debug("Found excess bytes in certificate")
return excess
}
log.Debug("No excess bytes found in certificate")
return nil
}
// Bytes returns the entire certificate in []byte form, trims payload to specified length.
func (c *Certificate) Bytes() []byte {
bytes := c.kind.Bytes()
bytes = append(bytes, c.len.Bytes()...)
bytes = append(bytes, c.Data()...)
log.WithFields(logrus.Fields{
"bytes_length": len(bytes),
}).Debug("Generated bytes for certificate")
return bytes
}
func (c *Certificate) length() (cert_len int) {
cert_len = len(c.Bytes())
return
}
// Type returns the Certificate type specified in the first byte of the Certificate,
func (c *Certificate) Type() (cert_type int) {
cert_type = c.kind.Int()
log.WithFields(logrus.Fields{
"cert_type": cert_type,
}).Debug("Retrieved certificate type")
return
}
// Length returns the payload length of a Certificate.
func (c *Certificate) Length() (length int) {
length = c.len.Int()
log.WithFields(logrus.Fields{
"length": length,
}).Debug("Retrieved certificate length")
return
}
// Data returns the payload of a Certificate, payload is trimmed to the specified length.
func (c *Certificate) Data() (data []byte) {
lastElement := c.Length()
if lastElement > len(c.payload) {
data = c.payload
log.Warn("Certificate payload shorter than specified length")
} else {
data = c.payload[0:lastElement]
}
log.WithFields(logrus.Fields{
"data_length": len(data),
}).Debug("Retrieved certificate data")
return
}
// 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 readCertificate(data []byte) (certificate Certificate, err error) {
certificate = Certificate{}
switch len(data) {
case 0:
certificate.kind = Integer([]byte{0})
certificate.len = Integer([]byte{0})
log.WithFields(logrus.Fields{
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": len(data),
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
}).Error("invalid certificate, empty")
err = oops.Errorf("error parsing certificate: certificate is empty")
return
case 1, 2:
certificate.kind = Integer(data[0 : len(data)-1])
certificate.len = Integer([]byte{0})
log.WithFields(logrus.Fields{
"at": "(Certificate) NewCertificate",
"certificate_bytes_length": len(data),
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
}).Error("invalid certificate, too short")
err = oops.Errorf("error parsing certificate: certificate is too short")
return
default:
certificate.kind = Integer(data[0:1])
certificate.len = Integer(data[1:3])
payloadLength := len(data) - CERT_MIN_SIZE
certificate.payload = data[CERT_MIN_SIZE:]
if certificate.len.Int() > len(data)-CERT_MIN_SIZE {
err = oops.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": payloadLength,
"data_bytes:": string(data),
"kind_bytes": data[0:1],
"len_bytes": data[1:3],
"reason": err.Error(),
}).Error("invalid certificate, shorter than specified by length")
return
}
log.WithFields(logrus.Fields{
"type": certificate.kind.Int(),
"length": certificate.len.Int(),
}).Debug("Successfully created new certificate")
return
}
}
// 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 = 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
}
remainder = certificate.ExcessBytes()
log.WithFields(logrus.Fields{
"remainder_length": len(remainder),
}).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),
}
}
func NewCertificateDeux(certType int, payload []byte) (*Certificate, error) {
if certType < 0 || certType > 255 {
return nil, oops.Errorf("invalid certificate type: %d", certType)
}
certTypeByte := byte(certType)
if len(payload) > 65535 {
return nil, oops.Errorf("payload too long: %d bytes", len(payload))
}
_len, err := NewIntegerFromInt(len(payload), 2)
if err != nil {
panic(err)
}
cert := &Certificate{
kind: Integer([]byte{certTypeByte}),
len: *_len,
payload: payload,
}
log.WithFields(logrus.Fields{
"type": certType,
"length": len(payload),
}).Debug("Successfully created new certificate")
return cert, nil
}
// 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, oops.Errorf("invalid certificate type: %d", certType)
}
// For NULL certificates, payload should be empty
if certType == CERT_NULL && len(payload) > 0 {
return nil, oops.Errorf("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, oops.Errorf("unexpected certificate type: %d", cert.Type())
}
if len(cert.payload) < 4 {
return 0, oops.Errorf("certificate payload too short to contain signature type")
}
sigType := int(binary.BigEndian.Uint16(cert.payload[2:4])) // Changed offset to read signing key type
return sigType, nil
}

View File

@ -0,0 +1,617 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="1146pt" height="928pt"
viewBox="0.00 0.00 1146.34 928.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 928)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-928 1146.344,-928 1146.344,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-920 1138.344,-920 1138.344,-8 8,-8"/>
<text text-anchor="middle" x="573.172" y="-899.8" font-family="Arial" font-size="18.00" fill="#000000">certificate</text>
</g>
<g id="clust5" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer</title>
<g id="a_clust5"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M1038.4239,-407C1038.4239,-407 1086.3103,-407 1086.3103,-407 1092.3103,-407 1098.3103,-413 1098.3103,-419 1098.3103,-419 1098.3103,-534 1098.3103,-534 1098.3103,-540 1092.3103,-546 1086.3103,-546 1086.3103,-546 1038.4239,-546 1038.4239,-546 1032.4239,-546 1026.4239,-540 1026.4239,-534 1026.4239,-534 1026.4239,-419 1026.4239,-419 1026.4239,-413 1032.4239,-407 1038.4239,-407"/>
<text text-anchor="middle" x="1062.3671" y="-415.5" font-family="Arial" font-size="15.00" fill="#222222">(Integer)</text>
</a>
</g>
</g>
<g id="clust4" class="cluster">
<title>cluster_*github.com/sirupsen/logrus.Logger</title>
<g id="a_clust4"><a xlink:title="type: *github.com/sirupsen/logrus.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M1035.7065,-262C1035.7065,-262 1090.0277,-262 1090.0277,-262 1096.0277,-262 1102.0277,-268 1102.0277,-274 1102.0277,-274 1102.0277,-328 1102.0277,-328 1102.0277,-334 1096.0277,-340 1090.0277,-340 1090.0277,-340 1035.7065,-340 1035.7065,-340 1029.7065,-340 1023.7065,-334 1023.7065,-328 1023.7065,-328 1023.7065,-274 1023.7065,-274 1023.7065,-268 1029.7065,-262 1035.7065,-262"/>
<text text-anchor="middle" x="1062.8671" y="-270.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust3" class="cluster">
<title>cluster_*github.com/go&#45;i2p/logger.Logger</title>
<g id="a_clust3"><a xlink:title="type: *github.com/go&#45;i2p/logger.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M1023.2577,-619C1023.2577,-619 1101.4765,-619 1101.4765,-619 1107.4765,-619 1113.4765,-625 1113.4765,-631 1113.4765,-631 1113.4765,-807 1113.4765,-807 1113.4765,-813 1107.4765,-819 1101.4765,-819 1101.4765,-819 1023.2577,-819 1023.2577,-819 1017.2577,-819 1011.2577,-813 1011.2577,-807 1011.2577,-807 1011.2577,-631 1011.2577,-631 1011.2577,-625 1017.2577,-619 1023.2577,-619"/>
<text text-anchor="middle" x="1062.3671" y="-627.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M322.261,-285C322.261,-285 866.0844,-285 866.0844,-285 872.0844,-285 878.0844,-291 878.0844,-297 878.0844,-297 878.0844,-534 878.0844,-534 878.0844,-540 872.0844,-546 866.0844,-546 866.0844,-546 322.261,-546 322.261,-546 316.261,-546 310.261,-540 310.261,-534 310.261,-534 310.261,-297 310.261,-297 310.261,-291 316.261,-285 322.261,-285"/>
<text text-anchor="middle" x="594.1727" y="-293.5" font-family="Arial" font-size="15.00" fill="#222222">(*Certificate)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate | defined in certificate.go:150&#10;at certificate.go:194: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:160: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at certificate.go:170: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at certificate.go:188: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at certificate.go:161: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:171: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:179: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:159: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:169: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:178: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:182: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:192: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:193: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:156: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:166: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:180: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:191: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M879.924,-615C879.924,-615 796.587,-615 796.587,-615 790.587,-615 784.587,-609 784.587,-603 784.587,-603 784.587,-591 784.587,-591 784.587,-585 790.587,-579 796.587,-579 796.587,-579 879.924,-579 879.924,-579 885.924,-579 891.924,-585 891.924,-591 891.924,-591 891.924,-603 891.924,-603 891.924,-609 885.924,-615 879.924,-615"/>
<text text-anchor="middle" x="838.2555" y="-592.8" font-family="Verdana" font-size="14.00" fill="#000000">readCertificate</text>
</a>
</g>
</g>
<!-- github.com/samber/oops.Errorf -->
<g id="node2" class="node">
<title>github.com/samber/oops.Errorf</title>
<g id="a_node2"><a xlink:title="github.com/samber/oops.Errorf | defined in oops.go:34">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1079.5624,-129C1079.5624,-129 1045.1718,-129 1045.1718,-129 1039.1718,-129 1033.1718,-123 1033.1718,-117 1033.1718,-117 1033.1718,-105 1033.1718,-105 1033.1718,-99 1039.1718,-93 1045.1718,-93 1045.1718,-93 1079.5624,-93 1079.5624,-93 1085.5624,-93 1091.5624,-99 1091.5624,-105 1091.5624,-105 1091.5624,-117 1091.5624,-117 1091.5624,-123 1085.5624,-129 1079.5624,-129"/>
<text text-anchor="middle" x="1062.3671" y="-115.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="1062.3671" y="-98.4" font-family="Verdana" font-size="14.00" fill="#000000">Errorf</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge17" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge17"><a xlink:title="at certificate.go:161: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:171: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:179: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M887.6922,-578.8268C900.2566,-572.1105 912.6559,-563.2952 921.3902,-552 962.8333,-498.4057 971.7912,-319.8683 994.3902,-256 1009.3883,-213.6131 1032.5644,-166.915 1047.601,-138.2675"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1050.7756,-139.7516 1052.3648,-129.2766 1044.5902,-136.4742 1050.7756,-139.7516"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="node17" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_node17"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithFields | defined in log.go:60">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1093.5862,-750C1093.5862,-750 1031.148,-750 1031.148,-750 1025.148,-750 1019.148,-744 1019.148,-738 1019.148,-738 1019.148,-726 1019.148,-726 1019.148,-720 1025.148,-714 1031.148,-714 1031.148,-714 1093.5862,-714 1093.5862,-714 1099.5862,-714 1105.5862,-720 1105.5862,-726 1105.5862,-726 1105.5862,-738 1105.5862,-738 1105.5862,-744 1099.5862,-750 1093.5862,-750"/>
<text text-anchor="middle" x="1062.3671" y="-736.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-719.4" font-family="Verdana" font-size="14.00" fill="#000000">WithFields</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge39" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge39"><a xlink:title="at certificate.go:156: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:166: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:180: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:191: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M862.2851,-615.121C892.2409,-637.2428 945.472,-675.0325 994.3902,-702 999.262,-704.6857 1004.4214,-707.3179 1009.6333,-709.8383"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.4809,-713.1637 1019.0207,-714.242 1011.4538,-706.8263 1008.4809,-713.1637"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="node19" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_node19"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).Error | defined in log.go:42">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1080.1334,-689C1080.1334,-689 1044.6008,-689 1044.6008,-689 1038.6008,-689 1032.6008,-683 1032.6008,-677 1032.6008,-677 1032.6008,-665 1032.6008,-665 1032.6008,-659 1038.6008,-653 1044.6008,-653 1044.6008,-653 1080.1334,-653 1080.1334,-653 1086.1334,-653 1092.1334,-659 1092.1334,-665 1092.1334,-665 1092.1334,-677 1092.1334,-677 1092.1334,-683 1086.1334,-689 1080.1334,-689"/>
<text text-anchor="middle" x="1062.3671" y="-675.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-658.4" font-family="Verdana" font-size="14.00" fill="#000000">Error</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge16" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge16"><a xlink:title="at certificate.go:160: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at certificate.go:170: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at certificate.go:188: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M891.9358,-614.7248C932.1804,-628.0133 986.3626,-645.9039 1022.7345,-657.9136"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.9014,-661.3243 1032.4946,-661.1363 1024.0963,-654.6773 1021.9014,-661.3243"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Debug -->
<g id="node20" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_node20"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Debug | defined in logger.go:221">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1081.1891,-332C1081.1891,-332 1043.5451,-332 1043.5451,-332 1037.5451,-332 1031.5451,-326 1031.5451,-320 1031.5451,-320 1031.5451,-308 1031.5451,-308 1031.5451,-302 1037.5451,-296 1043.5451,-296 1043.5451,-296 1081.1891,-296 1081.1891,-296 1087.1891,-296 1093.1891,-302 1093.1891,-308 1093.1891,-308 1093.1891,-320 1093.1891,-320 1093.1891,-326 1087.1891,-332 1081.1891,-332"/>
<text text-anchor="middle" x="1062.3671" y="-318.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="1062.3671" y="-301.4" font-family="Verdana" font-size="14.00" fill="#000000">Debug</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge2"><a xlink:title="at certificate.go:194: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M883.6249,-578.925C896.9934,-571.9937 910.8476,-563.037 921.3902,-552 972.8783,-498.0971 954.9975,-464.2831 994.3902,-401 1007.8831,-379.3241 1025.7385,-356.651 1039.7636,-339.887"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1042.5136,-342.0555 1046.305,-332.1623 1037.1716,-337.5318 1042.5136,-342.0555"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="node21" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_node21"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int | defined in integer.go:32">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1077.3671,-538C1077.3671,-538 1047.3671,-538 1047.3671,-538 1041.3671,-538 1035.3671,-532 1035.3671,-526 1035.3671,-526 1035.3671,-514 1035.3671,-514 1035.3671,-508 1041.3671,-502 1047.3671,-502 1047.3671,-502 1077.3671,-502 1077.3671,-502 1083.3671,-502 1089.3671,-508 1089.3671,-514 1089.3671,-514 1089.3671,-526 1089.3671,-526 1089.3671,-532 1083.3671,-538 1077.3671,-538"/>
<text text-anchor="middle" x="1062.3671" y="-524.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-507.4" font-family="Verdana" font-size="14.00" fill="#000000">Int</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge20" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge20"><a xlink:title="at certificate.go:159: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:169: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:178: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:182: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:192: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:193: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M890.7997,-578.9469C932.19,-564.7261 988.8409,-545.2621 1025.521,-532.6595"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1026.9878,-535.8565 1035.3079,-529.297 1024.7132,-529.2363 1026.9878,-535.8565"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate | defined in certificate.go:201&#10;at certificate.go:202: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate]&#10;at certificate.go:210: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:207: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes]&#10;at certificate.go:204: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at certificate.go:208: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M167.867,-845C167.867,-845 80.178,-845 80.178,-845 74.178,-845 68.178,-839 68.178,-833 68.178,-833 68.178,-821 68.178,-821 68.178,-815 74.178,-809 80.178,-809 80.178,-809 167.867,-809 167.867,-809 173.867,-809 179.867,-815 179.867,-821 179.867,-821 179.867,-833 179.867,-833 179.867,-839 173.867,-845 167.867,-845"/>
<text text-anchor="middle" x="124.0225" y="-822.8" font-family="Verdana" font-size="14.00" fill="#000000">ReadCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate -->
<g id="edge8" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate</title>
<g id="a_edge8"><a xlink:title="at certificate.go:202: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.readCertificate]">
<path fill="none" stroke="#000000" d="M180.1672,-827C229.1368,-827 302.0893,-827 365.6397,-827 365.6397,-827 365.6397,-827 527.1776,-827 662.8932,-827 778.1694,-683.7089 820.7207,-623.3279"/>
<polygon fill="#000000" stroke="#000000" points="823.6406,-625.2592 826.4648,-615.0477 817.889,-621.2692 823.6406,-625.2592"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes -->
<g id="node11" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes</title>
<g id="a_node11"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes | defined in certificate.go:87&#10;at certificate.go:90: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:92: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:95: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:88: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:89: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M400.8974,-477C400.8974,-477 330.382,-477 330.382,-477 324.382,-477 318.382,-471 318.382,-465 318.382,-465 318.382,-453 318.382,-453 318.382,-447 324.382,-441 330.382,-441 330.382,-441 400.8974,-441 400.8974,-441 406.8974,-441 412.8974,-447 412.8974,-453 412.8974,-453 412.8974,-465 412.8974,-465 412.8974,-471 406.8974,-477 400.8974,-477"/>
<text text-anchor="middle" x="365.6397" y="-454.8" font-family="Verdana" font-size="14.00" fill="#000000">ExcessBytes</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes -->
<g id="edge18" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes</title>
<g id="a_edge18"><a xlink:title="at certificate.go:207: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes]">
<path fill="none" stroke="#000000" d="M129.437,-808.9044C146.6115,-754.2052 204.7309,-588.3227 305.045,-490 307.6901,-487.4074 310.5958,-484.985 313.6587,-482.7299"/>
<polygon fill="#000000" stroke="#000000" points="315.668,-485.597 322.0625,-477.1494 311.7957,-479.7656 315.668,-485.597"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge22" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge22"><a xlink:title="at certificate.go:208: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M179.9695,-836.824C228.8138,-844.544 301.6938,-854 365.6397,-854 365.6397,-854 365.6397,-854 838.2555,-854 918.5747,-854 924.2112,-802.065 994.3902,-763 999.5451,-760.1306 1005.014,-757.3022 1010.5228,-754.5908"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1012.2784,-757.6307 1019.7827,-750.1517 1009.2523,-751.3185 1012.2784,-757.6307"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="node18" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_node18"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).Warn | defined in log.go:30">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1080.1334,-811C1080.1334,-811 1044.6008,-811 1044.6008,-811 1038.6008,-811 1032.6008,-805 1032.6008,-799 1032.6008,-799 1032.6008,-787 1032.6008,-787 1032.6008,-781 1038.6008,-775 1044.6008,-775 1044.6008,-775 1080.1334,-775 1080.1334,-775 1086.1334,-775 1092.1334,-781 1092.1334,-787 1092.1334,-787 1092.1334,-799 1092.1334,-799 1092.1334,-805 1086.1334,-811 1080.1334,-811"/>
<text text-anchor="middle" x="1062.3671" y="-797.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-780.4" font-family="Verdana" font-size="14.00" fill="#000000">Warn</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="edge21" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge21"><a xlink:title="at certificate.go:204: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M174.6643,-845.1314C223.0522,-860.819 298.3724,-881 365.6397,-881 365.6397,-881 365.6397,-881 838.2555,-881 892.3836,-881 907.9658,-880.678 958.3902,-861 985.466,-850.4337 1012.8462,-832.1507 1032.7088,-817.2021"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1034.9416,-819.9004 1040.7382,-811.0319 1030.6763,-814.3499 1034.9416,-819.9004"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge9" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge9"><a xlink:title="at certificate.go:210: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M126.618,-808.9925C142.1927,-704.3357 227.2637,-179 365.6397,-179 365.6397,-179 365.6397,-179 838.2555,-179 876.2584,-179 889.4097,-178.4702 921.3902,-199 965.6091,-227.3863 951.2954,-261.9346 994.3902,-292 1002.5446,-297.689 1012.2569,-301.9722 1021.752,-305.1723"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1020.9084,-308.5739 1031.4939,-308.1286 1022.9412,-301.8755 1020.9084,-308.5739"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init -->
<g id="node4" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init</title>
<g id="a_node4"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init | defined in .:0&#10;at certificate.go:18: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M139.0225,-59C139.0225,-59 109.0225,-59 109.0225,-59 103.0225,-59 97.0225,-53 97.0225,-47 97.0225,-47 97.0225,-35 97.0225,-35 97.0225,-29 103.0225,-23 109.0225,-23 109.0225,-23 139.0225,-23 139.0225,-23 145.0225,-23 151.0225,-29 151.0225,-35 151.0225,-35 151.0225,-47 151.0225,-47 151.0225,-53 145.0225,-59 139.0225,-59"/>
<text text-anchor="middle" x="124.0225" y="-36.8" font-family="Verdana" font-size="14.00" fill="#000000">init</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node5"><a xlink:title="github.com/go&#45;i2p/logger.GetGoI2PLogger | defined in log.go:120">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M414.3292,-59C414.3292,-59 316.9502,-59 316.9502,-59 310.9502,-59 304.9502,-53 304.9502,-47 304.9502,-47 304.9502,-35 304.9502,-35 304.9502,-29 310.9502,-23 316.9502,-23 316.9502,-23 414.3292,-23 414.3292,-23 420.3292,-23 426.3292,-29 426.3292,-35 426.3292,-35 426.3292,-47 426.3292,-47 426.3292,-53 420.3292,-59 414.3292,-59"/>
<text text-anchor="middle" x="365.6397" y="-45.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="365.6397" y="-28.4" font-family="Verdana" font-size="14.00" fill="#000000">GetGoI2PLogger</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge36" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge36"><a xlink:title="at certificate.go:18: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M151.2694,-41C185.8355,-41 246.7324,-41 294.8092,-41"/>
<polygon fill="#8b4513" stroke="#8b4513" points="294.8596,-44.5001 304.8596,-41 294.8595,-37.5001 294.8596,-44.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate | defined in certificate.go:281&#10;at certificate.go:282: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at certificate.go:283: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at certificate.go:283: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:286: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M220.0675,-223C220.0675,-223 27.9775,-223 27.9775,-223 21.9775,-223 15.9775,-217 15.9775,-211 15.9775,-211 15.9775,-199 15.9775,-199 15.9775,-193 21.9775,-187 27.9775,-187 27.9775,-187 220.0675,-187 220.0675,-187 226.0675,-187 232.0675,-193 232.0675,-199 232.0675,-199 232.0675,-211 232.0675,-211 232.0675,-217 226.0675,-223 220.0675,-223"/>
<text text-anchor="middle" x="124.0225" y="-200.8" font-family="Verdana" font-size="14.00" fill="#000000">GetSignatureTypeFromCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge4"><a xlink:title="at certificate.go:283: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:286: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M145.3922,-186.9364C185.6792,-154.7915 276.818,-91 365.6397,-91 365.6397,-91 365.6397,-91 718.6208,-91 829.0428,-91 959.081,-101.4127 1022.9377,-107.2115"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1022.6938,-110.7038 1032.9723,-108.1345 1023.335,-103.7332 1022.6938,-110.7038"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="node15" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_node15"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type | defined in certificate.go:116&#10;at certificate.go:117: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:120: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:118: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M380.6397,-416C380.6397,-416 350.6397,-416 350.6397,-416 344.6397,-416 338.6397,-410 338.6397,-404 338.6397,-404 338.6397,-392 338.6397,-392 338.6397,-386 344.6397,-380 350.6397,-380 350.6397,-380 380.6397,-380 380.6397,-380 386.6397,-380 392.6397,-386 392.6397,-392 392.6397,-392 392.6397,-404 392.6397,-404 392.6397,-410 386.6397,-416 380.6397,-416"/>
<text text-anchor="middle" x="365.6397" y="-393.8" font-family="Verdana" font-size="14.00" fill="#000000">Type</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_edge3"><a xlink:title="at certificate.go:282: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at certificate.go:283: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#000000" d="M140.8989,-223.1706C171.4062,-255.2997 238.7388,-322.9884 305.045,-368 312.5955,-373.1256 321.1482,-377.9048 329.3982,-382.0752"/>
<polygon fill="#000000" stroke="#000000" points="327.9911,-385.2828 338.5145,-386.5112 331.054,-378.9885 327.9911,-385.2828"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux -->
<g id="node7" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux</title>
<g id="a_node7"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux | defined in certificate.go:223&#10;at certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:225: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:230: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:246: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:233: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M896.0832,-153C896.0832,-153 780.4278,-153 780.4278,-153 774.4278,-153 768.4278,-147 768.4278,-141 768.4278,-141 768.4278,-129 768.4278,-129 768.4278,-123 774.4278,-117 780.4278,-117 780.4278,-117 896.0832,-117 896.0832,-117 902.0832,-117 908.0832,-123 908.0832,-129 908.0832,-129 908.0832,-141 908.0832,-141 908.0832,-147 902.0832,-153 896.0832,-153"/>
<text text-anchor="middle" x="838.2555" y="-130.8" font-family="Verdana" font-size="14.00" fill="#000000">NewCertificateDeux</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge23" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge23"><a xlink:title="at certificate.go:225: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:230: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M908.244,-127.505C945.9757,-123.4643 991.1517,-118.6264 1022.8055,-115.2366"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1023.4211,-118.6908 1032.9915,-114.1458 1022.6757,-111.7306 1023.4211,-118.6908"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt -->
<g id="node8" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt</title>
<g id="a_node8"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt | defined in integer.go:68">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1118.3209,-53C1118.3209,-53 1006.4133,-53 1006.4133,-53 1000.4133,-53 994.4133,-47 994.4133,-41 994.4133,-41 994.4133,-29 994.4133,-29 994.4133,-23 1000.4133,-17 1006.4133,-17 1006.4133,-17 1118.3209,-17 1118.3209,-17 1124.3209,-17 1130.3209,-23 1130.3209,-29 1130.3209,-29 1130.3209,-41 1130.3209,-41 1130.3209,-47 1124.3209,-53 1118.3209,-53"/>
<text text-anchor="middle" x="1062.3671" y="-39.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-22.4" font-family="Verdana" font-size="14.00" fill="#000000">NewIntegerFromInt</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt -->
<g id="edge37" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt</title>
<g id="a_edge37"><a xlink:title="at certificate.go:233: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt]">
<path fill="none" stroke="#8b4513" d="M878.8404,-116.8908C916.3257,-100.1646 972.1246,-75.2668 1012.3495,-57.3182"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1014.0001,-60.4143 1021.7061,-53.1432 1011.1477,-54.0218 1014.0001,-60.4143"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge12" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge12"><a xlink:title="at certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M851.522,-153.0586C870.1671,-179.3685 903.8061,-230.4117 921.3902,-279 953.8513,-368.6964 935.6768,-626.8209 994.3902,-702 998.6579,-707.4646 1004.1302,-711.9569 1010.1131,-715.6445"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.6953,-718.8555 1019.1632,-720.4908 1011.9999,-712.6846 1008.6953,-718.8555"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge34" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge34"><a xlink:title="at certificate.go:246: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M908.395,-144.374C926.6456,-149.8377 944.937,-158.4481 958.3902,-172 997.6189,-211.5165 955.4437,-252.2053 994.3902,-292 1001.7432,-299.5132 1011.6778,-304.4629 1021.6788,-307.7231"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.0388,-311.1769 1031.6088,-310.4525 1022.8941,-304.4273 1021.0388,-311.1769"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType -->
<g id="node9" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType</title>
<g id="a_node9"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType | defined in certificate.go:252&#10;at certificate.go:258: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:263: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:265: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M909.5251,-57C909.5251,-57 766.9859,-57 766.9859,-57 760.9859,-57 754.9859,-51 754.9859,-45 754.9859,-45 754.9859,-33 754.9859,-33 754.9859,-27 760.9859,-21 766.9859,-21 766.9859,-21 909.5251,-21 909.5251,-21 915.5251,-21 921.5251,-27 921.5251,-33 921.5251,-33 921.5251,-45 921.5251,-45 921.5251,-51 915.5251,-57 909.5251,-57"/>
<text text-anchor="middle" x="838.2555" y="-34.8" font-family="Verdana" font-size="14.00" fill="#000000">NewCertificateWithType</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge28" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge28"><a xlink:title="at certificate.go:258: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:263: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M894.519,-57.0757C934.8151,-70.0216 988.0345,-87.1193 1023.6417,-98.5588"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1022.6011,-101.9006 1033.1924,-101.6271 1024.7422,-95.236 1022.6011,-101.9006"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt -->
<g id="edge40" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt</title>
<g id="a_edge40"><a xlink:title="at certificate.go:265: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt]">
<path fill="none" stroke="#8b4513" d="M921.7064,-37.5105C942.1472,-37.1457 963.949,-36.7566 984.1349,-36.3963"/>
<polygon fill="#8b4513" stroke="#8b4513" points="984.2775,-39.8944 994.2134,-36.2164 984.1525,-32.8955 984.2775,-39.8944"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length -->
<g id="node10" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length</title>
<g id="a_node10"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length | defined in certificate.go:125&#10;at certificate.go:129: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:126: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:127: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M857.9142,-538C857.9142,-538 818.5968,-538 818.5968,-538 812.5968,-538 806.5968,-532 806.5968,-526 806.5968,-526 806.5968,-514 806.5968,-514 806.5968,-508 812.5968,-502 818.5968,-502 818.5968,-502 857.9142,-502 857.9142,-502 863.9142,-502 869.9142,-508 869.9142,-514 869.9142,-514 869.9142,-526 869.9142,-526 869.9142,-532 863.9142,-538 857.9142,-538"/>
<text text-anchor="middle" x="838.2555" y="-515.8" font-family="Verdana" font-size="14.00" fill="#000000">Length</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge38" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge38"><a xlink:title="at certificate.go:127: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M870.0778,-521.9339C886.97,-524.4397 907.1252,-529.9669 921.3902,-542 981.1357,-592.3975 938.7785,-647.0748 994.3902,-702 998.9677,-706.521 1004.3418,-710.4191 1010.0282,-713.7654"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.6741,-717.0082 1019.1517,-718.5799 1011.9411,-710.8173 1008.6741,-717.0082"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge24" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge24"><a xlink:title="at certificate.go:129: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M863.6821,-501.7945C880.5068,-489.4202 902.8082,-472.3815 921.3902,-456 964.9263,-417.6195 1011.6811,-368.8553 1038.9109,-339.6073"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1041.4949,-341.9681 1045.7268,-332.2552 1036.3615,-337.2091 1041.4949,-341.9681"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge35" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge35"><a xlink:title="at certificate.go:126: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M870.3652,-520C911.289,-520 981.8968,-520 1025.1348,-520"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1025.2399,-523.5001 1035.2399,-520 1025.2398,-516.5001 1025.2399,-523.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge6" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge6"><a xlink:title="at certificate.go:90: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M413.037,-477.0926C418.1184,-480.6981 422.7107,-484.966 426.2344,-490 463.4737,-543.2008 413.5692,-737.0025 462.2344,-780 503.5475,-816.5017 904.5976,-792.0624 958.3902,-780 975.6557,-776.1284 978.3402,-770.4489 994.3902,-763 1000.477,-760.1751 1006.8798,-757.2259 1013.2223,-754.3181"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1014.7903,-757.4497 1022.4278,-750.1066 1011.8781,-751.0842 1014.7903,-757.4497"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge19" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge19"><a xlink:title="at certificate.go:92: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:95: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M407.6685,-440.8914C414.1432,-437.349 420.556,-433.3622 426.2344,-429 480.1656,-387.5692 459.1696,-314 527.1776,-314 527.1776,-314 527.1776,-314 838.2555,-314 902.192,-314 976.3886,-314 1021.3294,-314"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.5535,-317.5001 1031.5535,-314 1021.5535,-310.5001 1021.5535,-317.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge30" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge30"><a xlink:title="at certificate.go:88: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at certificate.go:89: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M413.0536,-442.2321C444.9043,-432.4424 488.049,-422 527.1776,-422 527.1776,-422 527.1776,-422 718.6208,-422 779.7179,-422 950.1975,-479.98 1025.6438,-506.7463"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.618,-510.0963 1035.2127,-510.1547 1026.9669,-503.5021 1024.618,-510.0963"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="node12" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_node12"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes | defined in certificate.go:100&#10;at certificate.go:104: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:101: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:102: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:106: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:103: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M543.0641,-538C543.0641,-538 511.2911,-538 511.2911,-538 505.2911,-538 499.2911,-532 499.2911,-526 499.2911,-526 499.2911,-514 499.2911,-514 499.2911,-508 505.2911,-502 511.2911,-502 511.2911,-502 543.0641,-502 543.0641,-502 549.0641,-502 555.0641,-508 555.0641,-514 555.0641,-514 555.0641,-526 555.0641,-526 555.0641,-532 549.0641,-538 543.0641,-538"/>
<text text-anchor="middle" x="527.1776" y="-515.8" font-family="Verdana" font-size="14.00" fill="#000000">Bytes</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="node13" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_node13"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data | defined in certificate.go:134&#10;at certificate.go:138: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at certificate.go:144: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:135: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length]&#10;at certificate.go:142: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M670.1208,-538C670.1208,-538 640.1208,-538 640.1208,-538 634.1208,-538 628.1208,-532 628.1208,-526 628.1208,-526 628.1208,-514 628.1208,-514 628.1208,-508 634.1208,-502 640.1208,-502 640.1208,-502 670.1208,-502 670.1208,-502 676.1208,-502 682.1208,-508 682.1208,-514 682.1208,-514 682.1208,-526 682.1208,-526 682.1208,-532 676.1208,-538 670.1208,-538"/>
<text text-anchor="middle" x="655.1208" y="-515.8" font-family="Verdana" font-size="14.00" fill="#000000">Data</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="edge32" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_edge32"><a xlink:title="at certificate.go:103: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#000000" d="M555.2553,-520C573.6714,-520 597.9555,-520 617.9655,-520"/>
<polygon fill="#000000" stroke="#000000" points="617.9862,-523.5001 627.9861,-520 617.9861,-516.5001 617.9862,-523.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge1" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge1"><a xlink:title="at certificate.go:104: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M529.9125,-538.0109C538.4723,-586.9966 569.4835,-719 655.1208,-719 655.1208,-719 655.1208,-719 838.2555,-719 896.6494,-719 963.4583,-723.453 1008.8298,-727.1466"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.7727,-730.6539 1019.0281,-727.9935 1009.3521,-723.6779 1008.7727,-730.6539"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge27" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge27"><a xlink:title="at certificate.go:106: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M535.3242,-501.8239C552.2462,-467.1555 594.7211,-395 655.1208,-395 655.1208,-395 655.1208,-395 718.6208,-395 830.9451,-395 958.5435,-353.5187 1022.0321,-329.926"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1023.5331,-333.1008 1031.659,-326.3022 1021.067,-326.5495 1023.5331,-333.1008"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes -->
<g id="node22" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes</title>
<g id="a_node22"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes | defined in integer.go:27">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M1078.2536,-477C1078.2536,-477 1046.4806,-477 1046.4806,-477 1040.4806,-477 1034.4806,-471 1034.4806,-465 1034.4806,-465 1034.4806,-453 1034.4806,-453 1034.4806,-447 1040.4806,-441 1046.4806,-441 1046.4806,-441 1078.2536,-441 1078.2536,-441 1084.2536,-441 1090.2536,-447 1090.2536,-453 1090.2536,-453 1090.2536,-465 1090.2536,-465 1090.2536,-471 1084.2536,-477 1078.2536,-477"/>
<text text-anchor="middle" x="1062.3671" y="-463.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-446.4" font-family="Verdana" font-size="14.00" fill="#000000">Bytes</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes -->
<g id="edge25" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes</title>
<g id="a_edge25"><a xlink:title="at certificate.go:101: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:102: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]">
<path fill="none" stroke="#8b4513" d="M555.1926,-504.3634C580.5012,-491.7165 619.1824,-476 655.1208,-476 655.1208,-476 655.1208,-476 838.2555,-476 903.8206,-476 979.867,-468.6762 1024.3892,-463.6427"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.9341,-467.1032 1034.4676,-462.4812 1024.1326,-460.1492 1024.9341,-467.1032"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length -->
<g id="edge26" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length</title>
<g id="a_edge26"><a xlink:title="at certificate.go:135: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length]">
<path fill="none" stroke="#000000" d="M682.143,-520C712.169,-520 761.0347,-520 796.0998,-520"/>
<polygon fill="#000000" stroke="#000000" points="796.503,-523.5001 806.5029,-520 796.5029,-516.5001 796.503,-523.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge31" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge31"><a xlink:title="at certificate.go:142: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M662.5733,-538.0526C676.177,-568.6482 708.0373,-630.4325 755.1208,-662 765.7096,-669.0994 923.8065,-702.9794 1008.9624,-720.8715"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.4652,-724.3433 1018.9709,-722.9713 1009.9026,-717.4924 1008.4652,-724.3433"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="edge14" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge14"><a xlink:title="at certificate.go:138: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M660.6886,-538.1788C672.3115,-572.9981 702.5344,-649.1699 755.1208,-689 837.4468,-751.3554 959.4954,-777.7431 1022.106,-787.6955"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.9424,-791.211 1032.3563,-789.2615 1022.9997,-784.2913 1021.9424,-791.211"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge15" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge15"><a xlink:title="at certificate.go:144: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M682.1656,-509.4896C730.9543,-490.2072 836.5157,-447.009 921.3902,-402 958.6511,-382.2405 999.3255,-356.3539 1027.366,-337.7802"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1029.6243,-340.4813 1036.0057,-332.0238 1025.743,-334.6558 1029.6243,-340.4813"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length -->
<g id="node14" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length</title>
<g id="a_node14"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length | defined in certificate.go:110&#10;at certificate.go:111: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M383.1355,-538C383.1355,-538 348.1439,-538 348.1439,-538 342.1439,-538 336.1439,-532 336.1439,-526 336.1439,-526 336.1439,-514 336.1439,-514 336.1439,-508 342.1439,-502 348.1439,-502 348.1439,-502 383.1355,-502 383.1355,-502 389.1355,-502 395.1355,-508 395.1355,-514 395.1355,-514 395.1355,-526 395.1355,-526 395.1355,-532 389.1355,-538 383.1355,-538"/>
<text text-anchor="middle" x="365.6397" y="-515.8" font-family="Verdana" font-size="14.00" fill="#000000">length</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="edge7" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_edge7"><a xlink:title="at certificate.go:111: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="none" stroke="#000000" d="M395.2682,-520C421.6326,-520 460.3466,-520 489.0205,-520"/>
<polygon fill="#000000" stroke="#000000" points="489.0889,-523.5001 499.0889,-520 489.0888,-516.5001 489.0889,-523.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge33" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge33"><a xlink:title="at certificate.go:118: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M392.8854,-405.4307C405.0472,-410.1699 418.3791,-417.6229 426.2344,-429 508.5551,-548.228 369.8577,-641.3821 462.2344,-753 481.4902,-776.2666 496.9762,-773 527.1776,-773 527.1776,-773 527.1776,-773 838.2555,-773 897.4598,-773 964.0466,-758.9838 1009.1435,-747.3416"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1010.2151,-750.6788 1018.9943,-744.7479 1008.4327,-743.9095 1010.2151,-750.6788"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge11" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge11"><a xlink:title="at certificate.go:120: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M392.7503,-388.5653C404.0291,-383.6871 416.6888,-376.869 426.2344,-368 449.2966,-346.5723 437.5241,-326.5042 462.2344,-307 485.9407,-288.2882 496.9762,-287 527.1776,-287 527.1776,-287 527.1776,-287 838.2555,-287 902.7902,-287 977.0323,-298.1719 1021.7903,-306.143"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.2301,-309.5984 1031.6944,-307.9407 1022.4802,-302.711 1021.2301,-309.5984"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge10" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge10"><a xlink:title="at certificate.go:117: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M392.7931,-389.8024C424.6635,-380.9199 479.2568,-368 527.1776,-368 527.1776,-368 527.1776,-368 838.2555,-368 926.3206,-368 921.2143,-441.0025 994.3902,-490 1003.9919,-496.4291 1015.1971,-502.0322 1025.7081,-506.6001"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.5221,-509.8973 1035.0999,-510.4981 1027.2055,-503.432 1024.5221,-509.8973"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes -->
<g id="node16" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes</title>
<g id="a_node16"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes | defined in certificate.go:76&#10;at certificate.go:80: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:77: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:78: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:82: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M394.1852,-355C394.1852,-355 337.0942,-355 337.0942,-355 331.0942,-355 325.0942,-349 325.0942,-343 325.0942,-343 325.0942,-331 325.0942,-331 325.0942,-325 331.0942,-319 337.0942,-319 337.0942,-319 394.1852,-319 394.1852,-319 400.1852,-319 406.1852,-325 406.1852,-331 406.1852,-331 406.1852,-343 406.1852,-343 406.1852,-349 400.1852,-355 394.1852,-355"/>
<text text-anchor="middle" x="365.6397" y="-332.8" font-family="Verdana" font-size="14.00" fill="#000000">RawBytes</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge5" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge5"><a xlink:title="at certificate.go:80: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M406.2658,-351.7653C413.7563,-356.0336 420.8884,-361.3814 426.2344,-368 535.4971,-503.2716 353.2904,-746 527.1776,-746 527.1776,-746 527.1776,-746 838.2555,-746 896.665,-746 963.4713,-741.2044 1008.8379,-737.2267"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1009.3865,-740.6917 1019.035,-736.3147 1008.7629,-733.7195 1009.3865,-740.6917"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge29" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge29"><a xlink:title="at certificate.go:82: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M406.2343,-326.7314C413.3846,-323.7232 420.3965,-319.8824 426.2344,-315 450.677,-294.5581 440.8621,-276.6333 462.2344,-253 486.1323,-226.5738 491.5482,-206 527.1776,-206 527.1776,-206 527.1776,-206 838.2555,-206 895.5894,-206 911.0429,-220.6671 958.3902,-253 977.8704,-266.3028 974.5202,-279.2867 994.3902,-292 1002.6878,-297.309 1012.3789,-301.4413 1021.8004,-304.616"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1020.8641,-307.9898 1031.4513,-307.5869 1022.9237,-301.2996 1020.8641,-307.9898"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes -->
<g id="edge13" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes</title>
<g id="a_edge13"><a xlink:title="at certificate.go:77: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]&#10;at certificate.go:78: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Bytes]">
<path fill="none" stroke="#8b4513" d="M406.3953,-323.1598C413.0929,-320.6131 419.9087,-317.8521 426.2344,-315 472.8101,-294.0003 476.0867,-260 527.1776,-260 527.1776,-260 527.1776,-260 838.2555,-260 940.5999,-260 1017.9747,-377.4734 1048.3334,-431.9054"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1045.4271,-433.8864 1053.2885,-440.9891 1051.5723,-430.5342 1045.4271,-433.8864"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -0,0 +1,369 @@
package certificate
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCertificateTypeIsFirstByte(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x00}
certificate, err := readCertificate(bytes)
cert_type := certificate.Type()
assert.Equal(cert_type, 3, "certificate.Type() should be the first bytes in a certificate")
assert.Nil(err)
}
func TestCertificateLengthCorrect(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff}
certificate, err := readCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes")
assert.Nil(err)
}
func TestCertificateLengthErrWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x01}
certificate, _, err := ReadCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data")
if assert.NotNil(err) {
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
}
}
func TestCertificateLengthErrWhenDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
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")
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
}
func TestCertificateDataWhenCorrectSize(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x01, 0xaa}
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
assert.Nil(err, "certificate.Data() returned error with valid data")
cert_len := len(cert_data)
assert.Equal(cert_len, 1, "certificate.Length() did not return indicated length when data was valid")
assert.Equal(170, int(cert_data[0]), "certificate.Data() returned incorrect data")
}
func TestCertificateDataWhenTooLong(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
certificate, _, _ := ReadCertificate(bytes)
cert_data := certificate.Data()
cert_len := certificate.Length() // len(cert_data)
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
if cert_data[0] != 0xff || cert_data[1] != 0xff {
t.Fatal("certificate.Data() returned incorrect data when data was too long")
}
}
func TestCertificateDataWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
cert_len := len(cert_data)
assert.Equal(cert_len, 1, "certificate.Data() did not return correct amount of data when data too short")
assert.Equal(255, int(cert_data[0]), "certificate.Data() did not return correct data values when data was too short")
}
func TestReadCertificateWithCorrectData(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff, 0xff}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(cert.length(), 5, "ReadCertificate() did not return correct amount of data for valid certificate")
assert.Equal(len(remainder), 0, "ReadCertificate() did not return a zero length remainder on a valid certificate")
assert.Nil(err, "ReadCertificate() should not return an error with valid data")
}
func TestReadCertificateWithDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(cert.length(), 4, "ReadCertificate() did not return correct amount of data for certificate with missing data")
assert.Equal(len(remainder), 0, "ReadCertificate() did not return a zero length remainder on certificate with missing data")
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
}
func TestReadCertificateWithRemainder(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff, 0xff, 0x01}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(cert.length(), 5, "ReadCertificate() did not return correct amount of data for certificate with extra data")
assert.Equal(len(remainder), 1, "ReadCertificate() returned incorrect length remainder on certificate with extra data")
// assert.Equal(1, int(remainder[0]), "ReadCertificate() did not return correct remainder value")
assert.Nil(err)
}
func TestReadCertificateWithInvalidLength(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid")
assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate")
if assert.NotNil(err) {
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
}
}
func TestNewCertificateNullType(t *testing.T) {
assert := assert.New(t)
// Create a NULL certificate with no payload
cert, err := NewCertificateWithType(CERT_NULL, []byte{})
assert.Nil(err, "Expected no error when creating NULL certificate with empty payload")
assert.Equal(CERT_NULL, cert.Type(), "Certificate type should be CERT_NULL")
assert.Equal(0, cert.Length(), "Certificate length should be 0 for NULL certificate")
assert.Equal(0, len(cert.Data()), "Certificate data should be empty for NULL certificate")
}
func TestNewCertificateNullTypeWithPayload(t *testing.T) {
assert := assert.New(t)
// Attempt to create a NULL certificate with a payload (should fail)
_, err := NewCertificateWithType(CERT_NULL, []byte{0x00})
assert.NotNil(err, "Expected error when creating NULL certificate with payload")
assert.Equal("NULL certificates must have empty payload", err.Error(), "Correct error message should be returned")
}
func TestNewCertificateKeyType(t *testing.T) {
assert := assert.New(t)
payload := []byte{0x00, 0x01, 0x02, 0x03, 0x04}
cert, err := NewCertificateWithType(CERT_KEY, payload)
assert.Nil(err, "Expected no error when creating KEY certificate with valid payload")
assert.Equal(CERT_KEY, cert.Type(), "Certificate type should be CERT_KEY")
assert.Equal(len(payload), cert.Length(), "Certificate length should match payload length")
assert.Equal(payload, cert.Data(), "Certificate data should match payload")
}
func TestNewCertificateInvalidType(t *testing.T) {
assert := assert.New(t)
invalidCertType := uint8(6) // Invalid type (valid types are 0-5)
_, err := NewCertificateWithType(invalidCertType, []byte{})
assert.NotNil(err, "Expected error when creating certificate with invalid type")
assert.Equal("invalid certificate type: 6", err.Error(), "Correct error message should be returned")
}
/*
func TestNewCertificatePayloadTooLong(t *testing.T) {
assert := assert.New(t)
// Create a payload that exceeds the maximum allowed length (65535 bytes)
payload := make([]byte, 65536) // 65536 bytes
_, err := NewCertificateWithType(CERT_KEY, payload)
assert.NotNil(err, "Expected error when creating certificate with payload too long")
assert.Equal("certificate payload too long: maximum length is 65535 bytes", err.Error(), "Correct error message should be returned")
}
*/
func TestCertificateBytesSerialization(t *testing.T) {
assert := assert.New(t)
payload := []byte{0xAA, 0xBB, 0xCC}
certType := CERT_SIGNED
cert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating SIGNED certificate")
expectedBytes := []byte{
byte(certType), // Certificate type
0x00, byte(len(payload)), // Certificate length (2 bytes)
0xAA, 0xBB, 0xCC, // Payload
}
actualBytes := cert.Bytes()
assert.Equal(expectedBytes, actualBytes, "Certificate bytes should match expected serialization")
}
func TestCertificateFieldsAfterCreation(t *testing.T) {
assert := assert.New(t)
payload := []byte{0xDE, 0xAD, 0xBE, 0xEF}
certType := CERT_MULTIPLE
cert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating MULTIPLE certificate")
assert.Equal(certType, cert.Type(), "Certificate type should match")
assert.Equal(len(payload), cert.Length(), "Certificate length should match payload length")
assert.Equal(payload, cert.Data(), "Certificate data should match payload")
}
func TestCertificateWithZeroLengthPayload(t *testing.T) {
assert := assert.New(t)
certType := CERT_HASHCASH
cert, err := NewCertificateWithType(uint8(certType), []byte{})
assert.Nil(err, "Expected no error when creating certificate with zero-length payload")
assert.Equal(certType, cert.Type(), "Certificate type should match")
assert.Equal(0, cert.Length(), "Certificate length should be 0 for zero-length payload")
assert.Equal(0, len(cert.Data()), "Certificate data should be empty")
}
func TestNewCertificateDeuxFunction(t *testing.T) {
assert := assert.New(t)
payload := []byte{0x11, 0x22}
certType := CERT_HIDDEN
cert, err := NewCertificateDeux(certType, payload)
assert.Nil(err, "Expected no error when creating certificate with NewCertificateDeux")
assert.Equal(certType, cert.Type(), "Certificate type should match")
assert.Equal(len(payload), cert.Length(), "Certificate length should match payload length")
assert.Equal(payload, cert.Data(), "Certificate data should match payload")
}
func TestNewCertificateWithInvalidPayloadLength(t *testing.T) {
assert := assert.New(t)
payload := make([]byte, 70000) // Exceeds 65535 bytes
_, err := NewCertificateDeux(CERT_KEY, payload)
assert.NotNil(err, "Expected error when creating certificate with payload exceeding maximum length")
assert.Equal("payload too long: 70000 bytes", err.Error(), "Correct error message should be returned")
}
func TestCertificateExcessBytes(t *testing.T) {
assert := assert.New(t)
payload := []byte{0x01, 0x02}
extraBytes := []byte{0x03, 0x04}
certData := append(payload, extraBytes...)
certBytes := append([]byte{byte(CERT_SIGNED)}, []byte{0x00, byte(len(payload))}...)
certBytes = append(certBytes, certData...)
cert, err := readCertificate(certBytes)
assert.Nil(err, "Expected no error when reading certificate with excess bytes")
excess := cert.ExcessBytes()
assert.Equal(extraBytes, excess, "ExcessBytes should return the extra bytes in the payload")
assert.Equal(payload, cert.Data(), "Data() should return the valid payload excluding excess bytes")
}
func TestCertificateSerializationDeserialization(t *testing.T) {
assert := assert.New(t)
payload := []byte{0xAA, 0xBB, 0xCC}
certType := CERT_SIGNED
originalCert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating SIGNED certificate")
serializedBytes := originalCert.Bytes()
assert.NotNil(serializedBytes, "Serialized bytes should not be nil")
deserializedCert, err := readCertificate(serializedBytes)
assert.Nil(err, "Expected no error when deserializing certificate")
assert.Equal(originalCert.Type(), deserializedCert.Type(), "Certificate types should match")
assert.Equal(originalCert.Length(), deserializedCert.Length(), "Certificate lengths should match")
assert.Equal(originalCert.Data(), deserializedCert.Data(), "Certificate payloads should match")
}
func TestCertificateSerializationDeserializationWithExcessBytes(t *testing.T) {
assert := assert.New(t)
payload := []byte{0x01, 0x02}
certType := CERT_MULTIPLE
originalCert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating MULTIPLE certificate")
serializedBytes := originalCert.Bytes()
excessBytes := []byte{0x03, 0x04}
serializedBytesWithExcess := append(serializedBytes, excessBytes...)
deserializedCert, err := readCertificate(serializedBytesWithExcess)
assert.Nil(err, "Expected no error when deserializing certificate with excess bytes")
assert.Equal(originalCert.Type(), deserializedCert.Type(), "Certificate types should match")
assert.Equal(originalCert.Length(), deserializedCert.Length(), "Certificate lengths should match")
assert.Equal(originalCert.Data(), deserializedCert.Data(), "Certificate payloads should match")
excess := deserializedCert.ExcessBytes()
assert.Equal(excessBytes, excess, "ExcessBytes should return the extra bytes appended to the serialized data")
}
func TestCertificateSerializationDeserializationEmptyPayload(t *testing.T) {
assert := assert.New(t)
payload := []byte{}
certType := CERT_NULL
originalCert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating NULL certificate")
serializedBytes := originalCert.Bytes()
deserializedCert, err := readCertificate(serializedBytes)
assert.Nil(err, "Expected no error when deserializing NULL certificate")
assert.Equal(originalCert.Type(), deserializedCert.Type(), "Certificate types should match")
assert.Equal(originalCert.Length(), deserializedCert.Length(), "Certificate lengths should match")
assert.Equal(originalCert.Data(), deserializedCert.Data(), "Certificate payloads should match")
}
func TestCertificateSerializationDeserializationMaxPayload(t *testing.T) {
assert := assert.New(t)
payload := make([]byte, 65535)
for i := range payload {
payload[i] = byte(i % 256)
}
certType := CERT_KEY
originalCert, err := NewCertificateWithType(uint8(certType), payload)
assert.Nil(err, "Expected no error when creating KEY certificate with maximum payload")
serializedBytes := originalCert.Bytes()
assert.Equal(1+2+65535, len(serializedBytes), "Serialized bytes length should be correct for maximum payload")
deserializedCert, err := readCertificate(serializedBytes)
assert.Nil(err, "Expected no error when deserializing certificate with maximum payload")
assert.Equal(originalCert.Type(), deserializedCert.Type(), "Certificate types should match")
assert.Equal(originalCert.Length(), deserializedCert.Length(), "Certificate lengths should match")
assert.True(bytes.Equal(originalCert.Data(), deserializedCert.Data()), "Certificate payloads should match")
}

View File

@ -1,148 +0,0 @@
package common
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestCertificateTypeIsFirstByte(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x00}
certificate := Certificate(bytes)
cert_type, err := certificate.Type()
assert.Equal(cert_type, 3, "certificate.Type() should be the first bytes in a certificate")
assert.Nil(err)
}
func TestCertificateLengthCorrect(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff}
certificate := Certificate(bytes)
cert_len, err := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes")
assert.Nil(err)
}
func TestCertificateLengthErrWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x01}
certificate := Certificate(bytes)
cert_len, err := certificate.Length()
assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data")
if assert.NotNil(err) {
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned")
}
}
func TestCertificateLengthErrWhenDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate := Certificate(bytes)
cert_len, err := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was actually missing")
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
}
func TestCertificateDataWhenCorrectSize(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x01, 0xaa}
certificate := Certificate(bytes)
cert_data, err := certificate.Data()
assert.Nil(err, "certificate.Data() returned error with valid data")
cert_len := len(cert_data)
assert.Equal(cert_len, 1, "certificate.Length() did not return indicated length when data was valid")
assert.Equal(170, int(cert_data[0]), "certificate.Data() returned incorrect data")
}
func TestCertificateDataWhenTooLong(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
certificate := Certificate(bytes)
cert_data, err := certificate.Data()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate contains data beyond length", err.Error(), "correct error message should be returned")
}
cert_len := len(cert_data)
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
if cert_data[0] != 0xff || cert_data[1] != 0xff {
t.Fatal("certificate.Data() returned incorrect data when data was too long")
}
}
func TestCertificateDataWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate := Certificate(bytes)
cert_data, err := certificate.Data()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
cert_len := len(cert_data)
assert.Equal(cert_len, 1, "certificate.Data() did not return correct amount of data when data too short")
assert.Equal(255, int(cert_data[0]), "certificate.Data() did not return correct data values when data was too short")
}
func TestReadCertificateWithCorrectData(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff, 0xff}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(len(cert), 5, "ReadCertificate() did not return correct amount of data for valid certificate")
assert.Equal(len(remainder), 0, "ReadCertificate() did not return a zero length remainder on a valid certificate")
assert.Nil(err, "ReadCertificate() should not return an error with valid data")
}
func TestReadCertificateWithDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(len(cert), 4, "ReadCertificate() did not return correct amount of data for certificate with missing data")
assert.Equal(len(remainder), 0, "ReadCertificate() did not return a zero length remainder on certificate with missing data")
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
}
func TestReadCertificateWithRemainder(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00, 0x02, 0xff, 0xff, 0x01}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(len(cert), 5, "ReadCertificate() did not return correct amount of data for certificate with extra data")
assert.Equal(len(remainder), 1, "ReadCertificate() returned incorrect length remainder on certificate with extra data")
assert.Equal(1, int(remainder[0]), "ReadCertificate() did not return correct remainder value")
assert.Nil(err)
}
func TestReadCertificateWithInvalidLength(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x00, 0x00}
cert, remainder, err := ReadCertificate(bytes)
assert.Equal(len(cert), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid")
assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate")
if assert.NotNil(err) {
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned")
}
}

315
lib/common/data/README.md Normal file
View File

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

1306
lib/common/data/data.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 139 KiB

87
lib/common/data/date.go Normal file
View File

@ -0,0 +1,87 @@
// Package data implements common data structures used in higher level structures.
package data
import (
"time"
"github.com/go-i2p/logger"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
var log = logger.GetGoI2PLogger()
// DATE_SIZE is the length in bytes of an I2P Date.
const DATE_SIZE = 8
/*
[I2P Date]
Accurate for version 0.9.49
Description
The number of milliseconds since midnight on Januyar 1, 1970 in the GMT timezone.
If the number is 0, the date is undefined or null.
Contents
8 byte Integer
*/
// Date is the represenation of an I2P Date.
//
// https://geti2p.net/spec/common-structures#date
type Date [8]byte
// Bytes returns the raw []byte content of a Date.
func (i Date) Bytes() []byte {
return i[:]
}
// Int returns the Date as a Go integer.
func (i Date) Int() int {
return intFromBytes(i.Bytes())
}
// Time takes the value stored in date as an 8 byte big-endian integer representing the
// number of milliseconds since the beginning of unix time and converts it to a Go time.Time
// struct.
func (date Date) Time() (date_time time.Time) {
seconds := Integer(date[:])
date_time = time.Unix(0, int64(seconds.Int()*1000000))
return
}
// ReadDate creates a Date from []byte using the first DATE_SIZE bytes.
// Any data after DATE_SIZE is returned as a remainder.
func ReadDate(data []byte) (date Date, remainder []byte, err error) {
if len(data) < 8 {
log.WithFields(logrus.Fields{
"data": data,
}).Error("ReadDate: data is too short")
err = oops.Errorf("ReadDate: data is too short")
return
}
copy(date[:], data[:8])
remainder = data[8:]
log.WithFields(logrus.Fields{
"date_value": date.Int(),
"remainder_length": len(remainder),
}).Debug("Successfully read Date from data")
return
}
// NewDate creates a new Date from []byte using ReadDate.
// Returns a pointer to Date unlike ReadDate.
func NewDate(data []byte) (date *Date, remainder []byte, err error) {
objdate, remainder, err := ReadDate(data)
if err != nil {
log.WithError(err).Error("Failed to create new Date")
return nil, remainder, err
}
date = &objdate
log.WithFields(logrus.Fields{
"date_value": date.Int(),
"remainder_length": len(remainder),
}).Debug("Successfully created new Date")
return
}

View File

@ -1,11 +1,12 @@
package common
package data
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestTimeFromMiliseconds(t *testing.T) {
func TestTimeFromMilliseconds(t *testing.T) {
assert := assert.New(t)
next_day := Date{0x00, 0x00, 0x00, 0x00, 0x05, 0x26, 0x5c, 0x00}

31
lib/common/data/errors.go Normal file
View File

@ -0,0 +1,31 @@
package data
import (
"fmt"
"github.com/samber/oops"
)
var (
ErrZeroLength = fmt.Errorf("error parsing string: zero length")
ErrDataTooShort = fmt.Errorf("string parsing warning: string data is shorter than specified by length")
ErrDataTooLong = fmt.Errorf("string parsing warning: string contains data beyond length")
ErrLengthMismatch = fmt.Errorf("error reading I2P string, length does not match data")
ErrMappingLengthMismatch = fmt.Errorf("warning parsing mapping: mapping length exceeds provided data")
)
// WrapErrors compiles a slice of errors and returns them wrapped together as a single error.
func WrapErrors(errs []error) error {
var err error
for i, e := range errs {
err = oops.Errorf("%v\n\t%d: %v", err, i, e)
}
return err
}
// PrintErrors prints a formatted list of errors to the console.
func PrintErrors(errs []error) {
for i, e := range errs {
fmt.Printf("\t%d: %v\n", i, e)
}
}

47
lib/common/data/hash.go Normal file
View File

@ -0,0 +1,47 @@
package data
import (
"crypto/sha256"
"io"
)
/*
[I2P Hash]
Accurate for version 0.9.49
Description
Represents the SHA256 of some data.
Contents
32 bytes
[I2P Hash]:
*/
// Hash is the represenation of an I2P Hash.
//
// https://geti2p.net/spec/common-structures#hash
type Hash [32]byte
func (h Hash) Bytes() [32]byte {
return h
}
// HashData returns the SHA256 sum of a []byte input as Hash.
func HashData(data []byte) (h Hash) {
// log.Println("Hashing Data:", data)
h = sha256.Sum256(data)
return
}
// HashReader returns the SHA256 sum from all data read from an io.Reader.
// return error if one occurs while reading from reader
func HashReader(r io.Reader) (h Hash, err error) {
sha := sha256.New()
_, err = io.Copy(sha, r)
if err == nil {
d := sha.Sum(nil)
copy(h[:], d)
}
return
}

View File

@ -0,0 +1,78 @@
package data
import (
"encoding/binary"
)
// MAX_INTEGER_SIZE is the maximum length of an I2P integer in bytes.
const MAX_INTEGER_SIZE = 8
/*
[I2P Hash]
Accurate for version 0.9.49
Description
Represents a non-negative integer.
Contents
1 to 8 bytes in network byte order (big endian) representing an unsigned integer.
*/
// Integer is the represenation of an I2P Integer.
//
// https://geti2p.net/spec/common-structures#integer
type Integer []byte
// Bytes returns the raw []byte content of an Integer.
func (i Integer) Bytes() []byte {
return i[:]
}
// Int returns the Integer as a Go integer
func (i Integer) Int() int {
return intFromBytes(i.Bytes())
}
// Interpret a slice of bytes from length 0 to length 8 as a big-endian
// integer and return an int representation.
func intFromBytes(number []byte) (value int) {
numLen := len(number)
if numLen < MAX_INTEGER_SIZE {
paddedNumber := make([]byte, MAX_INTEGER_SIZE)
copy(paddedNumber[MAX_INTEGER_SIZE-numLen:], number)
number = paddedNumber
}
value = int(binary.BigEndian.Uint64(number))
return
}
// ReadInteger returns an Integer from a []byte of specified length.
// The remaining bytes after the specified length are also returned.
func ReadInteger(bytes []byte, size int) (Integer, []byte) {
if len(bytes) < size {
return bytes, nil
}
return bytes[:size], bytes[size:]
}
// NewInteger creates a new Integer from []byte using ReadInteger.
// Limits the length of the created Integer to MAX_INTEGER_SIZE.
// Returns a pointer to Integer unlike ReadInteger.
func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err error) {
i, remainder := ReadInteger(bytes, size)
integer = &i
return
}
// NewIntegerFromInt creates a new Integer from a Go integer of a specified []byte length.
func NewIntegerFromInt(value int, size int) (integer *Integer, err error) {
bytes := make([]byte, MAX_INTEGER_SIZE)
binary.BigEndian.PutUint64(bytes, uint64(value))
integerSize := MAX_INTEGER_SIZE
if size < MAX_INTEGER_SIZE {
integerSize = size
}
objinteger, _, err := NewInteger(bytes[MAX_INTEGER_SIZE-integerSize:], integerSize)
integer = objinteger
return
}

View File

@ -1,8 +1,9 @@
package common
package data
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestIntegerBigEndian(t *testing.T) {
@ -11,7 +12,7 @@ func TestIntegerBigEndian(t *testing.T) {
bytes := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
integer := Integer(bytes)
assert.Equal(integer, 1, "Integer() did not parse bytes big endian")
assert.Equal(integer.Int(), 1, "Integer() did not parse bytes big endian")
}
func TestWorksWithOneByte(t *testing.T) {
@ -19,7 +20,7 @@ func TestWorksWithOneByte(t *testing.T) {
integer := Integer([]byte{0x01})
assert.Equal(integer, 1, "Integer() did not correctly parse single byte slice")
assert.Equal(integer.Int(), 1, "Integer() did not correctly parse single byte slice")
}
func TestIsZeroWithNoData(t *testing.T) {
@ -27,5 +28,5 @@ func TestIsZeroWithNoData(t *testing.T) {
integer := Integer([]byte{})
assert.Equal(integer, 0, "Integer() did not correctly parse zero length byte slice")
assert.Equal(integer.Int(), 0, "Integer() did not correctly parse zero length byte slice")
}

260
lib/common/data/mapping.go Normal file
View File

@ -0,0 +1,260 @@
package data
import (
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
/*
[I2P Mapping]
Accurate for version 0.9.49
Description
A set of key/value mappings or properties
Contents
A 2-byte size Integer followed by a series of String=String; pairs
+----+----+----+----+----+----+----+----+
| size |key_string (len + data) | = |
+----+----+----+----+----+----+----+----+
| val_string (len + data) | ; | ...
+----+----+----+----+----+----+----+
size :: Integer
length -> 2 bytes
Total number of bytes that follow
key_string :: String
A string (one byte length followed by UTF-8 encoded characters)
= :: A single byte containing '='
val_string :: String
A string (one byte length followed by UTF-8 encoded characters)
; :: A single byte containing ';'
*/
// Mapping is the represenation of an I2P Mapping.
//
// https://geti2p.net/spec/common-structures#mapping
type Mapping struct {
size *Integer
vals *MappingValues
}
// Values returns the values contained in a Mapping as MappingValues.
func (mapping Mapping) Values() MappingValues {
if mapping.vals == nil {
log.Debug("Mapping values are nil, returning empty MappingValues")
return MappingValues{}
}
log.WithFields(logrus.Fields{
"values_count": len(*mapping.vals),
}).Debug("Retrieved Mapping values")
return *mapping.vals
}
// Data returns a Mapping in its []byte form.
func (mapping *Mapping) Data() []byte {
keyOrValIntegerLength := 1
bytes := mapping.size.Bytes()
for _, pair := range mapping.Values() {
klen, _ := pair[0].Length()
keylen, _ := NewIntegerFromInt(klen, keyOrValIntegerLength)
bytes = append(bytes, keylen.Bytes()...)
bytes = append(bytes, pair[0][1:]...)
bytes = append(bytes, 0x3d)
vlen, _ := pair[1].Length()
vallen, _ := NewIntegerFromInt(vlen, keyOrValIntegerLength)
bytes = append(bytes, vallen.Bytes()...)
bytes = append(bytes, pair[1][1:]...)
bytes = append(bytes, 0x3b)
}
return bytes
}
// HasDuplicateKeys returns true if two keys in a mapping are identical.
func (mapping *Mapping) HasDuplicateKeys() bool {
log.Debug("Checking for duplicate keys in Mapping")
seen_values := make(map[string]bool)
values := mapping.Values()
for _, pair := range values {
key, _ := pair[0].Data()
if _, present := seen_values[key]; present {
log.WithFields(logrus.Fields{
"duplicate_key": key,
}).Warn("Found duplicate key in Mapping")
return true
} else {
seen_values[key] = true
}
}
log.Debug("No duplicate keys found in Mapping")
return false
}
// GoMapToMapping converts a Go map of unformatted strings to *Mapping.
func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) {
log.WithFields(logrus.Fields{
"input_map_size": len(gomap),
}).Debug("Converting Go map to Mapping")
map_vals := MappingValues{}
for k, v := range gomap {
key_str, kerr := ToI2PString(k)
if kerr != nil {
log.WithError(kerr).Error("Failed to convert key to I2PString")
err = kerr
return
}
val_str, verr := ToI2PString(v)
if verr != nil {
log.WithError(verr).Error("Failed to convert value to I2PString")
err = verr
return
}
map_vals = append(
map_vals,
[2]I2PString{key_str, val_str},
)
}
mapping = ValuesToMapping(map_vals)
log.WithFields(logrus.Fields{
"mapping_size": len(map_vals),
}).Debug("Successfully converted Go map to Mapping")
return
}
// Check if the string parsing error indicates that the Mapping
// should no longer be parsed.
func stopValueRead(err error) bool {
result := err.Error() == "error parsing string: zero length"
if result {
log.WithError(err).Debug("Stopping value read due to zero length error")
}
return result
}
// Determine if the first byte in a slice of bytes is the provided byte.
func beginsWith(bytes []byte, chr byte) bool {
/*
return len(bytes) != 0 &&
bytes[0] == chr
*/
result := len(bytes) != 0 && bytes[0] == chr
log.WithFields(logrus.Fields{
"bytes_length": len(bytes),
"expected_char": string(chr),
"result": result,
}).Debug("Checked if bytes begin with specific character")
return result
}
// ReadMapping returns Mapping from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
log.WithFields(logrus.Fields{
"input_length": len(bytes),
}).Debug("Reading Mapping from bytes")
if len(bytes) < 3 {
log.WithFields(logrus.Fields{
"at": "ReadMapping",
"reason": "zero length",
}).Warn("mapping format violation")
e := oops.Errorf("zero length")
err = append(err, e)
return
}
size, remainder, e := NewInteger(bytes, 2)
if e != nil {
log.WithError(e).Error("Failed to read Mapping size")
err = append(err, e)
}
mapping.size = size
if size.Int() == 0 {
log.Warn("Mapping size is zero")
return
}
// Length Check
if len(remainder) < size.Int() {
log.WithFields(logrus.Fields{
"expected_size": size.Int(),
"actual_size": len(remainder),
}).Warn("mapping format violation: mapping length exceeds provided data")
e := oops.Errorf("warning parsing mapping: mapping length exceeds provided data")
err = append(err, e)
// Use whatever data is available (recovery)
map_bytes := remainder
remainder = nil
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *size)
err = append(err, mappingValueErrs...)
mapping.vals = vals
return
}
// Proceed normally if enough data is present
map_bytes := remainder[:size.Int()]
remainder = remainder[size.Int():]
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *size)
err = append(err, mappingValueErrs...)
mapping.vals = vals
if len(mappingValueErrs) > 0 {
log.WithFields(logrus.Fields{
"at": "ReadMapping",
"reason": "error parsing mapping values",
}).Warn("mapping format violation")
e := oops.Errorf("error parsing mapping values")
err = append(err, e)
}
if len(remainder) > 0 { // Handle extra bytes beyond mapping length
log.WithFields(logrus.Fields{
"expected_size": size.Int(),
"actual_size": len(remainder),
}).Error("mapping format violation: data exists beyond length of mapping")
e := oops.Errorf("warning parsing mapping: data exists beyond length of mapping")
err = append(err, e)
// Slice the exact mapping bytes
/* // Don't attempt recovery, can cause panics
map_bytes := remainder[:size.Int()]
remainder = remainder[size.Int():]
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *size)
err = append(err, mappingValueErrs...)
mapping.vals = vals
*/
return
}
log.WithFields(logrus.Fields{
"mapping_size": size.Int(),
"values_count": len(*mapping.vals),
"remainder_length": len(remainder),
"error_count": len(err),
}).Debug("Finished reading Mapping")
return
}
// NewMapping creates a new *Mapping from []byte using ReadMapping.
// Returns a pointer to Mapping unlike ReadMapping.
func NewMapping(bytes []byte) (values *Mapping, remainder []byte, err []error) {
log.WithFields(logrus.Fields{
"input_length": len(bytes),
}).Debug("Creating new Mapping")
objvalues, remainder, err := ReadMapping(bytes)
values = &objvalues
log.WithFields(logrus.Fields{
"values_count": len(values.Values()),
"remainder_length": len(remainder),
"error_count": len(err),
}).Debug("Finished creating new Mapping")
return
}

View File

@ -0,0 +1,192 @@
package data
import (
"bytes"
"testing"
"github.com/samber/oops"
"github.com/stretchr/testify/assert"
)
func TestValuesExclusesPairWithBadData(t *testing.T) {
assert := assert.New(t)
bad_key, _, errs := NewMapping([]byte{0x00, 0x0c, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x00})
values := bad_key.Values()
e := WrapErrors(errs)
t.Log(e)
assert.NotNil(errs, "Values() did not return errors when some values had bad key")
if assert.Equal(1, len(values), "Values() did not return valid values when some values had bad key") {
k := values[0][0]
key, _ := k.Data()
v := values[0][1]
val, _ := v.Data()
assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key")
assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key")
}
}
func TestValuesWarnsMissingData(t *testing.T) {
assert := assert.New(t)
_, _, errs := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62})
if assert.Equal(2, len(errs), "Values() reported wrong error count when mapping had missing data") {
assert.Equal(errs[0].Error(), "warning parsing mapping: mapping length exceeds provided data")
}
}
func TestValuesWarnsExtraData(t *testing.T) {
assert := assert.New(t)
mapping, _, errs := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x00})
values := mapping.Values()
key, kerr := values[0][0].Data()
val, verr := values[0][1].Data()
assert.Nil(kerr)
assert.Nil(verr)
assert.Equal(key, "a", "Values() did not return key in valid data")
assert.Equal(val, "b", "Values() did not return value in valid data")
if assert.Equal(1, len(errs), "Values() reported wrong error count when mapping had extra data") {
assert.Equal("warning parsing mapping: data exists beyond length of mapping", errs[0].Error(), "correct error message should be returned")
}
}
func TestValuesEnforcesEqualDelimitor(t *testing.T) {
assert := assert.New(t)
mapping, _, errs := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x30, 0x01, 0x62, 0x3b})
values := mapping.Values()
if assert.Equal(2, len(errs), "Values() reported wrong error count when mapping had = format error") {
assert.Equal("mapping format violation, expected =", errs[0].Error(), "correct error message should be returned")
}
assert.Equal(0, len(values), "Values() not empty with invalid data due to = format error")
}
func TestValuesEnforcedSemicolonDelimitor(t *testing.T) {
assert := assert.New(t)
mapping, _, errs := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x30})
values := mapping.Values()
if assert.Equal(2, len(errs), "Values() reported wrong error count when mapping had ; format error") {
assert.Equal("mapping format violation, expected ;", errs[0].Error(), "correct error message should be returned")
}
assert.Equal(0, len(values), "Values() not empty with invalid data due to ; format error")
}
func TestValuesReturnsValues(t *testing.T) {
assert := assert.New(t)
mapping, _, errs := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b})
values := mapping.Values()
key, kerr := values[0][0].Data()
val, verr := values[0][1].Data()
assert.Nil(errs, "Values() returned a errors with parsing valid data")
assert.Nil(kerr)
assert.Nil(verr)
assert.Equal("a", key, "Values() did not return key in valid data")
assert.Equal("b", val, "Values() did not return value in valid data")
}
func TestHasDuplicateKeysTrueWhenDuplicates(t *testing.T) {
assert := assert.New(t)
dups, _, _ := NewMapping([]byte{0x00, 0x0c, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b})
assert.Equal(true, dups.HasDuplicateKeys(), "HasDuplicateKeys() did not report true when duplicate keys present")
}
func TestHasDuplicateKeysFalseWithoutDuplicates(t *testing.T) {
assert := assert.New(t)
mapping, _, _ := NewMapping([]byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b})
assert.Equal(false, mapping.HasDuplicateKeys(), "HasDuplicateKeys() did not report false when no duplicate keys present")
}
func TestReadMappingHasDuplicateKeys(t *testing.T) {
assert := assert.New(t)
_, _, errs := NewMapping([]byte{0x00, 0x0c, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b})
assert.Equal("mapping format violation, duplicate key in mapping", errs[0].Error(), "ReadMapping should throw an error when duplicate keys are present.")
}
func TestGoMapToMappingProducesCorrectMapping(t *testing.T) {
assert := assert.New(t)
gomap := map[string]string{"a": "b"}
mapping, err := GoMapToMapping(gomap)
assert.Nil(err, "GoMapToMapping() returned error with valid data")
expected := []byte{0x00, 0x06, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b}
if bytes.Compare(mapping.Data(), expected) != 0 {
t.Fatal("GoMapToMapping did not produce correct Mapping", mapping, expected)
}
}
func TestFullGoMapToMappingProducesCorrectMapping(t *testing.T) {
assert := assert.New(t)
gomap := map[string]string{
"a": "b",
"c": "d",
}
mapping, err := GoMapToMapping(gomap)
assert.Nil(err, "GoMapToMapping() returned error with valid data")
expected := []byte{0x00, 0x0c, 0x01, 0x61, 0x3d, 0x01, 0x62, 0x3b, 0x01, 0x63, 0x3d, 0x01, 0x64, 0x3b}
if bytes.Compare(mapping.Data(), expected) != 0 {
t.Fatal("GoMapToMapping did not produce correct Mapping", mapping, expected)
}
}
func TestStopValueReadTrueWhenCorrectErr(t *testing.T) {
assert := assert.New(t)
status := stopValueRead(oops.Errorf("error parsing string: zero length"))
assert.Equal(true, status, "stopValueRead() did not return true when String error found")
}
func TestStopValueReadFalseWhenWrongErr(t *testing.T) {
assert := assert.New(t)
status := stopValueRead(oops.Errorf("something else"))
assert.Equal(false, status, "stopValueRead() did not return false when non String error found")
}
func TestBeginsWithCorrectWhenTrue(t *testing.T) {
assert := assert.New(t)
slice := []byte{0x41}
assert.Equal(true, beginsWith(slice, 0x41), "beginsWith() did not return true when correct")
}
func TestBeginsWithCorrectWhenFalse(t *testing.T) {
assert := assert.New(t)
slice := []byte{0x00}
assert.Equal(false, beginsWith(slice, 0x41), "beginsWith() did not false when incorrect")
}
func TestBeginsWithCorrectWhenNil(t *testing.T) {
assert := assert.New(t)
slice := make([]byte, 0)
assert.Equal(false, beginsWith(slice, 0x41), "beginsWith() did not return false on empty slice")
}

View File

@ -0,0 +1,224 @@
package data
import (
"sort"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
type MappingValues [][2]I2PString
func (m MappingValues) Get(key I2PString) I2PString {
keyBytes, _ := key.Data()
log.WithFields(logrus.Fields{
"key": string(keyBytes),
}).Debug("Searching for key in MappingValues")
for _, pair := range m {
kb, _ := pair[0][0:].Data()
if kb == keyBytes {
log.WithFields(logrus.Fields{
"key": string(keyBytes),
"value": string(pair[1][1:]),
}).Debug("Found matching key in MappingValues")
return pair[1]
}
}
log.WithFields(logrus.Fields{
"key": string(keyBytes),
}).Debug("Key not found in MappingValues")
return nil
}
// ValuesToMapping creates a *Mapping using MappingValues.
// The values are sorted in the order defined in mappingOrder.
func ValuesToMapping(values MappingValues) *Mapping {
mappingOrder(values)
// Default length to 2 * len
// 1 byte for ';'
// 1 byte for '='
log.WithFields(logrus.Fields{
"values_count": len(values),
}).Debug("Converting MappingValues to Mapping")
baseLength := 2 * len(values)
for _, mappingVals := range values {
for _, keyOrVal := range mappingVals {
baseLength += len(keyOrVal)
}
}
log.WithFields(logrus.Fields{
"mapping_size": baseLength,
}).Debug("Created Mapping from MappingValues")
mappingSize, _ := NewIntegerFromInt(baseLength, 2)
return &Mapping{
size: mappingSize,
vals: &values,
}
}
// I2P Mappings require consistent order in some cases for cryptographic signing, and sorting
// by keys. The Mapping is sorted lexographically by keys. Duplicate keys are allowed in general,
// but in implementations where they must be sorted like I2CP SessionConfig duplicate keys are not allowed.
// In practice routers do not seem to allow duplicate keys.
func mappingOrder(values MappingValues) {
sort.SliceStable(values, func(i, j int) bool {
// Lexographic sort on keys only
data1, _ := values[i][0].Data()
data2, _ := values[j][0].Data()
return data1 < data2
})
}
// ReadMappingValues returns *MappingValues from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
// mapping := remainder
// var remainder = mapping
// var err error
log.WithFields(logrus.Fields{
"input_length": len(remainder),
"map_length": map_length.Int(),
}).Debug("Reading MappingValues")
if remainder == nil || len(remainder) < 1 {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "data shorter than expected",
}).Error("mapping contained no data")
errs = []error{oops.Errorf("mapping contained no data")}
return
}
map_values := make(MappingValues, 0)
int_map_length := map_length.Int()
mapping_len := len(remainder)
if mapping_len > int_map_length {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"mapping_bytes_length": mapping_len,
"mapping_length_field": int_map_length,
"reason": "data longer than expected",
}).Warn("mapping format warning")
errs = append(errs, oops.Errorf("warning parsing mapping: data exists beyond length of mapping"))
} else if int_map_length > mapping_len {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"mapping_bytes_length": mapping_len,
"mapping_length_field": int_map_length,
"reason": "data shorter than expected",
}).Warn("mapping format warning")
errs = append(errs, oops.Errorf("warning parsing mapping: mapping length exceeds provided data"))
}
encounteredKeysMap := map[string]bool{}
// pop off length bytes before parsing kv pairs
// remainder = remainder[2:]
for {
// Read a key, breaking on fatal errors
// and appending warnings
// Minimum byte length required for another KV pair.
// Two bytes for each string length
// At least 1 byte per string
// One byte for =
// One byte for ;
if len(remainder) < 6 {
// Not returning an error here as the issue is already flagged by mapping length being wrong.
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "mapping format violation",
}).Warn("mapping format violation, too few bytes for a kv pair")
break
}
key_str, more, err := ReadI2PString(remainder)
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
// return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
// log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// Check if key has already been encountered in this mapping
keyBytes, _ := key_str.Data()
keyAsString := string(keyBytes)
_, ok := encounteredKeysMap[keyAsString]
if ok {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "duplicate key in mapping",
"key": string(key_str),
}).Error("mapping format violation")
log.Printf("DUPE: %s", key_str)
errs = append(errs, oops.Errorf("mapping format violation, duplicate key in mapping"))
// Based on other implementations this does not seem to happen often?
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
// i2pd as far as I can tell just overwrites the original value
// Continue on, we can check if the Mapping contains duplicate keys later.
}
if !beginsWith(remainder, 0x3d) {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "expected =",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, oops.Errorf("mapping format violation, expected ="))
log.Printf("ERRVAL: %s", remainder)
break
} else {
remainder = remainder[1:]
}
// Read a value, breaking on fatal errors
// and appending warnings
val_str, more, err := ReadI2PString(remainder)
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
// return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
// log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
if !beginsWith(remainder, 0x3b) {
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "expected ;",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, oops.Errorf("mapping format violation, expected ;"))
break
} else {
remainder = remainder[1:]
}
// Append the key-value pair and break if there is no more data to read
map_values = append(map_values, [2]I2PString{key_str, val_str})
if len(remainder) == 0 {
break
}
// Store the encountered key with arbitrary data
encounteredKeysMap[keyAsString] = true
}
values = &map_values
log.WithFields(logrus.Fields{
"values_count": len(map_values),
"remainder_length": len(remainder_bytes),
"error_count": len(errs),
}).Debug("Finished reading MappingValues")
return
}

View File

@ -0,0 +1,47 @@
package data
import (
"fmt"
"testing"
)
func TestMappingOrderSortsValuesThenKeys(t *testing.T) {
a, _ := ToI2PString("a")
b, _ := ToI2PString("b")
aa, _ := ToI2PString("aa")
ab, _ := ToI2PString("ab")
ac, _ := ToI2PString("ac")
values := MappingValues{
[2]I2PString{b, b},
[2]I2PString{ac, a},
[2]I2PString{ab, b},
[2]I2PString{aa, a},
[2]I2PString{a, a},
}
mappingOrder(values)
for i, pair := range values {
key, _ := pair[0].Data()
switch i {
case 0:
if !(key == "a") {
t.Fatal(fmt.Sprintf("mappingOrder expected key a, got %s at index", key), i)
}
case 1:
if !(key == "aa") {
t.Fatal(fmt.Sprintf("mappingOrder expected key aa, got %s at index", key), i)
}
case 2:
if !(key == "ab") {
t.Fatal(fmt.Sprintf("mappingOrder expected key ab, got %s at index", key), i)
}
case 3:
if !(key == "ac") {
t.Fatal(fmt.Sprintf("mappingOrder expected key ac, got %s at index", key), i)
}
case 4:
if !(key == "b") {
t.Fatal(fmt.Sprintf("mappingOrder expected key b, got %s at index", key), i)
}
}
}
}

191
lib/common/data/string.go Normal file
View File

@ -0,0 +1,191 @@
package data
import (
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
// STRING_MAX_SIZE is the maximum number of bytes that can be stored in an I2P string
const STRING_MAX_SIZE = 255
/*
[I2P String]
Accurate for version 0.9.49
Description
Represents a UTF-8 encoded string.
Contents
1 or more bytes where the first byte is the number of bytes (not characters!) in the string
and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array.
Length limit is 255 bytes (not characters). Length may be 0.
*/
// I2PString is the represenation of an I2P String.
//
// https://geti2p.net/spec/common-structures#string
type I2PString []byte
// Length returns the length specified in the first byte.
// Returns error if the specified does not match the actual length or the string is otherwise invalid.
func (str I2PString) Length() (length int, err error) {
if len(str) == 0 {
log.WithFields(logrus.Fields{
"at": "(I2PString) Length",
"reason": "no data",
}).Error("error parsing string")
err = ErrZeroLength
return
}
l, _, err := NewInteger(str[:], 1)
if err != nil {
log.WithError(err).Error("Failed to create Integer from I2PString")
return l.Int(), err
}
length = l.Int()
str_len := len(str)
if length > (str_len - 1) {
log.WithFields(logrus.Fields{
"at": "(I2PString) Length",
"string_bytes_length": str_len,
"string_length_field": length,
"reason": "data less than specified by length",
}).Warn("string format warning")
err = ErrDataTooShort
}
if (str_len - 1) > length {
log.WithFields(logrus.Fields{
"at": "(I2PString) Length",
"string_bytes_length": str_len,
"string_length_field": length,
"reason": "data contains extra bytes beyond specified length",
}).Warn("string format warning")
err = ErrDataTooLong
}
return
}
// Data returns the I2PString content as a string trimmed to the specified length and not including the length byte.
// Returns error encountered by Length.
func (str I2PString) Data() (data string, err error) {
length, err := str.Length()
if err != nil {
switch err {
case ErrZeroLength:
log.WithError(err).Warn("Zero length I2PString")
return "", err
case ErrDataTooShort:
log.WithError(err).Warn("I2PString data shorter than specified length")
/*
if is, e := ToI2PString(string(str[:])); e != nil {
log.WithError(e).Error("Failed to convert short I2PString")
return "", e
} else {
return is.Data()
}
*/ //Recovery attempt
return "", err
case ErrDataTooLong:
log.WithError(err).Warn("I2PString contains data beyond specified length")
data = string(str[1:])
// data = string(str[1 : length+1]) // Should we recover and trim?
return
default:
log.WithError(err).Error("Unknown error encountered in I2PString.Data()")
return "", err
}
}
if length == 0 {
log.Debug("I2PString is empty")
return "", nil
}
data = string(str[1 : length+1])
log.WithFields(logrus.Fields{
"data_length": len(data),
}).Debug("Retrieved I2PString data")
return data, nil
}
// ToI2PString converts a Go string to an I2PString.
// Returns error if the string exceeds STRING_MAX_SIZE.
func ToI2PString(data string) (str I2PString, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Converting string to I2PString")
data_len := len(data)
if data_len > STRING_MAX_SIZE {
log.WithFields(logrus.Fields{
"at": "ToI2PI2PString",
"string_len": data_len,
"max_len": STRING_MAX_SIZE,
"reason": "too much data",
}).Error("cannot create I2P string")
err = oops.Errorf("cannot store that much data in I2P string")
return
}
i2p_string := []byte{byte(data_len)}
i2p_string = append(i2p_string, []byte(data)...)
str = I2PString(i2p_string)
log.WithFields(logrus.Fields{
"i2pstring_length": len(str),
}).Debug("Successfully converted string to I2PString")
return
}
//
// Read a string from a slice of bytes, returning any extra data on the end
// of the slice and any errors encountered parsing the I2PString.
//
// ReadI2PString returns I2PString from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
if len(data) == 0 {
err = ErrZeroLength
log.WithError(err).Error("Passed data with len == 0")
return
}
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Reading I2PString from bytes")
length, _, err := NewInteger(data, 1)
if err != nil {
log.WithError(err).Error("Failed to read I2PString length")
return
}
data_len := length.Int() + 1
if data_len > len(data) {
log.Errorf("I2PString length %d exceeds available data %d", data_len-1, len(data)-1)
err = ErrDataTooShort
log.WithError(err).Error("Failed to read I2PString")
return
}
str = data[:data_len]
remainder = data[data_len:]
l, err := str.Length()
if l != data_len-1 {
err = ErrLengthMismatch
log.WithFields(logrus.Fields{
"expected_length": data_len - 1,
"actual_length": l,
}).Error("I2PString length mismatch")
return
}
log.WithFields(logrus.Fields{
"string_length": l,
"remainder_length": len(remainder),
}).Debug("Successfully read I2PString from bytes")
return
}
// NewI2PString creates a new *I2PString from []byte using ReadI2PString.
// Returns a pointer to I2PString unlike ReadI2PString.
/*func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
objstr, remainder, err := ReadI2PString(data)
str = &objstr
return
}*/

View File

@ -1,23 +1,24 @@
package common
package data
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestStringReportsCorrectLength(t *testing.T) {
assert := assert.New(t)
str_len, err := String([]byte{0x02, 0x00, 0x00}).Length()
str_len, err := I2PString([]byte{0x02, 0x00, 0x00}).Length()
assert.Equal(str_len, 2, "Length() did not report correct length")
assert.Nil(err, "Length() reported an error on valid string")
}
func TestStringReportsLengthZeroError(t *testing.T) {
func TestI2PStringReportsLengthZeroError(t *testing.T) {
assert := assert.New(t)
str_len, err := String(make([]byte, 0)).Length()
str_len, err := I2PString(make([]byte, 0)).Length()
assert.Equal(str_len, 0, "Length() reported non-zero length on empty slice")
if assert.NotNil(err) {
@ -25,10 +26,10 @@ func TestStringReportsLengthZeroError(t *testing.T) {
}
}
func TestStringReportsExtraDataError(t *testing.T) {
func TestI2PStringReportsExtraDataError(t *testing.T) {
assert := assert.New(t)
str_len, err := String([]byte{0x01, 0x00, 0x00}).Length()
str_len, err := I2PString([]byte{0x01, 0x00, 0x00}).Length()
assert.Equal(str_len, 1, "Length() reported wrong size when extra data present")
if assert.NotNil(err) {
@ -36,10 +37,10 @@ func TestStringReportsExtraDataError(t *testing.T) {
}
}
func TestStringDataReportsLengthZeroError(t *testing.T) {
func TestI2PStringDataReportsLengthZeroError(t *testing.T) {
assert := assert.New(t)
str_len, err := String([]byte{0x01}).Length()
str_len, err := I2PString([]byte{0x01}).Length()
assert.Equal(str_len, 1, "Length() reported wrong size with missing data")
if assert.NotNil(err) {
@ -47,22 +48,22 @@ func TestStringDataReportsLengthZeroError(t *testing.T) {
}
}
func TestStringDataReportsExtraDataError(t *testing.T) {
func TestI2PStringDataReportsExtraDataError(t *testing.T) {
assert := assert.New(t)
data, err := String([]byte{0x01, 0x00, 0x01}).Data()
data, err := I2PString([]byte{0x01, 0x00, 0x01}).Data()
data_len := len(data)
assert.Equal(data_len, 1, "Data() reported wrong size on string with extra data")
assert.Equal(data_len, 2, "Data() reported wrong size on string with extra data")
if assert.NotNil(err) {
assert.Equal(err.Error(), "string parsing warning: string contains data beyond length", "correct error message should be returned")
}
}
func TestStringDataEmptyWhenZeroLength(t *testing.T) {
func TestI2PStringDataEmptyWhenZeroLength(t *testing.T) {
assert := assert.New(t)
data, err := String(make([]byte, 0)).Data()
data, err := I2PString(make([]byte, 0)).Data()
assert.Equal(len(data), 0, "Data() returned data when none was present:")
if assert.NotNil(err) {
@ -70,10 +71,10 @@ func TestStringDataEmptyWhenZeroLength(t *testing.T) {
}
}
func TestStringDataErrorWhenNonZeroLengthOnly(t *testing.T) {
func TestI2PStringDataErrorWhenNonZeroLengthOnly(t *testing.T) {
assert := assert.New(t)
data, err := String([]byte{0x01}).Data()
data, err := I2PString([]byte{0x01}).Data()
assert.Equal(len(data), 0, "Data() returned data when only length was present")
if assert.NotNil(err) {
@ -81,7 +82,7 @@ func TestStringDataErrorWhenNonZeroLengthOnly(t *testing.T) {
}
}
func TestToI2PStringFormatsCorrectly(t *testing.T) {
func TestToI2PI2PStringFormatsCorrectly(t *testing.T) {
assert := assert.New(t)
i2p_string, err := ToI2PString(string([]byte{0x08, 0x09}))
@ -111,38 +112,42 @@ func TestReadStringReadsLength(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x01, 0x04, 0x06}
str, remainder, err := ReadString(bytes)
str, remainder, err := ReadI2PString(bytes)
assert.Nil(err, "ReadString() returned error reading string with extra data")
assert.Equal(len(str), 2, "ReadString() did not return correct string length")
assert.Equal(1, int(str[0]), "ReadString() did not return correct string")
assert.Equal(4, int(str[1]), "ReadString() did not return correct string")
assert.Equal(len(remainder), 1, "ReadString() did not return correct remainder length")
assert.Equal(6, int(remainder[0]), "ReadString() did not return correct remainder")
assert.Nil(err, "ReadI2PString() returned error reading string with extra data")
assert.Equal(len(str), 2, "ReadI2PString() did not return correct string length")
assert.Equal(1, int(str[0]), "ReadI2PString() did not return correct string")
assert.Equal(4, int(str[1]), "ReadI2PString() did not return correct string")
assert.Equal(len(remainder), 1, "ReadI2PString() did not return correct remainder length")
assert.Equal(6, int(remainder[0]), "ReadI2PString() did not return correct remainder")
}
func TestReadStringErrWhenEmptySlice(t *testing.T) {
func TestReadI2PStringErrWhenEmptySlice(t *testing.T) {
assert := assert.New(t)
bytes := make([]byte, 0)
_, _, err := ReadString(bytes)
_, _, err := ReadI2PString(bytes)
if assert.NotNil(err) {
assert.Equal(err.Error(), "error parsing string: zero length", "correct error message should be returned")
assert.Equal(err.Error(), ErrZeroLength.Error(), "correct error message should be returned")
}
}
func TestReadStringErrWhenDataTooShort(t *testing.T) {
func TestReadI2PStringErrWhenDataTooShort(t *testing.T) {
assert := assert.New(t)
short_str := []byte{0x03, 0x01}
str, remainder, err := ReadString(short_str)
str, remainder, err := ReadI2PString(short_str)
if assert.NotNil(err) {
assert.Equal(err.Error(), "string parsing warning: string data is shorter than specified by length", "correct error message should be returned")
assert.Equal(err.Error(), ErrDataTooShort.Error(), "correct error message should be returned")
}
assert.Equal(len(str), 2, "ReadString() did not return the slice as string when too long")
assert.Equal(3, int(str[0]), "ReadString() did not return the correct partial string")
assert.Equal(1, int(str[1]), "ReadString() did not return the correct partial string")
assert.Equal(len(remainder), 0, "ReadString() returned a remainder when the string data was too short")
/*
assert.Equal(len(str), 2, "ReadI2PString() did not return the slice as string when too long")
assert.Equal(3, int(str[0]), "ReadI2PString() did not return the correct partial string")
assert.Equal(1, int(str[1]), "ReadI2PString() did not return the correct partial string")
assert.Equal(len(remainder), 0, "ReadI2PString() returned a remainder when the string data was too short")
*/
assert.Equal(len(str), 0, "ReadI2PString() should not return any data when data is too short")
assert.Equal(len(remainder), 0, "ReadI2PString() should not return any remainder when data is too short")
}

View File

@ -1,24 +0,0 @@
package common
/*
I2P Date
https://geti2p.net/spec/common-structures#date
Accurate for version 0.9.24
*/
import (
"time"
)
type Date [8]byte
//
// Time takes the value stored in date as an 8 byte big-endian integer representing the
// number of milliseconds since the beginning of unix time and converts it to a Go time.Time
// struct.
//
func (date Date) Time() (date_time time.Time) {
seconds := Integer(date[:])
date_time = time.Unix(0, int64(seconds*1000000))
return
}

View File

@ -1,57 +0,0 @@
package common
/*
I2P Destination
https://geti2p.net/spec/common-structures#destination
Accurate for version 0.9.24
Identical to KeysAndCert
*/
import (
"github.com/go-i2p/go-i2p/lib/common/base32"
"github.com/go-i2p/go-i2p/lib/common/base64"
"github.com/go-i2p/go-i2p/lib/crypto"
"strings"
)
//
// A Destination is a KeysAndCert with functionallity
// for generating base32 and base64 addresses.
//
type Destination []byte
func (destination Destination) PublicKey() (crypto.PublicKey, error) {
return KeysAndCert(destination).PublicKey()
}
func (destination Destination) SigningPublicKey() (crypto.SigningPublicKey, error) {
return KeysAndCert(destination).SigningPublicKey()
}
func (destination Destination) Certificate() (Certificate, error) {
return KeysAndCert(destination).Certificate()
}
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
keys_and_cert, remainder, err := ReadKeysAndCert(data)
destination = Destination(keys_and_cert)
return
}
//
// Generate the I2P base32 address for this Destination.
//
func (destination Destination) Base32Address() (str string) {
hash := crypto.SHA256(destination)
str = strings.Trim(base32.EncodeToString(hash[:]), "=")
str = str + ".b32.i2p"
return
}
//
// Generate the I2P base64 address for this Destination.
//
func (destination Destination) Base64() string {
return base64.EncodeToString(destination)
}

View File

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

View File

@ -0,0 +1,87 @@
// Package destination implements the I2P Destination common data structure
package destination
import (
"strings"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
"github.com/go-i2p/go-i2p/lib/common/base32"
"github.com/go-i2p/go-i2p/lib/common/base64"
"github.com/go-i2p/go-i2p/lib/crypto"
)
var log = logger.GetGoI2PLogger()
/*
[Destination]
Accurate for version 0.9.49
Description
A Destination defines a particular endpoint to which messages can be directed for secure delivery.
Contents
Identical to KeysAndCert.
*/
// Destination is the represenation of an I2P Destination.
//
// https://geti2p.net/spec/common-structures#destination
type Destination struct {
*KeysAndCert
}
// Base32Address returns the I2P base32 address for this Destination.
func (destination Destination) Base32Address() (str string) {
log.Debug("Generating Base32 address for Destination")
cert := destination.KeysAndCert.Certificate()
dest := cert.Bytes()
hash := crypto.SHA256(dest)
str = strings.Trim(base32.EncodeToString(hash[:]), "=")
str = str + ".b32.i2p"
log.WithFields(logrus.Fields{
"base32_address": str,
}).Debug("Generated Base32 address for Destination")
return
}
// Base64 returns the I2P base64 address for this Destination.
func (destination Destination) Base64() string {
log.Debug("Generating Base64 address for Destination")
cert := destination.KeysAndCert.Certificate()
dest := cert.Bytes()
base64Address := base64.EncodeToString(dest)
log.WithFields(logrus.Fields{
"base64_address_length": len(base64Address),
}).Debug("Generated Base64 address for Destination")
return base64Address
}
// ReadDestination returns Destination from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Reading Destination from bytes")
keys_and_cert, remainder, err := ReadKeysAndCert(data)
destination = Destination{
keys_and_cert,
}
log.WithFields(logrus.Fields{
"remainder_length": len(remainder),
}).Debug("Successfully read Destination from bytes")
return
}

View File

@ -0,0 +1,300 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="357pt" height="609pt"
viewBox="0.00 0.00 356.94 609.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 609)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-609 356.9356,-609 356.9356,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-601 348.9356,-601 348.9356,-8 8,-8"/>
<text text-anchor="middle" x="178.4678" y="-580.8" font-family="Arial" font-size="18.00" fill="#000000">destination</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination</title>
<g id="a_clust6"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M28,-295C28,-295 131.0814,-295 131.0814,-295 137.0814,-295 143.0814,-301 143.0814,-307 143.0814,-307 143.0814,-422 143.0814,-422 143.0814,-428 137.0814,-434 131.0814,-434 131.0814,-434 28,-434 28,-434 22,-434 16,-428 16,-422 16,-422 16,-307 16,-307 16,-301 22,-295 28,-295"/>
<text text-anchor="middle" x="79.5407" y="-303.5" font-family="Arial" font-size="15.00" fill="#222222">(Destination)</text>
</a>
</g>
</g>
<g id="clust5" class="cluster">
<title>cluster_*github.com/sirupsen/logrus.Logger</title>
<g id="a_clust5"><a xlink:title="type: *github.com/sirupsen/logrus.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M249.4047,-121C249.4047,-121 303.7259,-121 303.7259,-121 309.7259,-121 315.7259,-127 315.7259,-133 315.7259,-133 315.7259,-187 315.7259,-187 315.7259,-193 309.7259,-199 303.7259,-199 303.7259,-199 249.4047,-199 249.4047,-199 243.4047,-199 237.4047,-193 237.4047,-187 237.4047,-187 237.4047,-133 237.4047,-133 237.4047,-127 243.4047,-121 249.4047,-121"/>
<text text-anchor="middle" x="276.5653" y="-129.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust4" class="cluster">
<title>cluster_*github.com/go&#45;i2p/logger.Logger</title>
<g id="a_clust4"><a xlink:title="type: *github.com/go&#45;i2p/logger.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M236.9559,-260C236.9559,-260 315.1747,-260 315.1747,-260 321.1747,-260 327.1747,-266 327.1747,-272 327.1747,-272 327.1747,-326 327.1747,-326 327.1747,-332 321.1747,-338 315.1747,-338 315.1747,-338 236.9559,-338 236.9559,-338 230.9559,-338 224.9559,-332 224.9559,-326 224.9559,-326 224.9559,-272 224.9559,-272 224.9559,-266 230.9559,-260 236.9559,-260"/>
<text text-anchor="middle" x="276.0653" y="-268.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust3" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert</title>
<g id="a_clust3"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M227.6382,-432C227.6382,-432 324.4924,-432 324.4924,-432 330.4924,-432 336.4924,-438 336.4924,-444 336.4924,-444 336.4924,-498 336.4924,-498 336.4924,-504 330.4924,-510 324.4924,-510 324.4924,-510 227.6382,-510 227.6382,-510 221.6382,-510 215.6382,-504 215.6382,-498 215.6382,-498 215.6382,-444 215.6382,-444 215.6382,-438 221.6382,-432 227.6382,-432"/>
<text text-anchor="middle" x="276.0653" y="-440.5" font-family="Arial" font-size="15.00" fill="#222222">(*KeysAndCert)</text>
</a>
</g>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M239.087,-346C239.087,-346 314.0436,-346 314.0436,-346 320.0436,-346 326.0436,-352 326.0436,-358 326.0436,-358 326.0436,-412 326.0436,-412 326.0436,-418 320.0436,-424 314.0436,-424 314.0436,-424 239.087,-424 239.087,-424 233.087,-424 227.087,-418 227.087,-412 227.087,-412 227.087,-358 227.087,-358 227.087,-352 233.087,-346 239.087,-346"/>
<text text-anchor="middle" x="276.5653" y="-354.5" font-family="Arial" font-size="15.00" fill="#222222">(*Certificate)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination | defined in destination.go:72&#10;at destination.go:77: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert]&#10;at destination.go:75: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:84: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:73: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at destination.go:82: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M126.3497,-191C126.3497,-191 32.7317,-191 32.7317,-191 26.7317,-191 20.7317,-185 20.7317,-179 20.7317,-179 20.7317,-167 20.7317,-167 20.7317,-161 26.7317,-155 32.7317,-155 32.7317,-155 126.3497,-155 126.3497,-155 132.3497,-155 138.3497,-161 138.3497,-167 138.3497,-167 138.3497,-179 138.3497,-179 138.3497,-185 132.3497,-191 126.3497,-191"/>
<text text-anchor="middle" x="79.5407" y="-168.8" font-family="Verdana" font-size="14.00" fill="#000000">ReadDestination</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert | defined in keys_and_cert.go:142">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M328.8062,-113C328.8062,-113 223.3244,-113 223.3244,-113 217.3244,-113 211.3244,-107 211.3244,-101 211.3244,-101 211.3244,-89 211.3244,-89 211.3244,-83 217.3244,-77 223.3244,-77 223.3244,-77 328.8062,-77 328.8062,-77 334.8062,-77 340.8062,-83 340.8062,-89 340.8062,-89 340.8062,-101 340.8062,-101 340.8062,-107 334.8062,-113 328.8062,-113"/>
<text text-anchor="middle" x="276.0653" y="-99.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="276.0653" y="-82.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadKeysAndCert</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_edge1"><a xlink:title="at destination.go:77: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert]">
<path fill="none" stroke="#8b4513" d="M119.8466,-154.9251C145.7433,-143.5438 180.215,-128.8228 211.195,-117 211.5179,-116.8768 211.8418,-116.7535 212.1667,-116.6302"/>
<polygon fill="#8b4513" stroke="#8b4513" points="213.6372,-119.8181 221.8003,-113.0642 211.2071,-113.2534 213.6372,-119.8181"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="node9" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_node9"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithFields | defined in log.go:60">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M307.2844,-330C307.2844,-330 244.8462,-330 244.8462,-330 238.8462,-330 232.8462,-324 232.8462,-318 232.8462,-318 232.8462,-306 232.8462,-306 232.8462,-300 238.8462,-294 244.8462,-294 244.8462,-294 307.2844,-294 307.2844,-294 313.2844,-294 319.2844,-300 319.2844,-306 319.2844,-306 319.2844,-318 319.2844,-318 319.2844,-324 313.2844,-330 307.2844,-330"/>
<text text-anchor="middle" x="276.0653" y="-316.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="276.0653" y="-299.4" font-family="Verdana" font-size="14.00" fill="#000000">WithFields</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge13" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge13"><a xlink:title="at destination.go:73: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at destination.go:82: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M95.6552,-191.3454C118.8737,-216.761 164.144,-262.6371 211.195,-290 215.0581,-292.2466 219.1849,-294.3077 223.4146,-296.1894"/>
<polygon fill="#8b4513" stroke="#8b4513" points="222.196,-299.4724 232.7765,-300.0243 224.8495,-292.9948 222.196,-299.4724"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Debug -->
<g id="node10" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_node10"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Debug | defined in logger.go:221">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M294.8873,-191C294.8873,-191 257.2433,-191 257.2433,-191 251.2433,-191 245.2433,-185 245.2433,-179 245.2433,-179 245.2433,-167 245.2433,-167 245.2433,-161 251.2433,-155 257.2433,-155 257.2433,-155 294.8873,-155 294.8873,-155 300.8873,-155 306.8873,-161 306.8873,-167 306.8873,-167 306.8873,-179 306.8873,-179 306.8873,-185 300.8873,-191 294.8873,-191"/>
<text text-anchor="middle" x="276.0653" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="276.0653" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">Debug</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge4"><a xlink:title="at destination.go:75: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:84: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M138.2384,-173C169.429,-173 207.0043,-173 235.0381,-173"/>
<polygon fill="#8b4513" stroke="#8b4513" points="235.282,-176.5001 245.282,-173 235.2819,-169.5001 235.282,-176.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init | defined in .:0&#10;at destination.go:17: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M94.5407,-52C94.5407,-52 64.5407,-52 64.5407,-52 58.5407,-52 52.5407,-46 52.5407,-40 52.5407,-40 52.5407,-28 52.5407,-28 52.5407,-22 58.5407,-16 64.5407,-16 64.5407,-16 94.5407,-16 94.5407,-16 100.5407,-16 106.5407,-22 106.5407,-28 106.5407,-28 106.5407,-40 106.5407,-40 106.5407,-46 100.5407,-52 94.5407,-52"/>
<text text-anchor="middle" x="79.5407" y="-29.8" font-family="Verdana" font-size="14.00" fill="#000000">init</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="node4" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node4"><a xlink:title="github.com/go&#45;i2p/logger.GetGoI2PLogger | defined in log.go:120">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M324.7548,-52C324.7548,-52 227.3758,-52 227.3758,-52 221.3758,-52 215.3758,-46 215.3758,-40 215.3758,-40 215.3758,-28 215.3758,-28 215.3758,-22 221.3758,-16 227.3758,-16 227.3758,-16 324.7548,-16 324.7548,-16 330.7548,-16 336.7548,-22 336.7548,-28 336.7548,-28 336.7548,-40 336.7548,-40 336.7548,-46 330.7548,-52 324.7548,-52"/>
<text text-anchor="middle" x="276.0653" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="276.0653" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">GetGoI2PLogger</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge14" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge14"><a xlink:title="at destination.go:17: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M106.8666,-34C132.1954,-34 170.9888,-34 205.043,-34"/>
<polygon fill="#8b4513" stroke="#8b4513" points="205.4392,-37.5001 215.4392,-34 205.4392,-30.5001 205.4392,-37.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString</title>
<g id="a_node5"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString | defined in base32.go:16">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M321.8244,-563C321.8244,-563 230.3062,-563 230.3062,-563 224.3062,-563 218.3062,-557 218.3062,-551 218.3062,-551 218.3062,-539 218.3062,-539 218.3062,-533 224.3062,-527 230.3062,-527 230.3062,-527 321.8244,-527 321.8244,-527 327.8244,-527 333.8244,-533 333.8244,-539 333.8244,-539 333.8244,-551 333.8244,-551 333.8244,-557 327.8244,-563 321.8244,-563"/>
<text text-anchor="middle" x="276.0653" y="-549.2" font-family="Verdana" font-size="14.00" fill="#000000">base32</text>
<text text-anchor="middle" x="276.0653" y="-532.4" font-family="Verdana" font-size="14.00" fill="#000000">EncodeToString</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString | defined in base64.go:16">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M321.8244,-252C321.8244,-252 230.3062,-252 230.3062,-252 224.3062,-252 218.3062,-246 218.3062,-240 218.3062,-240 218.3062,-228 218.3062,-228 218.3062,-222 224.3062,-216 230.3062,-216 230.3062,-216 321.8244,-216 321.8244,-216 327.8244,-216 333.8244,-222 333.8244,-228 333.8244,-228 333.8244,-240 333.8244,-240 333.8244,-246 327.8244,-252 321.8244,-252"/>
<text text-anchor="middle" x="276.0653" y="-238.2" font-family="Verdana" font-size="14.00" fill="#000000">base64</text>
<text text-anchor="middle" x="276.0653" y="-221.4" font-family="Verdana" font-size="14.00" fill="#000000">EncodeToString</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="node7" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_node7"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes | defined in certificate.go:100">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M304.0219,-416C304.0219,-416 248.1087,-416 248.1087,-416 242.1087,-416 236.1087,-410 236.1087,-404 236.1087,-404 236.1087,-392 236.1087,-392 236.1087,-386 242.1087,-380 248.1087,-380 248.1087,-380 304.0219,-380 304.0219,-380 310.0219,-380 316.0219,-386 316.0219,-392 316.0219,-392 316.0219,-404 316.0219,-404 316.0219,-410 310.0219,-416 304.0219,-416"/>
<text text-anchor="middle" x="276.0653" y="-402.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="276.0653" y="-385.4" font-family="Verdana" font-size="14.00" fill="#000000">Bytes</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="node8" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_node8"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate | defined in keys_and_cert.go:136">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M316.4196,-502C316.4196,-502 235.711,-502 235.711,-502 229.711,-502 223.711,-496 223.711,-490 223.711,-490 223.711,-478 223.711,-478 223.711,-472 229.711,-466 235.711,-466 235.711,-466 316.4196,-466 316.4196,-466 322.4196,-466 328.4196,-472 328.4196,-478 328.4196,-478 328.4196,-490 328.4196,-490 328.4196,-496 322.4196,-502 316.4196,-502"/>
<text text-anchor="middle" x="276.0653" y="-488.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="276.0653" y="-471.4" font-family="Verdana" font-size="14.00" fill="#000000">Certificate</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address -->
<g id="node11" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address</title>
<g id="a_node11"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address | defined in destination.go:38&#10;at destination.go:42: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at destination.go:41: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]&#10;at destination.go:39: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:49: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:44: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString]&#10;at destination.go:47: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M123.1221,-426C123.1221,-426 35.9593,-426 35.9593,-426 29.9593,-426 23.9593,-420 23.9593,-414 23.9593,-414 23.9593,-402 23.9593,-402 23.9593,-396 29.9593,-390 35.9593,-390 35.9593,-390 123.1221,-390 123.1221,-390 129.1221,-390 135.1221,-396 135.1221,-402 135.1221,-402 135.1221,-414 135.1221,-414 135.1221,-420 129.1221,-426 123.1221,-426"/>
<text text-anchor="middle" x="79.5407" y="-403.8" font-family="Verdana" font-size="14.00" fill="#000000">Base32Address</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString -->
<g id="edge9" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString</title>
<g id="a_edge9"><a xlink:title="at destination.go:44: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString]">
<path fill="none" stroke="#8b4513" d="M98.3658,-426.2155C122.8623,-449.2395 167.6924,-489.1061 211.195,-516 214.7364,-518.1894 218.4716,-520.3055 222.2878,-522.3296"/>
<polygon fill="#8b4513" stroke="#8b4513" points="220.7827,-525.4905 231.2865,-526.8769 223.9399,-519.2429 220.7827,-525.4905"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="edge2" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_edge2"><a xlink:title="at destination.go:42: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="none" stroke="#8b4513" d="M135.3003,-423.7554C148.355,-425.819 162.2348,-426.7045 175.195,-425 192.0147,-422.7879 210.016,-418.5853 226.0877,-414.143"/>
<polygon fill="#8b4513" stroke="#8b4513" points="227.1646,-417.4754 235.8175,-411.3617 225.2406,-410.745 227.1646,-417.4754"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="edge5" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_edge5"><a xlink:title="at destination.go:41: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="none" stroke="#8b4513" d="M126.1143,-426.0109C154.2801,-436.9032 190.3668,-450.8587 220.0806,-462.3496"/>
<polygon fill="#8b4513" stroke="#8b4513" points="218.8966,-465.6443 229.4859,-465.9868 221.4214,-459.1155 218.8966,-465.6443"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge10" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge10"><a xlink:title="at destination.go:47: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M135.4607,-410.5532C149.2676,-408.9965 163.4512,-405.3584 175.195,-398 200.9047,-381.8908 188.214,-359.8083 211.195,-340 215.0451,-336.6814 219.3484,-333.7036 223.8574,-331.0431"/>
<polygon fill="#8b4513" stroke="#8b4513" points="225.5446,-334.1099 232.7168,-326.3118 222.247,-327.9353 225.5446,-334.1099"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge8" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge8"><a xlink:title="at destination.go:39: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:49: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M128.4239,-389.9118C133.8188,-386.5287 138.8725,-382.5818 143.0814,-378 201.7913,-314.0883 148.9351,-255.4587 211.195,-195 217.9616,-188.4291 226.762,-183.8181 235.6865,-180.5832"/>
<polygon fill="#8b4513" stroke="#8b4513" points="236.8188,-183.8965 245.3289,-177.5856 234.7406,-177.2121 236.8188,-183.8965"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64 -->
<g id="node12" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64</title>
<g id="a_node12"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64 | defined in destination.go:55&#10;at destination.go:59: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at destination.go:58: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]&#10;at destination.go:60: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString]&#10;at destination.go:56: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:64: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:62: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M100.2514,-365C100.2514,-365 58.83,-365 58.83,-365 52.83,-365 46.83,-359 46.83,-353 46.83,-353 46.83,-341 46.83,-341 46.83,-335 52.83,-329 58.83,-329 58.83,-329 100.2514,-329 100.2514,-329 106.2514,-329 112.2514,-335 112.2514,-341 112.2514,-341 112.2514,-353 112.2514,-353 112.2514,-359 106.2514,-365 100.2514,-365"/>
<text text-anchor="middle" x="79.5407" y="-342.8" font-family="Verdana" font-size="14.00" fill="#000000">Base64</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString -->
<g id="edge7" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString</title>
<g id="a_edge7"><a xlink:title="at destination.go:60: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString]">
<path fill="none" stroke="#8b4513" d="M112.1939,-338.8592C122.5317,-335.4699 133.7005,-330.9153 143.0814,-325 176.9686,-303.632 175.1512,-282.1226 209.631,-257.6621"/>
<polygon fill="#8b4513" stroke="#8b4513" points="211.6947,-260.4935 218.1081,-252.0603 207.8355,-254.6534 211.6947,-260.4935"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="edge3" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_edge3"><a xlink:title="at destination.go:59: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="none" stroke="#8b4513" d="M112.2576,-348.1387C130.9214,-349.3528 154.6235,-351.8541 175.195,-357 193.2842,-361.5249 212.4093,-368.65 229.0864,-375.6996"/>
<polygon fill="#8b4513" stroke="#8b4513" points="228.0292,-379.056 238.5963,-379.8214 230.8129,-372.6333 228.0292,-379.056"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="edge6" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_edge6"><a xlink:title="at destination.go:58: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="none" stroke="#8b4513" d="M112.2798,-361.284C122.4063,-366.1451 133.4308,-371.9033 143.0814,-378 163.9636,-391.1922 214.3577,-432.4214 246.7655,-459.4025"/>
<polygon fill="#8b4513" stroke="#8b4513" points="244.6676,-462.2104 254.5883,-465.9293 249.1521,-456.8354 244.6676,-462.2104"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge12" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge12"><a xlink:title="at destination.go:62: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M112.3907,-341.0766C130.5996,-337.7992 153.6485,-333.6603 174.195,-330 190.0047,-327.1835 207.1979,-324.1387 222.8796,-321.3685"/>
<polygon fill="#8b4513" stroke="#8b4513" points="223.6975,-324.7783 232.9366,-319.5929 222.4804,-317.8849 223.6975,-324.7783"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge11" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge11"><a xlink:title="at destination.go:56: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:64: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M112.3191,-341.1468C123.1386,-337.8792 134.5697,-332.8178 143.0814,-325 168.1559,-301.9697 158.3099,-285.1129 174.195,-255 188.8126,-227.2898 186.6888,-214.5186 211.195,-195 218.2916,-189.3477 226.9195,-185.1105 235.5357,-181.9469"/>
<polygon fill="#8b4513" stroke="#8b4513" points="236.7484,-185.2331 245.1766,-178.8131 234.5844,-178.5759 236.7484,-185.2331"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

View File

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

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="272pt" height="306pt"
viewBox="0.00 0.00 271.84 306.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 306)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-306 271.8444,-306 271.8444,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-298 263.8444,-298 263.8444,-8 8,-8"/>
<text text-anchor="middle" x="135.9222" y="-277.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M162.9439,-60C162.9439,-60 237.9005,-60 237.9005,-60 243.9005,-60 249.9005,-66 249.9005,-72 249.9005,-72 249.9005,-248 249.9005,-248 249.9005,-254 243.9005,-260 237.9005,-260 237.9005,-260 162.9439,-260 162.9439,-260 156.9439,-260 150.9439,-254 150.9439,-248 150.9439,-248 150.9439,-72 150.9439,-72 150.9439,-66 156.9439,-60 162.9439,-60"/>
<text text-anchor="middle" x="200.4222" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(*Certificate)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]&#10;at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at fuzz.go:8: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length]&#10;at fuzz.go:9: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-160C58,-160 28,-160 28,-160 22,-160 16,-154 16,-148 16,-148 16,-136 16,-136 16,-130 22,-124 28,-124 28,-124 58,-124 58,-124 64,-124 70,-130 70,-136 70,-136 70,-148 70,-148 70,-154 64,-160 58,-160"/>
<text text-anchor="middle" x="43" y="-137.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate | defined in certificate.go:201">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M243.7667,-52C243.7667,-52 156.0777,-52 156.0777,-52 150.0777,-52 144.0777,-46 144.0777,-40 144.0777,-40 144.0777,-28 144.0777,-28 144.0777,-22 150.0777,-16 156.0777,-16 156.0777,-16 243.7667,-16 243.7667,-16 249.7667,-16 255.7667,-22 255.7667,-28 255.7667,-28 255.7667,-40 255.7667,-40 255.7667,-46 249.7667,-52 243.7667,-52"/>
<text text-anchor="middle" x="199.9222" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="199.9222" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]">
<path fill="none" stroke="#8b4513" d="M60.5563,-123.8395C78.2431,-106.2965 107.1045,-79.6361 142.3601,-57.393"/>
<polygon fill="#8b4513" stroke="#8b4513" points="144.2536,-60.3376 150.9601,-52.1355 140.6025,-54.3652 144.2536,-60.3376"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="node3" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_node3"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data | defined in certificate.go:134">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M227.8788,-130C227.8788,-130 171.9656,-130 171.9656,-130 165.9656,-130 159.9656,-124 159.9656,-118 159.9656,-118 159.9656,-106 159.9656,-106 159.9656,-100 165.9656,-94 171.9656,-94 171.9656,-94 227.8788,-94 227.8788,-94 233.8788,-94 239.8788,-100 239.8788,-106 239.8788,-106 239.8788,-118 239.8788,-118 239.8788,-124 233.8788,-130 227.8788,-130"/>
<text text-anchor="middle" x="199.9222" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="199.9222" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Data</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#8b4513" d="M70.3338,-136.7744C92.2913,-132.5766 123.7111,-126.5699 150.1132,-121.5224"/>
<polygon fill="#8b4513" stroke="#8b4513" points="150.7913,-124.9562 159.9562,-119.6406 149.4768,-118.0807 150.7913,-124.9562"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length -->
<g id="node4" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length</title>
<g id="a_node4"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length | defined in certificate.go:125">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M227.8788,-191C227.8788,-191 171.9656,-191 171.9656,-191 165.9656,-191 159.9656,-185 159.9656,-179 159.9656,-179 159.9656,-167 159.9656,-167 159.9656,-161 165.9656,-155 171.9656,-155 171.9656,-155 227.8788,-155 227.8788,-155 233.8788,-155 239.8788,-161 239.8788,-167 239.8788,-167 239.8788,-179 239.8788,-179 239.8788,-185 233.8788,-191 227.8788,-191"/>
<text text-anchor="middle" x="199.9222" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="199.9222" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">Length</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length</title>
<g id="a_edge3"><a xlink:title="at fuzz.go:8: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length]">
<path fill="none" stroke="#8b4513" d="M70.3338,-147.3998C92.2913,-151.7375 123.7111,-157.9445 150.1132,-163.1602"/>
<polygon fill="#8b4513" stroke="#8b4513" points="149.4674,-166.6002 159.9562,-165.1047 150.8241,-159.7329 149.4674,-166.6002"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="node5" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_node5"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type | defined in certificate.go:116">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M227.8788,-252C227.8788,-252 171.9656,-252 171.9656,-252 165.9656,-252 159.9656,-246 159.9656,-240 159.9656,-240 159.9656,-228 159.9656,-228 159.9656,-222 165.9656,-216 171.9656,-216 171.9656,-216 227.8788,-216 227.8788,-216 233.8788,-216 239.8788,-222 239.8788,-228 239.8788,-228 239.8788,-240 239.8788,-240 239.8788,-246 233.8788,-252 227.8788,-252"/>
<text text-anchor="middle" x="199.9222" y="-238.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="199.9222" y="-221.4" font-family="Verdana" font-size="14.00" fill="#000000">Type</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/certificate.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_edge4"><a xlink:title="at fuzz.go:9: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#8b4513" d="M70.1769,-159.2759C90.3621,-171.9616 118.6668,-189.4457 144,-204 148.084,-206.3463 152.3634,-208.7456 156.6592,-211.1147"/>
<polygon fill="#8b4513" stroke="#8b4513" points="154.9879,-214.1898 165.4424,-215.9086 158.3415,-208.0455 154.9879,-214.1898"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -1,9 +1,9 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
import common "github.com/go-i2p/go-i2p/lib/common/certificate"
func Fuzz(data []byte) int {
cert := common.Certificate(data)
cert, _, _ := common.ReadCertificate(data)
cert.Data()
cert.Length()
cert.Type()

View File

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

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="281pt" height="245pt"
viewBox="0.00 0.00 281.19 245.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 245)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-245 281.195,-245 281.195,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-237 273.195,-237 273.195,-8 8,-8"/>
<text text-anchor="middle" x="140.5975" y="-216.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination</title>
<g id="a_clust2"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M150.1136,-60C150.1136,-60 253.195,-60 253.195,-60 259.195,-60 265.195,-66 265.195,-72 265.195,-72 265.195,-187 265.195,-187 265.195,-193 259.195,-199 253.195,-199 253.195,-199 150.1136,-199 150.1136,-199 144.1136,-199 138.1136,-193 138.1136,-187 138.1136,-187 138.1136,-72 138.1136,-72 138.1136,-66 144.1136,-60 150.1136,-60"/>
<text text-anchor="middle" x="201.6543" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(Destination)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination]&#10;at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address]&#10;at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-130C58,-130 28,-130 28,-130 22,-130 16,-124 16,-118 16,-118 16,-106 16,-106 16,-100 22,-94 28,-94 28,-94 58,-94 58,-94 64,-94 70,-100 70,-106 70,-106 70,-118 70,-118 70,-124 64,-130 58,-130"/>
<text text-anchor="middle" x="43" y="-107.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination | defined in destination.go:72">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M248.4633,-52C248.4633,-52 154.8453,-52 154.8453,-52 148.8453,-52 142.8453,-46 142.8453,-40 142.8453,-40 142.8453,-28 142.8453,-28 142.8453,-22 148.8453,-16 154.8453,-16 154.8453,-16 248.4633,-16 248.4633,-16 254.4633,-16 260.4633,-22 260.4633,-28 260.4633,-28 260.4633,-40 260.4633,-40 260.4633,-46 254.4633,-52 248.4633,-52"/>
<text text-anchor="middle" x="201.6543" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">destination</text>
<text text-anchor="middle" x="201.6543" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadDestination</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination]">
<path fill="none" stroke="#8b4513" d="M70.1001,-94.0845C88.7169,-82.2726 114.281,-67.0087 138.1136,-56 138.2063,-55.9572 138.2992,-55.9144 138.3921,-55.8716"/>
<polygon fill="#8b4513" stroke="#8b4513" points="139.5119,-59.2012 147.2891,-52.0063 136.7226,-52.7809 139.5119,-59.2012"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address -->
<g id="node3" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address</title>
<g id="a_node3"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address | defined in destination.go:38">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M245.2357,-130C245.2357,-130 158.0729,-130 158.0729,-130 152.0729,-130 146.0729,-124 146.0729,-118 146.0729,-118 146.0729,-106 146.0729,-106 146.0729,-100 152.0729,-94 158.0729,-94 158.0729,-94 245.2357,-94 245.2357,-94 251.2357,-94 257.2357,-100 257.2357,-106 257.2357,-106 257.2357,-118 257.2357,-118 257.2357,-124 251.2357,-130 245.2357,-130"/>
<text text-anchor="middle" x="201.6543" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">destination</text>
<text text-anchor="middle" x="201.6543" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Base32Address</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address]">
<path fill="none" stroke="#8b4513" d="M70.2736,-112C88.3329,-112 112.8362,-112 135.7903,-112"/>
<polygon fill="#8b4513" stroke="#8b4513" points="135.853,-115.5001 145.853,-112 135.8529,-108.5001 135.853,-115.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64 -->
<g id="node4" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64</title>
<g id="a_node4"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64 | defined in destination.go:55">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M232.5916,-191C232.5916,-191 170.717,-191 170.717,-191 164.717,-191 158.717,-185 158.717,-179 158.717,-179 158.717,-167 158.717,-167 158.717,-161 164.717,-155 170.717,-155 170.717,-155 232.5916,-155 232.5916,-155 238.5916,-155 244.5916,-161 244.5916,-167 244.5916,-167 244.5916,-179 244.5916,-179 244.5916,-185 238.5916,-191 232.5916,-191"/>
<text text-anchor="middle" x="201.6543" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">destination</text>
<text text-anchor="middle" x="201.6543" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">Base64</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64 -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/destination.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64</title>
<g id="a_edge3"><a xlink:title="at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64]">
<path fill="none" stroke="#8b4513" d="M70.2736,-122.4863C91.973,-130.8293 122.976,-142.7495 149.4161,-152.9153"/>
<polygon fill="#8b4513" stroke="#8b4513" points="148.3351,-156.2494 158.9251,-156.5713 150.8473,-149.7157 148.3351,-156.2494"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -1,9 +1,9 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
import common "github.com/go-i2p/go-i2p/lib/common/destination"
func Fuzz(data []byte) int {
destination := common.Destination(data)
destination, _, _ := common.ReadDestination(data)
destination.Base32Address()
destination.Base64()
return 0

View File

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

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="295pt" height="306pt"
viewBox="0.00 0.00 295.20 306.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 306)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-306 295.202,-306 295.202,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-298 287.202,-298 287.202,-8 8,-8"/>
<text text-anchor="middle" x="147.601" y="-277.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M148.5386,-60C148.5386,-60 267.202,-60 267.202,-60 273.202,-60 279.202,-66 279.202,-72 279.202,-72 279.202,-248 279.202,-248 279.202,-254 273.202,-260 267.202,-260 267.202,-260 148.5386,-260 148.5386,-260 142.5386,-260 136.5386,-254 136.5386,-248 136.5386,-248 136.5386,-72 136.5386,-72 136.5386,-66 142.5386,-60 148.5386,-60"/>
<text text-anchor="middle" x="207.8703" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(*KeysAndCert)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert]&#10;at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]&#10;at fuzz.go:8: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey]&#10;at fuzz.go:9: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-160C58,-160 28,-160 28,-160 22,-160 16,-154 16,-148 16,-148 16,-136 16,-136 16,-130 22,-124 28,-124 28,-124 58,-124 58,-124 64,-124 70,-130 70,-136 70,-136 70,-148 70,-148 70,-154 64,-160 58,-160"/>
<text text-anchor="middle" x="43" y="-137.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert | defined in keys_and_cert.go:142">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M260.6112,-52C260.6112,-52 155.1294,-52 155.1294,-52 149.1294,-52 143.1294,-46 143.1294,-40 143.1294,-40 143.1294,-28 143.1294,-28 143.1294,-22 149.1294,-16 155.1294,-16 155.1294,-16 260.6112,-16 260.6112,-16 266.6112,-16 272.6112,-22 272.6112,-28 272.6112,-28 272.6112,-40 272.6112,-40 272.6112,-46 266.6112,-52 260.6112,-52"/>
<text text-anchor="middle" x="207.8703" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="207.8703" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadKeysAndCert</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert]">
<path fill="none" stroke="#8b4513" d="M58.0901,-123.9966C73.9008,-106.1275 100.4054,-78.8225 134.9201,-57.4503"/>
<polygon fill="#8b4513" stroke="#8b4513" points="137.0442,-60.2603 143.866,-52.1539 133.4779,-54.2368 137.0442,-60.2603"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="node3" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_node3"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate | defined in keys_and_cert.go:136">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M248.2246,-130C248.2246,-130 167.516,-130 167.516,-130 161.516,-130 155.516,-124 155.516,-118 155.516,-118 155.516,-106 155.516,-106 155.516,-100 161.516,-94 167.516,-94 167.516,-94 248.2246,-94 248.2246,-94 254.2246,-94 260.2246,-100 260.2246,-106 260.2246,-106 260.2246,-118 260.2246,-118 260.2246,-124 254.2246,-130 248.2246,-130"/>
<text text-anchor="middle" x="207.8703" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="207.8703" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Certificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="none" stroke="#8b4513" d="M70.225,-137.0461C90.5721,-133.3437 119.2244,-128.1301 145.123,-123.4176"/>
<polygon fill="#8b4513" stroke="#8b4513" points="146.0533,-126.8058 155.2652,-121.5721 144.8001,-119.9189 146.0533,-126.8058"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey -->
<g id="node4" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey</title>
<g id="a_node4"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey | defined in keys_and_cert.go:126">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M248.2246,-191C248.2246,-191 167.516,-191 167.516,-191 161.516,-191 155.516,-185 155.516,-179 155.516,-179 155.516,-167 155.516,-167 155.516,-161 161.516,-155 167.516,-155 167.516,-155 248.2246,-155 248.2246,-155 254.2246,-155 260.2246,-161 260.2246,-167 260.2246,-167 260.2246,-179 260.2246,-179 260.2246,-185 254.2246,-191 248.2246,-191"/>
<text text-anchor="middle" x="207.8703" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="207.8703" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">PublicKey</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey</title>
<g id="a_edge3"><a xlink:title="at fuzz.go:8: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).PublicKey]">
<path fill="none" stroke="#8b4513" d="M70.225,-147.119C90.5721,-150.9448 119.2244,-156.3322 145.123,-161.2018"/>
<polygon fill="#8b4513" stroke="#8b4513" points="144.7906,-164.7006 155.2652,-163.1088 146.0842,-157.8212 144.7906,-164.7006"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey -->
<g id="node5" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey</title>
<g id="a_node5"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey | defined in keys_and_cert.go:131">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M259.0341,-252C259.0341,-252 156.7065,-252 156.7065,-252 150.7065,-252 144.7065,-246 144.7065,-240 144.7065,-240 144.7065,-228 144.7065,-228 144.7065,-222 150.7065,-216 156.7065,-216 156.7065,-216 259.0341,-216 259.0341,-216 265.0341,-216 271.0341,-222 271.0341,-228 271.0341,-228 271.0341,-240 271.0341,-240 271.0341,-246 265.0341,-252 259.0341,-252"/>
<text text-anchor="middle" x="207.8703" y="-238.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="207.8703" y="-221.4" font-family="Verdana" font-size="14.00" fill="#000000">SigningPublicKey</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/keys_and_cert.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey</title>
<g id="a_edge4"><a xlink:title="at fuzz.go:9: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey]">
<path fill="none" stroke="#8b4513" d="M67.6184,-160.1635C86.0385,-173.2904 112.1509,-190.9378 136.5386,-204 141.4238,-206.6165 146.5867,-209.1688 151.811,-211.6095"/>
<polygon fill="#8b4513" stroke="#8b4513" points="150.6805,-214.9395 161.2342,-215.8722 153.5656,-208.5617 150.6805,-214.9395"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -1,6 +1,6 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
import common "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
func Fuzz(data []byte) int {
keys_and_cert, _, _ := common.ReadKeysAndCert(data)

View File

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

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="298pt" height="367pt"
viewBox="0.00 0.00 297.74 367.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 367)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-367 297.7392,-367 297.7392,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-359 289.7392,-359 289.7392,-8 8,-8"/>
<text text-anchor="middle" x="148.8696" y="-338.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress</title>
<g id="a_clust2"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M162.7686,-60C162.7686,-60 263.9706,-60 263.9706,-60 269.9706,-60 275.9706,-66 275.9706,-72 275.9706,-72 275.9706,-309 275.9706,-309 275.9706,-315 269.9706,-321 263.9706,-321 263.9706,-321 162.7686,-321 162.7686,-321 156.7686,-321 150.7686,-315 150.7686,-309 150.7686,-309 150.7686,-72 150.7686,-72 150.7686,-66 156.7686,-60 162.7686,-60"/>
<text text-anchor="middle" x="213.3696" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(RouterAddress)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:10: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle]&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress]&#10;at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost]&#10;at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration]&#10;at fuzz.go:9: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-191C58,-191 28,-191 28,-191 22,-191 16,-185 16,-179 16,-179 16,-167 16,-167 16,-161 22,-155 28,-155 28,-155 58,-155 58,-155 64,-155 70,-161 70,-167 70,-167 70,-179 70,-179 70,-185 64,-191 58,-191"/>
<text text-anchor="middle" x="43" y="-168.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress | defined in router_address.go:317">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M269.609,-52C269.609,-52 157.1302,-52 157.1302,-52 151.1302,-52 145.1302,-46 145.1302,-40 145.1302,-40 145.1302,-28 145.1302,-28 145.1302,-22 151.1302,-16 157.1302,-16 157.1302,-16 269.609,-16 269.609,-16 275.609,-16 281.609,-22 281.609,-28 281.609,-28 281.609,-40 281.609,-40 281.609,-46 275.609,-52 269.609,-52"/>
<text text-anchor="middle" x="213.3696" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">router_address</text>
<text text-anchor="middle" x="213.3696" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadRouterAddress</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.ReadRouterAddress]">
<path fill="none" stroke="#8b4513" d="M54.2,-154.8153C69.8891,-130.7191 100.687,-88.1071 143.143,-57.8152"/>
<polygon fill="#8b4513" stroke="#8b4513" points="145.2054,-60.6453 151.4961,-52.1202 141.2621,-54.8616 145.2054,-60.6453"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost -->
<g id="node3" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost</title>
<g id="a_node3"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost | defined in router_address.go:163">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M254.7758,-130C254.7758,-130 171.9634,-130 171.9634,-130 165.9634,-130 159.9634,-124 159.9634,-118 159.9634,-118 159.9634,-106 159.9634,-106 159.9634,-100 165.9634,-94 171.9634,-94 171.9634,-94 254.7758,-94 254.7758,-94 260.7758,-94 266.7758,-100 266.7758,-106 266.7758,-106 266.7758,-118 266.7758,-118 266.7758,-124 260.7758,-130 254.7758,-130"/>
<text text-anchor="middle" x="213.3696" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">router_address</text>
<text text-anchor="middle" x="213.3696" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Cost</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost</title>
<g id="a_edge3"><a xlink:title="at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Cost]">
<path fill="none" stroke="#8b4513" d="M70.3728,-163.1993C92.7676,-155.181 125.2557,-143.5488 153.6076,-133.3975"/>
<polygon fill="#8b4513" stroke="#8b4513" points="154.8086,-136.6851 163.0435,-130.019 152.4489,-130.0948 154.8086,-136.6851"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration -->
<g id="node4" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration</title>
<g id="a_node4"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration | defined in router_address.go:168">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M254.7758,-191C254.7758,-191 171.9634,-191 171.9634,-191 165.9634,-191 159.9634,-185 159.9634,-179 159.9634,-179 159.9634,-167 159.9634,-167 159.9634,-161 165.9634,-155 171.9634,-155 171.9634,-155 254.7758,-155 254.7758,-155 260.7758,-155 266.7758,-161 266.7758,-167 266.7758,-167 266.7758,-179 266.7758,-179 266.7758,-185 260.7758,-191 254.7758,-191"/>
<text text-anchor="middle" x="213.3696" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">router_address</text>
<text text-anchor="middle" x="213.3696" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">Expiration</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration</title>
<g id="a_edge4"><a xlink:title="at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Expiration]">
<path fill="none" stroke="#8b4513" d="M70.3728,-173C91.7248,-173 122.2521,-173 149.6217,-173"/>
<polygon fill="#8b4513" stroke="#8b4513" points="149.9311,-176.5001 159.931,-173 149.931,-169.5001 149.9311,-176.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options -->
<g id="node5" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options</title>
<g id="a_node5"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options | defined in router_address.go:305">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M254.7758,-252C254.7758,-252 171.9634,-252 171.9634,-252 165.9634,-252 159.9634,-246 159.9634,-240 159.9634,-240 159.9634,-228 159.9634,-228 159.9634,-222 165.9634,-216 171.9634,-216 171.9634,-216 254.7758,-216 254.7758,-216 260.7758,-216 266.7758,-222 266.7758,-228 266.7758,-228 266.7758,-240 266.7758,-240 266.7758,-246 260.7758,-252 254.7758,-252"/>
<text text-anchor="middle" x="213.3696" y="-238.2" font-family="Verdana" font-size="14.00" fill="#000000">router_address</text>
<text text-anchor="middle" x="213.3696" y="-221.4" font-family="Verdana" font-size="14.00" fill="#000000">Options</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options -->
<g id="edge5" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options</title>
<g id="a_edge5"><a xlink:title="at fuzz.go:9: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).Options]">
<path fill="none" stroke="#8b4513" d="M70.3728,-182.8007C92.7676,-190.819 125.2557,-202.4512 153.6076,-212.6025"/>
<polygon fill="#8b4513" stroke="#8b4513" points="152.4489,-215.9052 163.0435,-215.981 154.8086,-209.3149 152.4489,-215.9052"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle -->
<g id="node6" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle</title>
<g id="a_node6"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle | defined in router_address.go:173">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M255.0718,-313C255.0718,-313 171.6674,-313 171.6674,-313 165.6674,-313 159.6674,-307 159.6674,-301 159.6674,-301 159.6674,-289 159.6674,-289 159.6674,-283 165.6674,-277 171.6674,-277 171.6674,-277 255.0718,-277 255.0718,-277 261.0718,-277 267.0718,-283 267.0718,-289 267.0718,-289 267.0718,-301 267.0718,-301 267.0718,-307 261.0718,-313 255.0718,-313"/>
<text text-anchor="middle" x="213.3696" y="-299.2" font-family="Verdana" font-size="14.00" fill="#000000">router_address</text>
<text text-anchor="middle" x="213.3696" y="-282.4" font-family="Verdana" font-size="14.00" fill="#000000">TransportStyle</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_address.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:10: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/router_address.RouterAddress).TransportStyle]">
<path fill="none" stroke="#8b4513" d="M59.628,-191.1509C78.7338,-211.2098 111.7512,-243.5148 145,-265 149.0077,-267.5898 153.2766,-270.0551 157.6487,-272.3782"/>
<polygon fill="#8b4513" stroke="#8b4513" points="156.211,-275.5729 166.7171,-276.9412 159.3574,-269.3198 156.211,-275.5729"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,6 +1,6 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
import common "github.com/go-i2p/go-i2p/lib/common/router_address"
func Fuzz(data []byte) int {
router_address, _, _ := common.ReadRouterAddress(data)

View File

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

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="293pt" height="184pt"
viewBox="0.00 0.00 293.42 184.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 184)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-184 293.4152,-184 293.4152,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-176 285.4152,-176 285.4152,-8 8,-8"/>
<text text-anchor="middle" x="146.7076" y="-155.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M161.7805,-60C161.7805,-60 258.6347,-60 258.6347,-60 264.6347,-60 270.6347,-66 270.6347,-72 270.6347,-72 270.6347,-126 270.6347,-126 270.6347,-132 264.6347,-138 258.6347,-138 258.6347,-138 161.7805,-138 161.7805,-138 155.7805,-138 149.7805,-132 149.7805,-126 149.7805,-126 149.7805,-72 149.7805,-72 149.7805,-66 155.7805,-60 161.7805,-60"/>
<text text-anchor="middle" x="210.2076" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(*KeysAndCert)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity]&#10;at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-65C58,-65 28,-65 28,-65 22,-65 16,-59 16,-53 16,-53 16,-41 16,-41 16,-35 22,-29 28,-29 28,-29 58,-29 58,-29 64,-29 70,-35 70,-41 70,-41 70,-53 70,-53 70,-59 64,-65 58,-65"/>
<text text-anchor="middle" x="43" y="-42.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity | defined in router_identity.go:37">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M265.6234,-52C265.6234,-52 154.7918,-52 154.7918,-52 148.7918,-52 142.7918,-46 142.7918,-40 142.7918,-40 142.7918,-28 142.7918,-28 142.7918,-22 148.7918,-16 154.7918,-16 154.7918,-16 265.6234,-16 265.6234,-16 271.6234,-16 277.6234,-22 277.6234,-28 277.6234,-28 277.6234,-40 277.6234,-40 277.6234,-46 271.6234,-52 265.6234,-52"/>
<text text-anchor="middle" x="210.2076" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">router_identity</text>
<text text-anchor="middle" x="210.2076" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadRouterIdentity</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity]">
<path fill="none" stroke="#8b4513" d="M70.2369,-44.8824C87.33,-43.5534 110.3072,-41.767 132.6983,-40.0262"/>
<polygon fill="#8b4513" stroke="#8b4513" points="133.223,-43.496 142.9216,-39.2313 132.6803,-36.5171 133.223,-43.496"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="node3" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_node3"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate | defined in keys_and_cert.go:136">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M250.5619,-130C250.5619,-130 169.8533,-130 169.8533,-130 163.8533,-130 157.8533,-124 157.8533,-118 157.8533,-118 157.8533,-106 157.8533,-106 157.8533,-100 163.8533,-94 169.8533,-94 169.8533,-94 250.5619,-94 250.5619,-94 256.5619,-94 262.5619,-100 262.5619,-106 262.5619,-106 262.5619,-118 262.5619,-118 262.5619,-124 256.5619,-130 250.5619,-130"/>
<text text-anchor="middle" x="210.2076" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">keys_and_cert</text>
<text text-anchor="middle" x="210.2076" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Certificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/router_identity.Fuzz&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="none" stroke="#8b4513" d="M70.3186,-59.5347C90.2689,-68.4946 118.0733,-80.5827 143,-90 144.6187,-90.6115 146.2628,-91.2224 147.9247,-91.8308"/>
<polygon fill="#8b4513" stroke="#8b4513" points="146.9887,-95.2129 157.5834,-95.2765 149.3408,-88.6199 146.9887,-95.2129"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1,11 +1,11 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
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

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

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="257pt" height="245pt"
viewBox="0.00 0.00 257.22 245.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 245)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-245 257.2202,-245 257.2202,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-237 249.2202,-237 249.2202,-8 8,-8"/>
<text text-anchor="middle" x="128.6101" y="-216.8" font-family="Arial" font-size="18.00" fill="#000000">exportable</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString</title>
<g id="a_clust2"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M162.7812,-60C162.7812,-60 226.439,-60 226.439,-60 232.439,-60 238.439,-66 238.439,-72 238.439,-72 238.439,-187 238.439,-187 238.439,-193 232.439,-199 226.439,-199 226.439,-199 162.7812,-199 162.7812,-199 156.7812,-199 150.7812,-193 150.7812,-187 150.7812,-187 150.7812,-72 150.7812,-72 150.7812,-66 156.7812,-60 162.7812,-60"/>
<text text-anchor="middle" x="194.6101" y="-68.5" font-family="Arial" font-size="15.00" fill="#222222">(I2PString)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz | defined in fuzz.go:5&#10;at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data]&#10;at fuzz.go:10: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data]&#10;at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length]&#10;at fuzz.go:11: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length]&#10;at fuzz.go:9: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M58,-130C58,-130 28,-130 28,-130 22,-130 16,-124 16,-118 16,-118 16,-106 16,-106 16,-100 22,-94 28,-94 28,-94 58,-94 58,-94 64,-94 70,-100 70,-106 70,-106 70,-118 70,-118 70,-124 64,-130 58,-130"/>
<text text-anchor="middle" x="43" y="-107.8" font-family="Verdana" font-size="14.00" fill="#000000">Fuzz</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString | defined in string.go:114">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M229.3306,-52C229.3306,-52 159.8896,-52 159.8896,-52 153.8896,-52 147.8896,-46 147.8896,-40 147.8896,-40 147.8896,-28 147.8896,-28 147.8896,-22 153.8896,-16 159.8896,-16 159.8896,-16 229.3306,-16 229.3306,-16 235.3306,-16 241.3306,-22 241.3306,-28 241.3306,-28 241.3306,-40 241.3306,-40 241.3306,-46 235.3306,-52 229.3306,-52"/>
<text text-anchor="middle" x="194.6101" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="194.6101" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">ToI2PString</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString</title>
<g id="a_edge3"><a xlink:title="at fuzz.go:9: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ToI2PString]">
<path fill="none" stroke="#8b4513" d="M70.0043,-97.129C89.2049,-86.6594 115.8894,-72.3156 146.6535,-56.7465"/>
<polygon fill="#8b4513" stroke="#8b4513" points="148.5211,-59.7249 155.8799,-52.1027 145.374,-53.4722 148.5211,-59.7249"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data -->
<g id="node3" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data</title>
<g id="a_node3"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data | defined in string.go:73">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M209.6101,-130C209.6101,-130 179.6101,-130 179.6101,-130 173.6101,-130 167.6101,-124 167.6101,-118 167.6101,-118 167.6101,-106 167.6101,-106 167.6101,-100 173.6101,-94 179.6101,-94 179.6101,-94 209.6101,-94 209.6101,-94 215.6101,-94 221.6101,-100 221.6101,-106 221.6101,-106 221.6101,-118 221.6101,-118 221.6101,-124 215.6101,-130 209.6101,-130"/>
<text text-anchor="middle" x="194.6101" y="-116.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="194.6101" y="-99.4" font-family="Verdana" font-size="14.00" fill="#000000">Data</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data</title>
<g id="a_edge1"><a xlink:title="at fuzz.go:7: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data]&#10;at fuzz.go:10: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Data]">
<path fill="none" stroke="#8b4513" d="M70.1048,-112C94.3917,-112 130.2444,-112 157.2471,-112"/>
<polygon fill="#8b4513" stroke="#8b4513" points="157.4848,-115.5001 167.4848,-112 157.4847,-108.5001 157.4848,-115.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length -->
<g id="node4" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length</title>
<g id="a_node4"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length | defined in string.go:31">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M214.2688,-191C214.2688,-191 174.9514,-191 174.9514,-191 168.9514,-191 162.9514,-185 162.9514,-179 162.9514,-179 162.9514,-167 162.9514,-167 162.9514,-161 168.9514,-155 174.9514,-155 174.9514,-155 214.2688,-155 214.2688,-155 220.2688,-155 226.2688,-161 226.2688,-167 226.2688,-167 226.2688,-179 226.2688,-179 226.2688,-185 220.2688,-191 214.2688,-191"/>
<text text-anchor="middle" x="194.6101" y="-177.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="194.6101" y="-160.4" font-family="Verdana" font-size="14.00" fill="#000000">Length</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/fuzz/string.Fuzz&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length</title>
<g id="a_edge2"><a xlink:title="at fuzz.go:8: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length]&#10;at fuzz.go:11: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.I2PString).Length]">
<path fill="none" stroke="#8b4513" d="M70.1048,-122.9056C93.2412,-132.2144 126.8736,-145.7464 153.3522,-156.4"/>
<polygon fill="#8b4513" stroke="#8b4513" points="152.1674,-159.6959 162.7511,-160.1816 154.7804,-153.2018 152.1674,-159.6959"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -1,9 +1,9 @@
package exportable
import "github.com/go-i2p/go-i2p/lib/common"
import common "github.com/go-i2p/go-i2p/lib/common/data"
func Fuzz(data []byte) int {
str, _, _ := common.ReadString(data)
str := common.I2PString(data)
str.Data()
str.Length()
str, _ = common.ToI2PString(string(data))

View File

@ -1,27 +0,0 @@
package common
import (
"crypto/sha256"
"io"
)
// sha256 hash of some data
type Hash [32]byte
// calculate sha256 of a byte slice
func HashData(data []byte) (h Hash) {
h = sha256.Sum256(data)
return
}
// calulate sha256 of all data being read from an io.Reader
// return error if one occurs while reading from reader
func HashReader(r io.Reader) (h Hash, err error) {
sha := sha256.New()
_, err = io.Copy(sha, r)
if err == nil {
d := sha.Sum(nil)
copy(h[:], d)
}
return
}

View File

@ -1,32 +0,0 @@
package common
/*
I2P Integer
https://geti2p.net/spec/common-structures#integer
Accurate for version 0.9.24
*/
import (
"encoding/binary"
)
// Total byte length of an I2P integer
const (
INTEGER_SIZE = 8
)
//
// Interpret a slice of bytes from length 0 to length 8 as a big-endian
// integer and return an int representation.
//
func Integer(number []byte) (value int) {
num_len := len(number)
if num_len < INTEGER_SIZE {
number = append(
make([]byte, INTEGER_SIZE-num_len),
number...,
)
}
value = int(binary.BigEndian.Uint64(number))
return
}

View File

@ -1,246 +0,0 @@
package common
/*
I2P Key Certificate
https://geti2p.net/spec/common-structures#certificate
Accurate for version 0.9.24
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
case 5 -> KEY
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
*/
import (
"errors"
"github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
)
// Key Certificate Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1 = iota
KEYCERT_SIGN_P256
KEYCERT_SIGN_P384
KEYCERT_SIGN_P521
KEYCERT_SIGN_RSA2048
KEYCERT_SIGN_RSA3072
KEYCERT_SIGN_RSA4096
KEYCERT_SIGN_ED25519
KEYCERT_SIGN_ED25519PH
)
// Key Certificate Public Key Types
const (
KEYCERT_CRYPTO_ELG = iota
)
// SigningPublicKey sizes for Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
KEYCERT_SIGN_P384_SIZE = 96
KEYCERT_SIGN_P521_SIZE = 132
KEYCERT_SIGN_RSA2048_SIZE = 256
KEYCERT_SIGN_RSA3072_SIZE = 384
KEYCERT_SIGN_RSA4096_SIZE = 512
KEYCERT_SIGN_ED25519_SIZE = 32
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
// PublicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
)
// Sizes of structures in KeyCertificates
const (
KEYCERT_PUBKEY_SIZE = 256
KEYCERT_SPK_SIZE = 128
)
type KeyCertificate []byte
//
// The data contained in the Key Certificate.
//
func (key_certificate KeyCertificate) Data() ([]byte, error) {
return Certificate(key_certificate).Data()
}
//
// The SigningPublicKey type this Key Certificate describes and any errors encountered
// parsing the KeyCertificate.
//
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int, err error) {
data, err := key_certificate.Data()
if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SigningPublicKeyType",
"reason": err.Error(),
}).Error("error getting signing public key")
return
}
data_len := len(data)
if data_len < 2 {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SigningPublicKeyType",
"data_len": data_len,
"required_len": 2,
"reason": "not enough data",
}).Error("error parsing key certificate")
err = errors.New("error parsing key certificate: not enough data")
return
}
signing_pubkey_type = Integer(data[:2])
return
}
//
// The PublicKey type this Key Certificate describes and any errors encountered parsing
// this KeyCertificate.
//
func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int, err error) {
data, err := key_certificate.Data()
if err != nil {
return
}
data_len := len(data)
if data_len < 4 {
log.WithFields(log.Fields{
"at": "(KeyCertificate) PublicKeyType",
"data_len": data_len,
"required_len": 4,
"reason": "not enough data",
}).Error("error parsing key certificate")
err = errors.New("error parsing key certificate: not enough data")
return
}
pubkey_type = Integer(data[2:4])
return
}
//
// Given some bytes, build a PublicKey using any excess data that may be stored in the KeyCertificate and return
// it along with any errors encountered constructing the PublicKey.
//
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) {
key_type, err := key_certificate.PublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < KEYCERT_PUBKEY_SIZE {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructPublicKey",
"data_len": data_len,
"required_len": KEYCERT_PUBKEY_SIZE,
"reason": "not enough data",
}).Error("error constructing public key")
err = errors.New("error constructing public key: not enough data")
return
}
switch key_type {
case KEYCERT_CRYPTO_ELG:
var elg_key crypto.ElgPublicKey
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = elg_key
}
return
}
//
// Given some bytes, build a SigningPublicKey using any excess data that may be stored in the KeyCertificate and return
// it along with any errors encountered constructing the SigningPublicKey.
//
func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
signing_key_type, err := key_certificate.PublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < KEYCERT_SPK_SIZE {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructSigningPublicKey",
"data_len": data_len,
"required_len": KEYCERT_SPK_SIZE,
"reason": "not enough data",
}).Error("error constructing signing public key")
err = errors.New("error constructing signing public key: not enough data")
return
}
switch signing_key_type {
case KEYCERT_SIGN_DSA_SHA1:
var dsa_key crypto.DSAPublicKey
copy(dsa_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_DSA_SHA1_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = dsa_key
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
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
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[4:4+extra])
signing_public_key = ec_key
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
case KEYCERT_SIGN_RSA3072:
case KEYCERT_SIGN_RSA4096:
case KEYCERT_SIGN_ED25519:
case KEYCERT_SIGN_ED25519PH:
}
return
}
//
// 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: 40,
KEYCERT_SIGN_P256: 64,
KEYCERT_SIGN_P384: 96,
KEYCERT_SIGN_P521: 132,
KEYCERT_SIGN_RSA2048: 256,
KEYCERT_SIGN_RSA3072: 384,
KEYCERT_SIGN_RSA4096: 512,
KEYCERT_SIGN_ED25519: 64,
KEYCERT_SIGN_ED25519PH: 64,
}
key_type, err := key_certificate.SigningPublicKeyType()
if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SignatureSize",
"key_type": key_type,
"reason": "failed to read signing public key type",
}).Error("error getting signature size")
return 0
}
return sizes[int(key_type)]
}

View File

@ -0,0 +1,198 @@
# key_certificate
--
import "github.com/go-i2p/go-i2p/lib/common/key_certificate"
![key_certificate.svg](key_certificate.svg)
Package key_certificate implements the I2P Destination common data structure
## Usage
```go
const (
KEYCERT_SIGN_DSA_SHA1 = 0
KEYCERT_SIGN_P256 = 1
KEYCERT_SIGN_P384 = 2
KEYCERT_SIGN_P521 = 3
KEYCERT_SIGN_RSA2048 = 4
KEYCERT_SIGN_RSA3072 = 5
KEYCERT_SIGN_RSA4096 = 6
KEYCERT_SIGN_ED25519 = 7
KEYCERT_SIGN_ED25519PH = 8
)
```
Key Certificate Signing Key Types
```go
const (
KEYCERT_CRYPTO_ELG = 0
KEYCERT_CRYPTO_P256 = 1
KEYCERT_CRYPTO_P384 = 2
KEYCERT_CRYPTO_P521 = 3
KEYCERT_CRYPTO_X25519 = 4
)
```
Key Certificate Public Key Types
```go
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
KEYCERT_SIGN_P384_SIZE = 96
KEYCERT_SIGN_P521_SIZE = 132
KEYCERT_SIGN_RSA2048_SIZE = 256
KEYCERT_SIGN_RSA3072_SIZE = 384
KEYCERT_SIGN_RSA4096_SIZE = 512
KEYCERT_SIGN_ED25519_SIZE = 32
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
```
signingPublicKey sizes for Signing Key Types
```go
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
KEYCERT_CRYPTO_P384_SIZE = 96
KEYCERT_CRYPTO_P521_SIZE = 132
KEYCERT_CRYPTO_X25519_SIZE = 32
)
```
publicKey sizes for Public Key Types
```go
const (
KEYCERT_PUBKEY_SIZE = 256
KEYCERT_SPK_SIZE = 128
)
```
Sizes of structures in KeyCertificates
```go
const (
CRYPTO_KEY_TYPE_ELGAMAL = 0 // ElGamal
// Signature Types
SIGNATURE_TYPE_DSA_SHA1 = 0 // DSA-SHA1
SIGNATURE_TYPE_ED25519_SHA512 = 7 // Ed25519
)
```
```go
const (
KEYCERT_MIN_SIZE = 7
)
```
```go
var CryptoPublicKeySizes = map[uint16]int{
CRYPTO_KEY_TYPE_ELGAMAL: 256,
}
```
```go
var SignaturePublicKeySizes = map[uint16]int{
SIGNATURE_TYPE_DSA_SHA1: 128,
SIGNATURE_TYPE_ED25519_SHA512: 32,
}
```
#### type KeyCertificate
```go
type KeyCertificate struct {
Certificate
SpkType Integer
CpkType Integer
}
```
type KeyCertificate []byte
#### func KeyCertificateFromCertificate
```go
func KeyCertificateFromCertificate(cert Certificate) (*KeyCertificate, error)
```
#### func NewKeyCertificate
```go
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error)
```
NewKeyCertificate creates a new *KeyCertificate from []byte using
ReadCertificate. The remaining bytes after the specified length are also
returned. Returns a list of errors that occurred during parsing.
#### func (KeyCertificate) ConstructPublicKey
```go
func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.RecievingPublicKey, err error)
```
ConstructPublicKey returns a publicKey constructed using any excess data that
may be stored in the KeyCertififcate. Returns enr errors encountered while
parsing.
#### func (KeyCertificate) ConstructSigningPublicKey
```go
func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error)
```
ConstructSigningPublicKey returns a SingingPublicKey constructed using any
excess data that may be stored in the KeyCertificate. Returns any errors
encountered while parsing.
#### func (*KeyCertificate) CryptoPublicKeySize
```go
func (keyCertificate *KeyCertificate) CryptoPublicKeySize() (int, error)
```
#### func (KeyCertificate) CryptoSize
```go
func (keyCertificate KeyCertificate) CryptoSize() (size int)
```
CryptoSize return the size of a Public Key corresponding to the Key
Certificate's publicKey type.
#### func (KeyCertificate) Data
```go
func (keyCertificate KeyCertificate) Data() ([]byte, error)
```
Data returns the raw []byte contained in the Certificate.
#### func (KeyCertificate) PublicKeyType
```go
func (keyCertificate KeyCertificate) PublicKeyType() (pubkey_type int)
```
PublicKeyType returns the publicKey type as a Go integer.
#### func (KeyCertificate) SignatureSize
```go
func (keyCertificate KeyCertificate) SignatureSize() (size int)
```
SignatureSize return the size of a Signature corresponding to the Key
Certificate's signingPublicKey type.
#### func (*KeyCertificate) SigningPublicKeySize
```go
func (keyCertificate *KeyCertificate) SigningPublicKeySize() int
```
#### func (KeyCertificate) SigningPublicKeyType
```go
func (keyCertificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int)
```
SigningPublicKeyType returns the signingPublicKey type as a Go integer.
key_certificate
github.com/go-i2p/go-i2p/lib/common/key_certificate

View File

@ -0,0 +1,427 @@
// Package key_certificate implements the I2P Destination common data structure
package key_certificate
/*
I2P Key Certificate
https://geti2p.net/spec/common-structures#certificate
Accurate for version 0.9.24
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
case 5 -> KEY
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
*/
import (
"fmt"
"github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/samber/oops"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
. "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/crypto"
)
var log = logger.GetGoI2PLogger()
// Key Certificate Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1 = 0
KEYCERT_SIGN_P256 = 1
KEYCERT_SIGN_P384 = 2
KEYCERT_SIGN_P521 = 3
KEYCERT_SIGN_RSA2048 = 4
KEYCERT_SIGN_RSA3072 = 5
KEYCERT_SIGN_RSA4096 = 6
KEYCERT_SIGN_ED25519 = 7
KEYCERT_SIGN_ED25519PH = 8
)
// Key Certificate Public Key Types
const (
KEYCERT_CRYPTO_ELG = 0
KEYCERT_CRYPTO_P256 = 1
KEYCERT_CRYPTO_P384 = 2
KEYCERT_CRYPTO_P521 = 3
KEYCERT_CRYPTO_X25519 = 4
)
const (
KEYCERT_MIN_SIZE = 7
)
// signingPublicKey sizes for Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
KEYCERT_SIGN_P384_SIZE = 96
KEYCERT_SIGN_P521_SIZE = 132
KEYCERT_SIGN_RSA2048_SIZE = 256
KEYCERT_SIGN_RSA3072_SIZE = 384
KEYCERT_SIGN_RSA4096_SIZE = 512
KEYCERT_SIGN_ED25519_SIZE = 32
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
// publicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
KEYCERT_CRYPTO_P384_SIZE = 96
KEYCERT_CRYPTO_P521_SIZE = 132
KEYCERT_CRYPTO_X25519_SIZE = 32
)
// Sizes of structures in KeyCertificates
const (
KEYCERT_PUBKEY_SIZE = 256
KEYCERT_SPK_SIZE = 128
)
// type KeyCertificate []byte
type KeyCertificate struct {
Certificate
SpkType Integer
CpkType Integer
}
// Data returns the raw []byte contained in the Certificate.
func (keyCertificate KeyCertificate) Data() ([]byte, error) {
data := keyCertificate.Certificate.RawBytes()
log.WithFields(logrus.Fields{
"data_length": len(data),
}).Debug("Retrieved raw data from keyCertificate")
return keyCertificate.Certificate.RawBytes(), nil
}
// SigningPublicKeyType returns the signingPublicKey type as a Go integer.
func (keyCertificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) {
signing_pubkey_type = keyCertificate.SpkType.Int()
log.WithFields(logrus.Fields{
"signing_pubkey_type": signing_pubkey_type,
}).Debug("Retrieved signingPublicKey type")
return keyCertificate.SpkType.Int()
}
// PublicKeyType returns the publicKey type as a Go integer.
func (keyCertificate KeyCertificate) PublicKeyType() (pubkey_type int) {
pubkey_type = keyCertificate.CpkType.Int()
log.WithFields(logrus.Fields{
"pubkey_type": pubkey_type,
}).Debug("Retrieved publicKey type")
return keyCertificate.CpkType.Int()
}
// ConstructPublicKey returns a publicKey constructed using any excess data that may be stored in the KeyCertififcate.
// Returns enr errors encountered while parsing.
func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.RecievingPublicKey, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Constructing publicKey from keyCertificate")
key_type := keyCertificate.PublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < keyCertificate.CryptoSize() {
log.WithFields(logrus.Fields{
"at": "(keyCertificate) ConstructPublicKey",
"data_len": data_len,
"required_len": KEYCERT_PUBKEY_SIZE,
"reason": "not enough data",
}).Error("error constructing public key")
err = oops.Errorf("error constructing public key: not enough data")
return
}
switch key_type {
case KEYCERT_CRYPTO_ELG:
var elg_key crypto.ElgPublicKey
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = elg_key
log.Debug("Constructed ElgPublicKey")
case KEYCERT_CRYPTO_X25519:
var ed25519_key crypto.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = ed25519_key
log.Debug("Constructed Ed25519PublicKey")
default:
log.WithFields(logrus.Fields{
"key_type": key_type,
}).Warn("Unknown public key type")
}
return
}
const (
CRYPTO_KEY_TYPE_ELGAMAL = 0 // ElGamal
// Signature Types
SIGNATURE_TYPE_DSA_SHA1 = 0 // DSA-SHA1
SIGNATURE_TYPE_ED25519_SHA512 = 7 // Ed25519
)
var CryptoPublicKeySizes = map[uint16]int{
CRYPTO_KEY_TYPE_ELGAMAL: 256,
}
var SignaturePublicKeySizes = map[uint16]int{
SIGNATURE_TYPE_DSA_SHA1: 128,
SIGNATURE_TYPE_ED25519_SHA512: 32,
}
func (keyCertificate *KeyCertificate) CryptoPublicKeySize() (int, error) {
size, exists := CryptoPublicKeySizes[uint16(keyCertificate.CpkType.Int())]
if !exists {
return 0, oops.Errorf("unknown crypto key type: %d", keyCertificate.CpkType.Int())
}
return size, nil
}
func (keyCertificate *KeyCertificate) SigningPublicKeySize() int {
spk_type := keyCertificate.SpkType
switch spk_type.Int() {
case SIGNATURE_TYPE_DSA_SHA1:
log.Debug("Returning DSA_SHA1")
return 128
case signature.SIGNATURE_TYPE_ECDSA_SHA256_P256:
log.Debug("Returning ECDSA_SHA256_P256")
return 64
case signature.SIGNATURE_TYPE_ECDSA_SHA384_P384:
return 96
case signature.SIGNATURE_TYPE_ECDSA_SHA512_P521:
return 132
case signature.SIGNATURE_TYPE_RSA_SHA256_2048:
return 256
case signature.SIGNATURE_TYPE_RSA_SHA384_3072:
return 384
case signature.SIGNATURE_TYPE_RSA_SHA512_4096:
return 512
case SIGNATURE_TYPE_ED25519_SHA512:
return 32
default:
return 128
}
}
// ConstructSigningPublicKey returns a SingingPublicKey constructed using any excess data that may be stored in the KeyCertificate.
// Returns any errors encountered while parsing.
func (keyCertificate 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 := keyCertificate.SigningPublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < keyCertificate.SignatureSize() {
log.WithFields(logrus.Fields{
"at": "(keyCertificate) ConstructSigningPublicKey",
"data_len": data_len,
"required_len": KEYCERT_SPK_SIZE,
"reason": "not enough data",
}).Error("error constructing signing public key")
err = oops.Errorf("error constructing signing public key: not enough data")
return
}
switch signing_key_type {
case KEYCERT_SIGN_DSA_SHA1:
var dsa_key crypto.DSAPublicKey
copy(dsa_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_DSA_SHA1_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = dsa_key
log.Debug("Constructed DSAPublicKey")
case KEYCERT_SIGN_P256:
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_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_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 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:
/*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:
/*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:
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:
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")
return nil, oops.Errorf("unknown signing key type")
}
return
}
// SignatureSize return the size of a Signature corresponding to the Key Certificate's signingPublicKey type.
func (keyCertificate KeyCertificate) SignatureSize() (size int) {
sizes := map[int]int{
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
}
key_type := keyCertificate.SigningPublicKeyType()
size, exists := sizes[key_type]
if !exists {
log.WithFields(logrus.Fields{
"key_type": key_type,
}).Warn("Unknown signing key type")
return 0 // Or handle error appropriately
}
log.WithFields(logrus.Fields{
"key_type": key_type,
"signature_size": size,
}).Debug("Retrieved signature size")
return sizes[int(key_type)]
}
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's publicKey type.
func (keyCertificate KeyCertificate) CryptoSize() (size int) {
sizes := map[int]int{
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE,
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
}
key_type := keyCertificate.PublicKeyType()
size = sizes[int(key_type)]
log.WithFields(logrus.Fields{
"key_type": key_type,
"crypto_size": size,
}).Debug("Retrieved crypto size")
return sizes[int(key_type)]
}
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
log.WithFields(logrus.Fields{
"input_length": len(bytes),
}).Debug("Creating new keyCertificate")
var certificate Certificate
certificate, remainder, err = ReadCertificate(bytes)
if err != nil {
log.WithError(err).Error("Failed to read Certificate")
return
}
if certificate.Type() != CERT_KEY {
return nil, remainder, oops.Errorf("invalid certificate type: %d", certificate.Type())
}
if len(certificate.Data()) < 4 {
return nil, remainder, oops.Errorf("key certificate data too short")
}
log.Println("Certificate Data in NewKeyCertificate: ", certificate.Data()[0:2], certificate.Data()[2:4])
cpkType, _ := ReadInteger(certificate.Data()[2:4], 2)
spkType, _ := ReadInteger(certificate.Data()[0:2], 2)
key_certificate = &KeyCertificate{
Certificate: certificate,
CpkType: cpkType,
SpkType: spkType,
}
log.Println("cpkType in NewKeyCertificate: ", cpkType.Int(), "spkType in NewKeyCertificate: ", spkType.Int())
log.WithFields(logrus.Fields{
"spk_type": key_certificate.SpkType.Int(),
"cpk_type": key_certificate.CpkType.Int(),
"remainder_length": len(remainder),
}).Debug("Successfully created new keyCertificate")
return
}
func KeyCertificateFromCertificate(cert Certificate) (*KeyCertificate, error) {
if cert.Type() != CERT_KEY {
return nil, oops.Errorf("expected Key Certificate type, got %d", cert.Type())
}
data := cert.Data()
fmt.Printf("Certificate Data Length in KeyCertificateFromCertificate: %d\n", len(data))
fmt.Printf("Certificate Data Bytes in KeyCertificateFromCertificate: %v\n", data)
if len(data) < 4 {
return nil, oops.Errorf("certificate payload too short in KeyCertificateFromCertificate")
}
cpkTypeBytes := data[0:2]
spkTypeBytes := data[2:4]
fmt.Printf("cpkTypeBytes in KeyCertificateFromCertificate: %v\n", cpkTypeBytes)
fmt.Printf("spkTypeBytes in KeyCertificateFromCertificate: %v\n", spkTypeBytes)
cpkType := Integer(cpkTypeBytes)
spkType := Integer(spkTypeBytes)
fmt.Printf("cpkType (Int) in KeyCertificateFromCertificate: %d\n", cpkType.Int())
fmt.Printf("spkType (Int) in KeyCertificateFromCertificate: %d\n", spkType.Int())
keyCert := &KeyCertificate{
Certificate: cert,
CpkType: cpkType,
SpkType: spkType,
}
return keyCert, nil
}

View File

@ -0,0 +1,764 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
-->
<!-- Title: gocallvis Pages: 1 -->
<svg width="869pt" height="1198pt"
viewBox="0.00 0.00 868.95 1198.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(0 1198)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-1198 868.947,-1198 868.947,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-1190 860.947,-1190 860.947,-8 8,-8"/>
<text text-anchor="middle" x="434.4735" y="-1169.8" font-family="Arial" font-size="18.00" fill="#000000">key_certificate</text>
</g>
<g id="clust7" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate</title>
<g id="a_clust7"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M28,-616C28,-616 643.9118,-616 643.9118,-616 649.9118,-616 655.9118,-622 655.9118,-628 655.9118,-628 655.9118,-804 655.9118,-804 655.9118,-810 649.9118,-816 643.9118,-816 643.9118,-816 28,-816 28,-816 22,-816 16,-810 16,-804 16,-804 16,-628 16,-628 16,-622 22,-616 28,-616"/>
<text text-anchor="middle" x="335.9559" y="-624.5" font-family="Arial" font-size="15.00" fill="#222222">(KeyCertificate)</text>
</a>
</g>
</g>
<g id="clust6" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer</title>
<g id="a_clust6"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M773.0248,-279C773.0248,-279 821.0248,-279 821.0248,-279 827.0248,-279 833.0248,-285 833.0248,-291 833.0248,-291 833.0248,-345 833.0248,-345 833.0248,-351 827.0248,-357 821.0248,-357 821.0248,-357 773.0248,-357 773.0248,-357 767.0248,-357 761.0248,-351 761.0248,-345 761.0248,-345 761.0248,-291 761.0248,-291 761.0248,-285 767.0248,-279 773.0248,-279"/>
<text text-anchor="middle" x="797.0248" y="-287.5" font-family="Arial" font-size="15.00" fill="#222222">(Integer)</text>
</a>
</g>
</g>
<g id="clust5" class="cluster">
<title>cluster_*github.com/sirupsen/logrus.Logger</title>
<g id="a_clust5"><a xlink:title="type: *github.com/sirupsen/logrus.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M769.9673,-511C769.9673,-511 824.0823,-511 824.0823,-511 830.0823,-511 836.0823,-517 836.0823,-523 836.0823,-523 836.0823,-638 836.0823,-638 836.0823,-644 830.0823,-650 824.0823,-650 824.0823,-650 769.9673,-650 769.9673,-650 763.9673,-650 757.9673,-644 757.9673,-638 757.9673,-638 757.9673,-523 757.9673,-523 757.9673,-517 763.9673,-511 769.9673,-511"/>
<text text-anchor="middle" x="797.0248" y="-519.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust4" class="cluster">
<title>cluster_*github.com/go&#45;i2p/logger.Logger</title>
<g id="a_clust4"><a xlink:title="type: *github.com/go&#45;i2p/logger.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M757.9154,-835C757.9154,-835 836.1342,-835 836.1342,-835 842.1342,-835 848.1342,-841 848.1342,-847 848.1342,-847 848.1342,-1084 848.1342,-1084 848.1342,-1090 842.1342,-1096 836.1342,-1096 836.1342,-1096 757.9154,-1096 757.9154,-1096 751.9154,-1096 745.9154,-1090 745.9154,-1084 745.9154,-1084 745.9154,-847 745.9154,-847 745.9154,-841 751.9154,-835 757.9154,-835"/>
<text text-anchor="middle" x="797.0248" y="-843.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<g id="clust3" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate</title>
<g id="a_clust3"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M498.8136,-204C498.8136,-204 641.5794,-204 641.5794,-204 647.5794,-204 653.5794,-210 653.5794,-216 653.5794,-216 653.5794,-331 653.5794,-331 653.5794,-337 647.5794,-343 641.5794,-343 641.5794,-343 498.8136,-343 498.8136,-343 492.8136,-343 486.8136,-337 486.8136,-331 486.8136,-331 486.8136,-216 486.8136,-216 486.8136,-210 492.8136,-204 498.8136,-204"/>
<text text-anchor="middle" x="570.1965" y="-212.5" font-family="Arial" font-size="15.00" fill="#222222">(*KeyCertificate)</text>
</a>
</g>
</g>
<g id="clust2" class="cluster">
<title>cluster_*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M760.2527,-16C760.2527,-16 834.7969,-16 834.7969,-16 840.7969,-16 846.7969,-22 846.7969,-28 846.7969,-28 846.7969,-204 846.7969,-204 846.7969,-210 840.7969,-216 834.7969,-216 834.7969,-216 760.2527,-216 760.2527,-216 754.2527,-216 748.2527,-210 748.2527,-204 748.2527,-204 748.2527,-28 748.2527,-28 748.2527,-22 754.2527,-16 760.2527,-16"/>
<text text-anchor="middle" x="797.5248" y="-24.5" font-family="Arial" font-size="15.00" fill="#222222">(*Certificate)</text>
</a>
</g>
</g>
<!-- github.com/samber/oops.Errorf -->
<g id="node1" class="node">
<title>github.com/samber/oops.Errorf</title>
<g id="a_node1"><a xlink:title="github.com/samber/oops.Errorf | defined in oops.go:34">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M814.2201,-269C814.2201,-269 779.8295,-269 779.8295,-269 773.8295,-269 767.8295,-263 767.8295,-257 767.8295,-257 767.8295,-245 767.8295,-245 767.8295,-239 773.8295,-233 779.8295,-233 779.8295,-233 814.2201,-233 814.2201,-233 820.2201,-233 826.2201,-239 826.2201,-245 826.2201,-245 826.2201,-257 826.2201,-257 826.2201,-263 820.2201,-269 814.2201,-269"/>
<text text-anchor="middle" x="797.0248" y="-255.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="797.0248" y="-238.4" font-family="Verdana" font-size="14.00" fill="#000000">Errorf</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate | defined in key_certificate.go:356&#10;at key_certificate.go:368: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:369: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:369: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:373: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:362: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]&#10;at key_certificate.go:384: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:384: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:387: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:388: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:364: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at key_certificate.go:372: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:375: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:375: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:377: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:378: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:375: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:384: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:377: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:378: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:357: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:386: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:359: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:390: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:364: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M624.5242,-440C624.5242,-440 515.8688,-440 515.8688,-440 509.8688,-440 503.8688,-434 503.8688,-428 503.8688,-428 503.8688,-416 503.8688,-416 503.8688,-410 509.8688,-404 515.8688,-404 515.8688,-404 624.5242,-404 624.5242,-404 630.5242,-404 636.5242,-410 636.5242,-416 636.5242,-416 636.5242,-428 636.5242,-428 636.5242,-434 630.5242,-440 624.5242,-440"/>
<text text-anchor="middle" x="570.1965" y="-417.8" font-family="Verdana" font-size="14.00" fill="#000000">NewKeyCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge18" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge18"><a xlink:title="at key_certificate.go:369: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:373: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M596.8742,-403.9091C617.0949,-389.7754 645.2117,-369.2031 668.1026,-349 703.2178,-318.008 702.1893,-299.0641 741.1026,-273 746.3929,-269.4565 752.3392,-266.3522 758.328,-263.6791"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.7675,-266.8716 767.6857,-259.8322 757.1059,-260.3973 759.7675,-266.8716"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate | defined in certificate.go:201">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M840.8693,-411C840.8693,-411 753.1803,-411 753.1803,-411 747.1803,-411 741.1803,-405 741.1803,-399 741.1803,-399 741.1803,-387 741.1803,-387 741.1803,-381 747.1803,-375 753.1803,-375 753.1803,-375 840.8693,-375 840.8693,-375 846.8693,-375 852.8693,-381 852.8693,-387 852.8693,-387 852.8693,-399 852.8693,-399 852.8693,-405 846.8693,-411 840.8693,-411"/>
<text text-anchor="middle" x="797.0248" y="-397.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="797.0248" y="-380.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="edge20" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_edge20"><a xlink:title="at key_certificate.go:362: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]">
<path fill="none" stroke="#8b4513" d="M636.7198,-413.495C666.3047,-409.7126 701.0564,-405.2696 730.6267,-401.489"/>
<polygon fill="#8b4513" stroke="#8b4513" points="731.3777,-404.9216 740.853,-400.1816 730.4899,-397.9781 731.3777,-404.9216"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger -->
<g id="node4" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger</title>
<g id="a_node4"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger | defined in integer.go:51">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M831.4325,-472C831.4325,-472 762.6171,-472 762.6171,-472 756.6171,-472 750.6171,-466 750.6171,-460 750.6171,-460 750.6171,-448 750.6171,-448 750.6171,-442 756.6171,-436 762.6171,-436 762.6171,-436 831.4325,-436 831.4325,-436 837.4325,-436 843.4325,-442 843.4325,-448 843.4325,-448 843.4325,-460 843.4325,-460 843.4325,-466 837.4325,-472 831.4325,-472"/>
<text text-anchor="middle" x="797.0248" y="-458.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="797.0248" y="-441.4" font-family="Verdana" font-size="14.00" fill="#000000">ReadInteger</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger -->
<g id="edge42" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger</title>
<g id="a_edge42"><a xlink:title="at key_certificate.go:377: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:378: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]">
<path fill="none" stroke="#8b4513" d="M636.7198,-431.3848C669.748,-436.0443 709.2155,-441.6122 740.7245,-446.0574"/>
<polygon fill="#8b4513" stroke="#8b4513" points="740.2658,-449.5273 750.6567,-447.4586 741.2437,-442.5959 740.2658,-449.5273"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="node9" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_node9"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type | defined in certificate.go:116">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M824.9814,-147C824.9814,-147 769.0682,-147 769.0682,-147 763.0682,-147 757.0682,-141 757.0682,-135 757.0682,-135 757.0682,-123 757.0682,-123 757.0682,-117 763.0682,-111 769.0682,-111 769.0682,-111 824.9814,-111 824.9814,-111 830.9814,-111 836.9814,-117 836.9814,-123 836.9814,-123 836.9814,-135 836.9814,-135 836.9814,-141 830.9814,-147 824.9814,-147"/>
<text text-anchor="middle" x="797.0248" y="-133.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="797.0248" y="-116.4" font-family="Verdana" font-size="14.00" fill="#000000">Type</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="edge17" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_edge17"><a xlink:title="at key_certificate.go:368: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:369: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#8b4513" d="M603.5382,-403.7704C624.5147,-390.8516 650.7951,-371.7977 668.1026,-349 722.5518,-277.2789 681.9563,-227.8996 741.1026,-160 743.3959,-157.3673 745.9699,-154.9135 748.7209,-152.6345"/>
<polygon fill="#8b4513" stroke="#8b4513" points="750.8606,-155.4057 756.8567,-146.6709 746.7222,-149.76 750.8606,-155.4057"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="node10" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_node10"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data | defined in certificate.go:134">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M824.9814,-208C824.9814,-208 769.0682,-208 769.0682,-208 763.0682,-208 757.0682,-202 757.0682,-196 757.0682,-196 757.0682,-184 757.0682,-184 757.0682,-178 763.0682,-172 769.0682,-172 769.0682,-172 824.9814,-172 824.9814,-172 830.9814,-172 836.9814,-178 836.9814,-184 836.9814,-184 836.9814,-196 836.9814,-196 836.9814,-202 830.9814,-208 824.9814,-208"/>
<text text-anchor="middle" x="797.0248" y="-194.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="797.0248" y="-177.4" font-family="Verdana" font-size="14.00" fill="#000000">Data</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="edge27" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_edge27"><a xlink:title="at key_certificate.go:372: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:375: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:375: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:377: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:378: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#8b4513" d="M601.2704,-403.9136C622.0733,-390.6712 649.0339,-371.192 668.1026,-349 713.0667,-296.671 689.5991,-257.9074 741.1026,-212 743.2565,-210.0801 745.5977,-208.3183 748.0606,-206.7028"/>
<polygon fill="#8b4513" stroke="#8b4513" points="749.8257,-209.7255 756.8078,-201.7567 746.3802,-203.6322 749.8257,-209.7255"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="node13" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_node13"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithFields | defined in log.go:60">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M828.2439,-966C828.2439,-966 765.8057,-966 765.8057,-966 759.8057,-966 753.8057,-960 753.8057,-954 753.8057,-954 753.8057,-942 753.8057,-942 753.8057,-936 759.8057,-930 765.8057,-930 765.8057,-930 828.2439,-930 828.2439,-930 834.2439,-930 840.2439,-936 840.2439,-942 840.2439,-942 840.2439,-954 840.2439,-954 840.2439,-960 834.2439,-966 828.2439,-966"/>
<text text-anchor="middle" x="797.0248" y="-952.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-935.4" font-family="Verdana" font-size="14.00" fill="#000000">WithFields</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge47" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge47"><a xlink:title="at key_certificate.go:357: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:386: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M581.3431,-440.0377C601.1893,-472.8081 642.9244,-544.7714 668.1026,-610 691.4331,-670.4419 690.0503,-687.9844 705.1026,-751 722.7428,-824.8496 695.4332,-857.3432 741.1026,-918 742.5025,-919.8594 744.0522,-921.6161 745.7174,-923.2746"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.741,-926.185 753.652,-929.9296 748.2394,-920.8217 743.741,-926.185"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="node14" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_node14"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).Error | defined in log.go:42">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M814.7911,-1027C814.7911,-1027 779.2585,-1027 779.2585,-1027 773.2585,-1027 767.2585,-1021 767.2585,-1015 767.2585,-1015 767.2585,-1003 767.2585,-1003 767.2585,-997 773.2585,-991 779.2585,-991 779.2585,-991 814.7911,-991 814.7911,-991 820.7911,-991 826.7911,-997 826.7911,-1003 826.7911,-1003 826.7911,-1015 826.7911,-1015 826.7911,-1021 820.7911,-1027 814.7911,-1027"/>
<text text-anchor="middle" x="797.0248" y="-1013.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-996.4" font-family="Verdana" font-size="14.00" fill="#000000">Error</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge26" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge26"><a xlink:title="at key_certificate.go:364: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M581.9063,-440.1476C602.451,-472.8028 644.9967,-544.2038 668.1026,-610 723.495,-767.735 641.686,-844.5939 741.1026,-979 745.5619,-985.0288 751.603,-989.9724 758.0695,-993.9818"/>
<polygon fill="#8b4513" stroke="#8b4513" points="756.5889,-997.1611 767.0427,-998.8842 759.9451,-991.0181 756.5889,-997.1611"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="node16" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_node16"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithError | defined in log.go:66">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M825.5563,-905C825.5563,-905 768.4933,-905 768.4933,-905 762.4933,-905 756.4933,-899 756.4933,-893 756.4933,-893 756.4933,-881 756.4933,-881 756.4933,-875 762.4933,-869 768.4933,-869 768.4933,-869 825.5563,-869 825.5563,-869 831.5563,-869 837.5563,-875 837.5563,-881 837.5563,-881 837.5563,-893 837.5563,-893 837.5563,-899 831.5563,-905 825.5563,-905"/>
<text text-anchor="middle" x="797.0248" y="-891.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-874.4" font-family="Verdana" font-size="14.00" fill="#000000">WithError</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="edge49" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_edge49"><a xlink:title="at key_certificate.go:364: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M579.9178,-440.0117C597.8251,-473.3324 637.033,-546.9525 668.1026,-610 712.7258,-700.5509 762.2521,-809.5549 784.7302,-859.5321"/>
<polygon fill="#8b4513" stroke="#8b4513" points="781.5658,-861.0294 788.8557,-868.7176 787.9513,-858.1614 781.5658,-861.0294"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Debug -->
<g id="node17" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_node17"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Debug | defined in logger.go:221">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M815.8468,-642C815.8468,-642 778.2028,-642 778.2028,-642 772.2028,-642 766.2028,-636 766.2028,-630 766.2028,-630 766.2028,-618 766.2028,-618 766.2028,-612 772.2028,-606 778.2028,-606 778.2028,-606 815.8468,-606 815.8468,-606 821.8468,-606 827.8468,-612 827.8468,-618 827.8468,-618 827.8468,-630 827.8468,-630 827.8468,-636 821.8468,-642 815.8468,-642"/>
<text text-anchor="middle" x="797.0248" y="-628.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="797.0248" y="-611.4" font-family="Verdana" font-size="14.00" fill="#000000">Debug</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge48" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge48"><a xlink:title="at key_certificate.go:359: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:390: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M584.9677,-440.0797C612.8973,-473.4782 676.4662,-545.8263 741.1026,-594 746.1462,-597.759 751.7216,-601.3335 757.3408,-604.6188"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.6991,-607.7107 766.1369,-609.5284 759.1108,-601.5984 755.6991,-607.7107"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Println -->
<g id="node18" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Println</title>
<g id="a_node18"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Println | defined in logger.go:315">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M816.1399,-581C816.1399,-581 777.9097,-581 777.9097,-581 771.9097,-581 765.9097,-575 765.9097,-569 765.9097,-569 765.9097,-557 765.9097,-557 765.9097,-551 771.9097,-545 777.9097,-545 777.9097,-545 816.1399,-545 816.1399,-545 822.1399,-545 828.1399,-551 828.1399,-557 828.1399,-557 828.1399,-569 828.1399,-569 828.1399,-575 822.1399,-581 816.1399,-581"/>
<text text-anchor="middle" x="797.0248" y="-567.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="797.0248" y="-550.4" font-family="Verdana" font-size="14.00" fill="#000000">Println</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Println -->
<g id="edge28" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(*github.com/sirupsen/logrus.Logger).Println</title>
<g id="a_edge28"><a xlink:title="at key_certificate.go:375: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:384: calling [(*github.com/sirupsen/logrus.Logger).Println]">
<path fill="none" stroke="#8b4513" d="M613.0003,-440.1284C640.9539,-453.2026 677.2897,-472.6265 705.1026,-496 724.7105,-512.4782 720.4893,-525.7984 741.1026,-541 745.8362,-544.4909 751.1969,-547.5111 756.679,-550.0988"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.3592,-553.3409 765.9302,-554.0519 758.1098,-546.904 755.3592,-553.3409"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="node19" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_node19"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int | defined in integer.go:32">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M812.0248,-349C812.0248,-349 782.0248,-349 782.0248,-349 776.0248,-349 770.0248,-343 770.0248,-337 770.0248,-337 770.0248,-325 770.0248,-325 770.0248,-319 776.0248,-313 782.0248,-313 782.0248,-313 812.0248,-313 812.0248,-313 818.0248,-313 824.0248,-319 824.0248,-325 824.0248,-325 824.0248,-337 824.0248,-337 824.0248,-343 818.0248,-349 812.0248,-349"/>
<text text-anchor="middle" x="797.0248" y="-335.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="797.0248" y="-318.4" font-family="Verdana" font-size="14.00" fill="#000000">Int</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge21" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge21"><a xlink:title="at key_certificate.go:384: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:384: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:387: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:388: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M614.774,-403.8763C649.2358,-389.8959 698.151,-370.1187 741.1026,-353 747.4188,-350.4826 754.1434,-347.8212 760.6591,-345.2522"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.9606,-348.5013 769.9839,-341.5819 759.3968,-341.9877 761.9606,-348.5013"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init</title>
<g id="a_node5"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init | defined in .:0&#10;at key_certificate.go:44: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M129.5505,-52C129.5505,-52 99.5505,-52 99.5505,-52 93.5505,-52 87.5505,-46 87.5505,-40 87.5505,-40 87.5505,-28 87.5505,-28 87.5505,-22 93.5505,-16 99.5505,-16 99.5505,-16 129.5505,-16 129.5505,-16 135.5505,-16 141.5505,-22 141.5505,-28 141.5505,-28 141.5505,-40 141.5505,-40 141.5505,-46 135.5505,-52 129.5505,-52"/>
<text text-anchor="middle" x="114.5505" y="-29.8" font-family="Verdana" font-size="14.00" fill="#000000">init</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/logger.GetGoI2PLogger | defined in log.go:120">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M387.3852,-52C387.3852,-52 290.0062,-52 290.0062,-52 284.0062,-52 278.0062,-46 278.0062,-40 278.0062,-40 278.0062,-28 278.0062,-28 278.0062,-22 284.0062,-16 290.0062,-16 290.0062,-16 387.3852,-16 387.3852,-16 393.3852,-16 399.3852,-22 399.3852,-28 399.3852,-28 399.3852,-40 399.3852,-40 399.3852,-46 393.3852,-52 387.3852,-52"/>
<text text-anchor="middle" x="338.6957" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="338.6957" y="-21.4" font-family="Verdana" font-size="14.00" fill="#000000">GetGoI2PLogger</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge2"><a xlink:title="at key_certificate.go:44: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M141.5876,-34C172.6327,-34 224.7965,-34 267.6649,-34"/>
<polygon fill="#8b4513" stroke="#8b4513" points="267.7801,-37.5001 277.7801,-34 267.7801,-30.5001 267.7801,-37.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate -->
<g id="node7" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate</title>
<g id="a_node7"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate | defined in key_certificate.go:395&#10;at key_certificate.go:417: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:418: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:396: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:397: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:397: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:405: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:400: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M656.0088,-94C656.0088,-94 484.3842,-94 484.3842,-94 478.3842,-94 472.3842,-88 472.3842,-82 472.3842,-82 472.3842,-70 472.3842,-70 472.3842,-64 478.3842,-58 484.3842,-58 484.3842,-58 656.0088,-58 656.0088,-58 662.0088,-58 668.0088,-64 668.0088,-70 668.0088,-70 668.0088,-82 668.0088,-82 668.0088,-88 662.0088,-94 656.0088,-94"/>
<text text-anchor="middle" x="570.1965" y="-71.8" font-family="Verdana" font-size="14.00" fill="#000000">KeyCertificateFromCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge34" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge34"><a xlink:title="at key_certificate.go:397: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:405: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M667.4137,-94.0023C681.2903,-99.8803 694.4451,-107.6723 705.1026,-118 740.2286,-152.0391 709.1149,-184.9962 741.1026,-222 745.9705,-227.6313 752.203,-232.3181 758.7302,-236.1646"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.2348,-239.3328 767.7133,-240.8988 760.4984,-233.1401 757.2348,-239.3328"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type -->
<g id="edge22" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_edge22"><a xlink:title="at key_certificate.go:396: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:397: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#8b4513" d="M636.8741,-57.9784C659.2304,-55.0617 683.8606,-55.376 705.1026,-64 725.7789,-72.3943 723.0955,-85.8197 741.1026,-99 744.2629,-101.3132 747.6237,-103.5624 751.0685,-105.7208"/>
<polygon fill="#8b4513" stroke="#8b4513" points="749.3552,-108.774 759.7378,-110.8837 752.9369,-102.7598 749.3552,-108.774"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="edge50" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_edge50"><a xlink:title="at key_certificate.go:400: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#8b4513" d="M668.2729,-75.4271C681.4078,-78.5464 694.1161,-83.4785 705.1026,-91 733.6444,-110.54 716.7851,-135.4012 741.1026,-160 743.4263,-162.3506 745.9733,-164.5622 748.6595,-166.6352"/>
<polygon fill="#8b4513" stroke="#8b4513" points="746.8354,-169.6291 757.051,-172.4385 750.817,-163.8718 746.8354,-169.6291"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge12" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge12"><a xlink:title="at key_certificate.go:417: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:418: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M585.6811,-94.1768C605.4669,-117.6504 640.4609,-160.0092 668.1026,-198 702.8417,-245.7453 695.2619,-271.7837 741.1026,-309 746.8382,-313.6565 753.6796,-317.4203 760.5761,-320.4288"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.3279,-323.6987 769.916,-324.0763 761.8743,-317.1783 759.3279,-323.6987"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes -->
<g id="node8" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes</title>
<g id="a_node8"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes | defined in certificate.go:76">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M825.5703,-86C825.5703,-86 768.4793,-86 768.4793,-86 762.4793,-86 756.4793,-80 756.4793,-74 756.4793,-74 756.4793,-62 756.4793,-62 756.4793,-56 762.4793,-50 768.4793,-50 768.4793,-50 825.5703,-50 825.5703,-50 831.5703,-50 837.5703,-56 837.5703,-62 837.5703,-62 837.5703,-74 837.5703,-74 837.5703,-80 831.5703,-86 825.5703,-86"/>
<text text-anchor="middle" x="797.0248" y="-72.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="797.0248" y="-55.4" font-family="Verdana" font-size="14.00" fill="#000000">RawBytes</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize -->
<g id="node11" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize</title>
<g id="a_node11"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize | defined in key_certificate.go:200&#10;at key_certificate.go:202: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:204: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:207: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M633.4625,-335C633.4625,-335 506.9305,-335 506.9305,-335 500.9305,-335 494.9305,-329 494.9305,-323 494.9305,-323 494.9305,-311 494.9305,-311 494.9305,-305 500.9305,-299 506.9305,-299 506.9305,-299 633.4625,-299 633.4625,-299 639.4625,-299 645.4625,-305 645.4625,-311 645.4625,-311 645.4625,-323 645.4625,-323 645.4625,-329 639.4625,-335 633.4625,-335"/>
<text text-anchor="middle" x="570.1965" y="-312.8" font-family="Verdana" font-size="14.00" fill="#000000">SigningPublicKeySize</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge35" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge35"><a xlink:title="at key_certificate.go:204: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:207: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M645.8645,-325.397C654.0179,-328.7052 661.6716,-333.1247 668.1026,-339 755.1358,-418.513 668.3555,-501.2372 741.1026,-594 745.4422,-599.5336 751.0942,-604.1728 757.1344,-608.0195"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.7236,-611.2419 766.1542,-613.1004 759.1592,-605.1429 755.7236,-611.2419"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge23" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeySize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge23"><a xlink:title="at key_certificate.go:202: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M645.5417,-316.5867C664.9665,-316.8997 685.8285,-317.6037 705.1026,-319 723.1812,-320.3097 743.1442,-322.7896 759.8344,-325.1566"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.3568,-328.6239 769.7574,-326.6043 760.3674,-321.6972 759.3568,-328.6239"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize -->
<g id="node12" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize</title>
<g id="a_node12"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize | defined in key_certificate.go:192&#10;at key_certificate.go:193: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:195: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:195: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M631.2863,-274C631.2863,-274 509.1067,-274 509.1067,-274 503.1067,-274 497.1067,-268 497.1067,-262 497.1067,-262 497.1067,-250 497.1067,-250 497.1067,-244 503.1067,-238 509.1067,-238 509.1067,-238 631.2863,-238 631.2863,-238 637.2863,-238 643.2863,-244 643.2863,-250 643.2863,-250 643.2863,-262 643.2863,-262 643.2863,-268 637.2863,-274 631.2863,-274"/>
<text text-anchor="middle" x="570.1965" y="-251.8" font-family="Verdana" font-size="14.00" fill="#000000">CryptoPublicKeySize</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge46" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge46"><a xlink:title="at key_certificate.go:195: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M643.517,-254.3457C663.1929,-253.9049 684.4582,-253.4315 704.1026,-253 721.5707,-252.6163 740.8861,-252.1994 757.361,-251.846"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.8064,-255.3374 767.7291,-251.6239 757.6564,-248.339 757.8064,-255.3374"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge24" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoPublicKeySize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge24"><a xlink:title="at key_certificate.go:193: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:195: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M627.9893,-274.0642C641.1902,-278.2555 655.1461,-282.7384 668.1026,-287 699.2407,-297.2418 734.4523,-309.2911 760.1991,-318.1886"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.3255,-321.5899 769.9203,-321.5536 761.6153,-314.975 759.3255,-321.5899"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="node15" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_node15"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).Warn | defined in log.go:30">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M814.7911,-1088C814.7911,-1088 779.2585,-1088 779.2585,-1088 773.2585,-1088 767.2585,-1082 767.2585,-1076 767.2585,-1076 767.2585,-1064 767.2585,-1064 767.2585,-1058 773.2585,-1052 779.2585,-1052 779.2585,-1052 814.7911,-1052 814.7911,-1052 820.7911,-1052 826.7911,-1058 826.7911,-1064 826.7911,-1064 826.7911,-1076 826.7911,-1076 826.7911,-1082 820.7911,-1088 814.7911,-1088"/>
<text text-anchor="middle" x="797.0248" y="-1074.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-1057.4" font-family="Verdana" font-size="14.00" fill="#000000">Warn</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType -->
<g id="node20" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType</title>
<g id="a_node20"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType | defined in key_certificate.go:117&#10;at key_certificate.go:118: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:122: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:121: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:119: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M636.1277,-747C636.1277,-747 504.2653,-747 504.2653,-747 498.2653,-747 492.2653,-741 492.2653,-735 492.2653,-735 492.2653,-723 492.2653,-723 492.2653,-717 498.2653,-711 504.2653,-711 504.2653,-711 636.1277,-711 636.1277,-711 642.1277,-711 648.1277,-717 648.1277,-723 648.1277,-723 648.1277,-735 648.1277,-735 648.1277,-741 642.1277,-747 636.1277,-747"/>
<text text-anchor="middle" x="570.1965" y="-724.8" font-family="Verdana" font-size="14.00" fill="#000000">SigningPublicKeyType</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge36" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge36"><a xlink:title="at key_certificate.go:119: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M635.1572,-747.0429C660.136,-756.9365 686.9783,-771.6613 705.1026,-793 742.5292,-837.0644 704.7763,-873.0242 741.1026,-918 742.7078,-919.9874 744.481,-921.8609 746.3786,-923.6248"/>
<polygon fill="#8b4513" stroke="#8b4513" points="744.2256,-926.3846 754.2222,-929.8944 748.5962,-920.9167 744.2256,-926.3846"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge14" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge14"><a xlink:title="at key_certificate.go:121: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M644.8739,-710.9421C653.0147,-707.5817 660.9359,-703.632 668.1026,-699 688.4688,-685.8368 684.0953,-671.7025 704.1026,-658 719.8601,-647.2081 739.4571,-639.3771 756.5865,-633.9707"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.7558,-637.2744 766.3393,-631.0636 755.7561,-630.5661 757.7558,-637.2744"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge13" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge13"><a xlink:title="at key_certificate.go:118: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:122: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M648.07,-713.9279C655.5391,-710.0271 662.4293,-705.1342 668.1026,-699 719.4262,-643.507 689.4674,-606.9535 705.1026,-533 721.9781,-453.1801 688.7512,-415.5726 741.1026,-353 746.0734,-347.0587 752.8651,-342.7131 760.0032,-339.5374"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.6587,-342.6561 769.8133,-335.892 759.2204,-336.0945 761.6587,-342.6561"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="node21" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_node21"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType | defined in key_certificate.go:126&#10;at key_certificate.go:128: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:130: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:127: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:131: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M614.0634,-686C614.0634,-686 526.3296,-686 526.3296,-686 520.3296,-686 514.3296,-680 514.3296,-674 514.3296,-674 514.3296,-662 514.3296,-662 514.3296,-656 520.3296,-650 526.3296,-650 526.3296,-650 614.0634,-650 614.0634,-650 620.0634,-650 626.0634,-656 626.0634,-662 626.0634,-662 626.0634,-674 626.0634,-674 626.0634,-680 620.0634,-686 614.0634,-686"/>
<text text-anchor="middle" x="570.1965" y="-663.8" font-family="Verdana" font-size="14.00" fill="#000000">PublicKeyType</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge15" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge15"><a xlink:title="at key_certificate.go:128: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M626.1211,-676.7869C641.1497,-681.3767 656.4473,-688.3638 668.1026,-699 743.8881,-768.159 677.1256,-837.7918 741.1026,-918 742.6956,-919.9972 744.4589,-921.8787 746.3484,-923.6491"/>
<polygon fill="#8b4513" stroke="#8b4513" points="744.1829,-926.3989 754.1697,-929.9365 748.5687,-920.9432 744.1829,-926.3989"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge25" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge25"><a xlink:title="at key_certificate.go:130: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M626.0014,-649.968C649.8245,-642.9544 678.084,-635.5303 704.1026,-631 720.9685,-628.0634 739.7683,-626.3584 756.0215,-625.3687"/>
<polygon fill="#8b4513" stroke="#8b4513" points="756.4911,-628.8486 766.2884,-624.8159 756.1146,-621.8587 756.4911,-628.8486"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge37" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge37"><a xlink:title="at key_certificate.go:127: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:131: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M626.3136,-665.5853C641.4337,-662.4116 656.7317,-656.5409 668.1026,-646 709.344,-607.7689 691.1057,-579.4661 705.1026,-525 724.5416,-449.3569 690.7196,-412.6766 741.1026,-353 746.0999,-347.0809 752.9027,-342.7447 760.0433,-339.571"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.6984,-342.6898 769.8519,-335.9245 759.2591,-336.1286 761.6984,-342.6898"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="node22" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_node22"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize | defined in key_certificate.go:336&#10;at key_certificate.go:344: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]&#10;at key_certificate.go:349: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:346: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M370.1859,-747C370.1859,-747 307.2055,-747 307.2055,-747 301.2055,-747 295.2055,-741 295.2055,-735 295.2055,-735 295.2055,-723 295.2055,-723 295.2055,-717 301.2055,-711 307.2055,-711 307.2055,-711 370.1859,-711 370.1859,-711 376.1859,-711 382.1859,-717 382.1859,-723 382.1859,-723 382.1859,-735 382.1859,-735 382.1859,-741 376.1859,-747 370.1859,-747"/>
<text text-anchor="middle" x="338.6957" y="-724.8" font-family="Verdana" font-size="14.00" fill="#000000">CryptoSize</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge38" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge38"><a xlink:title="at key_certificate.go:346: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M380.2059,-747.179C397.1496,-754.3392 417.0217,-762.4086 435.2904,-769 537.1692,-805.7584 576.109,-783.8366 668.1026,-841 708.1568,-865.8891 703.6251,-889.3777 741.1026,-918 744.0796,-920.2736 747.2523,-922.4725 750.5162,-924.5764"/>
<polygon fill="#8b4513" stroke="#8b4513" points="748.933,-927.7098 759.297,-929.9096 752.5669,-921.7269 748.933,-927.7098"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge19" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge19"><a xlink:title="at key_certificate.go:349: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M382.3547,-745.9975C447.4686,-768.5657 572.5878,-801.0664 668.1026,-760 719.7372,-737.7998 760.3936,-683.6278 781.3742,-650.7454"/>
<polygon fill="#8b4513" stroke="#8b4513" points="784.4544,-652.42 786.7629,-642.0797 778.51,-648.7235 784.4544,-652.42"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="edge16" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_edge16"><a xlink:title="at key_certificate.go:344: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]">
<path fill="none" stroke="#000000" d="M382.2392,-717.5264C416.6513,-708.4588 465.2401,-695.6558 504.3944,-685.3387"/>
<polygon fill="#000000" stroke="#000000" points="505.3531,-688.7056 514.1312,-682.7731 503.5695,-681.9367 505.3531,-688.7056"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey -->
<g id="node23" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey</title>
<g id="a_node23"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey | defined in key_certificate.go:136&#10;at key_certificate.go:152: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:137: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:145: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]&#10;at key_certificate.go:169: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at key_certificate.go:139: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:160: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:165: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:140: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]&#10;at key_certificate.go:151: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M171.0885,-747C171.0885,-747 58.0125,-747 58.0125,-747 52.0125,-747 46.0125,-741 46.0125,-735 46.0125,-735 46.0125,-723 46.0125,-723 46.0125,-717 52.0125,-711 58.0125,-711 58.0125,-711 171.0885,-711 171.0885,-711 177.0885,-711 183.0885,-717 183.0885,-723 183.0885,-723 183.0885,-735 183.0885,-735 183.0885,-741 177.0885,-747 171.0885,-747"/>
<text text-anchor="middle" x="114.5505" y="-724.8" font-family="Verdana" font-size="14.00" fill="#000000">ConstructPublicKey</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge1" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge1"><a xlink:title="at key_certificate.go:152: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M183.4532,-714.7794C191.5582,-710.759 199.0724,-705.6054 205.101,-699 381.6728,-505.5329 76.7661,-125 338.6957,-125 338.6957,-125 338.6957,-125 570.1965,-125 630.8101,-125 656.4962,-108.7863 705.1026,-145 735.3968,-167.5704 714.9437,-194.7443 741.1026,-222 746.2048,-227.3162 752.4949,-231.8428 758.9942,-235.6272"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.4181,-238.753 767.8946,-240.3322 760.6895,-232.5644 757.4181,-238.753"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge6" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge6"><a xlink:title="at key_certificate.go:137: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M183.2373,-743.5944C191.4789,-747.7621 199.0879,-753.1179 205.101,-760 259.3545,-822.0933 182.9957,-883.4954 241.101,-942 272.3021,-973.4155 294.4188,-962 338.6957,-962 338.6957,-962 338.6957,-962 435.7904,-962 555.5251,-962 586.1221,-982.4179 705.1026,-969 717.8097,-967.567 731.321,-965.0531 743.9625,-962.2515"/>
<polygon fill="#8b4513" stroke="#8b4513" points="744.9277,-965.6207 753.8823,-959.9581 743.3509,-958.8006 744.9277,-965.6207"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge41" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge41"><a xlink:title="at key_certificate.go:151: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M183.2823,-743.5552C191.5171,-747.7288 199.1122,-753.0968 205.101,-760 261.1363,-824.5913 191.3196,-879.4744 241.101,-949 252.1089,-964.3739 260.0127,-964.4913 278.101,-970 450.222,-1022.4188 668.5942,-1016.8824 757.0879,-1011.839"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.452,-1015.3235 767.2242,-1011.2303 757.0323,-1008.3361 757.452,-1015.3235"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="edge29" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge29"><a xlink:title="at key_certificate.go:169: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M183.3243,-743.5189C191.5527,-747.698 199.1349,-753.0771 205.101,-760 275.1143,-841.2414 181.4402,-943.538 278.101,-990 442.4792,-1069.0119 666.8896,-1073.3858 757.0883,-1071.5264"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.2475,-1075.0236 767.159,-1071.2804 757.0765,-1068.0257 757.2475,-1075.0236"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge39" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge39"><a xlink:title="at key_certificate.go:139: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:160: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:165: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M179.7005,-710.861C188.4758,-707.4337 197.1754,-703.4889 205.101,-699 273.2704,-660.3902 260.3517,-584 338.6957,-584 338.6957,-584 338.6957,-584 570.1965,-584 636.1837,-584 711.3507,-600.6208 756.4438,-612.4345"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.5775,-615.8258 766.1419,-615.0232 757.3829,-609.0626 755.5775,-615.8258"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="edge40" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_edge40"><a xlink:title="at key_certificate.go:140: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]">
<path fill="none" stroke="#000000" d="M173.8034,-710.9401C204.6185,-702.2754 243.072,-692.5869 278.101,-687 355.0715,-674.7236 444.6608,-670.3373 504.1193,-668.7935"/>
<polygon fill="#000000" stroke="#000000" points="504.2147,-672.2923 514.1277,-668.5531 504.0465,-665.2943 504.2147,-672.2923"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="edge7" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_edge7"><a xlink:title="at key_certificate.go:145: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]">
<path fill="none" stroke="#000000" d="M183.3247,-729C216.0448,-729 254.5833,-729 285.0924,-729"/>
<polygon fill="#000000" stroke="#000000" points="285.1111,-732.5001 295.1111,-729 285.1111,-725.5001 285.1111,-732.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data -->
<g id="node24" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data</title>
<g id="a_node24"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data | defined in key_certificate.go:108&#10;at key_certificate.go:110: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:112: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:109: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]&#10;at key_certificate.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M129.5505,-686C129.5505,-686 99.5505,-686 99.5505,-686 93.5505,-686 87.5505,-680 87.5505,-674 87.5505,-674 87.5505,-662 87.5505,-662 87.5505,-656 93.5505,-650 99.5505,-650 99.5505,-650 129.5505,-650 129.5505,-650 135.5505,-650 141.5505,-656 141.5505,-662 141.5505,-662 141.5505,-674 141.5505,-674 141.5505,-680 135.5505,-686 129.5505,-686"/>
<text text-anchor="middle" x="114.5505" y="-663.8" font-family="Verdana" font-size="14.00" fill="#000000">Data</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes -->
<g id="edge30" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes</title>
<g id="a_edge30"><a xlink:title="at key_certificate.go:109: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]&#10;at key_certificate.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]">
<path fill="none" stroke="#8b4513" d="M141.9287,-669.3268C162.6011,-668.7047 189.9181,-664.0934 205.101,-646 285.6875,-549.9656 152.4213,-171.6155 241.101,-83 253.5589,-70.5512 382.4012,-77.9928 399.2904,-73 434.9752,-62.4508 436.5018,-42.1915 472.2904,-32 571.4708,-3.7565 601.0031,-24.2227 704.1026,-22 726.6307,-21.5143 749.3452,-32.5024 766.6773,-43.8595"/>
<polygon fill="#8b4513" stroke="#8b4513" points="765.0063,-46.9595 775.2207,-49.7733 768.9904,-41.2039 765.0063,-46.9595"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge8" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge8"><a xlink:title="at key_certificate.go:110: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M141.7476,-671.3138C161.5079,-675.0183 187.726,-682.7917 205.101,-699 293.2352,-781.2161 218.1672,-935 338.6957,-935 338.6957,-935 338.6957,-935 435.7904,-935 545.0244,-935 672.7184,-941.0101 743.2682,-944.8573"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.4934,-948.375 753.6712,-945.4316 743.8793,-941.3857 743.4934,-948.375"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge9" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge9"><a xlink:title="at key_certificate.go:112: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M141.9295,-672.2203C161.2735,-676.3484 186.8938,-684.255 205.101,-699 283.0789,-762.1498 238.354,-881 338.6957,-881 338.6957,-881 338.6957,-881 435.7904,-881 567.0107,-881 624.2079,-863.3191 705.1026,-760 733.5146,-723.7121 762.7128,-678.9988 780.3657,-650.9862"/>
<polygon fill="#8b4513" stroke="#8b4513" points="783.5501,-652.4956 785.8919,-642.1628 777.6176,-648.78 783.5501,-652.4956"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey -->
<g id="node25" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey</title>
<g id="a_node25"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey | defined in key_certificate.go:228&#10;at key_certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at key_certificate.go:244: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:301: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:300: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at key_certificate.go:232: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]&#10;at key_certificate.go:237: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]&#10;at key_certificate.go:229: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:238: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:298: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:231: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:252: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:257: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:262: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:291: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:296: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M193.1515,-808C193.1515,-808 35.9495,-808 35.9495,-808 29.9495,-808 23.9495,-802 23.9495,-796 23.9495,-796 23.9495,-784 23.9495,-784 23.9495,-778 29.9495,-772 35.9495,-772 35.9495,-772 193.1515,-772 193.1515,-772 199.1515,-772 205.1515,-778 205.1515,-784 205.1515,-784 205.1515,-796 205.1515,-796 205.1515,-802 199.1515,-808 193.1515,-808"/>
<text text-anchor="middle" x="114.5505" y="-785.8" font-family="Verdana" font-size="14.00" fill="#000000">ConstructSigningPublicKey</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge4" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge4"><a xlink:title="at key_certificate.go:244: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:301: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M187.6597,-771.8102C193.9477,-768.5056 199.8877,-764.6045 205.101,-760 308.7479,-668.4577 355.3858,-271.8646 472.2904,-198 545.8628,-151.5143 582.7247,-181.1353 668.1026,-198 699.8907,-204.2791 733.6942,-218.4884 758.7091,-230.6148"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.329,-233.837 767.8435,-235.1395 760.4362,-227.5644 757.329,-233.837"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge43" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge43"><a xlink:title="at key_certificate.go:229: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:238: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:298: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M116.0225,-808.043C121.4043,-860.6999 145.0776,-1014.3968 241.101,-1077 274.1986,-1098.5783 665.3623,-1010.046 705.1026,-996 715.3602,-992.3745 736.4205,-981.4738 755.7972,-970.9753"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.7253,-973.9104 764.827,-966.048 754.3723,-967.7656 757.7253,-973.9104"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge3" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge3"><a xlink:title="at key_certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M115.8282,-808.0832C120.6995,-861.6104 143.1637,-1019.5315 241.101,-1084 407.0141,-1193.2144 661.4299,-1080.7977 758.0127,-1030.5784"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.9097,-1033.5352 767.1271,-1025.7789 756.6481,-1027.3414 759.9097,-1033.5352"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="edge5" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge5"><a xlink:title="at key_certificate.go:300: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M116.8316,-808.3983C127.0704,-881.9631 175.6599,-1151 338.6957,-1151 338.6957,-1151 338.6957,-1151 570.1965,-1151 630.8101,-1151 648.5152,-1152.7226 705.1026,-1131 727.691,-1122.3289 750.3702,-1107.3614 767.55,-1094.4232"/>
<polygon fill="#8b4513" stroke="#8b4513" points="769.7414,-1097.1531 775.5175,-1088.2712 765.4633,-1091.6125 769.7414,-1097.1531"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge44" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge44"><a xlink:title="at key_certificate.go:231: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:252: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:257: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:262: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:291: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:296: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M119.1898,-808.1063C131.0901,-850.28 167.1025,-954.6126 241.101,-996 303.3494,-1030.8156 331.0158,-989.6295 399.2904,-969 524.3611,-931.2093 571.1409,-937.5743 668.1026,-850 731.0327,-793.1625 770.9949,-698.1555 787.8344,-651.522"/>
<polygon fill="#8b4513" stroke="#8b4513" points="791.1418,-652.6671 791.1677,-642.0723 784.5405,-650.3385 791.1418,-652.6671"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType -->
<g id="edge10" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType</title>
<g id="a_edge10"><a xlink:title="at key_certificate.go:232: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="none" stroke="#000000" d="M179.1608,-771.9389C188.1072,-768.4844 196.9981,-764.5112 205.101,-760 242.0423,-739.4332 238.3554,-713.4202 278.101,-699 314.4298,-685.8195 410.1854,-698.7747 482.2324,-711.5308"/>
<polygon fill="#000000" stroke="#000000" points="481.7713,-715.0039 492.2325,-713.3266 483.0087,-708.1141 481.7713,-715.0039"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="node26" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_node26"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize | defined in key_certificate.go:308&#10;at key_certificate.go:323: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:328: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:320: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]&#10;at key_certificate.go:331: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:325: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M377.452,-808C377.452,-808 299.9394,-808 299.9394,-808 293.9394,-808 287.9394,-802 287.9394,-796 287.9394,-796 287.9394,-784 287.9394,-784 287.9394,-778 293.9394,-772 299.9394,-772 299.9394,-772 377.452,-772 377.452,-772 383.452,-772 389.452,-778 389.452,-784 389.452,-784 389.452,-796 389.452,-796 389.452,-802 383.452,-808 377.452,-808"/>
<text text-anchor="middle" x="338.6957" y="-785.8" font-family="Verdana" font-size="14.00" fill="#000000">SignatureSize</text>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="edge33" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_edge33"><a xlink:title="at key_certificate.go:237: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]">
<path fill="none" stroke="#000000" d="M205.3958,-790C229.5957,-790 255.1662,-790 277.3684,-790"/>
<polygon fill="#000000" stroke="#000000" points="277.6448,-793.5001 287.6448,-790 277.6447,-786.5001 277.6448,-793.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge11" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge11"><a xlink:title="at key_certificate.go:323: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:328: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M375.8587,-808.2143C393.6287,-816.5905 415.3328,-826.3426 435.2904,-834 542.9578,-875.3102 672.6115,-913.453 743.777,-933.4278"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.2698,-936.9201 753.8429,-936.2413 745.1542,-930.1785 743.2698,-936.9201"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="edge45" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge45"><a xlink:title="at key_certificate.go:325: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M362.379,-808.0007C388.7396,-827.803 432.8315,-860.236 472.2904,-886 572.4968,-951.428 599.1366,-965.5171 704.1026,-1023 721.629,-1032.598 741.3434,-1042.6696 758.0891,-1051.0166"/>
<polygon fill="#8b4513" stroke="#8b4513" points="756.5402,-1054.1552 767.0541,-1055.4624 759.6502,-1047.8839 756.5402,-1054.1552"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge32" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge32"><a xlink:title="at key_certificate.go:331: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M389.6092,-800.6705C404.284,-803.2803 420.3629,-805.6964 435.2904,-807 539.28,-816.0809 572.5848,-818.1029 668.1026,-776 724.1995,-751.2732 764.3986,-687.971 783.8368,-651.3294"/>
<polygon fill="#8b4513" stroke="#8b4513" points="787.0763,-652.6838 788.5471,-642.1916 780.8543,-649.4765 787.0763,-652.6838"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType -->
<g id="edge31" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType</title>
<g id="a_edge31"><a xlink:title="at key_certificate.go:320: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="none" stroke="#000000" d="M389.4995,-776.6133C419.4211,-768.729 457.9034,-758.589 491.6603,-749.6941"/>
<polygon fill="#000000" stroke="#000000" points="492.7279,-753.0324 501.506,-747.0998 490.9442,-746.2634 492.7279,-753.0324"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -0,0 +1,132 @@
package key_certificate
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSigningPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
assert := assert.New(t)
// Create certificate with signing key type P521 (3)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x07})
assert.Nil(err)
pk_type := key_cert.SigningPublicKeyType()
assert.Equal(KEYCERT_SIGN_P521, pk_type, "SigningPublicKeyType() did not return correct type")
}
func TestSigningPublicKeyTypeWithInvalidData(t *testing.T) {
assert := assert.New(t)
// Test with invalid short data
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x01, 0x00})
assert.NotNil(err)
assert.Contains(err.Error(), "key certificate data too short")
assert.Nil(key_cert)
}
func TestPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
assert := assert.New(t)
// Create certificate with crypto type ELG (0)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
assert.Nil(err)
pk_type := key_cert.PublicKeyType()
assert.Equal(KEYCERT_CRYPTO_ELG, pk_type, "PublicKeyType() did not return correct type")
}
func TestPublicKeyTypeWithInvalidData(t *testing.T) {
assert := assert.New(t)
// Test with invalid short data
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x02})
assert.NotNil(err)
assert.Contains(err.Error(), "certificate parsing warning: certificate data is shorter than specified by length", "Expected error for invalid data")
assert.Nil(key_cert)
}
func TestConstructPublicKeyWithInsufficientData(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
assert.Nil(err)
// Test with data smaller than required size
data := make([]byte, 255) // ELG requires 256 bytes
_, err = key_cert.ConstructPublicKey(data)
assert.NotNil(err)
assert.Equal("error constructing public key: not enough data", err.Error())
}
func TestConstructPublicKeyReturnsCorrectDataWithElg(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 256)
pk, err := key_cert.ConstructPublicKey(data)
assert.Nil(err, "ConstructPublicKey() returned error with valid data")
assert.Equal(pk.Len(), 256, "ConstructPublicKey() did not return public key with correct length")
}
func TestConstructSigningPublicKeyReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 127)
_, err = key_cert.ConstructSigningPublicKey(data)
if assert.NotNil(err) {
assert.Equal("error constructing signing public key: not enough data", err.Error(), "correct error message should be returned")
}
}
func TestConstructSigningPublicKeyWithDSASHA1(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 128)
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")
}
func TestConstructSigningPublicKeyWithP256(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01})
data := make([]byte, 128)
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")
}
func TestConstructSigningPublicKeyWithP384(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02})
data := make([]byte, 128)
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")
}
/*
func TestConstructSigningPublicKeyWithP521(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 132)
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")
}
*/ //TODO -> Before implementing this test, we need to implement P521 first.

View File

@ -1,127 +0,0 @@
package common
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestSingingPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00})
pk_type, err := key_cert.SigningPublicKeyType()
assert.Nil(err, "SigningPublicKeyType() returned error with valid data")
assert.Equal(pk_type, KEYCERT_SIGN_P521, "SigningPublicKeyType() did not return correct typec")
}
func TestSingingPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x01, 0x00})
_, err := key_cert.SigningPublicKeyType()
if assert.NotNil(err) {
assert.Equal("error parsing key certificate: not enough data", err.Error(), "correct error message should be returned")
}
}
func TestPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03})
pk_type, err := key_cert.PublicKeyType()
assert.Nil(err, "PublicKey() returned error with valid data")
assert.Equal(pk_type, KEYCERT_SIGN_P521, "PublicKeyType() did not return correct typec")
}
func TestPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x02, 0x00, 0x00})
_, err := key_cert.PublicKeyType()
if assert.NotNil(err) {
assert.Equal("error parsing key certificate: not enough data", err.Error(), "correct error message should be returned")
}
}
func TestConstructPublicKeyReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 255)
_, err := key_cert.ConstructPublicKey(data)
if assert.NotNil(err) {
assert.Equal("error constructing public key: not enough data", err.Error(), "correct error message should be returned")
}
}
func TestConstructPublicKeyReturnsCorrectDataWithElg(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 256)
pk, err := key_cert.ConstructPublicKey(data)
assert.Nil(err, "ConstructPublicKey() returned error with valid data")
assert.Equal(pk.Len(), 256, "ConstructPublicKey() did not return public key with correct length")
}
func TestConstructSigningPublicKeyReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 127)
_, err := key_cert.ConstructSigningPublicKey(data)
if assert.NotNil(err) {
assert.Equal("error constructing signing public key: not enough data", err.Error(), "correct error message should be returned")
}
}
func TestConstructSigningPublicKeyWithDSASHA1(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 128)
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")
}
func TestConstructSigningPublicKeyWithP256(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01})
data := make([]byte, 128)
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")
}
func TestConstructSigningPublicKeyWithP384(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02})
data := make([]byte, 128)
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")
}
func TestConstructSigningPublicKeyWithP521(t *testing.T) {
assert := assert.New(t)
key_cert := KeyCertificate([]byte{0x05, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 128)
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")
}

View File

@ -1,203 +0,0 @@
package common
/*
I2P KeysAndCert
https://geti2p.net/spec/common-structures#keysandcert
Accurate for version 0.9.24
+----+----+----+----+----+----+----+----+
| public_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| padding (optional) |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| signing_key |
+ +
| |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| certificate |
+----+----+----+-//
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 == KEYS_AND_CERT_SPK_SIZE bytes
signing__key :: SigningPublicKey (partial or full)
length -> 128 bytes or as specified in key certificate
padding length + signing_key length == KEYS_AND_CERT_SPK_SIZE bytes
certificate :: Certificate
length -> >= 3 bytes
total length: 387+ bytes
*/
import (
"errors"
"github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
)
// Sizes of various KeysAndCert structures and requirements
const (
KEYS_AND_CERT_PUBKEY_SIZE = 256
KEYS_AND_CERT_SPK_SIZE = 128
KEYS_AND_CERT_MIN_SIZE = 387
KEYS_AND_CERT_DATA_SIZE = 384
)
type KeysAndCert []byte
//
// Return the PublicKey for this KeysAndCert, reading from the Key Certificate if it is present to
// determine correct lengths.
//
func (keys_and_cert KeysAndCert) PublicKey() (key crypto.PublicKey, err error) {
cert, err := keys_and_cert.Certificate()
if err != nil {
return
}
cert_len, err := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
} else {
// A Certificate is present in this KeysAndCert
cert_type, _ := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a PublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
key, err = KeyCertificate(cert).ConstructPublicKey(
keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey. No other Certificate
// types are currently in use.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
log.WithFields(log.Fields{
"at": "(KeysAndCert) PublicKey",
"cert_type": cert_type,
}).Warn("unused certificate type observed")
}
}
return
}
//
// Return the SigningPublicKey for this KeysAndCert, reading from the Key Certificate if it is present to
// determine correct lengths.
//
func (keys_and_cert KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey, err error) {
cert, err := keys_and_cert.Certificate()
if err != nil {
return
}
cert_len, err := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
} else {
// A Certificate is present in this KeysAndCert
cert_type, _ := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a SigningPublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
signing_public_key, err = KeyCertificate(cert).ConstructSigningPublicKey(
keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy SHA DSA1 SigningPublicKey.
// No other Certificate types are currently in use.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
}
}
return
}
//
// Return the Certificate contained in the KeysAndCert and any errors encountered while parsing the
// KeysAndCert or Certificate.
//
func (keys_and_cert KeysAndCert) Certificate() (cert Certificate, err error) {
keys_cert_len := len(keys_and_cert)
if keys_cert_len < KEYS_AND_CERT_MIN_SIZE {
log.WithFields(log.Fields{
"at": "(KeysAndCert) Certificate",
"data_len": keys_cert_len,
"required_len": KEYS_AND_CERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
return
}
cert, _, err = ReadCertificate(keys_and_cert[KEYS_AND_CERT_DATA_SIZE:])
return
}
//
// Read a KeysAndCert from a slice of bytes, retuning it and the remaining data as well as any errors
// encoutered parsing the KeysAndCert.
//
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
data_len := len(data)
if data_len < KEYS_AND_CERT_MIN_SIZE {
log.WithFields(log.Fields{
"at": "ReadKeysAndCert",
"data_len": data_len,
"required_len": KEYS_AND_CERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
return
}
keys_and_cert = KeysAndCert(data[:KEYS_AND_CERT_MIN_SIZE])
cert, _ := keys_and_cert.Certificate()
cert_len, cert_len_err := cert.Length()
if cert_len == 0 {
remainder = data[KEYS_AND_CERT_MIN_SIZE:]
return
}
if data_len < KEYS_AND_CERT_MIN_SIZE+cert_len {
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:]...)
err = cert_len_err
} else {
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:KEYS_AND_CERT_MIN_SIZE+cert_len]...)
remainder = data[KEYS_AND_CERT_MIN_SIZE+cert_len:]
}
return
}

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