411 Commits

Author SHA1 Message Date
d7888ac9be return corrected size 2025-06-28 13:53:13 -04:00
68408bb48e Expose WriteMessageToConn and start work on sessions 2025-05-31 13:40:33 -04:00
4715b76ade IGNORE THIS CHECKIN: regenerate call graphs, regenerate godoc 2025-05-15 20:30:26 -04:00
ac7e369b6a work on reseeding 2025-05-15 20:20:46 -04:00
7d51d83b40 Fix nil return in when performing noise handshake to return a session 2025-05-15 19:20:37 -04:00
89c82cb2fe Remove unused function, fix spelling, update godoc 2025-05-15 19:17:42 -04:00
808f7d6fdf move processors back due to import cycle 2025-05-15 19:03:41 -04:00
537ab808f8 fix issues with transports 2025-05-15 18:56:10 -04:00
b41bb0eef8 move sessionmessageprocessors to own directory 2025-05-15 18:42:39 -04:00
8787fea069 Put an X over handshake. It's broken, but it's there! 2025-05-10 23:22:43 -04:00
fc9734d43d fix page workflow 2025-05-10 23:19:50 -04:00
0a262d5780 Add GitHub Actions workflow for page generation 2025-05-10 23:15:45 -04:00
2f233e931d delete more now-unused functions 2025-05-10 23:13:47 -04:00
e9991099b7 update godoc again, delete more now-unused functions 2025-05-10 23:13:11 -04:00
761dcb5f98 get rid of math/rand usages 2025-05-10 23:09:22 -04:00
f68d9b5606 check in utility functions 2025-05-10 23:03:53 -04:00
9fd3400585 More function deletions 2025-05-10 22:55:39 -04:00
c85822163b Regenerate godoc 2025-05-10 22:36:36 -04:00
e2fdb7c4e0 Move to SessionProcessors 2025-05-10 22:33:43 -04:00
1babf06091 More code deduplication 2025-05-10 22:18:50 -04:00
62e565b36c More code deduplication 2025-05-10 22:16:25 -04:00
c7a17eac86 fmt 2025-05-10 21:55:30 -04:00
89e53fdb9f More migration to processors 2025-05-10 21:55:06 -04:00
ebdd1ae0aa Work on implementing and migrating to message processors 2025-05-10 21:46:07 -04:00
b65f6c2682 Work on implementing and migrating to message processors 2025-05-10 21:43:30 -04:00
14a0e56f6a Work on implementing and migrating to message processors 2025-05-10 21:37:47 -04:00
4a89c14734 Work on implementing and migrating to message processors 2025-05-10 21:23:05 -04:00
09fe22178d more method consolidation 2025-05-10 21:12:49 -04:00
ef156f6944 more method consolidation 2025-05-10 21:11:46 -04:00
a4acb01be9 handshake interface implementation stuff 2025-05-10 20:25:02 -04:00
dd116095aa More duplicated code reduction, interface improvement 2025-05-10 20:09:42 -04:00
1922f3a0ab Start implementing messages as message processors 2025-05-08 23:22:42 -04:00
2a28c8ee01 Start implementing the message handlers 2025-05-08 22:59:36 -04:00
9cb4af8f06 plan new handshake interfaces 2025-05-08 21:41:09 -04:00
56faebd746 Plan re-org of handshake functions 2025-05-08 20:29:46 -04:00
8b035711b6 Move sessionRequest methods to own file, organization changes 2025-05-08 18:01:58 -04:00
c93b258844 Move ntcp2 messages into ntcp2 directory 2025-05-08 16:22:22 -04:00
2df5d23528 Implement findClosestPeers 2025-05-08 14:24:08 -04:00
98ea3d55c4 Implement lookup for kadResolver, change kadresolver to KademliaResolver 2025-05-07 21:19:46 -04:00
b5454a4317 Implement lookup for kadResolver, change kadresolver to KademliaResolver 2025-05-07 21:17:38 -04:00
83502face7 change lookup interface, needs to be more intuitive to use, we can thread elsewhere 2025-05-07 20:51:30 -04:00
c99b15ba7f NetDB entry serialization and deserialization, TODO: leaseset struct port 2025-05-07 20:14:18 -04:00
8e73c36922 check in the stuff I have locally that I haven't yet, mostly ECDSA stuff which is not very useful 2025-05-05 22:37:46 -04:00
89b1995593 ecdsa_p256_private impl, rest of ecdsa to follow 2025-04-04 11:00:59 -04:00
4577408d6d return a descriptive error upon a hash size mismatch 2025-04-03 17:00:10 -04:00
e7e26ae021 Fix unimplemented funcs in rsa3072 2025-04-03 15:53:17 -04:00
1d1568de71 Add rsa4096 implementation and use the same functin for all key reads 2025-04-03 15:30:06 -04:00
b21a6cee9e Add rsa2048 implementation 2025-04-03 15:04:39 -04:00
35b47969b0 Add rsa3072 implementation 2025-04-03 14:57:08 -04:00
816df5642c implement first handshake message sender and reciever, create a test file 2025-03-31 21:49:31 -04:00
1bd439f989 Implement Sender for Handshake Message 1 2025-03-31 17:33:01 -04:00
6158eb68f3 fix some interfaces 2025-03-31 14:56:04 -04:00
03eeeab781 reorganized old hansdhake stuff 2025-03-31 14:55:05 -04:00
0099392f6d fix some interfaces 2025-03-31 14:51:53 -04:00
a09f155835 Add quantized padding file and my notes on quantized padding 2025-03-31 13:46:45 -04:00
fa561fc431 Merge branch 'master' of github.com:go-i2p/go-i2p 2025-03-29 17:54:58 -04:00
c5125c1bfd more ntcp2 progress, figure out what the rules of the crypto library interfaces need to be, etc 2025-03-29 17:54:23 -04:00
idk
9e1bac3ff1 Merge pull request #37 from satk0/add-database-lookup
Add DatabaseLookup
2025-03-29 14:41:44 -04:00
b4e1f3cfdf THIS LARGE CHECKIN CONTAINS REGENERATED DOCS ONLY. update/regenerate docs. 2025-03-27 22:18:24 -04:00
d4ff0e373c stub out more methods 2025-03-27 22:01:34 -04:00
0c9c8270a5 migrate hmac to crypto/hmac, I swear we do everything the hard way... 2025-03-27 21:56:23 -04:00
f2bacc5018 Add basic chacha20-poly1305 implementation 2025-03-27 21:45:23 -04:00
94691f1e75 Stub out ECDSA requirements 2025-03-27 20:30:31 -04:00
8c4f718601 Make all the tests compile again, some of the elgamal ones might fail but mixing up our packages with third-party elgamal packages was causing problems. We should bring crypto in-house as dependencies, wrap our interfaces around it per our requirements, and not touch the upstream library if we can help it. That means wrap private keys, public keys, signing and encryption operations with our own code reporting our own errors. 2025-03-27 20:13:17 -04:00
9a0d164276 Use curve25519+ChaCha20-Poly1305 instead of AES-GCM in curve25519, I think we might need to override it sometimes but it's the thing that makes sense right now 2025-03-27 19:50:55 -04:00
f3f5d744ed Fix curve25519 decrypter 2025-03-27 19:24:23 -04:00
3b9fb603f4 fix a few more compile errors and sync 2025-03-26 21:10:16 -04:00
29d5a20216 Fix compile errors in NTCP handshake 2025-03-26 19:38:01 -04:00
3c252e22cd split the rsa stub package into one file per component 2025-03-26 19:32:54 -04:00
dcb11d1fda split the rsa stub package into one file per component 2025-03-26 19:31:32 -04:00
a721856688 split the elgamal package into one file per component 2025-03-26 19:26:03 -04:00
b66c5813cb split the ed25519 package into one file per component 2025-03-26 19:19:24 -04:00
441549743d Fix some of the compile errors in routerinfo_keystore.go 2025-03-26 18:57:27 -04:00
30f84713ea split the ecdsa package into one file per component 2025-03-26 18:52:51 -04:00
6057677956 split the dsa package into one file per component 2025-03-26 18:48:12 -04:00
c026b9a4a5 split the curve25519 package into one file per component 2025-03-26 18:40:38 -04:00
9c6cfc14e5 split the curve25519 package into one file per component 2025-03-26 18:40:31 -04:00
4533c2fd92 split the aes package into one file per component 2025-03-26 18:24:31 -04:00
89e51820f1 Add DatabaseLookup and test it 2025-03-26 20:32:44 +01:00
17a789bed7 refactor crypto library into smaller components 2025-03-25 19:08:47 -04:00
d236f19f81 add custom handshake manager 2025-03-25 18:37:14 -04:00
d0b81d9ce9 add remaining session messages 2025-03-25 18:17:34 -04:00
06cf6b41b4 add remaining session messages 2025-03-25 18:15:44 -04:00
ac8349d083 Add SessionCreated implementation 2025-03-25 17:02:25 -04:00
45296be6d3 let the machine find simple errors in the common library and call it a night 2025-03-24 23:55:04 -04:00
1f25f0c9b3 Finish initialization of NTCP2Sessions 2025-03-24 23:22:23 -04:00
d1a708a594 Actually use the message objects, duh 2025-03-24 23:16:12 -04:00
b153bfc050 Refactor and comment ComposeInitiatorHandshakeMessage 2025-03-24 19:36:14 -04:00
d401b06c0f Remove dot-imports from LeaseSets 2025-03-22 18:49:26 -04:00
9091834074 fix more tests 2025-03-22 18:12:13 -04:00
8561b3ec69 fmt 2025-03-22 18:03:24 -04:00
8aac97351d fix some tests 2025-03-22 18:03:06 -04:00
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
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
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
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
346 changed files with 51846 additions and 2313 deletions

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

60
.github/workflows/page.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Generate and Deploy GitHub Pages
on:
# Run once hourly
schedule:
- cron: '0 * * * *'
# Allow manual trigger
workflow_dispatch:
# Run on pushes to main branch
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for proper repo data
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24.x'
cache: true
- name: Build Site Generator
run: |
go install github.com/go-i2p/go-gh-page/cmd/github-site-gen@latest
export GOBIN=$(go env GOPATH)/bin
cp -v "$GOBIN/github-site-gen" ./github-site-gen
# Ensure the binary is executable
chmod +x github-site-gen
- name: Generate Site
run: |
# Determine current repository owner and name
REPO_OWNER=$(echo $GITHUB_REPOSITORY | cut -d '/' -f 1)
REPO_NAME=$(echo $GITHUB_REPOSITORY | cut -d '/' -f 2)
# Generate the site
./github-site-gen -repo "${REPO_OWNER}/${REPO_NAME}" -output ./site
# Create a .nojekyll file to disable Jekyll processing
touch ./site/.nojekyll
# Add a .gitattributes file to ensure consistent line endings
echo "* text=auto" > ./site/.gitattributes
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: site # The folder the action should deploy
branch: gh-pages # The branch the action should deploy to
clean: true # Automatically remove deleted files from the deploy branch
commit-message: "Deploy site generated on ${{ github.sha }}"

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

5
.gitignore vendored
View File

@ -7,3 +7,8 @@
go-i2p
*.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

@ -2,6 +2,8 @@ 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
@ -15,19 +17,44 @@ 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: fmt
$(GO) test -vv -failfast ./lib/common/...
# 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 gofmt -w -s {} \;
find . -name '*.go' -exec gofumpt -w {} \;
info:
echo "GOROOT: ${GOROOT}"
@ -36,3 +63,6 @@ info:
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

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

View File

@ -15,33 +15,31 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Datagrams
- [ ] I2CP
- [ ] Message routing
- [ ] SAM
- [ ] Streaming
- [ ] Tunnel Manager
- Cryptographic primitives
- Signing
- [ ] ECDSA_SHA256_P256
- [ ] ECDSA_SHA384_P384
- [ ] ECDSA_SHA512_P521
- [ ] Ed25519
- [X] Ed25519
- Verifying
- [ ] DSA
- [X] DSA
- [ ] ECDSA_SHA256_P256
- [ ] ECDSA_SHA384_P384
- [ ] ECDSA_SHA512_P521
- [ ] RSA_SHA256_2048
- [ ] RSA_SHA384_3072
- [ ] RSA_SHA512_4096
- [ ] Ed25519
- [X] Ed25519
- [ ] Red25519
- [ ] ElGamal
- [ ] AES256
- [ ] X25519
- [ ] ChaCha20/Poly1305
- [X] ElGamal
- [X] AES256
- [X] X25519
- [X] ChaCha20/Poly1305
- [ ] Elligator2
- [ ] HKDF
- [ ] HMAC
- [ ] Noise subsystem
- [X] HMAC
- [X] Noise subsystem
- End-to-End Crypto
- [ ] Garlic messages
- [ ] ElGamal/AES+SessionTag
@ -50,8 +48,8 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Message parsing
- [ ] Message handling
- NetDB
- [ ] Local storage
- [/] Persistence to disk
- [~] Local storage
- [~] Persistence to disk
- [X] Reseeding
- [ ] Lookups
- [ ] Expiry
@ -62,7 +60,7 @@ please keep up with these changes, as they will not be backward compatible and r
- Transports
- [X] Transport manager
- NTCP2
- [ ] Handshake
- [X] Handshake
- [ ] Session tracking
- [ ] Automatic session creation
- SSU2
@ -79,7 +77,7 @@ please keep up with these changes, as they will not be backward compatible and r
- [ ] Tunnel Message Crypto
- [ ] Tunnel Message Fragmentation/Reassembly
- Common Data Structures
- [/] Keys and Cert
- [X] Keys and Cert
- [X] Key Certificates
- [X] Certificate
- [X] Lease
@ -93,6 +91,37 @@ please keep up with these changes, as they will not be backward compatible and r
- [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
See CONTRIBUTING.md for more information.

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 2 -type f -name "*.go" -not -name "fuzz")
#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"
godocdown -template template.md -o "$dir/README.md" "./$dir"
git add -v "$dir/README.md"
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

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

@ -0,0 +1,74 @@
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-database-lookup
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
test-i2np-database-lookup:
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupKeyTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupKeyValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFromTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFromValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFlagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFlagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDNotIncluded
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupSizeTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupSizeValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersZeroSize
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyKeyTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyKeyValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsZeroTags
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupValidData
.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 \
test-i2np-database-lookup

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

45
go.mod
View File

@ -1,11 +1,50 @@
module github.com/go-i2p/go-i2p
go 1.16
go 1.23.3
toolchain go1.23.5
require (
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/stretchr/testify v1.7.0
golang.org/x/crypto v0.23.0
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
)

131
go.sum
View File

@ -1,71 +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/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/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
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/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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/crypto v0.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/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/net v0.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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
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=

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

@ -0,0 +1,57 @@
# 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(ctx context.Context, n int) ([]router_info.RouterInfo, error)
}
```
interface defining a way to bootstrap into the i2p network
#### type ReseedBootstrap
```go
type ReseedBootstrap struct {
}
```
ReseedBootstrap implements the Bootstrap interface using HTTP reseeding
#### func NewReseedBootstrap
```go
func NewReseedBootstrap(config *config.BootstrapConfig) *ReseedBootstrap
```
NewReseedBootstrap creates a new reseeder with the provided configuration
#### func (*ReseedBootstrap) GetPeers
```go
func (rb *ReseedBootstrap) GetPeers(ctx context.Context, n int) ([]router_info.RouterInfo, error)
```
GetPeers implements the Bootstrap interface by obtaining RouterInfos from
configured reseed servers
bootstrap
github.com/go-i2p/go-i2p/lib/bootstrap
[go-i2p template file](/template.md)

View File

@ -1,6 +1,10 @@
package bootstrap
import "github.com/go-i2p/go-i2p/lib/common/router_info"
import (
"context"
"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 +13,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 []router_info.RouterInfo, error)
GetPeers(ctx context.Context, n int) ([]router_info.RouterInfo, error)
}

258
lib/bootstrap/bootstrap.svg Normal file
View File

@ -0,0 +1,258 @@
<?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="365pt" height="722pt"
viewBox="0.00 0.00 364.72 722.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 722)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-722 364.7182,-722 364.7182,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="0,-8 0,-714 356.7182,-714 356.7182,-8 0,-8"/>
<text text-anchor="middle" x="178.3591" y="-693.8" font-family="Arial" font-size="18.00" fill="#000000">bootstrap</text>
</g>
<g id="clust5" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed</title>
<g id="a_clust5"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M242.0218,-598C242.0218,-598 334.2252,-598 334.2252,-598 340.2252,-598 346.2252,-604 346.2252,-610 346.2252,-610 346.2252,-664 346.2252,-664 346.2252,-670 340.2252,-676 334.2252,-676 334.2252,-676 242.0218,-676 242.0218,-676 236.0218,-676 230.0218,-670 230.0218,-664 230.0218,-664 230.0218,-610 230.0218,-610 230.0218,-604 236.0218,-598 242.0218,-598"/>
<text text-anchor="middle" x="288.1235" y="-606.5" font-family="Arial" font-size="15.00" fill="#222222">(Reseed)</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="M261.4629,-451C261.4629,-451 315.7841,-451 315.7841,-451 321.7841,-451 327.7841,-457 327.7841,-463 327.7841,-463 327.7841,-578 327.7841,-578 327.7841,-584 321.7841,-590 315.7841,-590 315.7841,-590 261.4629,-590 261.4629,-590 255.4629,-590 249.4629,-584 249.4629,-578 249.4629,-578 249.4629,-463 249.4629,-463 249.4629,-457 255.4629,-451 261.4629,-451"/>
<text text-anchor="middle" x="288.6235" y="-459.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="M249.0141,-182C249.0141,-182 327.2329,-182 327.2329,-182 333.2329,-182 339.2329,-188 339.2329,-194 339.2329,-194 339.2329,-431 339.2329,-431 339.2329,-437 333.2329,-443 327.2329,-443 327.2329,-443 249.0141,-443 249.0141,-443 243.0141,-443 237.0141,-437 237.0141,-431 237.0141,-431 237.0141,-194 237.0141,-194 237.0141,-188 243.0141,-182 249.0141,-182"/>
<text text-anchor="middle" x="288.1235" y="-190.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/bootstrap.ReseedBootstrap</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M20,-304C20,-304 143.5288,-304 143.5288,-304 149.5288,-304 155.5288,-310 155.5288,-316 155.5288,-316 155.5288,-370 155.5288,-370 155.5288,-376 149.5288,-382 143.5288,-382 143.5288,-382 20,-382 20,-382 14,-382 8,-376 8,-370 8,-370 8,-316 8,-316 8,-310 14,-304 20,-304"/>
<text text-anchor="middle" x="81.7644" y="-312.5" font-family="Arial" font-size="15.00" fill="#222222">(*ReseedBootstrap)</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="M305.3188,-113C305.3188,-113 270.9282,-113 270.9282,-113 264.9282,-113 258.9282,-107 258.9282,-101 258.9282,-101 258.9282,-89 258.9282,-89 258.9282,-83 264.9282,-77 270.9282,-77 270.9282,-77 305.3188,-77 305.3188,-77 311.3188,-77 317.3188,-83 317.3188,-89 317.3188,-89 317.3188,-101 317.3188,-101 317.3188,-107 311.3188,-113 305.3188,-113"/>
<text text-anchor="middle" x="288.1235" y="-99.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="288.1235" y="-82.4" font-family="Verdana" font-size="14.00" fill="#000000">Errorf</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed</title>
<g id="a_node2"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed | defined in new.go:10">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M321.4764,-174C321.4764,-174 254.7706,-174 254.7706,-174 248.7706,-174 242.7706,-168 242.7706,-162 242.7706,-162 242.7706,-150 242.7706,-150 242.7706,-144 248.7706,-138 254.7706,-138 254.7706,-138 321.4764,-138 321.4764,-138 327.4764,-138 333.4764,-144 333.4764,-150 333.4764,-150 333.4764,-162 333.4764,-162 333.4764,-168 327.4764,-174 321.4764,-174"/>
<text text-anchor="middle" x="288.1235" y="-160.2" font-family="Verdana" font-size="14.00" fill="#000000">reseed</text>
<text text-anchor="middle" x="288.1235" y="-143.4" font-family="Verdana" font-size="14.00" fill="#000000">NewReseed</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.init -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.init</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.init | defined in .:0&#10;at reseed_bootstrap.go:15: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M96.2644,-52C96.2644,-52 66.2644,-52 66.2644,-52 60.2644,-52 54.2644,-46 54.2644,-40 54.2644,-40 54.2644,-28 54.2644,-28 54.2644,-22 60.2644,-16 66.2644,-16 66.2644,-16 96.2644,-16 96.2644,-16 102.2644,-16 108.2644,-22 108.2644,-28 108.2644,-28 108.2644,-40 108.2644,-40 108.2644,-46 102.2644,-52 96.2644,-52"/>
<text text-anchor="middle" x="81.2644" 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="M336.813,-52C336.813,-52 239.434,-52 239.434,-52 233.434,-52 227.434,-46 227.434,-40 227.434,-40 227.434,-28 227.434,-28 227.434,-22 233.434,-16 239.434,-16 239.434,-16 336.813,-16 336.813,-16 342.813,-16 348.813,-22 348.813,-28 348.813,-28 348.813,-40 348.813,-40 348.813,-46 342.813,-52 336.813,-52"/>
<text text-anchor="middle" x="288.1235" y="-38.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="288.1235" 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/bootstrap.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge10" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge10"><a xlink:title="at reseed_bootstrap.go:15: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M108.3076,-34C135.736,-34 179.3573,-34 216.7663,-34"/>
<polygon fill="#8b4513" stroke="#8b4513" points="217.1342,-37.5001 227.1342,-34 217.1341,-30.5001 217.1342,-37.5001"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers -->
<g id="node5" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers</title>
<g id="a_node5"><a xlink:title="(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers | defined in reseed_bootstrap.go:32&#10;at reseed_bootstrap.go:40: calling [github.com/samber/oops.Errorf]&#10;at reseed_bootstrap.go:53: calling [github.com/samber/oops.Errorf]&#10;at reseed_bootstrap.go:73: calling [github.com/samber/oops.Errorf]&#10;at reseed_bootstrap.go:43: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]&#10;at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]&#10;at reseed_bootstrap.go:43: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at reseed_bootstrap.go:63: calling [(*github.com/sirupsen/logrus.Logger).Info]&#10;at reseed_bootstrap.go:46: calling [github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed]&#10;at reseed_bootstrap.go:49: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed]&#10;at reseed_bootstrap.go:59: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M106.2947,-374C106.2947,-374 56.2341,-374 56.2341,-374 50.2341,-374 44.2341,-368 44.2341,-362 44.2341,-362 44.2341,-350 44.2341,-350 44.2341,-344 50.2341,-338 56.2341,-338 56.2341,-338 106.2947,-338 106.2947,-338 112.2947,-338 118.2947,-344 118.2947,-350 118.2947,-350 118.2947,-362 118.2947,-362 118.2947,-368 112.2947,-374 106.2947,-374"/>
<text text-anchor="middle" x="81.2644" y="-351.8" font-family="Verdana" font-size="14.00" fill="#000000">GetPeers</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge1" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge1"><a xlink:title="at reseed_bootstrap.go:40: calling [github.com/samber/oops.Errorf]&#10;at reseed_bootstrap.go:53: calling [github.com/samber/oops.Errorf]&#10;at reseed_bootstrap.go:73: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M118.4074,-352.073C131.5385,-349.0001 145.5161,-343.5697 155.5288,-334 190.8891,-300.2044 195.4391,-162.9154 227.5288,-126 233.5557,-119.0668 241.5102,-113.4857 249.6658,-109.0748"/>
<polygon fill="#8b4513" stroke="#8b4513" points="251.4166,-112.115 258.8672,-104.5824 248.3454,-105.8247 251.4166,-112.115"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed -->
<g id="edge7" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed</title>
<g id="a_edge7"><a xlink:title="at reseed_bootstrap.go:46: calling [github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.NewReseed]">
<path fill="none" stroke="#8b4513" d="M118.6751,-351.3434C131.5313,-348.1844 145.2575,-342.8857 155.5288,-334 213.2793,-284.0401 171.3098,-229.6772 227.5288,-178 229.4394,-176.2438 231.5009,-174.6252 233.6705,-173.1338"/>
<polygon fill="#8b4513" stroke="#8b4513" points="235.6115,-176.0535 242.4829,-167.9892 232.0823,-170.0083 235.6115,-176.0535"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithField -->
<g id="node6" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithField</title>
<g id="a_node6"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithField | defined in log.go:54">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M316.398,-252C316.398,-252 259.849,-252 259.849,-252 253.849,-252 247.849,-246 247.849,-240 247.849,-240 247.849,-228 247.849,-228 247.849,-222 253.849,-216 259.849,-216 259.849,-216 316.398,-216 316.398,-216 322.398,-216 328.398,-222 328.398,-228 328.398,-228 328.398,-240 328.398,-240 328.398,-246 322.398,-252 316.398,-252"/>
<text text-anchor="middle" x="288.1235" y="-238.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="288.1235" y="-221.4" font-family="Verdana" font-size="14.00" fill="#000000">WithField</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField -->
<g id="edge2" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField</title>
<g id="a_edge2"><a xlink:title="at reseed_bootstrap.go:43: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]&#10;at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]">
<path fill="none" stroke="#8b4513" d="M118.5683,-348.6617C130.8549,-345.2944 144.2489,-340.5496 155.5288,-334 193.8581,-311.7444 191.4175,-290.6986 227.5288,-265 231.4159,-262.2337 235.5842,-259.5689 239.8482,-257.0424"/>
<polygon fill="#8b4513" stroke="#8b4513" points="241.6859,-260.0242 248.6757,-252.0623 238.2464,-253.9275 241.6859,-260.0242"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="node7" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_node7"><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="M316.655,-313C316.655,-313 259.592,-313 259.592,-313 253.592,-313 247.592,-307 247.592,-301 247.592,-301 247.592,-289 247.592,-289 247.592,-283 253.592,-277 259.592,-277 259.592,-277 316.655,-277 316.655,-277 322.655,-277 328.655,-283 328.655,-289 328.655,-289 328.655,-301 328.655,-301 328.655,-307 322.655,-313 316.655,-313"/>
<text text-anchor="middle" x="288.1235" y="-299.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="288.1235" y="-282.4" font-family="Verdana" font-size="14.00" fill="#000000">WithError</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="edge4" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_edge4"><a xlink:title="at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M118.725,-344.9534C151.9288,-335.162 200.7001,-320.78 237.3948,-309.9592"/>
<polygon fill="#8b4513" stroke="#8b4513" points="238.7997,-313.194 247.4014,-307.0084 236.8198,-306.4798 238.7997,-313.194"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="node8" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_node8"><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="M305.8898,-374C305.8898,-374 270.3572,-374 270.3572,-374 264.3572,-374 258.3572,-368 258.3572,-362 258.3572,-362 258.3572,-350 258.3572,-350 258.3572,-344 264.3572,-338 270.3572,-338 270.3572,-338 305.8898,-338 305.8898,-338 311.8898,-338 317.8898,-344 317.8898,-350 317.8898,-350 317.8898,-362 317.8898,-362 317.8898,-368 311.8898,-374 305.8898,-374"/>
<text text-anchor="middle" x="288.1235" y="-360.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="288.1235" y="-343.4" font-family="Verdana" font-size="14.00" fill="#000000">Warn</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#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/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_edge5"><a xlink:title="at reseed_bootstrap.go:52: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M118.725,-356C155.3343,-356 210.8683,-356 248.2746,-356"/>
<polygon fill="#8b4513" stroke="#8b4513" points="248.3136,-359.5001 258.3136,-356 248.3135,-352.5001 248.3136,-359.5001"/>
</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="M319.3426,-435C319.3426,-435 256.9044,-435 256.9044,-435 250.9044,-435 244.9044,-429 244.9044,-423 244.9044,-423 244.9044,-411 244.9044,-411 244.9044,-405 250.9044,-399 256.9044,-399 256.9044,-399 319.3426,-399 319.3426,-399 325.3426,-399 331.3426,-405 331.3426,-411 331.3426,-411 331.3426,-423 331.3426,-423 331.3426,-429 325.3426,-435 319.3426,-435"/>
<text text-anchor="middle" x="288.1235" y="-421.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="288.1235" y="-404.4" font-family="Verdana" font-size="14.00" fill="#000000">WithFields</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge9" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge9"><a xlink:title="at reseed_bootstrap.go:59: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M118.725,-367.0466C151.1839,-376.6183 198.5195,-390.577 234.9071,-401.3072"/>
<polygon fill="#8b4513" stroke="#8b4513" points="234.2768,-404.7703 244.8585,-404.2417 236.2568,-398.0561 234.2768,-404.7703"/>
</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="M306.9455,-521C306.9455,-521 269.3015,-521 269.3015,-521 263.3015,-521 257.3015,-515 257.3015,-509 257.3015,-509 257.3015,-497 257.3015,-497 257.3015,-491 263.3015,-485 269.3015,-485 269.3015,-485 306.9455,-485 306.9455,-485 312.9455,-485 318.9455,-491 318.9455,-497 318.9455,-497 318.9455,-509 318.9455,-509 318.9455,-515 312.9455,-521 306.9455,-521"/>
<text text-anchor="middle" x="288.1235" y="-507.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="288.1235" y="-490.4" font-family="Verdana" font-size="14.00" fill="#000000">Debug</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge3" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge3"><a xlink:title="at reseed_bootstrap.go:43: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M106.6294,-374.0251C143.6948,-400.3648 212.738,-449.4289 254.1541,-478.8604"/>
<polygon fill="#8b4513" stroke="#8b4513" points="252.3722,-481.8878 262.551,-484.8275 256.427,-476.1818 252.3722,-481.8878"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Info -->
<g id="node11" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Info</title>
<g id="a_node11"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Info | defined in logger.go:225">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M305.6193,-582C305.6193,-582 270.6277,-582 270.6277,-582 264.6277,-582 258.6277,-576 258.6277,-570 258.6277,-570 258.6277,-558 258.6277,-558 258.6277,-552 264.6277,-546 270.6277,-546 270.6277,-546 305.6193,-546 305.6193,-546 311.6193,-546 317.6193,-552 317.6193,-558 317.6193,-558 317.6193,-570 317.6193,-570 317.6193,-576 311.6193,-582 305.6193,-582"/>
<text text-anchor="middle" x="288.1235" y="-568.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="288.1235" y="-551.4" font-family="Verdana" font-size="14.00" fill="#000000">Info</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/sirupsen/logrus.Logger).Info -->
<g id="edge6" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(*github.com/sirupsen/logrus.Logger).Info</title>
<g id="a_edge6"><a xlink:title="at reseed_bootstrap.go:63: calling [(*github.com/sirupsen/logrus.Logger).Info]">
<path fill="none" stroke="#8b4513" d="M92.3256,-374.0399C114.3749,-408.7975 166.9292,-485.8578 227.5288,-534 234.1285,-539.243 241.7932,-543.9051 249.4061,-547.8995"/>
<polygon fill="#8b4513" stroke="#8b4513" points="248.0753,-551.1458 258.5915,-552.435 251.1745,-544.8692 248.0753,-551.1458"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed -->
<g id="node12" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed</title>
<g id="a_node12"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed | defined in reseed.go:31">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M326.3271,-668C326.3271,-668 249.9199,-668 249.9199,-668 243.9199,-668 237.9199,-662 237.9199,-656 237.9199,-656 237.9199,-644 237.9199,-644 237.9199,-638 243.9199,-632 249.9199,-632 249.9199,-632 326.3271,-632 326.3271,-632 332.3271,-632 338.3271,-638 338.3271,-644 338.3271,-644 338.3271,-656 338.3271,-656 338.3271,-662 332.3271,-668 326.3271,-668"/>
<text text-anchor="middle" x="288.1235" y="-654.2" font-family="Verdana" font-size="14.00" fill="#000000">reseed</text>
<text text-anchor="middle" x="288.1235" y="-637.4" font-family="Verdana" font-size="14.00" fill="#000000">SingleReseed</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed -->
<g id="edge8" class="edge">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/bootstrap.ReseedBootstrap).GetPeers&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed</title>
<g id="a_edge8"><a xlink:title="at reseed_bootstrap.go:49: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/netdb/reseed.Reseed).SingleReseed]">
<path fill="none" stroke="#8b4513" d="M89.919,-374.0435C110.3702,-415.6822 164.7136,-520.678 227.5288,-596 236.2167,-606.4176 246.9389,-616.6363 256.9371,-625.3325"/>
<polygon fill="#8b4513" stroke="#8b4513" points="254.8567,-628.1572 264.7475,-631.9549 259.3837,-622.8181 254.8567,-628.1572"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,77 @@
package bootstrap
import (
"context"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/config"
"github.com/go-i2p/go-i2p/lib/netdb/reseed"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
"github.com/samber/oops"
)
var log = logger.GetGoI2PLogger()
// ReseedBootstrap implements the Bootstrap interface using HTTP reseeding
type ReseedBootstrap struct {
// Configuration containing reseed servers
config *config.BootstrapConfig
}
// NewReseedBootstrap creates a new reseeder with the provided configuration
func NewReseedBootstrap(config *config.BootstrapConfig) *ReseedBootstrap {
return &ReseedBootstrap{
config: config,
}
}
// GetPeers implements the Bootstrap interface by obtaining RouterInfos
// from configured reseed servers
func (rb *ReseedBootstrap) GetPeers(ctx context.Context, n int) ([]router_info.RouterInfo, error) {
var allRouterInfos []router_info.RouterInfo
var lastErr error
// Try each reseed server until we get enough routerInfos or exhaust all servers
for _, server := range rb.config.ReseedServers {
// Check if context is canceled before making request
if ctx.Err() != nil {
return nil, oops.Errorf("reseed canceled: %v", ctx.Err())
}
log.WithField("server", server.Url).Debug("Attempting to reseed from server")
// Use the existing Reseed implementation with a timeout context
reseeder := reseed.NewReseed()
// Perform the actual reseeding operation synchronously
serverRIs, err := reseeder.SingleReseed(server.Url)
if err != nil {
log.WithError(err).WithField("server", server.Url).Warn("Reseed attempt failed")
lastErr = oops.Errorf("reseed from %s failed: %v", server.Url, err)
continue
}
// Add the retrieved RouterInfos to our collection
allRouterInfos = append(allRouterInfos, serverRIs...)
log.WithFields(logrus.Fields{
"server": server.Url,
"count": len(serverRIs),
"total": len(allRouterInfos),
}).Info("Successfully obtained router infos from reseed server")
// Check if we have enough RouterInfos
if n > 0 && len(allRouterInfos) >= n {
break
}
}
// If we couldn't get any RouterInfos from any server, return the last error
if len(allRouterInfos) == 0 && lastErr != nil {
return nil, oops.Errorf("all reseed attempts failed: %w", lastErr)
}
return allRouterInfos, nil
}

View File

@ -0,0 +1,43 @@
# base32
--
import "github.com/go-i2p/go-i2p/lib/common/base32"
![base32.svg](base32.svg)
Package base32 implements 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 base32 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
[go-i2p template file](/template.md)

View File

@ -1,4 +1,4 @@
// Package base32 implmenets utilities for encoding and decoding text using I2P's alphabet
// Package base32 implements utilities for encoding and decoding text using I2P's alphabet
package base32
import (
@ -17,7 +17,7 @@ func EncodeToString(data []byte) string {
return I2PEncoding.EncodeToString(data)
}
// DecodeString decodes base64 string to []byte I2PEncoding
// DecodeString decodes base32 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,43 @@
# 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
[go-i2p template file](/template.md)

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,127 @@
# 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
[go-i2p template file](/template.md)

View File

@ -3,13 +3,20 @@
package certificate
import (
"encoding/binary"
"fmt"
log "github.com/sirupsen/logrus"
"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
@ -70,12 +77,23 @@ 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 {
return c.payload[c.len.Int():]
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.
@ -83,6 +101,9 @@ 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
}
@ -94,12 +115,18 @@ func (c *Certificate) length() (cert_len int) {
// 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
}
@ -108,48 +135,52 @@ 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
}
// NewCertificate creates a new Certficiate from []byte
// readCertificate creates a new Certficiate from []byte
// returns err if the certificate is too short or if the payload doesn't match specified length.
func NewCertificate(data []byte) (certificate *Certificate, err error) {
certificate = &Certificate{}
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(log.Fields{
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 = fmt.Errorf("error parsing certificate: certificate is empty")
err = oops.Errorf("error parsing certificate: certificate is empty")
return
case 1 , 2:
certificate.kind = Integer(data[0:len(data)-1])
case 1, 2:
certificate.kind = Integer(data[0 : len(data)-1])
certificate.len = Integer([]byte{0})
log.WithFields(log.Fields{
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 = fmt.Errorf("error parsing certificate: certificate is 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])
payleng := len(data) - CERT_MIN_SIZE
payloadLength := len(data) - CERT_MIN_SIZE
certificate.payload = data[CERT_MIN_SIZE:]
if certificate.len.Int() > len(data)-CERT_MIN_SIZE {
err = fmt.Errorf("certificate parsing warning: certificate data is shorter than specified by length")
log.WithFields(log.Fields{
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": payleng,
"certificate_payload_length": payloadLength,
"data_bytes:": string(data),
"kind_bytes": data[0:1],
"len_bytes": data[1:3],
@ -157,17 +188,103 @@ func NewCertificate(data []byte) (certificate *Certificate, 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 = NewCertificate(data)
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,-465C1038.4239,-465 1086.3103,-465 1086.3103,-465 1092.3103,-465 1098.3103,-471 1098.3103,-477 1098.3103,-477 1098.3103,-592 1098.3103,-592 1098.3103,-598 1092.3103,-604 1086.3103,-604 1086.3103,-604 1038.4239,-604 1038.4239,-604 1032.4239,-604 1026.4239,-598 1026.4239,-592 1026.4239,-592 1026.4239,-477 1026.4239,-477 1026.4239,-471 1032.4239,-465 1038.4239,-465"/>
<text text-anchor="middle" x="1062.3671" y="-473.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,-235C1035.7065,-235 1090.0277,-235 1090.0277,-235 1096.0277,-235 1102.0277,-241 1102.0277,-247 1102.0277,-247 1102.0277,-301 1102.0277,-301 1102.0277,-307 1096.0277,-313 1090.0277,-313 1090.0277,-313 1035.7065,-313 1035.7065,-313 1029.7065,-313 1023.7065,-307 1023.7065,-301 1023.7065,-301 1023.7065,-247 1023.7065,-247 1023.7065,-241 1029.7065,-235 1035.7065,-235"/>
<text text-anchor="middle" x="1062.8671" y="-243.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,-612C1023.2577,-612 1101.4765,-612 1101.4765,-612 1107.4765,-612 1113.4765,-618 1113.4765,-624 1113.4765,-624 1113.4765,-800 1113.4765,-800 1113.4765,-806 1107.4765,-812 1101.4765,-812 1101.4765,-812 1023.2577,-812 1023.2577,-812 1017.2577,-812 1011.2577,-806 1011.2577,-800 1011.2577,-800 1011.2577,-624 1011.2577,-624 1011.2577,-618 1017.2577,-612 1023.2577,-612"/>
<text text-anchor="middle" x="1062.3671" y="-620.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,-413C322.261,-413 866.0844,-413 866.0844,-413 872.0844,-413 878.0844,-419 878.0844,-425 878.0844,-425 878.0844,-662 878.0844,-662 878.0844,-668 872.0844,-674 866.0844,-674 866.0844,-674 322.261,-674 322.261,-674 316.261,-674 310.261,-668 310.261,-662 310.261,-662 310.261,-425 310.261,-425 310.261,-419 316.261,-413 322.261,-413"/>
<text text-anchor="middle" x="594.1727" y="-421.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.init -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.init</title>
<g id="a_node1"><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,-882C139.0225,-882 109.0225,-882 109.0225,-882 103.0225,-882 97.0225,-876 97.0225,-870 97.0225,-870 97.0225,-858 97.0225,-858 97.0225,-852 103.0225,-846 109.0225,-846 109.0225,-846 139.0225,-846 139.0225,-846 145.0225,-846 151.0225,-852 151.0225,-858 151.0225,-858 151.0225,-870 151.0225,-870 151.0225,-876 145.0225,-882 139.0225,-882"/>
<text text-anchor="middle" x="124.0225" y="-859.8" font-family="Verdana" font-size="14.00" fill="#000000">init</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node2"><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,-882C414.3292,-882 316.9502,-882 316.9502,-882 310.9502,-882 304.9502,-876 304.9502,-870 304.9502,-870 304.9502,-858 304.9502,-858 304.9502,-852 310.9502,-846 316.9502,-846 316.9502,-846 414.3292,-846 414.3292,-846 420.3292,-846 426.3292,-852 426.3292,-858 426.3292,-858 426.3292,-870 426.3292,-870 426.3292,-876 420.3292,-882 414.3292,-882"/>
<text text-anchor="middle" x="365.6397" y="-868.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="365.6397" y="-851.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="edge28" 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_edge28"><a xlink:title="at certificate.go:18: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M151.2694,-864C185.8355,-864 246.7324,-864 294.8092,-864"/>
<polygon fill="#8b4513" stroke="#8b4513" points="294.8596,-867.5001 304.8596,-864 294.8595,-860.5001 294.8596,-867.5001"/>
</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:150&#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]&#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:194: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M879.924,-404C879.924,-404 796.587,-404 796.587,-404 790.587,-404 784.587,-398 784.587,-392 784.587,-392 784.587,-380 784.587,-380 784.587,-374 790.587,-368 796.587,-368 796.587,-368 879.924,-368 879.924,-368 885.924,-368 891.924,-374 891.924,-380 891.924,-380 891.924,-392 891.924,-392 891.924,-398 885.924,-404 879.924,-404"/>
<text text-anchor="middle" x="838.2555" y="-381.8" font-family="Verdana" font-size="14.00" fill="#000000">readCertificate</text>
</a>
</g>
</g>
<!-- github.com/samber/oops.Errorf -->
<g id="node4" class="node">
<title>github.com/samber/oops.Errorf</title>
<g id="a_node4"><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,-67C1079.5624,-67 1045.1718,-67 1045.1718,-67 1039.1718,-67 1033.1718,-61 1033.1718,-55 1033.1718,-55 1033.1718,-43 1033.1718,-43 1033.1718,-37 1039.1718,-31 1045.1718,-31 1045.1718,-31 1079.5624,-31 1079.5624,-31 1085.5624,-31 1091.5624,-37 1091.5624,-43 1091.5624,-43 1091.5624,-55 1091.5624,-55 1091.5624,-61 1085.5624,-67 1079.5624,-67"/>
<text text-anchor="middle" x="1062.3671" y="-53.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="1062.3671" y="-36.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="edge5" 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_edge5"><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="M843.461,-367.7596C858.7506,-317.0084 907.9694,-172.161 994.3902,-85 1002.7534,-76.5652 1013.511,-69.6458 1023.9897,-64.207"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1025.5893,-67.3212 1033.0592,-59.8078 1022.5343,-61.023 1025.5893,-67.3212"/>
</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,-743C1093.5862,-743 1031.148,-743 1031.148,-743 1025.148,-743 1019.148,-737 1019.148,-731 1019.148,-731 1019.148,-719 1019.148,-719 1019.148,-713 1025.148,-707 1031.148,-707 1031.148,-707 1093.5862,-707 1093.5862,-707 1099.5862,-707 1105.5862,-713 1105.5862,-719 1105.5862,-719 1105.5862,-731 1105.5862,-731 1105.5862,-737 1099.5862,-743 1093.5862,-743"/>
<text text-anchor="middle" x="1062.3671" y="-729.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-712.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="edge3" 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_edge3"><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="M891.917,-391.3773C902.8347,-394.724 913.4056,-399.9381 921.3902,-408 967.6993,-454.7571 951.8882,-644.7571 994.3902,-695 998.8122,-700.2274 1004.3228,-704.5768 1010.2804,-708.1876"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.7824,-711.3552 1019.2541,-712.9655 1012.0722,-705.1764 1008.7824,-711.3552"/>
</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,-682C1080.1334,-682 1044.6008,-682 1044.6008,-682 1038.6008,-682 1032.6008,-676 1032.6008,-670 1032.6008,-670 1032.6008,-658 1032.6008,-658 1032.6008,-652 1038.6008,-646 1044.6008,-646 1044.6008,-646 1080.1334,-646 1080.1334,-646 1086.1334,-646 1092.1334,-652 1092.1334,-658 1092.1334,-658 1092.1334,-670 1092.1334,-670 1092.1334,-676 1086.1334,-682 1080.1334,-682"/>
<text text-anchor="middle" x="1062.3671" y="-668.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-651.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="edge4" 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_edge4"><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="M892.211,-392.2353C902.8574,-395.5536 913.2416,-400.5393 921.3902,-408 991.7973,-472.4634 938.6811,-532.4811 994.3902,-610 1002.5208,-621.3137 1013.6427,-631.4976 1024.5356,-639.8926"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1022.6393,-642.8427 1032.7675,-645.9526 1026.7892,-637.2055 1022.6393,-642.8427"/>
</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,-305C1081.1891,-305 1043.5451,-305 1043.5451,-305 1037.5451,-305 1031.5451,-299 1031.5451,-293 1031.5451,-293 1031.5451,-281 1031.5451,-281 1031.5451,-275 1037.5451,-269 1043.5451,-269 1043.5451,-269 1081.1891,-269 1081.1891,-269 1087.1891,-269 1093.1891,-275 1093.1891,-281 1093.1891,-281 1093.1891,-293 1093.1891,-293 1093.1891,-299 1087.1891,-305 1081.1891,-305"/>
<text text-anchor="middle" x="1062.3671" y="-291.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="1062.3671" y="-274.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="edge22" 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_edge22"><a xlink:title="at certificate.go:194: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M892.1337,-371.7653C913.1934,-365.4801 937.3031,-357.3779 958.3902,-348 982.1042,-337.4539 1007.2418,-322.8114 1026.8594,-310.5158"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1028.8939,-313.3699 1035.4595,-305.0547 1025.1415,-307.4606 1028.8939,-313.3699"/>
</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,-535C1077.3671,-535 1047.3671,-535 1047.3671,-535 1041.3671,-535 1035.3671,-529 1035.3671,-523 1035.3671,-523 1035.3671,-511 1035.3671,-511 1035.3671,-505 1041.3671,-499 1047.3671,-499 1047.3671,-499 1077.3671,-499 1077.3671,-499 1083.3671,-499 1089.3671,-505 1089.3671,-511 1089.3671,-511 1089.3671,-523 1089.3671,-523 1089.3671,-529 1083.3671,-535 1077.3671,-535"/>
<text text-anchor="middle" x="1062.3671" y="-521.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-504.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="edge19" 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_edge19"><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="M892.1796,-396.8988C902.1529,-399.8488 912.2861,-403.5071 921.3902,-408 965.8313,-429.9318 1009.8542,-467.0947 1036.5817,-491.8403"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1034.288,-494.4876 1043.9749,-498.7788 1039.0783,-489.3834 1034.288,-494.4876"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate</title>
<g id="a_node5"><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:207: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes]&#10;at certificate.go:208: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:210: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:204: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M167.867,-544C167.867,-544 80.178,-544 80.178,-544 74.178,-544 68.178,-538 68.178,-532 68.178,-532 68.178,-520 68.178,-520 68.178,-514 74.178,-508 80.178,-508 80.178,-508 167.867,-508 167.867,-508 173.867,-508 179.867,-514 179.867,-520 179.867,-520 179.867,-532 179.867,-532 179.867,-538 173.867,-544 167.867,-544"/>
<text text-anchor="middle" x="124.0225" y="-521.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="edge10" 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_edge10"><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="M133.2712,-507.925C160.9369,-456.6575 248.4485,-314 365.6397,-314 365.6397,-314 365.6397,-314 655.1208,-314 709.2908,-314 766.614,-341.6219 802.4026,-362.6485"/>
<polygon fill="#000000" stroke="#000000" points="800.6488,-365.6779 811.0225,-367.8314 804.2559,-359.6788 800.6488,-365.6779"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes -->
<g id="node14" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).ExcessBytes</title>
<g id="a_node14"><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: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]&#10;at certificate.go:90: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M400.8974,-544C400.8974,-544 330.382,-544 330.382,-544 324.382,-544 318.382,-538 318.382,-532 318.382,-532 318.382,-520 318.382,-520 318.382,-514 324.382,-508 330.382,-508 330.382,-508 400.8974,-508 400.8974,-508 406.8974,-508 412.8974,-514 412.8974,-520 412.8974,-520 412.8974,-532 412.8974,-532 412.8974,-538 406.8974,-544 400.8974,-544"/>
<text text-anchor="middle" x="365.6397" y="-521.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="edge11" 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_edge11"><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="M180.0616,-526C218.4529,-526 269.2339,-526 307.9697,-526"/>
<polygon fill="#000000" stroke="#000000" points="308.0482,-529.5001 318.0481,-526 308.0481,-522.5001 308.0482,-529.5001"/>
</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="edge23" 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_edge23"><a xlink:title="at certificate.go:208: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M140.2328,-544.1019C202.5506,-612.8635 428.1494,-854 527.1776,-854 527.1776,-854 527.1776,-854 838.2555,-854 894.5306,-854 917.4231,-852.5822 958.3902,-814 980.4768,-793.1992 971.6124,-776.0416 994.3902,-756 999.1192,-751.8391 1004.5002,-748.1413 1010.1157,-744.8806"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1011.8901,-747.901 1019.0729,-740.1127 1008.601,-741.7219 1011.8901,-747.901"/>
</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,-804C1080.1334,-804 1044.6008,-804 1044.6008,-804 1038.6008,-804 1032.6008,-798 1032.6008,-792 1032.6008,-792 1032.6008,-780 1032.6008,-780 1032.6008,-774 1038.6008,-768 1044.6008,-768 1044.6008,-768 1080.1334,-768 1080.1334,-768 1086.1334,-768 1092.1334,-774 1092.1334,-780 1092.1334,-780 1092.1334,-792 1092.1334,-792 1092.1334,-798 1086.1334,-804 1080.1334,-804"/>
<text text-anchor="middle" x="1062.3671" y="-790.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="1062.3671" y="-773.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="edge29" 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_edge29"><a xlink:title="at certificate.go:204: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M133.608,-544.0044C157.4753,-587.4339 223.5529,-699.4196 305.045,-768 315.6386,-776.9151 513.3319,-881 527.1776,-881 527.1776,-881 527.1776,-881 838.2555,-881 911.0468,-881 987.3433,-837.9917 1029.4741,-809.8508"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1031.6358,-812.6133 1037.9322,-804.0924 1027.6964,-806.827 1031.6358,-812.6133"/>
</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="edge26" 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_edge26"><a xlink:title="at certificate.go:210: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M132.0037,-507.8323C163.941,-436.4345 284.7068,-179 365.6397,-179 365.6397,-179 365.6397,-179 838.2555,-179 894.5306,-179 912.3964,-186.5738 958.3902,-219 979.6082,-233.959 973.1094,-250.1304 994.3902,-265 1002.5405,-270.6949 1012.2512,-274.9803 1021.7462,-278.1807"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1020.9029,-281.5823 1031.4883,-281.1365 1022.9353,-274.8838 1020.9029,-281.5823"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateWithType</title>
<g id="a_node6"><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,-84C909.5251,-84 766.9859,-84 766.9859,-84 760.9859,-84 754.9859,-78 754.9859,-72 754.9859,-72 754.9859,-60 754.9859,-60 754.9859,-54 760.9859,-48 766.9859,-48 766.9859,-48 909.5251,-48 909.5251,-48 915.5251,-48 921.5251,-54 921.5251,-60 921.5251,-60 921.5251,-72 921.5251,-72 921.5251,-78 915.5251,-84 909.5251,-84"/>
<text text-anchor="middle" x="838.2555" y="-61.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="edge1" 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_edge1"><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="M921.7064,-59.6698C956.3568,-57.0414 994.9181,-54.1164 1022.8896,-51.9946"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1023.3546,-55.4694 1033.0612,-51.223 1022.8251,-48.4895 1023.3546,-55.4694"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt -->
<g id="node7" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt</title>
<g id="a_node7"><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,-133C1118.3209,-133 1006.4133,-133 1006.4133,-133 1000.4133,-133 994.4133,-127 994.4133,-121 994.4133,-121 994.4133,-109 994.4133,-109 994.4133,-103 1000.4133,-97 1006.4133,-97 1006.4133,-97 1118.3209,-97 1118.3209,-97 1124.3209,-97 1130.3209,-103 1130.3209,-109 1130.3209,-109 1130.3209,-121 1130.3209,-121 1130.3209,-127 1124.3209,-133 1118.3209,-133"/>
<text text-anchor="middle" x="1062.3671" y="-119.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-102.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.NewCertificateWithType&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt -->
<g id="edge12" 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_edge12"><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="M920.7516,-84.037C941.5594,-88.5865 963.8317,-93.4561 984.4085,-97.9551"/>
<polygon fill="#8b4513" stroke="#8b4513" points="983.843,-101.414 994.3598,-100.1308 985.3382,-94.5756 983.843,-101.414"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate -->
<g id="node8" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate</title>
<g id="a_node8"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.GetSignatureTypeFromCertificate | defined in certificate.go:281&#10;at certificate.go:283: calling [github.com/samber/oops.Errorf]&#10;at certificate.go:286: calling [github.com/samber/oops.Errorf]&#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]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M220.0675,-267C220.0675,-267 27.9775,-267 27.9775,-267 21.9775,-267 15.9775,-261 15.9775,-255 15.9775,-255 15.9775,-243 15.9775,-243 15.9775,-237 21.9775,-231 27.9775,-231 27.9775,-231 220.0675,-231 220.0675,-231 226.0675,-231 232.0675,-237 232.0675,-243 232.0675,-243 232.0675,-255 232.0675,-255 232.0675,-261 226.0675,-267 220.0675,-267"/>
<text text-anchor="middle" x="124.0225" y="-244.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="edge13" 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_edge13"><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="M132.0558,-230.7953C157.5611,-176.1035 242.3532,-17 365.6397,-17 365.6397,-17 365.6397,-17 838.2555,-17 903.7059,-17 978.8384,-30.5409 1023.3611,-40.0059"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1022.6748,-43.4383 1033.1892,-42.1352 1024.157,-36.597 1022.6748,-43.4383"/>
</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:118: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:120: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M380.6397,-483C380.6397,-483 350.6397,-483 350.6397,-483 344.6397,-483 338.6397,-477 338.6397,-471 338.6397,-471 338.6397,-459 338.6397,-459 338.6397,-453 344.6397,-447 350.6397,-447 350.6397,-447 380.6397,-447 380.6397,-447 386.6397,-447 392.6397,-453 392.6397,-459 392.6397,-459 392.6397,-471 392.6397,-471 392.6397,-477 386.6397,-483 380.6397,-483"/>
<text text-anchor="middle" x="365.6397" y="-460.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="edge34" 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_edge34"><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="M136.3729,-267.189C162.9531,-305.0493 229.3421,-392.9539 305.045,-443 312.2922,-447.791 320.7156,-451.6993 328.9357,-454.8197"/>
<polygon fill="#000000" stroke="#000000" points="327.8145,-458.1353 338.4093,-458.1265 330.1214,-451.5264 327.8145,-458.1353"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux -->
<g id="node9" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux</title>
<g id="a_node9"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.NewCertificateDeux | defined in certificate.go:223&#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:233: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.NewIntegerFromInt]&#10;at certificate.go:246: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M896.0832,-149C896.0832,-149 780.4278,-149 780.4278,-149 774.4278,-149 768.4278,-143 768.4278,-137 768.4278,-137 768.4278,-125 768.4278,-125 768.4278,-119 774.4278,-113 780.4278,-113 780.4278,-113 896.0832,-113 896.0832,-113 902.0832,-113 908.0832,-119 908.0832,-125 908.0832,-125 908.0832,-137 908.0832,-137 908.0832,-143 902.0832,-149 896.0832,-149"/>
<text text-anchor="middle" x="838.2555" y="-126.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="edge7" 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_edge7"><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="M887.7152,-112.9032C928.6571,-97.923 986.0139,-76.9368 1023.6641,-63.161"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1025.0712,-66.3732 1033.2596,-59.6501 1022.6658,-59.7994 1025.0712,-66.3732"/>
</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="edge14" 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_edge14"><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="M908.244,-126.0033C932.2872,-124.2868 959.3532,-122.3545 984.017,-120.5936"/>
<polygon fill="#8b4513" stroke="#8b4513" points="984.3351,-124.0799 994.0604,-119.8766 983.8365,-117.0977 984.3351,-124.0799"/>
</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="edge39" 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_edge39"><a xlink:title="at certificate.go:243: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M845.9375,-149.0798C861.787,-186.9105 898.5391,-277.4256 921.3902,-356 921.7264,-357.1562 993.6297,-694.0665 994.3902,-695 998.7149,-700.3083 1004.1684,-704.705 1010.0968,-708.34"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.5792,-711.4976 1019.0463,-713.1381 1011.8868,-705.3283 1008.5792,-711.4976"/>
</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="edge27" 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_edge27"><a xlink:title="at certificate.go:246: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M908.1164,-143.6497C926.2572,-149.7304 944.5615,-158.7196 958.3902,-172 990.358,-202.7003 962.1796,-234.5546 994.3902,-265 1001.9625,-272.1573 1011.8843,-276.9863 1021.7984,-280.2443"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.0486,-283.6691 1031.6227,-283.0067 1022.9434,-276.9305 1021.0486,-283.6691"/>
</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:127: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#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]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M857.9142,-666C857.9142,-666 818.5968,-666 818.5968,-666 812.5968,-666 806.5968,-660 806.5968,-654 806.5968,-654 806.5968,-642 806.5968,-642 806.5968,-636 812.5968,-630 818.5968,-630 818.5968,-630 857.9142,-630 857.9142,-630 863.9142,-630 869.9142,-636 869.9142,-642 869.9142,-642 869.9142,-654 869.9142,-654 869.9142,-660 863.9142,-666 857.9142,-666"/>
<text text-anchor="middle" x="838.2555" y="-643.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="edge8" 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_edge8"><a xlink:title="at certificate.go:127: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M870.0649,-657.1505C894.3918,-664.3043 928.6908,-674.7273 958.3902,-685 975.198,-690.8137 993.3464,-697.6116 1009.7037,-703.9367"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.5154,-707.23 1019.104,-707.5952 1011.0543,-700.7066 1008.5154,-707.23"/>
</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="edge15" 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_edge15"><a xlink:title="at certificate.go:129: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M870.2398,-646.2549C887.181,-643.8062 907.3314,-638.2734 921.3902,-626 927.7074,-620.4851 1018.9507,-394.8409 1051.1873,-314.8006"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1054.5008,-315.9419 1054.9885,-305.3583 1048.0072,-313.3277 1054.5008,-315.9419"/>
</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="edge36" 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_edge36"><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="M864.0849,-629.8445C894.4986,-608.8505 946.8993,-573.8677 994.3902,-548 1004.4193,-542.5372 1015.5908,-537.1651 1025.9324,-532.4675"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1027.4335,-535.6304 1035.1399,-528.3598 1024.5815,-529.2377 1027.4335,-535.6304"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="node11" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data</title>
<g id="a_node11"><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:135: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length]&#10;at certificate.go:144: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at certificate.go:138: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#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,-666C670.1208,-666 640.1208,-666 640.1208,-666 634.1208,-666 628.1208,-660 628.1208,-654 628.1208,-654 628.1208,-642 628.1208,-642 628.1208,-636 634.1208,-630 640.1208,-630 640.1208,-630 670.1208,-630 670.1208,-630 676.1208,-630 682.1208,-636 682.1208,-642 682.1208,-642 682.1208,-654 682.1208,-654 682.1208,-660 676.1208,-666 670.1208,-666"/>
<text text-anchor="middle" x="655.1208" y="-643.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).Data&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Length -->
<g id="edge9" 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_edge9"><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,-648C712.169,-648 761.0347,-648 796.0998,-648"/>
<polygon fill="#000000" stroke="#000000" points="796.503,-651.5001 806.5029,-648 796.5029,-644.5001 796.503,-651.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="edge38" 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_edge38"><a xlink:title="at certificate.go:142: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M682.4043,-657.6911C702.3376,-664.4675 730.1361,-673.2919 755.1208,-679 802.2639,-689.7705 934.1095,-708.0217 1008.8674,-717.9895"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.6484,-721.4911 1019.0224,-719.3394 1009.5708,-714.5521 1008.6484,-721.4911"/>
</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="edge37" 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_edge37"><a xlink:title="at certificate.go:138: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M682.3875,-663.988C702.0815,-675.0131 729.5957,-689.3622 755.1208,-699 842.3604,-731.94 868.9683,-724.5515 958.3902,-751 979.854,-757.3484 1003.5224,-765.2437 1022.8484,-771.9279"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.9294,-775.314 1032.5242,-775.2983 1024.2321,-768.7036 1021.9294,-775.314"/>
</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="edge16" 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_edge16"><a xlink:title="at certificate.go:144: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M658.5576,-629.7931C670.1306,-570.4882 709.5214,-384.53 755.1208,-347 790.2822,-318.0609 913.965,-331.0103 958.3902,-321 979.6897,-316.2006 1002.8275,-308.8553 1021.8572,-302.2184"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1023.1499,-305.4736 1031.4026,-298.8296 1020.8079,-298.877 1023.1499,-305.4736"/>
</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: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:103: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at certificate.go:104: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at certificate.go:106: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M543.0641,-666C543.0641,-666 511.2911,-666 511.2911,-666 505.2911,-666 499.2911,-660 499.2911,-654 499.2911,-654 499.2911,-642 499.2911,-642 499.2911,-636 505.2911,-630 511.2911,-630 511.2911,-630 543.0641,-630 543.0641,-630 549.0641,-630 555.0641,-636 555.0641,-642 555.0641,-642 555.0641,-654 555.0641,-654 555.0641,-660 549.0641,-666 543.0641,-666"/>
<text text-anchor="middle" x="527.1776" y="-643.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).Bytes&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data -->
<g id="edge18" 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_edge18"><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,-648C573.6714,-648 597.9555,-648 617.9655,-648"/>
<polygon fill="#000000" stroke="#000000" points="617.9862,-651.5001 627.9861,-648 617.9861,-644.5001 617.9862,-651.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="edge21" 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_edge21"><a xlink:title="at certificate.go:104: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M545.7592,-666.2843C569.1882,-687.3211 611.6811,-719 655.1208,-719 655.1208,-719 655.1208,-719 838.2555,-719 896.5723,-719 963.3943,-721.0552 1008.79,-722.76"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1008.8674,-726.2654 1018.9941,-723.1508 1009.1354,-719.2706 1008.8674,-726.2654"/>
</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="edge25" 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_edge25"><a xlink:title="at certificate.go:106: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M539.3693,-629.5694C584.2939,-561.7745 738.8297,-329.6601 755.1208,-320 766.4099,-313.3059 940.0128,-297.5598 1021.1524,-290.5147"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.838,-293.9686 1031.4992,-289.62 1021.2348,-286.9946 1021.838,-293.9686"/>
</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,-596C1078.2536,-596 1046.4806,-596 1046.4806,-596 1040.4806,-596 1034.4806,-590 1034.4806,-584 1034.4806,-584 1034.4806,-572 1034.4806,-572 1034.4806,-566 1040.4806,-560 1046.4806,-560 1046.4806,-560 1078.2536,-560 1078.2536,-560 1084.2536,-560 1090.2536,-566 1090.2536,-572 1090.2536,-572 1090.2536,-584 1090.2536,-584 1090.2536,-590 1084.2536,-596 1078.2536,-596"/>
<text text-anchor="middle" x="1062.3671" y="-582.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="1062.3671" y="-565.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="edge17" 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_edge17"><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.0762,-638.0068C575.1324,-631.2441 602.9632,-622.7139 628.1208,-618 772.8777,-590.8763 811.8943,-606.1391 958.3902,-591 980.1715,-588.7491 1004.4569,-585.7409 1024.0763,-583.1852"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.7029,-586.633 1034.1607,-581.8581 1023.7895,-579.6928 1024.7029,-586.633"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length -->
<g id="node13" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).length</title>
<g id="a_node13"><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,-666C383.1355,-666 348.1439,-666 348.1439,-666 342.1439,-666 336.1439,-660 336.1439,-654 336.1439,-654 336.1439,-642 336.1439,-642 336.1439,-636 342.1439,-630 348.1439,-630 348.1439,-630 383.1355,-630 383.1355,-630 389.1355,-630 395.1355,-636 395.1355,-642 395.1355,-642 395.1355,-654 395.1355,-654 395.1355,-660 389.1355,-666 383.1355,-666"/>
<text text-anchor="middle" x="365.6397" y="-643.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="edge2" 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_edge2"><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,-648C421.6326,-648 460.3466,-648 489.0205,-648"/>
<polygon fill="#000000" stroke="#000000" points="489.0889,-651.5001 499.0889,-648 489.0888,-644.5001 489.0889,-651.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="edge30" 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_edge30"><a xlink:title="at certificate.go:90: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M412.5676,-544.0107C417.7937,-547.6396 422.5498,-551.9357 426.2344,-557 485.2988,-638.1814 396.3344,-704.2623 462.2344,-780 482.0589,-802.784 496.9762,-800 527.1776,-800 527.1776,-800 527.1776,-800 838.2555,-800 892.3836,-800 908.0531,-799.9004 958.3902,-780 976.273,-772.9302 977.5883,-765.3527 994.3902,-756 999.5451,-753.1306 1005.014,-750.3022 1010.5228,-747.5908"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1012.2784,-750.6307 1019.7827,-743.1517 1009.2523,-744.3185 1012.2784,-750.6307"/>
</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="edge6" 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_edge6"><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="M405.4356,-507.8408C412.5122,-504.1802 419.7033,-500.1675 426.2344,-496 562.2814,-409.1877 562.5915,-323.0791 718.1208,-280 824.2056,-250.6162 955.7957,-267.1277 1021.3056,-278.7111"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1020.7729,-282.1715 1031.2382,-280.52 1022.0271,-275.2848 1020.7729,-282.1715"/>
</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="edge20" 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_edge20"><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="M412.9808,-525.3885C543.5153,-523.7023 906.6987,-519.0109 1024.7631,-517.4858"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1025.1354,-520.9813 1035.0893,-517.3524 1025.0449,-513.9819 1025.1354,-520.9813"/>
</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="edge32" 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_edge32"><a xlink:title="at certificate.go:118: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M392.6545,-473.715C404.3228,-478.6537 417.3145,-485.9052 426.2344,-496 512.9968,-594.1905 396.1467,-773 527.1776,-773 527.1776,-773 527.1776,-773 838.2555,-773 897.8141,-773 964.3408,-756.5908 1009.3268,-742.9609"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1010.6311,-746.2212 1019.1517,-739.9244 1008.5641,-739.5333 1010.6311,-746.2212"/>
</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="edge33" 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_edge33"><a xlink:title="at certificate.go:120: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M392.8289,-459.1026C403.9921,-455.721 416.5427,-450.5915 426.2344,-443 472.1347,-407.0463 457.8603,-375.0815 499.2344,-334 547.9268,-285.6519 563.1359,-271.033 628.1208,-249 664.8556,-236.5452 929.1911,-213.2157 958.3902,-226 979.9989,-235.461 974.5202,-252.2867 994.3902,-265 1002.6878,-270.309 1012.3789,-274.4413 1021.8004,-277.616"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1020.8641,-280.9898 1031.4513,-280.5869 1022.9237,-274.2996 1020.8641,-280.9898"/>
</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="edge31" 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_edge31"><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.9111,-456.9816C403.603,-453.3592 415.7874,-448.6212 426.2344,-443 475.4534,-416.5169 471.2861,-368 527.1776,-368 527.1776,-368 527.1776,-368 655.1208,-368 708.3726,-368 706.5758,-412.1107 755.1208,-434 847.7784,-475.78 965.9196,-500.3729 1025.077,-510.9061"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.6235,-514.3798 1035.0765,-512.652 1025.8276,-507.4841 1024.6235,-514.3798"/>
</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:82: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#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:80: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M394.1852,-605C394.1852,-605 337.0942,-605 337.0942,-605 331.0942,-605 325.0942,-599 325.0942,-593 325.0942,-593 325.0942,-581 325.0942,-581 325.0942,-575 331.0942,-569 337.0942,-569 337.0942,-569 394.1852,-569 394.1852,-569 400.1852,-569 406.1852,-575 406.1852,-581 406.1852,-581 406.1852,-593 406.1852,-593 406.1852,-599 400.1852,-605 394.1852,-605"/>
<text text-anchor="middle" x="365.6397" y="-582.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="edge40" 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_edge40"><a xlink:title="at certificate.go:80: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M406.333,-601.2928C413.9118,-605.6099 421.0617,-611.0968 426.2344,-618 477.5109,-686.4304 405.2015,-743.2877 462.2344,-807 482.3778,-829.5025 496.9762,-827 527.1776,-827 527.1776,-827 527.1776,-827 838.2555,-827 892.3836,-827 912.5458,-835.7773 958.3902,-807 981.8891,-792.2494 973.0274,-773.7034 994.3902,-756 999.1747,-752.0351 1004.549,-748.4685 1010.1248,-745.2901"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1011.7827,-748.3727 1018.9968,-740.6134 1008.5185,-742.1803 1011.7827,-748.3727"/>
</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="edge24" 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_edge24"><a xlink:title="at certificate.go:82: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M404.2549,-568.9863C411.6595,-565.2239 419.2712,-561.1374 426.2344,-557 443.513,-546.7335 447.2136,-543.1361 463.2344,-531 596.6603,-429.9276 597.9858,-350.6775 755.1208,-293 802.7976,-275.4999 949.494,-280.7109 1021.5592,-284.5316"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1021.4534,-288.031 1031.6296,-285.0824 1021.8357,-281.0414 1021.4534,-288.031"/>
</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="edge35" 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_edge35"><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.3658,-586.4739C530.5398,-584.8699 903.2432,-580.0555 1024.087,-578.4945"/>
<polygon fill="#8b4513" stroke="#8b4513" points="1024.3727,-581.9912 1034.3266,-578.3622 1024.2822,-574.9918 1024.3727,-581.9912"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,6 +1,7 @@
package certificate
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
@ -10,7 +11,7 @@ func TestCertificateTypeIsFirstByte(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x00}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_type := certificate.Type()
assert.Equal(cert_type, 3, "certificate.Type() should be the first bytes in a certificate")
@ -21,7 +22,7 @@ func TestCertificateLengthCorrect(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes")
@ -32,12 +33,12 @@ func TestCertificateLengthErrWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x01}
certificate, err := NewCertificate(bytes)
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 length: certificate is too short", err.Error(), "correct error message should be returned")
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
}
}
@ -45,7 +46,7 @@ func TestCertificateLengthErrWhenDataTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_len := certificate.Length()
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was actually missing")
@ -58,7 +59,7 @@ func TestCertificateDataWhenCorrectSize(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x01, 0xaa}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
assert.Nil(err, "certificate.Data() returned error with valid data")
@ -71,13 +72,10 @@ func TestCertificateDataWhenTooLong(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
certificate, err := NewCertificate(bytes)
certificate, _, _ := ReadCertificate(bytes)
cert_data := certificate.Data()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned")
}
cert_len := certificate.Length() //len(cert_data)
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")
@ -88,7 +86,7 @@ func TestCertificateDataWhenTooShort(t *testing.T) {
assert := assert.New(t)
bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, err := NewCertificate(bytes)
certificate, err := readCertificate(bytes)
cert_data := certificate.Data()
if assert.NotNil(err) {
@ -144,6 +142,228 @@ func TestReadCertificateWithInvalidLength(t *testing.T) {
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 length: certificate is too short", err.Error(), "correct error message should be returned")
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
}
}
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")
}

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

@ -0,0 +1,324 @@
# 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 = 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")
)
```
#### 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 DateFromTime
```go
func DateFromTime(t time.Time) (date *Date, err error)
```
DateFromTime takes a time.Time and returns a data.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
[go-i2p template file](/template.md)

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

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 147 KiB

View File

@ -2,12 +2,15 @@
package data
import (
"errors"
"time"
log "github.com/sirupsen/logrus"
"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
@ -51,14 +54,18 @@ func (date Date) Time() (date_time time.Time) {
// 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(log.Fields{
log.WithFields(logrus.Fields{
"data": data,
}).Error("ReadDate: data is too short")
err = errors.New("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
}
@ -66,6 +73,37 @@ func ReadDate(data []byte) (date Date, remainder []byte, err error) {
// 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
}
// DateFromTime takes a time.Time and returns a data.Date
func DateFromTime(t time.Time) (date *Date, err error) {
// Create a new Date
date = new(Date)
// Convert time to milliseconds since Unix epoch
msec := t.UnixNano() / int64(1000000)
// Convert to big-endian bytes
for i := 7; i >= 0; i-- {
date[i] = byte(msec & 0xff)
msec >>= 8
}
log.WithFields(logrus.Fields{
"date_value": date.Int(),
"time": t,
}).Debug("Successfully created Date from time.Time")
return
}

View File

@ -6,7 +6,7 @@ import (
"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}

View File

@ -1,12 +1,24 @@
package data
import "fmt"
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 = fmt.Errorf("%v\n\t%d: %v", err, i, e)
err = oops.Errorf("%v\n\t%d: %v", err, i, e)
}
return err
}

View File

@ -23,8 +23,13 @@ Contents
// 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
}

View File

@ -28,16 +28,29 @@ func (i Integer) Bytes() []byte {
return i[:]
}
// Int returns the Date as a Go integer
// 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[:size], bytes[len(bytes):]
return bytes, nil
}
return bytes[:size], bytes[size:]
}
@ -46,13 +59,7 @@ func ReadInteger(bytes []byte, size int) (Integer, []byte) {
// 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) {
integerSize := MAX_INTEGER_SIZE
if size < MAX_INTEGER_SIZE {
integerSize = size
}
intBytes := bytes[:integerSize]
remainder = bytes[integerSize:]
i, _ := ReadInteger(intBytes, integerSize)
i, remainder := ReadInteger(bytes, size)
integer = &i
return
}
@ -69,17 +76,3 @@ func NewIntegerFromInt(value int, size int) (integer *Integer, err error) {
integer = objinteger
return
}
// 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) {
num_len := len(number)
if num_len < MAX_INTEGER_SIZE {
number = append(
make([]byte, MAX_INTEGER_SIZE-num_len),
number...,
)
}
value = int(binary.BigEndian.Uint64(number))
return
}

View File

@ -1,9 +1,8 @@
package data
import (
"errors"
log "github.com/sirupsen/logrus"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
/*
@ -48,8 +47,12 @@ type Mapping struct {
// 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
}
@ -74,30 +77,40 @@ func (mapping *Mapping) Data() []byte {
// 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
}
@ -107,74 +120,141 @@ func GoMapToMapping(gomap map[string]string) (mapping *Mapping, err error) {
)
}
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 {
return err.Error() == "error parsing string: zero length"
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
/*
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(log.Fields{
log.WithFields(logrus.Fields{
"at": "ReadMapping",
"reason": "zero length",
}).Warn("mapping format violation")
e := errors.New("zero length")
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)
}
if size.Int() == 0 {
return
}
mapping.size = size
map_bytes := remainder[:mapping.size.Int()]
remainder = remainder[mapping.size.Int():]
if len(remainder) == 0 {
log.WithFields(log.Fields{
"at": "ReadMapping",
"reason": "zero length",
}).Warn("mapping format violation")
e := errors.New("zero length")
err = append(err, e)
if size.Int() == 0 {
log.Warn("Mapping size is zero")
return
}
// TODO: this should take the remainder and the length we already parsed above, as a parameter.
// Like tomorrow morning.
// ReadMappingValues should not attempt to figure out the length of the bytes it's reading over.
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *mapping.size)
// 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(log.Fields{
log.WithFields(logrus.Fields{
"at": "ReadMapping",
"reason": "error parsing mapping values",
}).Warn("mapping format violation")
e := errors.New("error parsing mapping values")
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

@ -2,9 +2,9 @@ package data
import (
"bytes"
"errors"
"testing"
"github.com/samber/oops"
"github.com/stretchr/testify/assert"
)
@ -27,7 +27,6 @@ func TestValuesExclusesPairWithBadData(t *testing.T) {
assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key")
assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key")
}
}
func TestValuesWarnsMissingData(t *testing.T) {
@ -54,7 +53,7 @@ func TestValuesWarnsExtraData(t *testing.T) {
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(2, len(errs), "Values() reported wrong error count when mapping had extra 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")
}
}
@ -155,7 +154,7 @@ func TestFullGoMapToMappingProducesCorrectMapping(t *testing.T) {
func TestStopValueReadTrueWhenCorrectErr(t *testing.T) {
assert := assert.New(t)
status := stopValueRead(errors.New("error parsing string: zero length"))
status := stopValueRead(oops.Errorf("error parsing string: zero length"))
assert.Equal(true, status, "stopValueRead() did not return true when String error found")
}
@ -163,7 +162,7 @@ func TestStopValueReadTrueWhenCorrectErr(t *testing.T) {
func TestStopValueReadFalseWhenWrongErr(t *testing.T) {
assert := assert.New(t)
status := stopValueRead(errors.New("something else"))
status := stopValueRead(oops.Errorf("something else"))
assert.Equal(false, status, "stopValueRead() did not return false when non String error found")
}

View File

@ -1,10 +1,10 @@
package data
import (
"errors"
"sort"
log "github.com/sirupsen/logrus"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
@ -12,21 +12,36 @@ 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 {
return pair[1][1:]
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 =
// 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 {
@ -34,6 +49,10 @@ func ValuesToMapping(values MappingValues) *Mapping {
}
}
log.WithFields(logrus.Fields{
"mapping_size": baseLength,
}).Debug("Created Mapping from MappingValues")
mappingSize, _ := NewIntegerFromInt(baseLength, 2)
return &Mapping{
size: mappingSize,
@ -58,41 +77,46 @@ func mappingOrder(values MappingValues) {
// 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
// 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(log.Fields{
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "data shorter than expected",
}).Error("mapping contained no data")
errs = []error{errors.New("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(log.Fields{
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, errors.New("warning parsing mapping: data exists beyond length of mapping"))
errs = append(errs, oops.Errorf("warning parsing mapping: data exists beyond length of mapping"))
} else if int_map_length > mapping_len {
log.WithFields(log.Fields{
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, errors.New("warning parsing mapping: mapping length exceeds provided data"))
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:]
// remainder = remainder[2:]
for {
// Read a key, breaking on fatal errors
@ -105,7 +129,7 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
// 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(log.Fields{
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "mapping format violation",
}).Warn("mapping format violation, too few bytes for a kv pair")
@ -116,25 +140,25 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
//return
// return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// log.Printf("(MAPPING VALUES DEBUG) 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(log.Fields{
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, errors.New("mapping format violation, duplicate key in mapping"))
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
@ -142,12 +166,12 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
}
if !beginsWith(remainder, 0x3d) {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "expected =",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, errors.New("mapping format violation, expected ="))
errs = append(errs, oops.Errorf("mapping format violation, expected ="))
log.Printf("ERRVAL: %s", remainder)
break
} else {
@ -160,20 +184,20 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
if err != nil {
if stopValueRead(err) {
errs = append(errs, err)
//return
// return
}
}
// overwriting remainder with more as another var to prevent memory weirdness in loops
remainder = more
//log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
//log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
// log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
// log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
if !beginsWith(remainder, 0x3b) {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(Mapping) Values",
"reason": "expected ;",
"value:": string(remainder),
}).Warn("mapping format violation")
errs = append(errs, errors.New("mapping format violation, expected ;"))
errs = append(errs, oops.Errorf("mapping format violation, expected ;"))
break
} else {
remainder = remainder[1:]
@ -189,6 +213,12 @@ func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingVal
encounteredKeysMap[keyAsString] = true
}
values = &map_values
return
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

@ -1,9 +1,8 @@
package data
import (
"errors"
log "github.com/sirupsen/logrus"
"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
@ -31,25 +30,41 @@ type I2PString []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(log.Fields{
log.WithFields(logrus.Fields{
"at": "(I2PString) Length",
"reason": "no data",
}).Error("error parsing string")
err = errors.New("error parsing string: zero length")
err = ErrZeroLength
return
}
l, _, _ := NewInteger(str, 1)
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) - 1
if length != str_len {
log.WithFields(log.Fields{
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",
}).Error("string format warning")
err = errors.New("string parsing warning: string data is shorter 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
}
@ -58,41 +73,65 @@ func (str I2PString) Length() (length int, err error) {
func (str I2PString) Data() (data string, err error) {
length, err := str.Length()
if err != nil {
switch err.Error() {
case "error parsing string: zero length":
return
case "string parsing warning: string data is shorter than specified by length":
data = string(str[1:])
return
case "string parsing warning: string contains data beyond length":
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 {
return
log.Debug("I2PString is empty")
return "", nil
}
data = string(str[1 : length+1])
return
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(log.Fields{
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 = errors.New("cannot store that much data in 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
}
@ -105,21 +144,48 @@ func ToI2PString(data string) (str I2PString, err error) {
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
length, _, err := NewInteger(data, 1)
if err != nil {
if len(data) == 0 {
err = ErrZeroLength
log.WithError(err).Error("Passed data with len == 0")
return
}
data_len := length.Int()
str = data[:data_len+1]
remainder = data[data_len+1:]
_, err = str.Length()
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) {
/*func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
objstr, remainder, err := ReadI2PString(data)
str = &objstr
return
}
}*/

View File

@ -54,7 +54,7 @@ func TestI2PStringDataReportsExtraDataError(t *testing.T) {
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")
}
@ -129,7 +129,7 @@ func TestReadI2PStringErrWhenEmptySlice(t *testing.T) {
_, _, 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")
}
}
@ -140,10 +140,14 @@ func TestReadI2PStringErrWhenDataTooShort(t *testing.T) {
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, "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), 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

@ -0,0 +1,52 @@
# 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
[go-i2p template file](/template.md)

View File

@ -4,13 +4,18 @@ 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/crypto/types"
"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
@ -31,34 +36,52 @@ type Destination struct {
// Base32Address returns the I2P base32 address for this Destination.
func (destination Destination) Base32Address() (str string) {
dest := destination.KeysAndCert.KeyCertificate.Bytes()
hash := crypto.SHA256(dest)
log.Debug("Generating Base32 address for Destination")
cert := destination.KeysAndCert.Certificate()
dest := cert.Bytes()
hash := types.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 {
dest := destination.KeysAndCert.KeyCertificate.Bytes()
return base64.EncodeToString(dest)
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) {
keys_and_cert, remainder, err := NewKeysAndCert(data)
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
}
// NewDestination creates a new *Destination from []byte using ReadDestination.
// Returns a pointer to Destination unlike ReadDestination.
func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) {
objdestination, remainder, err := ReadDestination(data)
destination = &objdestination
return destination, remainder, err
}

View File

@ -0,0 +1,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/base64.EncodeToString -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString</title>
<g id="a_node1"><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,-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">base64</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/destination.init -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.init</title>
<g id="a_node2"><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="node3" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node3"><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="node4" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString</title>
<g id="a_node4"><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,-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">base32</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/destination.ReadDestination -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.ReadDestination</title>
<g id="a_node5"><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:73: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at destination.go:82: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;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="#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="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert | defined in keys_and_cert.go:145">
<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="edge3" 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_edge3"><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="edge10" 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_edge10"><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="edge11" 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_edge11"><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/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:139">
<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).Base64 -->
<g id="node11" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base64</title>
<g id="a_node11"><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:56: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:64: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#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:62: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at destination.go:59: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at destination.go:60: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base64.EncodeToString]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M100.2514,-426C100.2514,-426 58.83,-426 58.83,-426 52.83,-426 46.83,-420 46.83,-414 46.83,-414 46.83,-402 46.83,-402 46.83,-396 52.83,-390 58.83,-390 58.83,-390 100.2514,-390 100.2514,-390 106.2514,-390 112.2514,-396 112.2514,-402 112.2514,-402 112.2514,-414 112.2514,-414 112.2514,-420 106.2514,-426 100.2514,-426"/>
<text text-anchor="middle" x="79.5407" y="-403.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="edge13" 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_edge13"><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="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).Base64&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<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/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_edge12"><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.1879,-418.8431C130.6228,-423.6963 154.1242,-427.7712 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).Base64&#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).Base64&#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:58: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]">
<path fill="none" stroke="#8b4513" d="M112.4345,-420.7207C141.699,-432.0378 185.1203,-448.8298 219.8807,-462.2723"/>
<polygon fill="#8b4513" stroke="#8b4513" points="218.8469,-465.6251 229.4362,-465.9676 221.3718,-459.0963 218.8469,-465.6251"/>
</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="edge6" 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_edge6"><a xlink:title="at destination.go:62: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M112.4292,-411.4826C132.0464,-411.9602 156.6597,-409.6138 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).Base64&#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.Destination).Base64&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge4"><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.3758,-398.1648C123.3279,-393.5268 134.8287,-386.9839 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).Base32Address -->
<g id="node12" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/destination.Destination).Base32Address</title>
<g id="a_node12"><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:39: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:49: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at destination.go:47: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#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:42: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at destination.go:44: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/base32.EncodeToString]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M123.1221,-365C123.1221,-365 35.9593,-365 35.9593,-365 29.9593,-365 23.9593,-359 23.9593,-353 23.9593,-353 23.9593,-341 23.9593,-341 23.9593,-335 29.9593,-329 35.9593,-329 35.9593,-329 123.1221,-329 123.1221,-329 129.1221,-329 135.1221,-335 135.1221,-341 135.1221,-341 135.1221,-353 135.1221,-353 135.1221,-359 129.1221,-365 123.1221,-365"/>
<text text-anchor="middle" x="79.5407" y="-342.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="M135.3517,-329.3908C138.0203,-328.0191 140.6127,-326.5566 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).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="edge8" 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_edge8"><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.1378,-350.1402C148.3907,-351.6214 162.3985,-353.799 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).Base32Address&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate -->
<g id="edge7" 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_edge7"><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="M119.9234,-365.0468C127.7753,-369.014 135.8175,-373.4111 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).Base32Address&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<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/logger.Logger).WithFields</title>
<g id="a_edge2"><a xlink:title="at destination.go:47: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M135.0927,-336.9958C147.9322,-334.6911 161.5384,-332.2547 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).Base32Address&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge1" 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_edge1"><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="M135.2387,-330.9936C138.0332,-329.2017 140.674,-327.2111 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,23 @@
# 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
[go-i2p template file](/template.md)

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

@ -0,0 +1,23 @@
# 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
[go-i2p template file](/template.md)

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

@ -0,0 +1,23 @@
# 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
[go-i2p template file](/template.md)

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:9: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).SigningPublicKey]&#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]">
<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:145">
<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="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.ReadKeysAndCert</title>
<g id="a_edge2"><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:139">
<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="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).Certificate</title>
<g id="a_edge3"><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:129">
<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="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).PublicKey</title>
<g id="a_edge4"><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:134">
<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="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.KeysAndCert).SigningPublicKey</title>
<g id="a_edge1"><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

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

View File

@ -0,0 +1,23 @@
# 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
[go-i2p template file](/template.md)

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:345">
<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:323">
<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

@ -0,0 +1,23 @@
# 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
[go-i2p template file](/template.md)

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:7: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Certificate]&#10;at fuzz.go:6: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/router_identity.ReadRouterIdentity]">
<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="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/router_identity.ReadRouterIdentity</title>
<g id="a_edge2"><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:139">
<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="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/keys_and_cert.KeysAndCert).Certificate</title>
<g id="a_edge1"><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

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

View File

@ -0,0 +1,23 @@
# 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
[go-i2p template file](/template.md)

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: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]&#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]">
<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="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.ToI2PString</title>
<g id="a_edge2"><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="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.I2PString).Data</title>
<g id="a_edge3"><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="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).Length</title>
<g id="a_edge1"><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

@ -0,0 +1,200 @@
# 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 types.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 types.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
[go-i2p template file](/template.md)

View File

@ -28,41 +28,52 @@ payload :: data
*/
import (
"errors"
"fmt"
"github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/go-i2p/go-i2p/lib/crypto/dsa"
"github.com/go-i2p/go-i2p/lib/crypto/ecdsa"
"github.com/go-i2p/go-i2p/lib/crypto/ed25519"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"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"
log "github.com/sirupsen/logrus"
)
var log = logger.GetGoI2PLogger()
// 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
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 = iota
KEYCERT_CRYPTO_P256
KEYCERT_CRYPTO_P384
KEYCERT_CRYPTO_P521
KEYCERT_CRYPTO_X25519
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
// signingPublicKey sizes for Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
@ -75,7 +86,7 @@ const (
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
// PublicKey sizes for Public Key Types
// publicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
@ -92,110 +103,213 @@ const (
// type KeyCertificate []byte
type KeyCertificate struct {
*Certificate
spkType Integer
cpkType Integer
Certificate
SpkType Integer
CpkType Integer
}
// Data returns the raw []byte contained in the Certificate.
func (key_certificate KeyCertificate) Data() ([]byte, error) {
return key_certificate.Certificate.RawBytes(), nil
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 (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) {
return key_certificate.spkType.Int()
// 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 (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) {
return key_certificate.cpkType.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.
// ConstructPublicKey returns a publicKey constructed using any excess data that may be stored in the KeyCertififcate.
// Returns enr errors encountered while parsing.
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) {
key_type := key_certificate.PublicKeyType()
func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key types.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 < key_certificate.CryptoSize() {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructPublicKey",
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 = errors.New("error constructing public key: not enough data")
err = oops.Errorf("error constructing public key: not enough data")
return
}
switch key_type {
case KEYCERT_CRYPTO_ELG:
var elg_key crypto.ElgPublicKey
var elg_key elgamal.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
var ed25519_key ed25519.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 (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
signing_key_type := key_certificate.PublicKeyType()
func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key types.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 < key_certificate.SignatureSize() {
log.WithFields(log.Fields{
"at": "(KeyCertificate) ConstructSigningPublicKey",
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 = errors.New("error constructing signing public key: not enough data")
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
var dsa_key dsa.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_key crypto.ECP256PublicKey
copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_key
var ec_p256_key ecdsa.ECP256PublicKey
copy(ec_p256_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p256_key
log.Debug("Constructed P256PublicKey")
case KEYCERT_SIGN_P384:
var ec_key crypto.ECP384PublicKey
copy(ec_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_key
var ec_p384_key ecdsa.ECP384PublicKey
copy(ec_p384_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p384_key
log.Debug("Constructed P384PublicKey")
case KEYCERT_SIGN_P521:
var ec_key crypto.ECP521PublicKey
extra := KEYCERT_SIGN_P521_SIZE - KEYCERT_SPK_SIZE
copy(ec_key[:], data)
copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra])
signing_public_key = ec_key
/*var ec_p521_key crypto.ECP521PublicKey
copy(ec_p521_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P521_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p521_key
log.Debug("Constructed P521PublicKey")*/
panic("unimplemented P521SigningPublicKey")
case KEYCERT_SIGN_RSA2048:
//var rsa_key crypto.RSA2048PublicKey
//extra := KEYCERT_SIGN_RSA2048_SIZE - 128
//copy(rsa_key[:], data)
//copy(rsa_key[128:], key_certificate[4:4+extra])
//signing_public_key = rsa_key
/*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 ed25519.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 ed25519.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 (key_certificate KeyCertificate) SignatureSize() (size int) {
// 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,
@ -207,12 +321,23 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) {
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
}
key_type := key_certificate.SigningPublicKeyType()
return sizes[int(key_type)]
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 size
}
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type.
func (key_certificate KeyCertificate) CryptoSize() (size int) {
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's publicKey type.
func (keyCertificate KeyCertificate) CryptoSize() (size int) {
sizes := map[int]int{
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
@ -220,33 +345,87 @@ func (key_certificate KeyCertificate) CryptoSize() (size int) {
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
}
key_type := key_certificate.PublicKeyType()
return sizes[int(key_type)]
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 size
}
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
var certificate *Certificate
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 len(bytes) < KEYCERT_MIN_SIZE {
err = errors.New("error parsing key certificate: not enough data")
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,
spkType: Integer(bytes[4:5]),
cpkType: Integer(bytes[6:7]),
CpkType: cpkType,
SpkType: spkType,
}
remainder = bytes[KEYCERT_MIN_SIZE:]
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
}
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
func KeyCertificateFromCertificate(certificate *Certificate) *KeyCertificate {
k, _, _ := NewKeyCertificate(certificate.RawBytes())
return k
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,-508C28,-508 643.9118,-508 643.9118,-508 649.9118,-508 655.9118,-514 655.9118,-520 655.9118,-520 655.9118,-696 655.9118,-696 655.9118,-702 649.9118,-708 643.9118,-708 643.9118,-708 28,-708 28,-708 22,-708 16,-702 16,-696 16,-696 16,-520 16,-520 16,-514 22,-508 28,-508"/>
<text text-anchor="middle" x="335.9559" y="-516.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,-293C773.0248,-293 821.0248,-293 821.0248,-293 827.0248,-293 833.0248,-299 833.0248,-305 833.0248,-305 833.0248,-359 833.0248,-359 833.0248,-365 827.0248,-371 821.0248,-371 821.0248,-371 773.0248,-371 773.0248,-371 767.0248,-371 761.0248,-365 761.0248,-359 761.0248,-359 761.0248,-305 761.0248,-305 761.0248,-299 767.0248,-293 773.0248,-293"/>
<text text-anchor="middle" x="797.0248" y="-301.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,-513C769.9673,-513 824.0823,-513 824.0823,-513 830.0823,-513 836.0823,-519 836.0823,-525 836.0823,-525 836.0823,-640 836.0823,-640 836.0823,-646 830.0823,-652 824.0823,-652 824.0823,-652 769.9673,-652 769.9673,-652 763.9673,-652 757.9673,-646 757.9673,-640 757.9673,-640 757.9673,-525 757.9673,-525 757.9673,-519 763.9673,-513 769.9673,-513"/>
<text text-anchor="middle" x="797.0248" y="-521.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,-815C757.9154,-815 836.1342,-815 836.1342,-815 842.1342,-815 848.1342,-821 848.1342,-827 848.1342,-827 848.1342,-1064 848.1342,-1064 848.1342,-1070 842.1342,-1076 836.1342,-1076 836.1342,-1076 757.9154,-1076 757.9154,-1076 751.9154,-1076 745.9154,-1070 745.9154,-1064 745.9154,-1064 745.9154,-827 745.9154,-827 745.9154,-821 751.9154,-815 757.9154,-815"/>
<text text-anchor="middle" x="797.0248" y="-823.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,-218C498.8136,-218 641.5794,-218 641.5794,-218 647.5794,-218 653.5794,-224 653.5794,-230 653.5794,-230 653.5794,-345 653.5794,-345 653.5794,-351 647.5794,-357 641.5794,-357 641.5794,-357 498.8136,-357 498.8136,-357 492.8136,-357 486.8136,-351 486.8136,-345 486.8136,-345 486.8136,-230 486.8136,-230 486.8136,-224 492.8136,-218 498.8136,-218"/>
<text text-anchor="middle" x="570.1965" y="-226.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/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate | defined in key_certificate.go:360&#10;at key_certificate.go:379: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:388: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:361: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:390: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#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:388: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:391: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:392: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:373: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:377: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:376: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:379: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:379: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:381: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:382: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:363: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:394: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:381: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:382: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:368: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at key_certificate.go:366: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]&#10;at key_certificate.go:368: 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).Type]&#10;at key_certificate.go:373: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M624.5242,-467C624.5242,-467 515.8688,-467 515.8688,-467 509.8688,-467 503.8688,-461 503.8688,-455 503.8688,-455 503.8688,-443 503.8688,-443 503.8688,-437 509.8688,-431 515.8688,-431 515.8688,-431 624.5242,-431 624.5242,-431 630.5242,-431 636.5242,-437 636.5242,-443 636.5242,-443 636.5242,-455 636.5242,-455 636.5242,-461 630.5242,-467 624.5242,-467"/>
<text text-anchor="middle" x="570.1965" y="-444.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/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="M840.8693,-432C840.8693,-432 753.1803,-432 753.1803,-432 747.1803,-432 741.1803,-426 741.1803,-420 741.1803,-420 741.1803,-408 741.1803,-408 741.1803,-402 747.1803,-396 753.1803,-396 753.1803,-396 840.8693,-396 840.8693,-396 846.8693,-396 852.8693,-402 852.8693,-408 852.8693,-408 852.8693,-420 852.8693,-420 852.8693,-426 846.8693,-432 840.8693,-432"/>
<text text-anchor="middle" x="797.0248" y="-418.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="797.0248" y="-401.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="edge40" 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_edge40"><a xlink:title="at key_certificate.go:366: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.ReadCertificate]">
<path fill="none" stroke="#8b4513" d="M636.7198,-438.7353C666.3047,-434.1703 701.0564,-428.8081 730.6267,-424.2453"/>
<polygon fill="#8b4513" stroke="#8b4513" points="731.5038,-427.6515 740.853,-422.6674 730.4362,-420.7334 731.5038,-427.6515"/>
</a>
</g>
</g>
<!-- github.com/samber/oops.Errorf -->
<g id="node3" class="node">
<title>github.com/samber/oops.Errorf</title>
<g id="a_node3"><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&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge20" 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_edge20"><a xlink:title="at key_certificate.go:373: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:377: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M592.0565,-430.722C612.2147,-413.6523 642.7607,-387.2381 668.1026,-363 701.9493,-330.6275 704.9435,-316.7675 741.1026,-287 746.7409,-282.3583 753.0068,-277.8127 759.246,-273.599"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.2259,-276.4862 767.676,-268.081 757.3922,-270.6294 761.2259,-276.4862"/>
</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,-493C831.4325,-493 762.6171,-493 762.6171,-493 756.6171,-493 750.6171,-487 750.6171,-481 750.6171,-481 750.6171,-469 750.6171,-469 750.6171,-463 756.6171,-457 762.6171,-457 762.6171,-457 831.4325,-457 831.4325,-457 837.4325,-457 843.4325,-463 843.4325,-469 843.4325,-469 843.4325,-481 843.4325,-481 843.4325,-487 837.4325,-493 831.4325,-493"/>
<text text-anchor="middle" x="797.0248" y="-479.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="797.0248" y="-462.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="edge28" 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_edge28"><a xlink:title="at key_certificate.go:381: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]&#10;at key_certificate.go:382: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/data.ReadInteger]">
<path fill="none" stroke="#8b4513" d="M636.7198,-456.6252C669.605,-460.3946 708.874,-464.8958 740.3148,-468.4997"/>
<polygon fill="#8b4513" stroke="#8b4513" points="740.3232,-472.0235 750.6567,-469.6851 741.1204,-465.069 740.3232,-472.0235"/>
</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="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/certificate.Certificate).Type</title>
<g id="a_edge42"><a xlink:title="at key_certificate.go:372: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:373: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#8b4513" d="M597.7099,-430.7753C619.4829,-415.0985 649.2621,-390.6798 668.1026,-363 722.0518,-283.7398 678.9762,-233.0274 741.1026,-160 743.4021,-157.297 745.9993,-154.7857 748.7841,-152.4604"/>
<polygon fill="#8b4513" stroke="#8b4513" points="751.0523,-155.137 757.0373,-146.3946 746.9067,-149.4966 751.0523,-155.137"/>
</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="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/certificate.Certificate).Data</title>
<g id="a_edge21"><a xlink:title="at key_certificate.go:376: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:379: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:379: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:381: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:382: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#8b4513" d="M596.0873,-430.8702C617.4775,-414.8951 647.5602,-390.012 668.1026,-363 713.2253,-303.6663 686.4413,-262.6822 741.1026,-212 743.2543,-210.0049 745.6082,-208.1827 748.0938,-206.5194"/>
<polygon fill="#8b4513" stroke="#8b4513" points="750.006,-209.4579 756.9505,-201.4564 746.5319,-203.3808 750.006,-209.4579"/>
</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,-946C828.2439,-946 765.8057,-946 765.8057,-946 759.8057,-946 753.8057,-940 753.8057,-934 753.8057,-934 753.8057,-922 753.8057,-922 753.8057,-916 759.8057,-910 765.8057,-910 765.8057,-910 828.2439,-910 828.2439,-910 834.2439,-910 840.2439,-916 840.2439,-922 840.2439,-922 840.2439,-934 840.2439,-934 840.2439,-940 834.2439,-946 828.2439,-946"/>
<text text-anchor="middle" x="797.0248" y="-932.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-915.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="edge7" 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_edge7"><a xlink:title="at key_certificate.go:361: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:390: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M623.0634,-467.0108C639.8358,-475.2035 656.9099,-486.5992 668.1026,-502 720.7097,-574.3854 688.3588,-825.7141 741.1026,-898 742.5009,-899.9163 744.0595,-901.7225 745.7416,-903.4235"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.8953,-906.4454 753.7936,-910.2235 748.4118,-901.0973 743.8953,-906.4454"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="node14" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_node14"><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,-885C825.5563,-885 768.4933,-885 768.4933,-885 762.4933,-885 756.4933,-879 756.4933,-873 756.4933,-873 756.4933,-861 756.4933,-861 756.4933,-855 762.4933,-849 768.4933,-849 768.4933,-849 825.5563,-849 825.5563,-849 831.5563,-849 837.5563,-855 837.5563,-861 837.5563,-861 837.5563,-873 837.5563,-873 837.5563,-879 831.5563,-885 825.5563,-885"/>
<text text-anchor="middle" x="797.0248" y="-871.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-854.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="edge34" 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_edge34"><a xlink:title="at key_certificate.go:368: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M619.7032,-467.0685C636.9732,-475.4409 655.2327,-486.9381 668.1026,-502 713.5515,-555.1898 770.3507,-763.2971 789.9745,-839.1469"/>
<polygon fill="#8b4513" stroke="#8b4513" points="786.6128,-840.1278 792.4917,-848.9419 793.3925,-838.3855 786.6128,-840.1278"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="node15" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_node15"><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,-1007C814.7911,-1007 779.2585,-1007 779.2585,-1007 773.2585,-1007 767.2585,-1001 767.2585,-995 767.2585,-995 767.2585,-983 767.2585,-983 767.2585,-977 773.2585,-971 779.2585,-971 779.2585,-971 814.7911,-971 814.7911,-971 820.7911,-971 826.7911,-977 826.7911,-983 826.7911,-983 826.7911,-995 826.7911,-995 826.7911,-1001 820.7911,-1007 814.7911,-1007"/>
<text text-anchor="middle" x="797.0248" y="-993.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-976.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="edge41" 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_edge41"><a xlink:title="at key_certificate.go:368: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M623.7847,-467.1103C640.4085,-475.2727 657.2065,-486.6243 668.1026,-502 727.5659,-585.9095 681.4809,-875.203 741.1026,-959 745.4938,-965.1718 751.5597,-970.1923 758.084,-974.2348"/>
<polygon fill="#8b4513" stroke="#8b4513" points="756.6925,-977.4618 767.1508,-979.1573 760.0325,-971.31 756.6925,-977.4618"/>
</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,-644C815.8468,-644 778.2028,-644 778.2028,-644 772.2028,-644 766.2028,-638 766.2028,-632 766.2028,-632 766.2028,-620 766.2028,-620 766.2028,-614 772.2028,-608 778.2028,-608 778.2028,-608 815.8468,-608 815.8468,-608 821.8468,-608 827.8468,-614 827.8468,-620 827.8468,-620 827.8468,-632 827.8468,-632 827.8468,-638 821.8468,-644 815.8468,-644"/>
<text text-anchor="middle" x="797.0248" y="-630.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="797.0248" y="-613.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="edge27" 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_edge27"><a xlink:title="at key_certificate.go:363: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:394: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M616.1891,-467.2083C633.5337,-475.3783 652.7609,-486.1065 668.1026,-499 709.4081,-533.714 700.1502,-560.8701 741.1026,-596 745.9867,-600.1897 751.5531,-604.0292 757.2362,-607.4602"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.7522,-610.6416 766.1815,-612.5073 759.192,-604.545 755.7522,-610.6416"/>
</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,-583C816.1399,-583 777.9097,-583 777.9097,-583 771.9097,-583 765.9097,-577 765.9097,-571 765.9097,-571 765.9097,-559 765.9097,-559 765.9097,-553 771.9097,-547 777.9097,-547 777.9097,-547 816.1399,-547 816.1399,-547 822.1399,-547 828.1399,-553 828.1399,-559 828.1399,-559 828.1399,-571 828.1399,-571 828.1399,-577 822.1399,-583 816.1399,-583"/>
<text text-anchor="middle" x="797.0248" y="-569.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="797.0248" y="-552.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="edge1" 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_edge1"><a xlink:title="at key_certificate.go:379: calling [(*github.com/sirupsen/logrus.Logger).Println]&#10;at key_certificate.go:388: calling [(*github.com/sirupsen/logrus.Logger).Println]">
<path fill="none" stroke="#8b4513" d="M607.2479,-467.1522C625.6994,-476.3862 648.2508,-487.966 668.1026,-499 701.2139,-517.4039 707.135,-526.2291 741.1026,-543 746.0139,-545.4249 751.2628,-547.7804 756.5041,-549.9931"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.2746,-553.2715 765.856,-553.8057 757.9173,-546.7895 755.2746,-553.2715"/>
</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,-363C812.0248,-363 782.0248,-363 782.0248,-363 776.0248,-363 770.0248,-357 770.0248,-351 770.0248,-351 770.0248,-339 770.0248,-339 770.0248,-333 776.0248,-327 782.0248,-327 782.0248,-327 812.0248,-327 812.0248,-327 818.0248,-327 824.0248,-333 824.0248,-339 824.0248,-339 824.0248,-351 824.0248,-351 824.0248,-357 818.0248,-363 812.0248,-363"/>
<text text-anchor="middle" x="797.0248" y="-349.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="797.0248" y="-332.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="edge16" 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_edge16"><a xlink:title="at key_certificate.go:388: 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:391: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:392: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M605.8558,-430.9584C640.1896,-413.8102 693.7389,-387.6466 741.1026,-367 747.3355,-364.283 754.0192,-361.5235 760.5202,-358.9193"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.8255,-362.167 769.8405,-355.238 759.2539,-355.6564 761.8255,-362.167"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate -->
<g id="node5" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate</title>
<g id="a_node5"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificateFromCertificate | defined in key_certificate.go:399&#10;at key_certificate.go:400: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:401: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:404: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]&#10;at key_certificate.go:421: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:422: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:401: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:409: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M656.0088,-114C656.0088,-114 484.3842,-114 484.3842,-114 478.3842,-114 472.3842,-108 472.3842,-102 472.3842,-102 472.3842,-90 472.3842,-90 472.3842,-84 478.3842,-78 484.3842,-78 484.3842,-78 656.0088,-78 656.0088,-78 662.0088,-78 668.0088,-84 668.0088,-90 668.0088,-90 668.0088,-102 668.0088,-102 668.0088,-108 662.0088,-114 656.0088,-114"/>
<text text-anchor="middle" x="570.1965" y="-91.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="edge35" 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_edge35"><a xlink:title="at key_certificate.go:401: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:409: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M651.5509,-114.0242C670.7669,-121.2245 690.0263,-131.2083 705.1026,-145 732.9766,-170.499 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.KeyCertificateFromCertificate&#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/key_certificate.KeyCertificateFromCertificate&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type</title>
<g id="a_edge3"><a xlink:title="at key_certificate.go:400: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]&#10;at key_certificate.go:401: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Type]">
<path fill="none" stroke="#8b4513" d="M601.5673,-77.8999C629.4562,-64.2822 670.9789,-50.1462 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="edge8" 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_edge8"><a xlink:title="at key_certificate.go:404: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Data]">
<path fill="none" stroke="#8b4513" d="M668.0534,-103.566C681.0075,-106.9449 693.7239,-111.6066 705.1026,-118 726.5364,-130.0431 721.9436,-144.5929 741.1026,-160 743.9761,-162.3108 747.0542,-164.5302 750.2341,-166.6425"/>
<polygon fill="#8b4513" stroke="#8b4513" points="748.4772,-169.6715 758.819,-171.9733 752.1699,-163.7246 748.4772,-169.6715"/>
</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="edge9" 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_edge9"><a xlink:title="at key_certificate.go:421: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:422: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M586.8453,-114.3241C606.9191,-136.7278 641.2986,-176.1025 668.1026,-212 703.4297,-259.3119 695.2619,-285.7837 741.1026,-323 746.8382,-327.6565 753.6796,-331.4203 760.5761,-334.4288"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.3279,-337.6987 769.916,-338.0763 761.8743,-331.1783 759.3279,-337.6987"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.init | defined in .:0&#10;at key_certificate.go:48: 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="node7" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node7"><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="edge6" 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_edge6"><a xlink:title="at key_certificate.go:48: 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/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:204&#10;at key_certificate.go:208: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:211: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:206: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M633.4625,-349C633.4625,-349 506.9305,-349 506.9305,-349 500.9305,-349 494.9305,-343 494.9305,-337 494.9305,-337 494.9305,-325 494.9305,-325 494.9305,-319 500.9305,-313 506.9305,-313 506.9305,-313 633.4625,-313 633.4625,-313 639.4625,-313 645.4625,-319 645.4625,-325 645.4625,-325 645.4625,-337 645.4625,-337 645.4625,-343 639.4625,-349 633.4625,-349"/>
<text text-anchor="middle" x="570.1965" y="-326.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="edge2" 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_edge2"><a xlink:title="at key_certificate.go:208: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:211: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M645.4873,-339.0777C653.8051,-342.4273 661.6016,-346.9437 668.1026,-353 750.6139,-429.8669 669.7467,-508.6789 741.1026,-596 745.5524,-601.4454 751.2597,-606.0403 757.3207,-609.8704"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.9164,-613.0961 766.3488,-614.9446 759.3462,-606.9938 755.9164,-613.0961"/>
</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="edge15" 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_edge15"><a xlink:title="at key_certificate.go:206: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M645.6234,-318.263C665.0468,-316.6337 685.8878,-316.3348 705.1026,-319 723.4681,-321.5473 743.3236,-326.8283 759.8653,-331.9696"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.1023,-335.4006 769.6936,-335.1269 761.2433,-328.736 759.1023,-335.4006"/>
</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:196&#10;at key_certificate.go:199: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:197: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:199: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M631.2863,-288C631.2863,-288 509.1067,-288 509.1067,-288 503.1067,-288 497.1067,-282 497.1067,-276 497.1067,-276 497.1067,-264 497.1067,-264 497.1067,-258 503.1067,-252 509.1067,-252 509.1067,-252 631.2863,-252 631.2863,-252 637.2863,-252 643.2863,-258 643.2863,-264 643.2863,-264 643.2863,-276 643.2863,-276 643.2863,-282 637.2863,-288 631.2863,-288"/>
<text text-anchor="middle" x="570.1965" y="-265.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="edge4" 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_edge4"><a xlink:title="at key_certificate.go:199: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M643.5279,-263.8575C681.4384,-260.682 726.2062,-256.932 757.5799,-254.3041"/>
<polygon fill="#8b4513" stroke="#8b4513" points="758.004,-257.7809 767.6769,-253.4583 757.4196,-250.8053 758.004,-257.7809"/>
</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="edge22" 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_edge22"><a xlink:title="at key_certificate.go:197: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:199: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M628.0978,-288.0155C651.9954,-295.5652 679.9378,-304.5401 705.1026,-313 723.3121,-319.1217 743.4769,-326.1171 760.2691,-332.003"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.1313,-335.3129 769.7261,-335.3253 761.4515,-328.7086 759.1313,-335.3129"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Warn -->
<g id="node16" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Warn</title>
<g id="a_node16"><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,-1068C814.7911,-1068 779.2585,-1068 779.2585,-1068 773.2585,-1068 767.2585,-1062 767.2585,-1056 767.2585,-1056 767.2585,-1044 767.2585,-1044 767.2585,-1038 773.2585,-1032 779.2585,-1032 779.2585,-1032 814.7911,-1032 814.7911,-1032 820.7911,-1032 826.7911,-1038 826.7911,-1044 826.7911,-1044 826.7911,-1056 826.7911,-1056 826.7911,-1062 820.7911,-1068 814.7911,-1068"/>
<text text-anchor="middle" x="797.0248" y="-1054.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="797.0248" y="-1037.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).Data -->
<g id="node20" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data</title>
<g id="a_node20"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).Data | defined in key_certificate.go:112&#10;at key_certificate.go:114: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:116: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]&#10;at key_certificate.go:117: 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,-578C129.5505,-578 99.5505,-578 99.5505,-578 93.5505,-578 87.5505,-572 87.5505,-566 87.5505,-566 87.5505,-554 87.5505,-554 87.5505,-548 93.5505,-542 99.5505,-542 99.5505,-542 129.5505,-542 129.5505,-542 135.5505,-542 141.5505,-548 141.5505,-554 141.5505,-554 141.5505,-566 141.5505,-566 141.5505,-572 135.5505,-578 129.5505,-578"/>
<text text-anchor="middle" x="114.5505" y="-555.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="edge47" 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_edge47"><a xlink:title="at key_certificate.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]&#10;at key_certificate.go:117: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).RawBytes]">
<path fill="none" stroke="#8b4513" d="M141.8533,-561.2631C162.484,-560.6057 189.7819,-555.9783 205.101,-538 270.8837,-460.7984 168.816,-154.1501 241.101,-83 253.6525,-70.6456 382.083,-76.7521 399.2904,-73 433.2418,-65.5968 438.4768,-53.0091 472.2904,-45 573.0364,-21.1372 600.6956,-27.1174 704.1026,-22 726.9146,-20.8711 749.9406,-32.1614 767.3644,-43.8374"/>
<polygon fill="#8b4513" stroke="#8b4513" points="765.7527,-46.9851 775.9346,-49.9146 769.8019,-41.2751 765.7527,-46.9851"/>
</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="edge26" 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_edge26"><a xlink:title="at key_certificate.go:114: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M141.7498,-563.3115C161.5111,-567.0148 187.7296,-574.7878 205.101,-591 316.8749,-695.3155 185.8065,-908 338.6957,-908 338.6957,-908 338.6957,-908 570.1965,-908 629.7364,-908 697.7289,-914.9224 743.6205,-920.622"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.2799,-924.1067 753.6404,-921.8907 744.1593,-917.1622 743.2799,-924.1067"/>
</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="edge39" 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_edge39"><a xlink:title="at key_certificate.go:116: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M141.7662,-557.4005C160.5544,-554.6763 185.5718,-549.1485 205.101,-538 225.0267,-526.6252 219.9643,-509.9252 241.101,-501 284.9094,-482.5014 624.3308,-511.4148 668.1026,-530 708.3627,-547.0941 705.346,-570.8097 741.1026,-596 746.245,-599.6227 751.8751,-603.1218 757.5197,-606.372"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.8904,-609.4706 766.3336,-611.2569 759.2837,-603.348 755.8904,-609.4706"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType -->
<g id="node21" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType</title>
<g id="a_node21"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType | defined in key_certificate.go:121&#10;at key_certificate.go:123: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:125: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#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:126: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M636.1277,-639C636.1277,-639 504.2653,-639 504.2653,-639 498.2653,-639 492.2653,-633 492.2653,-627 492.2653,-627 492.2653,-615 492.2653,-615 492.2653,-609 498.2653,-603 504.2653,-603 504.2653,-603 636.1277,-603 636.1277,-603 642.1277,-603 648.1277,-609 648.1277,-615 648.1277,-615 648.1277,-627 648.1277,-627 648.1277,-633 642.1277,-639 636.1277,-639"/>
<text text-anchor="middle" x="570.1965" y="-616.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="edge10" 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_edge10"><a xlink:title="at key_certificate.go:123: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M581.0927,-639.2384C617.0142,-699.2874 730.0448,-887.591 741.1026,-898 743.4692,-900.2277 746.033,-902.3404 748.717,-904.335"/>
<polygon fill="#8b4513" stroke="#8b4513" points="746.8064,-907.268 757.0532,-909.9612 750.7224,-901.4658 746.8064,-907.268"/>
</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="edge11" 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_edge11"><a xlink:title="at key_certificate.go:125: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M647.9406,-622.7137C684.307,-623.5153 726.121,-624.4371 756.1934,-625.0999"/>
<polygon fill="#8b4513" stroke="#8b4513" points="756.2378,-628.6017 766.3126,-625.323 756.3921,-621.6034 756.2378,-628.6017"/>
</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="edge29" 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_edge29"><a xlink:title="at key_certificate.go:122: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:126: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M647.9789,-605.1274C655.3709,-601.3712 662.2691,-596.7311 668.1026,-591 742.7956,-517.618 669.3076,-443.2196 741.1026,-367 746.3649,-361.4134 753.2205,-357.2209 760.3193,-354.0825"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.9006,-357.2269 770.0233,-350.4245 759.4314,-350.6768 761.9006,-357.2269"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="node22" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_node22"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize | defined in key_certificate.go:312&#10;at key_certificate.go:324: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]&#10;at key_certificate.go:329: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at key_certificate.go:335: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:327: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:332: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M377.452,-700C377.452,-700 299.9394,-700 299.9394,-700 293.9394,-700 287.9394,-694 287.9394,-688 287.9394,-688 287.9394,-676 287.9394,-676 287.9394,-670 293.9394,-664 299.9394,-664 299.9394,-664 377.452,-664 377.452,-664 383.452,-664 389.452,-670 389.452,-676 389.452,-676 389.452,-688 389.452,-688 389.452,-694 383.452,-700 377.452,-700"/>
<text text-anchor="middle" x="338.6957" y="-677.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).SignatureSize&#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).SignatureSize&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge36"><a xlink:title="at key_certificate.go:327: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:332: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M342.7172,-700.0575C351.9702,-737.0183 378.478,-821.1605 435.2904,-861 534.5454,-930.6023 586.7038,-874.9665 705.1026,-901 717.7926,-903.7903 731.2972,-907.3917 743.9377,-911.0495"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.2759,-914.5035 753.8578,-913.9806 745.2595,-907.7904 743.2759,-914.5035"/>
</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="edge13" 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_edge13"><a xlink:title="at key_certificate.go:329: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M345.1186,-700.1563C358.1538,-735.2742 390.3372,-813.8106 435.2904,-868 491.5764,-935.8507 497.6648,-988.0156 704.1026,-1050 720.9923,-1055.0713 740.4007,-1055.8116 757.0973,-1054.9951"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.3587,-1058.4855 767.0961,-1054.3103 756.8803,-1051.5018 757.3587,-1058.4855"/>
</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="edge30" 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_edge30"><a xlink:title="at key_certificate.go:335: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M389.4942,-681.912C454.4469,-681.1497 570.2284,-677.6033 668.1026,-663 684.8412,-660.5025 688.779,-658.4675 705.1026,-654 722.0257,-649.3684 740.5584,-643.8166 756.5219,-638.8823"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.5841,-642.2174 766.0921,-635.9036 755.5037,-635.5337 757.5841,-642.2174"/>
</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="edge12" 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_edge12"><a xlink:title="at key_certificate.go:324: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="none" stroke="#000000" d="M389.4995,-668.6133C419.4211,-660.729 457.9034,-650.589 491.6603,-641.6941"/>
<polygon fill="#000000" stroke="#000000" points="492.7279,-645.0324 501.506,-639.0998 490.9442,-638.2634 492.7279,-645.0324"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey -->
<g id="node23" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey</title>
<g id="a_node23"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey | defined in key_certificate.go:232&#10;at key_certificate.go:248: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:305: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:247: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at key_certificate.go:304: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at key_certificate.go:233: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:242: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:302: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:235: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:256: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:261: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:266: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:295: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:300: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:241: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]&#10;at key_certificate.go:236: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M193.1515,-700C193.1515,-700 35.9495,-700 35.9495,-700 29.9495,-700 23.9495,-694 23.9495,-688 23.9495,-688 23.9495,-676 23.9495,-676 23.9495,-670 29.9495,-664 35.9495,-664 35.9495,-664 193.1515,-664 193.1515,-664 199.1515,-664 205.1515,-670 205.1515,-676 205.1515,-676 205.1515,-688 205.1515,-688 205.1515,-694 199.1515,-700 193.1515,-700"/>
<text text-anchor="middle" x="114.5505" y="-677.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="edge14" 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_edge14"><a xlink:title="at key_certificate.go:248: calling [github.com/samber/oops.Errorf]&#10;at key_certificate.go:305: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M185.8097,-663.9163C192.693,-660.5797 199.2712,-656.6424 205.101,-652 294.5878,-580.7396 372.5956,-268.097 472.2904,-212 564.5477,-160.088 694.6519,-204.4679 758.5524,-232.4231"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.2982,-235.6962 767.8559,-236.5832 760.1557,-229.306 757.2982,-235.6962"/>
</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:233: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:242: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:302: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M115.4199,-700.2202C119.1911,-757.5229 138.9928,-935.4509 241.101,-1023 274.714,-1051.8203 294.4188,-1043 338.6957,-1043 338.6957,-1043 338.6957,-1043 570.1965,-1043 580.2699,-1043 691.2857,-984.5405 754.1829,-950.9826"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.9242,-954.0206 763.0959,-946.2221 752.6263,-947.8461 755.9242,-954.0206"/>
</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="edge23" 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_edge23"><a xlink:title="at key_certificate.go:247: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M117.5027,-700.3087C129.7346,-773.906 178.7318,-1046.961 241.101,-1104 273.7745,-1133.8811 294.4188,-1124 338.6957,-1124 338.6957,-1124 338.6957,-1124 570.1965,-1124 659.113,-1124 664.2242,-1064.675 741.1026,-1020 746.5823,-1016.8157 752.3994,-1013.5098 758.1307,-1010.2949"/>
<polygon fill="#8b4513" stroke="#8b4513" points="759.9747,-1013.2741 767.0058,-1005.3485 756.5669,-1007.1597 759.9747,-1013.2741"/>
</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="edge24" 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_edge24"><a xlink:title="at key_certificate.go:304: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M115.0994,-700.1598C117.9264,-763.8672 135.2532,-980.3879 241.101,-1111 270.6153,-1147.4195 291.8184,-1151 338.6957,-1151 338.6957,-1151 338.6957,-1151 570.1965,-1151 614.6089,-1151 626.8787,-1147.5243 668.1026,-1131 703.6582,-1116.7478 740.2711,-1092.6758 765.3511,-1074.4683"/>
<polygon fill="#8b4513" stroke="#8b4513" points="767.7482,-1077.0495 773.7205,-1068.2984 763.5944,-1071.415 767.7482,-1077.0495"/>
</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:235: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:256: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:261: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:266: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:295: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:300: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M117.7292,-700.2744C127.0872,-748.247 159.2034,-878.4422 241.101,-942 276.0801,-969.146 294.4188,-962 338.6957,-962 338.6957,-962 338.6957,-962 570.1965,-962 644.4407,-962 750.3701,-733.7936 785.3338,-653.523"/>
<polygon fill="#8b4513" stroke="#8b4513" points="788.6671,-654.6327 789.4225,-644.0648 782.2418,-651.855 788.6671,-654.6327"/>
</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="edge48" 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_edge48"><a xlink:title="at key_certificate.go:236: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="none" stroke="#000000" d="M205.1838,-664.1126C228.8582,-659.787 254.3872,-655.4283 278.101,-652 346.3058,-642.1398 423.8965,-634.0512 481.9585,-628.6115"/>
<polygon fill="#000000" stroke="#000000" points="482.5659,-632.0703 492.1994,-627.6606 481.9186,-625.1003 482.5659,-632.0703"/>
</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="edge45" 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_edge45"><a xlink:title="at key_certificate.go:241: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]">
<path fill="none" stroke="#000000" d="M205.3958,-682C229.5957,-682 255.1662,-682 277.3684,-682"/>
<polygon fill="#000000" stroke="#000000" points="277.6448,-685.5001 287.6448,-682 277.6447,-678.5001 277.6448,-685.5001"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="node24" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_node24"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType | defined in key_certificate.go:130&#10;at key_certificate.go:131: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:135: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:132: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:134: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M614.0634,-578C614.0634,-578 526.3296,-578 526.3296,-578 520.3296,-578 514.3296,-572 514.3296,-566 514.3296,-566 514.3296,-554 514.3296,-554 514.3296,-548 520.3296,-542 526.3296,-542 526.3296,-542 614.0634,-542 614.0634,-542 620.0634,-542 626.0634,-548 626.0634,-554 626.0634,-554 626.0634,-566 626.0634,-566 626.0634,-572 620.0634,-578 614.0634,-578"/>
<text text-anchor="middle" x="570.1965" y="-555.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="edge31" 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_edge31"><a xlink:title="at key_certificate.go:132: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M626.2048,-566.7497C641.7798,-571.2694 657.3527,-578.7289 668.1026,-591 728.7699,-660.2526 680.4543,-706.0213 704.1026,-795 716.5966,-842.0098 709.3359,-861.1639 741.1026,-898 742.8025,-899.9712 744.6649,-901.834 746.6453,-903.5917"/>
<polygon fill="#8b4513" stroke="#8b4513" points="744.7178,-906.525 754.7751,-909.857 748.9908,-900.9804 744.7178,-906.525"/>
</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="edge46" 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_edge46"><a xlink:title="at key_certificate.go:134: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M626.2664,-576.3146C666.6787,-588.0733 720.2731,-603.6676 756.5598,-614.2259"/>
<polygon fill="#8b4513" stroke="#8b4513" points="755.7306,-617.6298 766.3102,-617.063 757.6863,-610.9085 755.7306,-617.6298"/>
</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="edge17" 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_edge17"><a xlink:title="at key_certificate.go:131: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]&#10;at key_certificate.go:135: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M626.1258,-556.6834C641.0684,-553.4725 656.3196,-547.8079 668.1026,-538 731.6148,-485.1337 681.8387,-424.5885 741.1026,-367 746.5038,-361.7514 753.3056,-357.7136 760.2885,-354.621"/>
<polygon fill="#8b4513" stroke="#8b4513" points="761.7281,-357.8174 769.8085,-350.9647 759.2184,-351.2827 761.7281,-357.8174"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="node25" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_node25"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize | defined in key_certificate.go:340&#10;at key_certificate.go:353: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:348: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]&#10;at key_certificate.go:350: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M370.1859,-612C370.1859,-612 307.2055,-612 307.2055,-612 301.2055,-612 295.2055,-606 295.2055,-600 295.2055,-600 295.2055,-588 295.2055,-588 295.2055,-582 301.2055,-576 307.2055,-576 307.2055,-576 370.1859,-576 370.1859,-576 376.1859,-576 382.1859,-582 382.1859,-588 382.1859,-588 382.1859,-600 382.1859,-600 382.1859,-606 376.1859,-612 370.1859,-612"/>
<text text-anchor="middle" x="338.6957" y="-589.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="edge32" 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_edge32"><a xlink:title="at key_certificate.go:350: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M360.0798,-612.048C418.7586,-661.1461 588.1145,-800.0073 741.1026,-898 744.7034,-900.3064 748.4979,-902.6031 752.3444,-904.8399"/>
<polygon fill="#8b4513" stroke="#8b4513" points="750.9195,-908.0548 761.3476,-909.927 754.3631,-901.9604 750.9195,-908.0548"/>
</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="edge18" 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_edge18"><a xlink:title="at key_certificate.go:353: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M370.1352,-612.0532C396.4613,-626.0704 435.5268,-644.3639 472.2904,-652 573.0055,-672.9194 694.5205,-650.9913 756.4461,-636.5388"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.3076,-639.9315 766.2204,-634.2033 755.6808,-633.1232 757.3076,-639.9315"/>
</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="edge25" 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_edge25"><a xlink:title="at key_certificate.go:348: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]">
<path fill="none" stroke="#000000" d="M382.2392,-587.6049C416.5055,-582.5722 464.8286,-575.4751 503.8962,-569.7374"/>
<polygon fill="#000000" stroke="#000000" points="504.746,-573.1502 514.1312,-568.2342 503.7288,-566.2245 504.746,-573.1502"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey -->
<g id="node26" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey</title>
<g id="a_node26"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey | defined in key_certificate.go:140&#10;at key_certificate.go:143: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:164: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:169: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:173: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]&#10;at key_certificate.go:141: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:150: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:171: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:144: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]&#10;at key_certificate.go:149: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]&#10;at key_certificate.go:155: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at key_certificate.go:156: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M171.0885,-639C171.0885,-639 58.0125,-639 58.0125,-639 52.0125,-639 46.0125,-633 46.0125,-627 46.0125,-627 46.0125,-615 46.0125,-615 46.0125,-609 52.0125,-603 58.0125,-603 58.0125,-603 171.0885,-603 171.0885,-603 177.0885,-603 183.0885,-609 183.0885,-615 183.0885,-615 183.0885,-627 183.0885,-627 183.0885,-633 177.0885,-639 171.0885,-639"/>
<text text-anchor="middle" x="114.5505" y="-616.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="edge50" 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_edge50"><a xlink:title="at key_certificate.go:156: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M183.501,-606.1756C191.4981,-602.2488 198.9711,-597.2821 205.101,-591 276.3174,-518.016 236.7229,-152 338.6957,-152 338.6957,-152 338.6957,-152 570.1965,-152 630.8101,-152 653.3325,-140.4745 705.1026,-172 728.4904,-186.2421 720.3826,-204.0972 741.1026,-222 746.3846,-226.5639 752.5091,-230.6547 758.7276,-234.2247"/>
<polygon fill="#8b4513" stroke="#8b4513" points="757.3484,-237.4558 767.8185,-239.0768 760.6445,-231.2804 757.3484,-237.4558"/>
</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="edge33" 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_edge33"><a xlink:title="at key_certificate.go:141: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:150: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at key_certificate.go:171: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M183.1721,-635.0418C191.5301,-639.2893 199.1887,-644.8145 205.101,-652 280.0619,-743.1037 160.4793,-828.8655 241.101,-915 271.3579,-947.3258 294.4188,-935 338.6957,-935 338.6957,-935 338.6957,-935 570.1965,-935 629.5346,-935 697.5627,-932.5772 743.5179,-930.5823"/>
<polygon fill="#8b4513" stroke="#8b4513" points="743.7171,-934.077 753.5526,-930.1383 743.4076,-927.0839 743.7171,-934.077"/>
</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="edge49" 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_edge49"><a xlink:title="at key_certificate.go:155: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M183.195,-635.023C191.5497,-639.2732 199.2013,-644.8043 205.101,-652 281.8578,-745.6184 186.4513,-813.9749 241.101,-922 268.2868,-975.7377 278.4727,-1016 338.6957,-1016 338.6957,-1016 338.6957,-1016 570.1965,-1016 630.1959,-1016 645.657,-1019.1336 705.1026,-1011 722.3068,-1008.646 740.9944,-1004.4791 756.9994,-1000.4002"/>
<polygon fill="#8b4513" stroke="#8b4513" points="758.3033,-1003.6766 767.087,-997.7524 756.5261,-996.9059 758.3033,-1003.6766"/>
</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="edge19" 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_edge19"><a xlink:title="at key_certificate.go:173: calling [(*github.com/go&#45;i2p/logger.Logger).Warn]">
<path fill="none" stroke="#8b4513" d="M183.2169,-635.0051C191.5683,-639.258 199.2132,-644.7945 205.101,-652 244.3777,-700.0669 224.0146,-869.3247 241.101,-929 251.9953,-967.0491 258.4895,-975.6225 278.101,-1010 301.4501,-1050.9293 291.5747,-1097 338.6957,-1097 338.6957,-1097 338.6957,-1097 570.1965,-1097 636.9353,-1097 712.4651,-1077.2499 757.344,-1063.3553"/>
<polygon fill="#8b4513" stroke="#8b4513" points="758.4999,-1066.6608 766.9836,-1060.3143 756.3939,-1059.9851 758.4999,-1066.6608"/>
</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="edge5" 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_edge5"><a xlink:title="at key_certificate.go:143: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:164: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at key_certificate.go:169: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M177.2345,-639.0854C186.8255,-642.805 196.4144,-647.1072 205.101,-652 241.9399,-672.7497 238.3554,-698.5798 278.101,-713 449.1911,-775.0734 668.2926,-687.8277 757.0394,-646.0883"/>
<polygon fill="#8b4513" stroke="#8b4513" points="758.6913,-649.1783 766.2127,-641.7164 755.6797,-642.8592 758.6913,-649.1783"/>
</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="edge37" 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_edge37"><a xlink:title="at key_certificate.go:144: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]">
<path fill="none" stroke="#000000" d="M170.2024,-602.8963C181.7625,-599.0422 193.8482,-594.9437 205.101,-591 237.7467,-579.5587 244.0923,-570.3284 278.101,-564 354.6924,-549.7478 444.5388,-551.1595 504.1551,-554.5684"/>
<polygon fill="#000000" stroke="#000000" points="503.996,-558.0651 514.1897,-555.1775 504.4202,-551.078 503.996,-558.0651"/>
</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="edge38" 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_edge38"><a xlink:title="at key_certificate.go:149: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]">
<path fill="none" stroke="#000000" d="M183.3247,-612.7156C216.0448,-608.7742 254.5833,-604.132 285.0924,-600.4569"/>
<polygon fill="#000000" stroke="#000000" points="285.6015,-603.921 295.1111,-599.2501 284.7643,-596.9712 285.6015,-603.921"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -6,61 +6,60 @@ import (
"github.com/stretchr/testify/assert"
)
func TestSingingPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
func TestSigningPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00})
pk_type := key_cert.SigningPublicKeyType()
// Create certificate with signing key type P521 (3)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x07})
assert.Nil(err)
assert.Nil(err, "SigningPublicKeyType() returned error with valid data")
assert.Equal(pk_type, KEYCERT_SIGN_P521, "SigningPublicKeyType() did not return correct typec")
pk_type := key_cert.SigningPublicKeyType()
assert.Equal(KEYCERT_SIGN_P521, pk_type, "SigningPublicKeyType() did not return correct type")
}
func TestSingingPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) {
func TestSigningPublicKeyTypeWithInvalidData(t *testing.T) {
assert := assert.New(t)
// Test with invalid short data
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x01, 0x00})
sk_type := key_cert.SigningPublicKeyType()
assert.Equal(sk_type, 0, "SigningPublicKeyType() did not return correct typec")
if assert.NotNil(err) {
assert.Equal("error parsing key certificate: not enough data", err.Error(), "correct error message should be returned")
}
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)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03})
pk_type := key_cert.PublicKeyType()
// Create certificate with crypto type ELG (0)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
assert.Nil(err)
assert.Nil(err, "PublicKey() returned error with valid data")
assert.Equal(pk_type, KEYCERT_SIGN_P521, "PublicKeyType() did not return correct typec")
pk_type := key_cert.PublicKeyType()
assert.Equal(KEYCERT_CRYPTO_ELG, pk_type, "PublicKeyType() did not return correct type")
}
func TestPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) {
func TestPublicKeyTypeWithInvalidData(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x02, 0x00, 0x00})
pk_type := key_cert.PublicKeyType()
if assert.NotNil(err) {
assert.Equal("error parsing key certificate: not enough data", err.Error(), "correct error message should be returned")
}
assert.Equal(pk_type, 0, "PublicKeyType() did not return correct typec")
// 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 TestConstructPublicKeyReportsWhenDataTooSmall(t *testing.T) {
func TestConstructPublicKeyWithInsufficientData(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 255)
assert.Nil(err)
// Test with data smaller than required size
data := make([]byte, 255) // ELG requires 256 bytes
_, 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")
}
assert.NotNil(err)
assert.Equal("error constructing public key: not enough data", err.Error())
}
func TestConstructPublicKeyReturnsCorrectDataWithElg(t *testing.T) {
@ -94,7 +93,7 @@ func TestConstructSigningPublicKeyWithDSASHA1(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with DSA SHA1 returned error with valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_DSA_SHA1_SIZE, "ConstructSigningPublicKey() with DSA SHA1 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_DSA_SHA1_SIZE, "ConstructSigningPublicKey() with DSA SHA1 returned incorrect signingPublicKey length")
}
func TestConstructSigningPublicKeyWithP256(t *testing.T) {
@ -105,7 +104,7 @@ func TestConstructSigningPublicKeyWithP256(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with P256 returned err on valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_P256_SIZE, "ConstructSigningPublicKey() with P256 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_P256_SIZE, "ConstructSigningPublicKey() with P256 returned incorrect signingPublicKey length")
}
func TestConstructSigningPublicKeyWithP384(t *testing.T) {
@ -116,16 +115,18 @@ func TestConstructSigningPublicKeyWithP384(t *testing.T) {
spk, err := key_cert.ConstructSigningPublicKey(data)
assert.Nil(err, "ConstructSigningPublicKey() with P384 returned err on valid data")
assert.Equal(spk.Len(), KEYCERT_SIGN_P384_SIZE, "ConstructSigningPublicKey() with P384 returned incorrect SigningPublicKey length")
assert.Equal(spk.Len(), KEYCERT_SIGN_P384_SIZE, "ConstructSigningPublicKey() with P384 returned incorrect signingPublicKey length")
}
/*
func TestConstructSigningPublicKeyWithP521(t *testing.T) {
assert := assert.New(t)
key_cert, _, err := NewKeyCertificate([]byte{0x05, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00})
data := make([]byte, 128)
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")
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

@ -0,0 +1,118 @@
# keys_and_cert
--
import "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
![keys_and_cert.svg](keys_and_cert.svg)
Package keys_and_cert implements the I2P KeysAndCert common data structure
## Usage
```go
const (
KEYS_AND_CERT_PUBKEY_SIZE = 256
KEYS_AND_CERT_SPK_SIZE = 128
KEYS_AND_CERT_MIN_SIZE = 387
KEYS_AND_CERT_DATA_SIZE = 384
)
```
Sizes of various KeysAndCert structures and requirements
#### type KeysAndCert
```go
type KeysAndCert struct {
KeyCertificate *KeyCertificate
ReceivingPublic types.RecievingPublicKey
Padding []byte
SigningPublic types.SigningPublicKey
}
```
KeysAndCert is the represenation of an I2P KeysAndCert.
https://geti2p.net/spec/common-structures#keysandcert
#### func NewKeysAndCert
```go
func NewKeysAndCert(
keyCertificate *KeyCertificate,
publicKey types.RecievingPublicKey,
padding []byte,
signingPublicKey types.SigningPublicKey,
) (*KeysAndCert, error)
```
NewKeysAndCert creates a new KeysAndCert instance with the provided parameters.
It validates the sizes of the provided keys and padding before assembling the
struct.
#### func ReadKeysAndCert
```go
func ReadKeysAndCert(data []byte) (*KeysAndCert, []byte, error)
```
ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
#### func ReadKeysAndCertElgAndEd25519
```go
func ReadKeysAndCertElgAndEd25519(data []byte) (keysAndCert *KeysAndCert, remainder []byte, err error)
```
#### func (KeysAndCert) Bytes
```go
func (keys_and_cert KeysAndCert) Bytes() []byte
```
Bytes returns the entire keyCertificate in []byte form, trims payload to
specified length.
#### func (*KeysAndCert) Certificate
```go
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate)
```
Certfificate returns the certificate.
#### func (*KeysAndCert) PublicKey
```go
func (keys_and_cert *KeysAndCert) PublicKey() (key types.RecievingPublicKey)
```
publicKey returns the public key as a types.publicKey.
#### func (*KeysAndCert) SigningPublicKey
```go
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key types.SigningPublicKey)
```
signingPublicKey returns the signing public key.
#### type PrivateKeysAndCert
```go
type PrivateKeysAndCert struct {
KeysAndCert
PK_KEY crypto.PrivateKey
SPK_KEY crypto.PrivateKey
}
```
PrivateKeysAndCert contains a KeysAndCert along with the corresponding private
keys for the Public Key and the Signing Public Key
#### func NewPrivateKeysAndCert
```go
func NewPrivateKeysAndCert() (*PrivateKeysAndCert, error)
```
keys_and_cert
github.com/go-i2p/go-i2p/lib/common/keys_and_cert
[go-i2p template file](/template.md)

View File

@ -2,14 +2,20 @@
package keys_and_cert
import (
"errors"
"github.com/go-i2p/go-i2p/lib/crypto/ed25519"
"github.com/go-i2p/logger"
"github.com/samber/oops"
. "github.com/go-i2p/go-i2p/lib/common/certificate"
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
"github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/sirupsen/logrus"
)
var log = logger.GetGoI2PLogger()
// Sizes of various KeysAndCert structures and requirements
const (
KEYS_AND_CERT_PUBKEY_SIZE = 256
@ -18,6 +24,8 @@ const (
KEYS_AND_CERT_DATA_SIZE = 384
)
// Key sizes in bytes
/*
[KeysAndCert]
Accurate for version 0.9.49
@ -26,7 +34,7 @@ Description
An encryption public key, a signing public key, and a certificate, used as either a RouterIdentity or a Destination.
Contents
A PublicKey followed by a SigningPublicKey and then a Certificate.
A publicKey followed by a signingPublicKey and then a Certificate.
+----+----+----+----+----+----+----+----+
| public_key |
@ -51,14 +59,14 @@ A PublicKey followed by a SigningPublicKey and then a Certificate.
| certificate |
+----+----+----+-//
public_key :: PublicKey (partial or full)
public_key :: publicKey (partial or full)
length -> 256 bytes or as specified in key certificate
padding :: random data
length -> 0 bytes or as specified in key certificate
padding length + signing_key length == 128 bytes
signing__key :: SigningPublicKey (partial or full)
signing__key :: signingPublicKey (partial or full)
length -> 128 bytes or as specified in key certificate
padding length + signing_key length == 128 bytes
@ -72,140 +80,290 @@ total length: 387+ bytes
//
// https://geti2p.net/spec/common-structures#keysandcert
type KeysAndCert struct {
KeyCertificate *KeyCertificate
publicKey crypto.PublicKey
padding []byte
signingPublicKey crypto.SigningPublicKey
KeyCertificate *KeyCertificate
ReceivingPublic types.RecievingPublicKey
Padding []byte
SigningPublic types.SigningPublicKey
}
// Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length.
func (keys_and_cert *KeysAndCert) Bytes() []byte {
return keys_and_cert.KeyCertificate.Bytes()
// Bytes returns the entire keyCertificate in []byte form, trims payload to specified length.
func (keys_and_cert KeysAndCert) Bytes() []byte {
bytes := []byte{}
rpublen := 0
if keys_and_cert.ReceivingPublic != nil {
bytes = append(bytes, keys_and_cert.ReceivingPublic.Bytes()...)
rpublen = len(keys_and_cert.ReceivingPublic.Bytes())
}
// bytes = append(bytes, keys_and_cert.ReceivingPublic.Bytes()...)
padlen := 0
if keys_and_cert.Padding != nil {
bytes = append(bytes, keys_and_cert.Padding...)
padlen = len(keys_and_cert.Padding)
}
// bytes = append(bytes, keys_and_cert.Padding...)
spublen := 0
if keys_and_cert.SigningPublic != nil {
bytes = append(bytes, keys_and_cert.SigningPublic.Bytes()...)
spublen = len(keys_and_cert.SigningPublic.Bytes())
}
// bytes = append(bytes, keys_and_cert.SigningPublic.Bytes()...)
certlen := 0
if keys_and_cert.KeyCertificate != nil {
bytes = append(bytes, keys_and_cert.KeyCertificate.Bytes()...)
certlen = len(keys_and_cert.KeyCertificate.Bytes())
}
// bytes = append(bytes, keys_and_cert.KeyCertificate.Bytes()...)
log.WithFields(logrus.Fields{
"bytes": bytes,
"padding": keys_and_cert.Padding,
"bytes_length": len(bytes),
"pk_bytes_length": rpublen,
"padding_bytes_length": padlen,
"spk_bytes_length": spublen,
"cert_bytes_length": certlen,
}).Debug("Retrieved bytes from KeysAndCert")
return bytes
}
// PublicKey returns the public key as a crypto.PublicKey.
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
/*cert := keys_and_cert.Certificate()
cert_len := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
} else {
// A Certificate is present in this KeysAndCert
cert_type := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a PublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
key, err = KeyCertificateFromCertificate(cert).ConstructPublicKey(
keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
// PublicKey space as ElgPublicKey. No other Certificate
// types are currently in use.
var elg_key crypto.ElgPublicKey
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
key = elg_key
log.WithFields(log.Fields{
"at": "(KeysAndCert) PublicKey",
"cert_type": cert_type,
}).Warn("unused certificate type observed")
}
}
return*/
return keys_and_cert.publicKey
// publicKey returns the public key as a types.publicKey.
func (keys_and_cert *KeysAndCert) PublicKey() (key types.RecievingPublicKey) {
return keys_and_cert.ReceivingPublic
}
// SigningPublicKey returns the signing public key.
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
/*cert := keys_and_cert.Certificate()
cert_len := cert.Length()
if err != nil {
return
}
if cert_len == 0 {
// No Certificate is present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
} else {
// A Certificate is present in this KeysAndCert
cert_type := cert.Type()
if cert_type == CERT_KEY {
// This KeysAndCert contains a Key Certificate, construct
// a SigningPublicKey from the data in the KeysAndCert and
// any additional data in the Certificate.
signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey(
keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE],
)
} else {
// Key Certificate is not present, return the KEYS_AND_CERT_SPK_SIZE byte
// SigningPublicKey space as legacy SHA DSA1 SigningPublicKey.
// No other Certificate types are currently in use.
var dsa_pk crypto.DSAPublicKey
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
signing_public_key = dsa_pk
}
}*/
return keys_and_cert.signingPublicKey
// signingPublicKey returns the signing public key.
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key types.SigningPublicKey) {
return keys_and_cert.SigningPublic
}
// Certfificate returns the certificate.
func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) {
return keys_and_cert.KeyCertificate.Certificate
}
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
// ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
func ReadKeysAndCert(data []byte) (*KeysAndCert, []byte, error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Reading KeysAndCert from data")
var err error
var remainder []byte
var keys_and_cert KeysAndCert
data_len := len(data)
keys_and_cert = &KeysAndCert{}
if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE {
log.WithFields(log.Fields{
if data_len < KEYS_AND_CERT_MIN_SIZE {
log.WithFields(logrus.Fields{
"at": "ReadKeysAndCert",
"data_len": data_len,
"required_len": KEYS_AND_CERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing keys and cert")
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
return
} else if data_len < KEYS_AND_CERT_DATA_SIZE {
log.WithFields(log.Fields{
"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
err = oops.Errorf("error parsing KeysAndCert: data is smaller than minimum valid size")
return &keys_and_cert, remainder, err
}
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
if err != nil {
return nil, nil, err
log.WithError(err).Error("Failed to create keyCertificate")
return &keys_and_cert, remainder, err
}
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same.
// a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE
// and KEYS_AND_CERT_SPK_SIZE constants in the future.
keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
// Get the actual key sizes from the certificate
pubKeySize := keys_and_cert.KeyCertificate.CryptoSize()
sigKeySize := keys_and_cert.KeyCertificate.SignatureSize()
// Construct public key
keys_and_cert.ReceivingPublic, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:pubKeySize])
if err != nil {
return nil, nil, err
log.WithError(err).Error("Failed to construct publicKey")
return &keys_and_cert, remainder, err
}
keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE])
// Calculate padding size and extract padding
paddingSize := KEYS_AND_CERT_DATA_SIZE - pubKeySize - sigKeySize
if paddingSize > 0 {
keys_and_cert.Padding = make([]byte, paddingSize)
copy(keys_and_cert.Padding, data[pubKeySize:pubKeySize+paddingSize])
}
// Construct signing public key
keys_and_cert.SigningPublic, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(
data[KEYS_AND_CERT_DATA_SIZE-sigKeySize : KEYS_AND_CERT_DATA_SIZE],
)
if err != nil {
return nil, nil, err
log.WithError(err).Error("Failed to construct signingPublicKey")
return &keys_and_cert, remainder, err
}
padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE]
keys_and_cert.padding = padding
return keys_and_cert, remainder, err
log.WithFields(logrus.Fields{
"public_key_type": keys_and_cert.KeyCertificate.PublicKeyType(),
"signing_public_key_type": keys_and_cert.KeyCertificate.SigningPublicKeyType(),
"padding_length": len(keys_and_cert.Padding),
"remainder_length": len(remainder),
}).Debug("Successfully read KeysAndCert")
return &keys_and_cert, remainder, err
}
func ReadKeysAndCertElgAndEd25519(data []byte) (keysAndCert *KeysAndCert, remainder []byte, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Reading KeysAndCert from data")
// Constants based on fixed key sizes
const (
pubKeySize = 256 // ElGamal public key size
sigKeySize = 32 // Ed25519 public key size
totalKeySize = 384 // KEYS_AND_CERT_DATA_SIZE
paddingSize = totalKeySize - pubKeySize - sigKeySize // 96 bytes
minDataLength = totalKeySize + 3
)
dataLen := len(data)
if dataLen < minDataLength {
err = oops.Errorf("error parsing KeysAndCert: data is smaller than minimum valid size, got %d bytes", dataLen)
log.WithError(err).Error("Data is smaller than minimum valid size")
return
}
// Initialize KeysAndCert
keysAndCert = &KeysAndCert{}
// Extract public key
publicKeyData := data[:pubKeySize]
if len(publicKeyData) != pubKeySize {
err = oops.Errorf("invalid ElGamal public key length")
log.WithError(err).Error("Invalid ElGamal public key length")
return
}
var elgPublicKey elgamal.ElgPublicKey
copy(elgPublicKey[:], publicKeyData)
keysAndCert.ReceivingPublic = elgPublicKey
// Extract padding
paddingStart := pubKeySize
paddingEnd := paddingStart + paddingSize
keysAndCert.Padding = data[paddingStart:paddingEnd]
// Extract signing public key
signingPubKeyData := data[paddingEnd : paddingEnd+sigKeySize]
if len(signingPubKeyData) != sigKeySize {
err = oops.Errorf("invalid Ed25519 public key length")
log.WithError(err).Error("Invalid Ed25519 public key length")
return
}
edPublicKey := ed25519.Ed25519PublicKey(signingPubKeyData)
keysAndCert.SigningPublic = edPublicKey
// Extract the certificate
certData := data[totalKeySize:]
keysAndCert.KeyCertificate, remainder, err = NewKeyCertificate(certData)
if err != nil {
log.WithError(err).Error("Failed to read keyCertificate")
return
}
log.WithFields(logrus.Fields{
"public_key_type": "ElGamal",
"signing_public_key_type": "Ed25519",
"padding_length": len(keysAndCert.Padding),
"remainder_length": len(remainder),
}).Debug("Successfully read KeysAndCert")
return
}
func constructPublicKey(data []byte, cryptoType uint16) (types.RecievingPublicKey, error) {
switch cryptoType {
case CRYPTO_KEY_TYPE_ELGAMAL:
if len(data) != 256 {
return nil, oops.Errorf("invalid ElGamal public key length")
}
var elgPublicKey elgamal.ElgPublicKey
copy(elgPublicKey[:], data)
return elgPublicKey, nil
// Handle other crypto types...
default:
return nil, oops.Errorf("unsupported crypto key type: %d", cryptoType)
}
}
func constructSigningPublicKey(data []byte, sigType uint16) (types.SigningPublicKey, error) {
switch sigType {
case SIGNATURE_TYPE_ED25519_SHA512:
if len(data) != 32 {
return nil, oops.Errorf("invalid Ed25519 public key length")
}
return ed25519.Ed25519PublicKey(data), nil
// Handle other signature types...
default:
return nil, oops.Errorf("unsupported signature key type: %d", sigType)
}
}
// NewKeysAndCert creates a new KeysAndCert instance with the provided parameters.
// It validates the sizes of the provided keys and padding before assembling the struct.
func NewKeysAndCert(
keyCertificate *KeyCertificate,
publicKey types.RecievingPublicKey,
padding []byte,
signingPublicKey types.SigningPublicKey,
) (*KeysAndCert, error) {
log.Debug("Creating new KeysAndCert with provided parameters")
if keyCertificate == nil {
log.Error("KeyCertificate is nil")
return nil, oops.Errorf("KeyCertificate cannot be nil")
}
// Get actual key sizes from certificate
pubKeySize := keyCertificate.CryptoSize()
sigKeySize := keyCertificate.SignatureSize()
// Validate public key size
if publicKey != nil {
if publicKey.Len() != pubKeySize {
log.WithFields(logrus.Fields{
"expected_size": pubKeySize,
"actual_size": publicKey.Len(),
}).Error("Invalid publicKey size")
return nil, oops.Errorf("publicKey has invalid size: expected %d, got %d", pubKeySize, publicKey.Len())
}
}
if signingPublicKey != nil {
// Validate signing key size
if signingPublicKey.Len() != sigKeySize {
log.WithFields(logrus.Fields{
"expected_size": sigKeySize,
"actual_size": signingPublicKey.Len(),
}).Error("Invalid signingPublicKey size")
return nil, oops.Errorf("signingPublicKey has invalid size: expected %d, got %d", sigKeySize, signingPublicKey.Len())
}
}
// Calculate expected padding size
expectedPaddingSize := KEYS_AND_CERT_DATA_SIZE - pubKeySize - sigKeySize
if len(padding) != expectedPaddingSize {
log.WithFields(logrus.Fields{
"expected_size": expectedPaddingSize,
"actual_size": len(padding),
}).Error("Invalid padding size")
return nil, oops.Errorf("invalid padding size")
}
keysAndCert := &KeysAndCert{
KeyCertificate: keyCertificate,
ReceivingPublic: publicKey,
Padding: padding,
SigningPublic: signingPublicKey,
}
/*log.WithFields(logrus.Fields{
"public_key_length": publicKey.Len(),
"signing_public_key_length": signingPublicKey.Len(),
"padding_length": len(padding),
}).Debug("Successfully created KeysAndCert")*/
return keysAndCert, nil
}

View File

@ -0,0 +1,531 @@
<?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="518pt" height="992pt"
viewBox="0.00 0.00 517.94 992.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 992)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-992 517.944,-992 517.944,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-984 509.944,-984 509.944,-8 8,-8"/>
<text text-anchor="middle" x="258.972" y="-963.8" font-family="Arial" font-size="18.00" fill="#000000">keys_and_cert</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert</title>
<g id="a_clust6"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M82.9783,-787C82.9783,-787 172.8647,-787 172.8647,-787 178.8647,-787 184.8647,-793 184.8647,-799 184.8647,-799 184.8647,-853 184.8647,-853 184.8647,-859 178.8647,-865 172.8647,-865 172.8647,-865 82.9783,-865 82.9783,-865 76.9783,-865 70.9783,-859 70.9783,-853 70.9783,-853 70.9783,-799 70.9783,-799 70.9783,-793 76.9783,-787 82.9783,-787"/>
<text text-anchor="middle" x="127.9215" y="-795.5" font-family="Arial" font-size="15.00" fill="#222222">(KeysAndCert)</text>
</a>
</g>
</g>
<g id="clust5" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate</title>
<g id="a_clust5"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M316.843,-16C316.843,-16 489.944,-16 489.944,-16 495.944,-16 501.944,-22 501.944,-28 501.944,-28 501.944,-387 501.944,-387 501.944,-393 495.944,-399 489.944,-399 489.944,-399 316.843,-399 316.843,-399 310.843,-399 304.843,-393 304.843,-387 304.843,-387 304.843,-28 304.843,-28 304.843,-22 310.843,-16 316.843,-16"/>
<text text-anchor="middle" x="403.3935" y="-24.5" font-family="Arial" font-size="15.00" fill="#222222">(KeyCertificate)</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="M376.7329,-729C376.7329,-729 431.0541,-729 431.0541,-729 437.0541,-729 443.0541,-735 443.0541,-741 443.0541,-741 443.0541,-795 443.0541,-795 443.0541,-801 437.0541,-807 431.0541,-807 431.0541,-807 376.7329,-807 376.7329,-807 370.7329,-807 364.7329,-801 364.7329,-795 364.7329,-795 364.7329,-741 364.7329,-741 364.7329,-735 370.7329,-729 376.7329,-729"/>
<text text-anchor="middle" x="403.8935" y="-737.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="M364.2841,-521C364.2841,-521 442.5029,-521 442.5029,-521 448.5029,-521 454.5029,-527 454.5029,-533 454.5029,-533 454.5029,-709 454.5029,-709 454.5029,-715 448.5029,-721 442.5029,-721 442.5029,-721 364.2841,-721 364.2841,-721 358.2841,-721 352.2841,-715 352.2841,-709 352.2841,-709 352.2841,-533 352.2841,-533 352.2841,-527 358.2841,-521 364.2841,-521"/>
<text text-anchor="middle" x="403.3935" y="-529.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="#eed8ae" stroke="#000000" stroke-width=".5" d="M366.4152,-815C366.4152,-815 441.3718,-815 441.3718,-815 447.3718,-815 453.3718,-821 453.3718,-827 453.3718,-827 453.3718,-881 453.3718,-881 453.3718,-887 447.3718,-893 441.3718,-893 441.3718,-893 366.4152,-893 366.4152,-893 360.4152,-893 354.4152,-887 354.4152,-881 354.4152,-881 354.4152,-827 354.4152,-827 354.4152,-821 360.4152,-815 366.4152,-815"/>
<text text-anchor="middle" x="403.8935" y="-823.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/keys_and_cert.ReadKeysAndCertElgAndEd25519 -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519 | defined in keys_and_cert.go:208&#10;at keys_and_cert.go:224: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:235: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:251: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:260: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate]&#10;at keys_and_cert.go:209: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:266: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:211: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:271: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:225: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:236: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:252: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:262: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:225: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:236: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:252: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:262: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M227.7646,-735C227.7646,-735 28.0784,-735 28.0784,-735 22.0784,-735 16.0784,-729 16.0784,-723 16.0784,-723 16.0784,-711 16.0784,-711 16.0784,-705 22.0784,-699 28.0784,-699 28.0784,-699 227.7646,-699 227.7646,-699 233.7646,-699 239.7646,-705 239.7646,-711 239.7646,-711 239.7646,-723 239.7646,-723 239.7646,-729 233.7646,-735 227.7646,-735"/>
<text text-anchor="middle" x="127.9215" y="-712.8" font-family="Verdana" font-size="14.00" fill="#000000">ReadKeysAndCertElgAndEd25519</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="M420.5888,-452C420.5888,-452 386.1982,-452 386.1982,-452 380.1982,-452 374.1982,-446 374.1982,-440 374.1982,-440 374.1982,-428 374.1982,-428 374.1982,-422 380.1982,-416 386.1982,-416 386.1982,-416 420.5888,-416 420.5888,-416 426.5888,-416 432.5888,-422 432.5888,-428 432.5888,-428 432.5888,-440 432.5888,-440 432.5888,-446 426.5888,-452 420.5888,-452"/>
<text text-anchor="middle" x="403.3935" y="-438.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="403.3935" y="-421.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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge2"><a xlink:title="at keys_and_cert.go:224: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:235: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:251: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M146.004,-698.8408C176.8074,-667.0023 239.7206,-597.918 276.843,-529 291.5665,-501.6656 281.7398,-485.741 304.843,-465 321.0956,-450.4092 344.1851,-442.685 363.9298,-438.5964"/>
<polygon fill="#8b4513" stroke="#8b4513" points="364.6896,-442.0156 373.8962,-436.7726 363.4295,-435.1299 364.6896,-442.0156"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate | defined in key_certificate.go:360">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M457.7212,-513C457.7212,-513 349.0658,-513 349.0658,-513 343.0658,-513 337.0658,-507 337.0658,-501 337.0658,-501 337.0658,-489 337.0658,-489 337.0658,-483 343.0658,-477 349.0658,-477 349.0658,-477 457.7212,-477 457.7212,-477 463.7212,-477 469.7212,-483 469.7212,-489 469.7212,-489 469.7212,-501 469.7212,-501 469.7212,-507 463.7212,-513 457.7212,-513"/>
<text text-anchor="middle" x="403.3935" y="-499.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-482.4" font-family="Verdana" font-size="14.00" fill="#000000">NewKeyCertificate</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate</title>
<g id="a_edge3"><a xlink:title="at keys_and_cert.go:260: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate]">
<path fill="none" stroke="#8b4513" d="M212.8066,-698.9758C236.6297,-690.0351 260.4683,-676.7354 276.843,-657 317.361,-608.166 260.4756,-562.3652 304.843,-517 311.1661,-510.5347 318.9426,-505.7817 327.3299,-502.3134"/>
<polygon fill="#8b4513" stroke="#8b4513" points="328.7338,-505.5303 337.0142,-498.9208 326.4193,-498.9239 328.7338,-505.5303"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="node11" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_node11"><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="M434.6126,-713C434.6126,-713 372.1744,-713 372.1744,-713 366.1744,-713 360.1744,-707 360.1744,-701 360.1744,-701 360.1744,-689 360.1744,-689 360.1744,-683 366.1744,-677 372.1744,-677 372.1744,-677 434.6126,-677 434.6126,-677 440.6126,-677 446.6126,-683 446.6126,-689 446.6126,-689 446.6126,-701 446.6126,-701 446.6126,-707 440.6126,-713 434.6126,-713"/>
<text text-anchor="middle" x="403.3935" y="-699.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="403.3935" y="-682.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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge11"><a xlink:title="at keys_and_cert.go:209: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:266: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M183.9764,-735.0227C212.1204,-741.5241 246.5799,-745.5956 276.843,-738 290.536,-734.5633 291.7551,-728.2931 304.843,-723 319.1783,-717.2024 335.1427,-712.1134 349.9764,-707.9203"/>
<polygon fill="#8b4513" stroke="#8b4513" points="351.3132,-711.183 360.0314,-705.1628 349.4618,-704.4322 351.3132,-711.183"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="node12" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_node12"><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="M431.925,-591C431.925,-591 374.862,-591 374.862,-591 368.862,-591 362.862,-585 362.862,-579 362.862,-579 362.862,-567 362.862,-567 362.862,-561 368.862,-555 374.862,-555 374.862,-555 431.925,-555 431.925,-555 437.925,-555 443.925,-561 443.925,-567 443.925,-567 443.925,-579 443.925,-579 443.925,-585 437.925,-591 431.925,-591"/>
<text text-anchor="middle" x="403.3935" y="-577.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="403.3935" y="-560.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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="edge23" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_edge23"><a xlink:title="at keys_and_cert.go:225: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:236: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:252: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:262: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M239.7864,-705.5201C253.3416,-700.452 266.1498,-693.4946 276.843,-684 305.0119,-658.9885 277.7843,-630.2086 304.843,-604 317.7667,-591.4823 335.6939,-584.0148 352.7191,-579.5617"/>
<polygon fill="#8b4513" stroke="#8b4513" points="353.6431,-582.9404 362.5945,-577.2727 352.0624,-576.1212 353.6431,-582.9404"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="node13" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_node13"><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="M421.1598,-652C421.1598,-652 385.6272,-652 385.6272,-652 379.6272,-652 373.6272,-646 373.6272,-640 373.6272,-640 373.6272,-628 373.6272,-628 373.6272,-622 379.6272,-616 385.6272,-616 385.6272,-616 421.1598,-616 421.1598,-616 427.1598,-616 433.1598,-622 433.1598,-628 433.1598,-628 433.1598,-640 433.1598,-640 433.1598,-646 427.1598,-652 421.1598,-652"/>
<text text-anchor="middle" x="403.3935" y="-638.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="403.3935" y="-621.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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge24" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge24"><a xlink:title="at keys_and_cert.go:225: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:236: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:252: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:262: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M239.9764,-724.425C252.97,-721.8776 265.5828,-717.6299 276.843,-711 297.4676,-698.8564 285.9998,-679.7571 304.843,-665 321.6006,-651.8763 343.9993,-644.2583 363.2081,-639.8617"/>
<polygon fill="#8b4513" stroke="#8b4513" points="364.1228,-643.2466 373.2045,-637.7901 362.7023,-636.3922 364.1228,-643.2466"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Debug -->
<g id="node14" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_node14"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Debug | defined in logger.go:221">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M422.2155,-799C422.2155,-799 384.5715,-799 384.5715,-799 378.5715,-799 372.5715,-793 372.5715,-787 372.5715,-787 372.5715,-775 372.5715,-775 372.5715,-769 378.5715,-763 384.5715,-763 384.5715,-763 422.2155,-763 422.2155,-763 428.2155,-763 434.2155,-769 434.2155,-775 434.2155,-775 434.2155,-787 434.2155,-787 434.2155,-793 428.2155,-799 422.2155,-799"/>
<text text-anchor="middle" x="403.3935" y="-785.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="403.3935" y="-768.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/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge16" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCertElgAndEd25519&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge16"><a xlink:title="at keys_and_cert.go:211: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:271: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M205.7561,-735.0832C256.798,-746.9417 321.4702,-761.9669 362.6519,-771.5346"/>
<polygon fill="#8b4513" stroke="#8b4513" points="362.0605,-774.9903 372.5931,-773.8442 363.6446,-768.1719 362.0605,-774.9903"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.init -->
<g id="node4" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.init</title>
<g id="a_node4"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.init | defined in .:0&#10;at keys_and_cert.go:17: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M142.9215,-946C142.9215,-946 112.9215,-946 112.9215,-946 106.9215,-946 100.9215,-940 100.9215,-934 100.9215,-934 100.9215,-922 100.9215,-922 100.9215,-916 106.9215,-910 112.9215,-910 112.9215,-910 142.9215,-910 142.9215,-910 148.9215,-910 154.9215,-916 154.9215,-922 154.9215,-922 154.9215,-934 154.9215,-934 154.9215,-940 148.9215,-946 142.9215,-946"/>
<text text-anchor="middle" x="127.9215" y="-923.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="M452.083,-946C452.083,-946 354.704,-946 354.704,-946 348.704,-946 342.704,-940 342.704,-934 342.704,-934 342.704,-922 342.704,-922 342.704,-916 348.704,-910 354.704,-910 354.704,-910 452.083,-910 452.083,-910 458.083,-910 464.083,-916 464.083,-922 464.083,-922 464.083,-934 464.083,-934 464.083,-940 458.083,-946 452.083,-946"/>
<text text-anchor="middle" x="403.3935" y="-932.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="403.3935" y="-915.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/keys_and_cert.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge28" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge28"><a xlink:title="at keys_and_cert.go:17: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M155.0887,-928C195.9363,-928 274.546,-928 332.4167,-928"/>
<polygon fill="#8b4513" stroke="#8b4513" points="332.6037,-931.5001 342.6036,-928 332.6036,-924.5001 332.6037,-931.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert | defined in keys_and_cert.go:306&#10;at keys_and_cert.go:315: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:329: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:340: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:351: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:312: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:316: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:330: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:341: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:352: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:320: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]&#10;at keys_and_cert.go:326: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:337: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:348: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:321: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M179.8247,-573C179.8247,-573 76.0183,-573 76.0183,-573 70.0183,-573 64.0183,-567 64.0183,-561 64.0183,-561 64.0183,-549 64.0183,-549 64.0183,-543 70.0183,-537 76.0183,-537 76.0183,-537 179.8247,-537 179.8247,-537 185.8247,-537 191.8247,-543 191.8247,-549 191.8247,-549 191.8247,-561 191.8247,-561 191.8247,-567 185.8247,-573 179.8247,-573"/>
<text text-anchor="middle" x="127.9215" y="-550.8" font-family="Verdana" font-size="14.00" fill="#000000">NewKeysAndCert</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge13" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge13"><a xlink:title="at keys_and_cert.go:316: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:330: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:341: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:352: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M191.8965,-553.1217C220.4159,-549.3895 252.8996,-540.8189 276.843,-522 299.0339,-504.5585 283.4287,-483.3867 304.843,-465 321.414,-450.7718 344.5191,-443.0654 364.1924,-438.8955"/>
<polygon fill="#8b4513" stroke="#8b4513" points="364.938,-442.3167 374.1147,-437.0215 363.6389,-435.4383 364.938,-442.3167"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge18" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge18"><a xlink:title="at keys_and_cert.go:326: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:337: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:348: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M191.7073,-570.8448C220.1869,-580.3469 252.6917,-594.8088 276.843,-616 295.6968,-632.543 285.2385,-649.3539 304.843,-665 317.9239,-675.4397 334.6098,-682.2558 350.5174,-686.7024"/>
<polygon fill="#8b4513" stroke="#8b4513" points="349.7291,-690.1131 360.2824,-689.176 351.4481,-683.3275 349.7291,-690.1131"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge9" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge9"><a xlink:title="at keys_and_cert.go:315: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:329: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:340: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:351: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M191.693,-565.6594C218.4695,-571.1293 249.6464,-578.821 276.843,-589 290.0649,-593.9486 291.8051,-598.5849 304.843,-604 323.7959,-611.8718 345.5587,-618.7143 363.8043,-623.8686"/>
<polygon fill="#8b4513" stroke="#8b4513" points="362.968,-627.2686 373.5388,-626.5542 364.8298,-620.5207 362.968,-627.2686"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge12" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge12"><a xlink:title="at keys_and_cert.go:312: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M143.619,-573.2317C172.9395,-606.566 239.033,-678.3812 304.843,-727 322.9652,-740.3882 344.7931,-752.6867 363.2951,-762.1539"/>
<polygon fill="#8b4513" stroke="#8b4513" points="361.8467,-765.3431 372.3541,-766.7016 364.9872,-759.0871 361.8467,-765.3431"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="node15" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_node15"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize | defined in key_certificate.go:340">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M445.0648,-391C445.0648,-391 361.7222,-391 361.7222,-391 355.7222,-391 349.7222,-385 349.7222,-379 349.7222,-379 349.7222,-367 349.7222,-367 349.7222,-361 355.7222,-355 361.7222,-355 361.7222,-355 445.0648,-355 445.0648,-355 451.0648,-355 457.0648,-361 457.0648,-367 457.0648,-367 457.0648,-379 457.0648,-379 457.0648,-385 451.0648,-391 445.0648,-391"/>
<text text-anchor="middle" x="403.3935" y="-377.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-360.4" font-family="Verdana" font-size="14.00" fill="#000000">CryptoSize</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="edge17" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_edge17"><a xlink:title="at keys_and_cert.go:320: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]">
<path fill="none" stroke="#8b4513" d="M191.9603,-542.8506C221.5442,-534.1629 254.8989,-519.5009 276.843,-495 307.6354,-460.6197 271.3481,-426.7532 304.843,-395 314.4235,-385.9176 326.8952,-380.2749 339.7281,-376.8342"/>
<polygon fill="#8b4513" stroke="#8b4513" points="340.5865,-380.2285 349.57,-374.6117 339.0446,-373.4005 340.5865,-380.2285"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="node16" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_node16"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize | defined in key_certificate.go:312">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M445.0648,-330C445.0648,-330 361.7222,-330 361.7222,-330 355.7222,-330 349.7222,-324 349.7222,-318 349.7222,-318 349.7222,-306 349.7222,-306 349.7222,-300 355.7222,-294 361.7222,-294 361.7222,-294 445.0648,-294 445.0648,-294 451.0648,-294 457.0648,-300 457.0648,-306 457.0648,-306 457.0648,-318 457.0648,-318 457.0648,-324 451.0648,-330 445.0648,-330"/>
<text text-anchor="middle" x="403.3935" y="-316.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-299.4" font-family="Verdana" font-size="14.00" fill="#000000">SignatureSize</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="edge21" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.NewKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_edge21"><a xlink:title="at keys_and_cert.go:321: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]">
<path fill="none" stroke="#8b4513" d="M191.6333,-538.3302C209.0089,-531.2859 226.6553,-521.4852 239.843,-508 294.9511,-451.6489 247.1801,-396.7339 304.843,-343 314.6721,-333.8407 327.1866,-327.3873 339.9736,-322.8406"/>
<polygon fill="#8b4513" stroke="#8b4513" points="341.2988,-326.0918 349.765,-319.7221 339.1744,-319.4219 341.2988,-326.0918"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert -->
<g id="node7" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert</title>
<g id="a_node7"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert | defined in keys_and_cert.go:145&#10;at keys_and_cert.go:172: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]&#10;at keys_and_cert.go:148: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:203: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:161: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:173: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]&#10;at keys_and_cert.go:176: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey]&#10;at keys_and_cert.go:190: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey]&#10;at keys_and_cert.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:155: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:198: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:165: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate]&#10;at keys_and_cert.go:200: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]&#10;at keys_and_cert.go:199: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]&#10;at keys_and_cert.go:160: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:178: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:194: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:178: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:194: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M180.6624,-276C180.6624,-276 75.1806,-276 75.1806,-276 69.1806,-276 63.1806,-270 63.1806,-264 63.1806,-264 63.1806,-252 63.1806,-252 63.1806,-246 69.1806,-240 75.1806,-240 75.1806,-240 180.6624,-240 180.6624,-240 186.6624,-240 192.6624,-246 192.6624,-252 192.6624,-252 192.6624,-264 192.6624,-264 192.6624,-270 186.6624,-276 180.6624,-276"/>
<text text-anchor="middle" x="127.9215" y="-253.8" font-family="Verdana" font-size="14.00" fill="#000000">ReadKeysAndCert</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge5" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge5"><a xlink:title="at keys_and_cert.go:161: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M192.7503,-258.0039C221.9744,-261.3701 254.7962,-270.3559 276.843,-292 313.7651,-328.2477 269.057,-367.6302 304.843,-405 320.144,-420.9782 343.7549,-428.2808 364.0303,-431.5638"/>
<polygon fill="#8b4513" stroke="#8b4513" points="363.5864,-435.0356 373.965,-432.9061 364.5237,-428.0986 363.5864,-435.0356"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate -->
<g id="edge14" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate</title>
<g id="a_edge14"><a xlink:title="at keys_and_cert.go:165: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.NewKeyCertificate]">
<path fill="none" stroke="#8b4513" d="M192.8901,-269.8234C222.6941,-278.5308 255.9655,-293.4844 276.843,-319 318.6833,-370.1354 260.6645,-415.8706 304.843,-465 311.1222,-471.9828 318.9715,-477.3633 327.4827,-481.5049"/>
<polygon fill="#8b4513" stroke="#8b4513" points="326.3632,-484.8323 336.935,-485.53 329.1057,-478.3918 326.3632,-484.8323"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#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/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge10"><a xlink:title="at keys_and_cert.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:155: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:198: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M156.7391,-276.0245C191.8161,-299.7174 249.7172,-344.8662 276.843,-400 302.9849,-453.134 267.1364,-619.34 304.843,-665 316.0763,-678.6028 333.2845,-686.1769 350.1953,-690.3486"/>
<polygon fill="#8b4513" stroke="#8b4513" points="349.5633,-693.7922 360.0703,-692.4315 351.008,-686.9429 349.5633,-693.7922"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="edge30" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_edge30"><a xlink:title="at keys_and_cert.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:178: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at keys_and_cert.go:194: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M181.978,-276.0712C214.8155,-289.9419 254.5742,-312.4816 276.843,-346 327.73,-422.5938 242.6033,-483.3072 304.843,-551 316.9438,-564.161 335.0435,-570.3274 352.4422,-572.9835"/>
<polygon fill="#8b4513" stroke="#8b4513" points="352.2152,-576.4807 362.5546,-574.1681 353.0297,-569.5283 352.2152,-576.4807"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge29" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge29"><a xlink:title="at keys_and_cert.go:160: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:167: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:178: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at keys_and_cert.go:194: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M165.8039,-276.1094C200.9077,-295.0524 251.4165,-328.2733 276.843,-373 327.9532,-462.9058 238.3807,-524.7657 304.843,-604 319.1001,-620.9969 342.6787,-628.5658 363.1982,-631.8527"/>
<polygon fill="#8b4513" stroke="#8b4513" points="362.9061,-635.3443 373.2768,-633.1767 363.8179,-628.4039 362.9061,-635.3443"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge4"><a xlink:title="at keys_and_cert.go:148: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:203: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M149.8852,-276.3573C175.7187,-299.2451 217.8609,-340.8881 239.843,-386 307.426,-524.6946 214.0787,-602.2382 304.843,-727 319.0117,-746.4758 342.4323,-759.7254 362.8871,-768.2247"/>
<polygon fill="#8b4513" stroke="#8b4513" points="361.7455,-771.5362 372.3337,-771.9113 364.2904,-765.0152 361.7455,-771.5362"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize</title>
<g id="a_edge1"><a xlink:title="at keys_and_cert.go:172: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).CryptoSize]">
<path fill="none" stroke="#8b4513" d="M193.0215,-245.8598C221.2702,-244.1831 253.2195,-247.5373 276.843,-265 306.4618,-286.8945 278.1663,-317.6032 304.843,-343 314.5458,-352.2373 327.008,-358.6374 339.7841,-363.0697"/>
<polygon fill="#8b4513" stroke="#8b4513" points="338.9873,-366.4866 349.5747,-366.09 341.0508,-359.7976 338.9873,-366.4866"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize -->
<g id="edge6" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize</title>
<g id="a_edge6"><a xlink:title="at keys_and_cert.go:173: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SignatureSize]">
<path fill="none" stroke="#8b4513" d="M168.2865,-239.944C199.7136,-228.7549 243.4563,-219.6725 276.843,-238 297.1622,-249.1541 286.3872,-267.9761 304.843,-282 315.226,-289.8896 327.6891,-295.7187 340.2051,-300.0209"/>
<polygon fill="#8b4513" stroke="#8b4513" points="339.1635,-303.3623 349.7529,-303.0221 341.2626,-296.6844 339.1635,-303.3623"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey -->
<g id="node17" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey</title>
<g id="a_node17"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey | defined in key_certificate.go:140">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M459.9315,-208C459.9315,-208 346.8555,-208 346.8555,-208 340.8555,-208 334.8555,-202 334.8555,-196 334.8555,-196 334.8555,-184 334.8555,-184 334.8555,-178 340.8555,-172 346.8555,-172 346.8555,-172 459.9315,-172 459.9315,-172 465.9315,-172 471.9315,-178 471.9315,-184 471.9315,-184 471.9315,-196 471.9315,-196 471.9315,-202 465.9315,-208 459.9315,-208"/>
<text text-anchor="middle" x="403.3935" y="-194.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-177.4" font-family="Verdana" font-size="14.00" fill="#000000">ConstructPublicKey</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey -->
<g id="edge7" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey</title>
<g id="a_edge7"><a xlink:title="at keys_and_cert.go:176: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructPublicKey]">
<path fill="none" stroke="#8b4513" d="M170.1904,-239.9546C199.3631,-228.2252 239.3262,-213.5716 275.843,-205 291.4821,-201.3291 308.421,-198.5363 324.6895,-196.4182"/>
<polygon fill="#8b4513" stroke="#8b4513" points="325.217,-199.8797 334.7147,-195.1847 324.3621,-192.9321 325.217,-199.8797"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey -->
<g id="node18" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey</title>
<g id="a_node18"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey | defined in key_certificate.go:232">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M481.9945,-269C481.9945,-269 324.7925,-269 324.7925,-269 318.7925,-269 312.7925,-263 312.7925,-257 312.7925,-257 312.7925,-245 312.7925,-245 312.7925,-239 318.7925,-233 324.7925,-233 324.7925,-233 481.9945,-233 481.9945,-233 487.9945,-233 493.9945,-239 493.9945,-245 493.9945,-245 493.9945,-257 493.9945,-257 493.9945,-263 487.9945,-269 481.9945,-269"/>
<text text-anchor="middle" x="403.3935" y="-255.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-238.4" font-family="Verdana" font-size="14.00" fill="#000000">ConstructSigningPublicKey</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey -->
<g id="edge8" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey</title>
<g id="a_edge8"><a xlink:title="at keys_and_cert.go:190: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).ConstructSigningPublicKey]">
<path fill="none" stroke="#8b4513" d="M157.2875,-239.8536C186.9108,-223.6807 234.2347,-203.6196 276.843,-211 289.8634,-213.2553 292.2965,-216.8525 304.843,-221 313.8541,-223.9788 323.3641,-227.0118 332.7788,-229.9484"/>
<polygon fill="#8b4513" stroke="#8b4513" points="331.9429,-233.3534 342.5307,-232.9675 334.0131,-226.6665 331.9429,-233.3534"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="node19" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_node19"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType | defined in key_certificate.go:130">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M447.2604,-86C447.2604,-86 359.5266,-86 359.5266,-86 353.5266,-86 347.5266,-80 347.5266,-74 347.5266,-74 347.5266,-62 347.5266,-62 347.5266,-56 353.5266,-50 359.5266,-50 359.5266,-50 447.2604,-50 447.2604,-50 453.2604,-50 459.2604,-56 459.2604,-62 459.2604,-62 459.2604,-74 459.2604,-74 459.2604,-80 453.2604,-86 447.2604,-86"/>
<text text-anchor="middle" x="403.3935" y="-72.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-55.4" font-family="Verdana" font-size="14.00" fill="#000000">PublicKeyType</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType -->
<g id="edge22" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType</title>
<g id="a_edge22"><a xlink:title="at keys_and_cert.go:199: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).PublicKeyType]">
<path fill="none" stroke="#8b4513" d="M143.0358,-239.8329C171.4082,-206.8614 236.0176,-136.9837 304.843,-98 315.0554,-92.2156 326.5081,-87.4254 337.8941,-83.4998"/>
<polygon fill="#8b4513" stroke="#8b4513" points="338.9873,-86.8247 347.414,-80.4028 336.8217,-80.1681 338.9873,-86.8247"/>
</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:121">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M469.3247,-147C469.3247,-147 337.4623,-147 337.4623,-147 331.4623,-147 325.4623,-141 325.4623,-135 325.4623,-135 325.4623,-123 325.4623,-123 325.4623,-117 331.4623,-111 337.4623,-111 337.4623,-111 469.3247,-111 469.3247,-111 475.3247,-111 481.3247,-117 481.3247,-123 481.3247,-123 481.3247,-135 481.3247,-135 481.3247,-141 475.3247,-147 469.3247,-147"/>
<text text-anchor="middle" x="403.3935" y="-133.2" font-family="Verdana" font-size="14.00" fill="#000000">key_certificate</text>
<text text-anchor="middle" x="403.3935" y="-116.4" font-family="Verdana" font-size="14.00" fill="#000000">SigningPublicKeyType</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType -->
<g id="edge19" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.ReadKeysAndCert&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType</title>
<g id="a_edge19"><a xlink:title="at keys_and_cert.go:200: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/key_certificate.KeyCertificate).SigningPublicKeyType]">
<path fill="none" stroke="#8b4513" d="M156.4385,-239.8447C190.674,-218.6123 250.3098,-183.3979 304.843,-160 312.8069,-156.583 321.2752,-153.3516 329.7737,-150.3574"/>
<polygon fill="#8b4513" stroke="#8b4513" points="331.0269,-153.6279 339.3564,-147.0804 328.7619,-147.0045 331.0269,-153.6279"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructPublicKey -->
<g id="node8" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructPublicKey</title>
<g id="a_node8"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructPublicKey | defined in keys_and_cert.go:276&#10;at keys_and_cert.go:287: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:280: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M183.3373,-434C183.3373,-434 72.5057,-434 72.5057,-434 66.5057,-434 60.5057,-428 60.5057,-422 60.5057,-422 60.5057,-410 60.5057,-410 60.5057,-404 66.5057,-398 72.5057,-398 72.5057,-398 183.3373,-398 183.3373,-398 189.3373,-398 195.3373,-404 195.3373,-410 195.3373,-410 195.3373,-422 195.3373,-422 195.3373,-428 189.3373,-434 183.3373,-434"/>
<text text-anchor="middle" x="127.9215" y="-411.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/keys_and_cert.constructPublicKey&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge20" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructPublicKey&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge20"><a xlink:title="at keys_and_cert.go:287: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:280: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M195.3095,-420.4033C248.2482,-423.8624 320.1393,-428.56 364.0707,-431.4306"/>
<polygon fill="#8b4513" stroke="#8b4513" points="363.8663,-434.9246 374.0732,-432.0841 364.3227,-427.9395 363.8663,-434.9246"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructSigningPublicKey -->
<g id="node9" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructSigningPublicKey</title>
<g id="a_node9"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructSigningPublicKey | defined in keys_and_cert.go:291&#10;at keys_and_cert.go:300: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:295: calling [github.com/samber/oops.Errorf]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M204.9005,-495C204.9005,-495 50.9425,-495 50.9425,-495 44.9425,-495 38.9425,-489 38.9425,-483 38.9425,-483 38.9425,-471 38.9425,-471 38.9425,-465 44.9425,-459 50.9425,-459 50.9425,-459 204.9005,-459 204.9005,-459 210.9005,-459 216.9005,-465 216.9005,-471 216.9005,-471 216.9005,-483 216.9005,-483 216.9005,-489 210.9005,-495 204.9005,-495"/>
<text text-anchor="middle" x="127.9215" y="-472.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/keys_and_cert.constructSigningPublicKey&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge26" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.constructSigningPublicKey&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge26"><a xlink:title="at keys_and_cert.go:300: calling [github.com/samber/oops.Errorf]&#10;at keys_and_cert.go:295: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M216.9789,-463.0985C266.5502,-455.3607 325.7755,-446.1158 363.9573,-440.1558"/>
<polygon fill="#8b4513" stroke="#8b4513" points="364.8024,-443.5664 374.1429,-438.5659 363.7228,-436.6501 364.8024,-443.5664"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="node10" class="node">
<title>(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_node10"><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="M431.3501,-885C431.3501,-885 375.4369,-885 375.4369,-885 369.4369,-885 363.4369,-879 363.4369,-873 363.4369,-873 363.4369,-861 363.4369,-861 363.4369,-855 369.4369,-849 375.4369,-849 375.4369,-849 431.3501,-849 431.3501,-849 437.3501,-849 443.3501,-855 443.3501,-861 443.3501,-861 443.3501,-873 443.3501,-873 443.3501,-879 437.3501,-885 431.3501,-885"/>
<text text-anchor="middle" x="403.3935" y="-871.2" font-family="Verdana" font-size="14.00" fill="#000000">certificate</text>
<text text-anchor="middle" x="403.3935" y="-854.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).Bytes -->
<g id="node21" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes</title>
<g id="a_node21"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes | defined in keys_and_cert.go:90&#10;at keys_and_cert.go:116: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at keys_and_cert.go:124: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at keys_and_cert.go:112: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at keys_and_cert.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M143.808,-857C143.808,-857 112.035,-857 112.035,-857 106.035,-857 100.035,-851 100.035,-845 100.035,-845 100.035,-833 100.035,-833 100.035,-827 106.035,-821 112.035,-821 112.035,-821 143.808,-821 143.808,-821 149.808,-821 155.808,-827 155.808,-833 155.808,-833 155.808,-845 155.808,-845 155.808,-851 149.808,-857 143.808,-857"/>
<text text-anchor="middle" x="127.9215" y="-834.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/keys_and_cert.KeysAndCert).Bytes&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes -->
<g id="edge27" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes&#45;&gt;(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes</title>
<g id="a_edge27"><a xlink:title="at keys_and_cert.go:112: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]&#10;at keys_and_cert.go:113: calling [(*github.com/go&#45;i2p/go&#45;i2p/lib/common/certificate.Certificate).Bytes]">
<path fill="none" stroke="#8b4513" d="M155.8512,-841.8389C202.046,-846.5343 295.0028,-855.9828 352.9328,-861.871"/>
<polygon fill="#8b4513" stroke="#8b4513" points="352.6682,-865.362 362.9709,-862.8913 353.3761,-858.3979 352.6682,-865.362"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes&#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/keys_and_cert.KeysAndCert).Bytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge15"><a xlink:title="at keys_and_cert.go:116: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M155.9801,-841.0394C189.2057,-841.8433 244.1494,-837.8569 276.843,-807 305.4619,-779.9889 276.3984,-750.1946 304.843,-723 317.0867,-711.2944 333.8593,-704.423 350.0969,-700.4091"/>
<polygon fill="#8b4513" stroke="#8b4513" points="351.051,-703.784 360.0927,-698.2614 349.5805,-696.9402 351.051,-703.784"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge25" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/keys_and_cert.KeysAndCert).Bytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge25"><a xlink:title="at keys_and_cert.go:124: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M155.9661,-836.9962C186.146,-834.4326 235.3964,-829.0664 276.843,-819 289.684,-815.8812 292.2583,-813.0302 304.843,-809 323.764,-802.9407 344.9356,-796.8384 362.7916,-791.8842"/>
<polygon fill="#8b4513" stroke="#8b4513" points="363.8935,-795.2112 372.6066,-789.1835 362.0363,-788.462 363.8935,-795.2112"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,12 +1,23 @@
package keys_and_cert
import (
"bytes"
"crypto/rand"
"testing"
"github.com/go-i2p/go-i2p/lib/crypto/ed25519"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/go-i2p/go-i2p/lib/common/certificate"
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/key_certificate"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/stretchr/testify/assert"
)
/*func TestCertificateWithMissingData(t *testing.T) {
/*
func TestCertificateWithMissingData(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
@ -16,15 +27,122 @@ import (
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
}
}*/
}
func TestCertificateWithValidData(t *testing.T) {
*/
// createValidKeyCertificate creates a valid KeyCertificate for testing.
func createValidKeyAndCert(t *testing.T) *KeysAndCert {
// Generate signing key pair (Ed25519)
// var ed25519_privkey crypto.Ed25519PrivateKey
ed25519_privkey, err := ed25519.GenerateEd25519Key()
if err != nil {
t.Fatalf("Failed to generate Ed25519 private %s", err)
}
// Copy the full private key (includes public key)
//ed25519_privkey := make(ed25519.Ed25519PrivateKey, ed25519.PrivateKeySize)
//copy(ed25519_privkey, priv)
//_, err = (ed25519_privkey).Generate()
if err != nil {
t.Fatalf("Failed to generate Ed25519 private key: %v\n", err)
}
ed25519_pubkey_raw, err := ed25519_privkey.Public()
if err != nil {
t.Fatalf("Failed to derive Ed25519 public key: %v\n", err)
}
ed25519_pubkey, ok := ed25519_pubkey_raw.(types.SigningPublicKey)
if !ok {
t.Fatalf("Failed to get SigningPublicKey from Ed25519 public key")
}
// Generate encryption key pair (ElGamal)
var elgamal_privkey elgamal.PrivateKey
err = elgamal.ElgamalGenerate(&elgamal_privkey.PrivateKey, rand.Reader)
if err != nil {
t.Fatalf("Failed to generate ElGamal private key: %v\n", err)
}
// Convert elgamal public key to crypto.ElgPublicKey
var elg_pubkey elgamal.ElgPublicKey
yBytes := elgamal_privkey.PublicKey.Y.Bytes()
if len(yBytes) > 256 {
t.Fatalf("ElGamal public key Y too large")
}
copy(elg_pubkey[256-len(yBytes):], yBytes)
// Create KeyCertificate specifying key types
var payload bytes.Buffer
cryptoPublicKeyType, err := data.NewIntegerFromInt(0, 2) // ElGamal
if err != nil {
t.Fatalf("Failed to create crypto public key type integer: %v", err)
}
signingPublicKeyType, err := data.NewIntegerFromInt(7, 2) // Ed25519
if err != nil {
t.Fatalf("Failed to create signing public key type integer: %v", err)
}
payload.Write(*cryptoPublicKeyType)
payload.Write(*signingPublicKeyType)
// Create certificate
cert, err := certificate.NewCertificateWithType(certificate.CERT_KEY, payload.Bytes())
if err != nil {
t.Fatalf("Failed to create new certificate: %v\n", err)
}
keyCert, err := key_certificate.KeyCertificateFromCertificate(*cert)
if err != nil {
t.Fatalf("KeyCertificateFromCertificate failed: %v\n", err)
}
pubKeySize := keyCert.CryptoSize()
sigKeySize := keyCert.SignatureSize()
paddingSize := KEYS_AND_CERT_DATA_SIZE - pubKeySize - sigKeySize
// Generate random padding
padding := make([]byte, paddingSize)
_, err = rand.Read(padding)
if err != nil {
t.Fatal(err)
}
t.Logf("pubkey len: %v\n", ed25519_pubkey.Len())
t.Logf("pubkey bytes: %v\n", ed25519_pubkey.Bytes())
keysAndCert, err := NewKeysAndCert(keyCert, elg_pubkey, padding, ed25519_pubkey)
if err != nil {
t.Fatal(err)
}
t.Logf("pubkey bytes after NewKeysAndCert: %v\n", keysAndCert.SigningPublic.Bytes())
return keysAndCert
}
func TestCertificateWithValidDataElgAndEd25519(t *testing.T) {
assert := assert.New(t)
keysAndCert := createValidKeyAndCert(t)
// Serialize KeysAndCert to bytes
serialized := keysAndCert.Bytes()
// Deserialize KeysAndCert from bytes
parsedKeysAndCert, remainder, err := ReadKeysAndCertElgAndEd25519(serialized)
assert.Nil(err, "ReadKeysAndCert should not error with valid data")
assert.Empty(remainder, "There should be no remainder after parsing KeysAndCert")
// Compare individual fields
assert.Equal(keysAndCert.KeyCertificate.Bytes(), parsedKeysAndCert.KeyCertificate.Bytes(), "KeyCertificates should match")
assert.Equal(keysAndCert.ReceivingPublic.Bytes(), parsedKeysAndCert.ReceivingPublic.Bytes(), "PublicKeys should match")
assert.Equal(keysAndCert.Padding, parsedKeysAndCert.Padding, "Padding should match")
assert.Equal(keysAndCert.SigningPublic.Bytes(), parsedKeysAndCert.SigningPublic.Bytes(), "SigningPublicKeys should match")
}
func TestCertificateWithValidDataManual(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
data := make([]byte, 128+256)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
assert.Nil(err)
cert := keys_and_cert.Certificate()
@ -43,7 +161,7 @@ func TestPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) {
@ -54,51 +172,51 @@ func TestPublicKeyWithBadData(t *testing.T) {
func TestPublicKeyWithBadCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
pub_key_data := make([]byte, 256)
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
log.WithError(err).Debug("Correctly got error")
}
pub_key := keys_and_cert.PublicKey()
assert.Nil(pub_key)
}
func TestPublicKeyWithNullCertificate(t *testing.T) {
assert := assert.New(t)
/*
func TestPublicKeyWithNullCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x00, 0x00, 0x00}
pub_key_data := make([]byte, 256)
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
cert_data := []byte{0x00, 0x00, 0x00}
pub_key_data := make([]byte, 256)
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
assert.Equal(len(pub_key_data), pub_key.Len())
}
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
assert.Equal(len(pub_key_data), pub_key.Len())
}
func TestPublicKeyWithKeyCertificate(t *testing.T) {
assert := assert.New(t)
func TestPublicKeyWithKeyCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
pub_key_data := make([]byte, 256)
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
assert.Equal(len(pub_key_data), pub_key.Len())
}
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}
pub_key_data := make([]byte, 256)
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := ReadKeysAndCert(data)
pub_key := keys_and_cert.PublicKey()
assert.Nil(err)
assert.Equal(len(pub_key_data), pub_key.Len())
}
*/
func TestSigningPublicKeyWithBadData(t *testing.T) {
assert := assert.New(t)
@ -107,12 +225,10 @@ func TestSigningPublicKeyWithBadData(t *testing.T) {
data := make([]byte, 93)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) {
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
}
assert.NotNil(err)
assert.Nil(signing_pub_key)
}
@ -124,15 +240,13 @@ func TestSigningPublicKeyWithBadCertificate(t *testing.T) {
data := make([]byte, 128)
data = append(data, pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
}
assert.NotNil(err)
assert.Nil(signing_pub_key)
}
/*
func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
assert := assert.New(t)
@ -141,7 +255,7 @@ func TestSigningPublicKeyWithNullCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err)
@ -156,77 +270,84 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
signing_pub_key_data := make([]byte, 128)
data := append(pub_key_data, signing_pub_key_data...)
data = append(data, cert_data...)
keys_and_cert, _, err := NewKeysAndCert(data)
keys_and_cert, _, err := ReadKeysAndCert(data)
signing_pub_key := keys_and_cert.SigningPublicKey()
assert.Nil(err)
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
}
*/
func TestNewKeysAndCertWithMissingData(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
if assert.NotNil(err) {
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
}
}
func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
assert := assert.New(t)
/*
func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
_, remainder, err := NewKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01}...)
_, remainder, err := ReadKeysAndCertDeux(cert_data)
assert.Equal(0, len(remainder))
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
}
}
}
*/
func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
assert.Nil(err)
}
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
_, remainder, err := NewKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
assert.Nil(err)
}
/*
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00}...)
_, remainder, err := ReadKeysAndCert(cert_data)
assert.Equal(0, len(remainder))
assert.Nil(err)
}
*/
func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0]))
}
assert.Nil(err)
}
/*
func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
assert := assert.New(t)
cert_data := make([]byte, 128+256)
cert_data = append(cert_data, []byte{0x00, 0x00, 0x00, 0x41}...)
_, remainder, err := NewKeysAndCert(cert_data)
_, remainder, err := ReadKeysAndCert(cert_data)
if assert.Equal(1, len(remainder)) {
assert.Equal("A", string(remainder[0]))
}
assert.Nil(err)
}
*/

View File

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

View File

@ -0,0 +1,77 @@
# lease
--
import "github.com/go-i2p/go-i2p/lib/common/lease"
![lease.svg](lease.svg)
Package lease implements the I2P lease common data structure
## Usage
```go
const (
LEASE_SIZE = 44
LEASE_TUNNEL_GW_SIZE = 32
LEASE_TUNNEL_ID_SIZE = 4
)
```
Sizes in bytes of various components of a Lease
#### type Lease
```go
type Lease [LEASE_SIZE]byte
```
#### func NewLease
```go
func NewLease(tunnelGateway Hash, tunnelID uint32, expirationTime time.Time) (*Lease, error)
```
NewLease creates a new Lease with the provided parameters.
#### func NewLeaseFromBytes
```go
func NewLeaseFromBytes(data []byte) (lease *Lease, remainder []byte, err error)
```
NewLeaseFromBytes creates a new *Lease from []byte using ReadLease. Returns a
pointer to Lease unlike ReadLease.
#### func ReadLease
```go
func ReadLease(data []byte) (lease Lease, remainder []byte, err error)
```
ReadLease returns Lease from a []byte. The remaining bytes after the specified
length are also returned. Returns a list of errors that occurred during parsing.
#### func (Lease) Date
```go
func (lease Lease) Date() (date Date)
```
Date returns the date as an I2P Date.
#### func (Lease) TunnelGateway
```go
func (lease Lease) TunnelGateway() (hash Hash)
```
TunnelGateway returns the tunnel gateway as a Hash.
#### func (Lease) TunnelID
```go
func (lease Lease) TunnelID() uint32
```
TunnelID returns the tunnel id as a uint23.
lease
github.com/go-i2p/go-i2p/lib/common/lease
[go-i2p template file](/template.md)

View File

@ -1,12 +1,20 @@
// Package lease implements the I2P lease common data structure
package lease
import . "github.com/go-i2p/go-i2p/lib/common/data"
import (
"encoding/binary"
"time"
. "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/logger"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
// Sizes in bytes of various components of a Lease
const (
LEASE_SIZE = 44
LEASE_HASH_SIZE = 32
LEASE_TUNNEL_GW_SIZE = 32
LEASE_TUNNEL_ID_SIZE = 4
)
@ -47,17 +55,20 @@ end_date :: Date
// Lease is the represenation of an I2P Lease.
//
// https://geti2p.net/spec/common-structures#lease
var log = logger.GetGoI2PLogger()
type Lease [LEASE_SIZE]byte
// TunnelGateway returns the tunnel gateway as a Hash.
func (lease Lease) TunnelGateway() (hash Hash) {
copy(hash[:], lease[:LEASE_HASH_SIZE])
copy(hash[:], lease[:LEASE_TUNNEL_GW_SIZE])
return
}
// TunnelID returns the tunnel id as a uint23.
func (lease Lease) TunnelID() uint32 {
i := Integer(lease[LEASE_HASH_SIZE : LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE])
i := Integer(lease[LEASE_TUNNEL_GW_SIZE : LEASE_TUNNEL_GW_SIZE+LEASE_TUNNEL_ID_SIZE])
return uint32(
i.Int(),
)
@ -65,7 +76,7 @@ func (lease Lease) TunnelID() uint32 {
// Date returns the date as an I2P Date.
func (lease Lease) Date() (date Date) {
copy(date[:], lease[LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE:])
copy(date[:], lease[LEASE_TUNNEL_GW_SIZE+LEASE_TUNNEL_ID_SIZE:])
return
}
@ -73,13 +84,76 @@ func (lease Lease) Date() (date Date) {
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadLease(data []byte) (lease Lease, remainder []byte, err error) {
// TODO: stub
log.WithField("input_length", len(data)).Debug("Reading Lease from bytes")
if len(data) < LEASE_SIZE {
err = oops.Errorf("error parsing lease: not enough data")
log.WithFields(logrus.Fields{
"data_length": len(data),
"required_length": LEASE_SIZE,
}).Error("Failed to read lease: insufficient data")
return
}
copy(lease[:], data[:LEASE_SIZE])
remainder = data[LEASE_SIZE:]
log.WithFields(logrus.Fields{
"tunnel_id": lease.TunnelID(),
"expiration": lease.Date().Time(),
"remainder_length": len(remainder),
}).Debug("Successfully read Lease")
return
}
// NewLease creates a new *NewLease from []byte using ReadLease.
// Returns a pointer to KeysAndCert unlike ReadLease.
func NewLease(data []byte) (lease *Lease, remainder []byte, err error) {
// TODO: stub
// NewLease creates a new Lease with the provided parameters.
func NewLease(tunnelGateway Hash, tunnelID uint32, expirationTime time.Time) (*Lease, error) {
log.Debug("Creating new Lease")
var lease Lease
// Gateway hash
copy(lease[:LEASE_TUNNEL_GW_SIZE], tunnelGateway[:])
// Convert and copy tunnel ID
tunnelIDBytes := make([]byte, LEASE_TUNNEL_ID_SIZE)
binary.BigEndian.PutUint32(tunnelIDBytes, tunnelID)
copy(lease[LEASE_TUNNEL_GW_SIZE:LEASE_TUNNEL_GW_SIZE+LEASE_TUNNEL_ID_SIZE], tunnelIDBytes)
// Convert and copy expiration date
millis := expirationTime.UnixNano() / int64(time.Millisecond)
dateBytes := make([]byte, DATE_SIZE)
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
copy(lease[LEASE_TUNNEL_GW_SIZE+LEASE_TUNNEL_ID_SIZE:], dateBytes)
log.WithFields(logrus.Fields{
"tunnel_id": tunnelID,
"expiration": expirationTime,
}).Debug("Successfully created new Lease")
return &lease, nil
}
// NewLeaseFromBytes creates a new *Lease from []byte using ReadLease.
// Returns a pointer to Lease unlike ReadLease.
func NewLeaseFromBytes(data []byte) (lease *Lease, remainder []byte, err error) {
log.WithField("input_length", len(data)).Debug("Creating Lease from bytes")
var l Lease
l, remainder, err = ReadLease(data)
if err != nil {
log.WithError(err).Error("Failed to read Lease from bytes")
return nil, remainder, err
}
lease = &l
log.WithFields(logrus.Fields{
"tunnel_id": lease.TunnelID(),
"expiration": lease.Date().Time(),
"remainder_length": len(remainder),
}).Debug("Successfully created Lease from bytes")
return
}

391
lib/common/lease/lease.svg Normal file
View File

@ -0,0 +1,391 @@
<?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="675pt" height="695pt"
viewBox="0.00 0.00 674.70 695.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 695)">
<title>gocallvis</title>
<polygon fill="#d3d3d3" stroke="transparent" points="0,0 0,-695 674.6972,-695 674.6972,0 0,0"/>
<g id="clust1" class="cluster">
<title>cluster_focus</title>
<polygon fill="#e6ecfa" stroke="#000000" stroke-width=".5" points="8,-8 8,-687 667.6972,-687 667.6972,-8 8,-8"/>
<text text-anchor="middle" x="337.8486" y="-666.8" font-family="Arial" font-size="18.00" fill="#000000">lease</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease</title>
<g id="a_clust6"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease">
<path fill="#b0c4de" stroke="#000000" stroke-width=".5" d="M436.3753,-424C436.3753,-424 506.8003,-424 506.8003,-424 512.8003,-424 518.8003,-430 518.8003,-436 518.8003,-436 518.8003,-551 518.8003,-551 518.8003,-557 512.8003,-563 506.8003,-563 506.8003,-563 436.3753,-563 436.3753,-563 430.3753,-563 424.3753,-557 424.3753,-551 424.3753,-551 424.3753,-436 424.3753,-436 424.3753,-430 430.3753,-424 436.3753,-424"/>
<text text-anchor="middle" x="471.5878" y="-432.5" font-family="Arial" font-size="15.00" fill="#222222">(Lease)</text>
</a>
</g>
</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="M599.6972,-424C599.6972,-424 647.6972,-424 647.6972,-424 653.6972,-424 659.6972,-430 659.6972,-436 659.6972,-436 659.6972,-490 659.6972,-490 659.6972,-496 653.6972,-502 647.6972,-502 647.6972,-502 599.6972,-502 599.6972,-502 593.6972,-502 587.6972,-496 587.6972,-490 587.6972,-490 587.6972,-436 587.6972,-436 587.6972,-430 593.6972,-424 599.6972,-424"/>
<text text-anchor="middle" x="623.6972" y="-432.5" font-family="Arial" font-size="15.00" fill="#222222">(Integer)</text>
</a>
</g>
</g>
<g id="clust4" class="cluster">
<title>cluster_github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date</title>
<g id="a_clust4"><a xlink:title="type: github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M448.5878,-285C448.5878,-285 494.5878,-285 494.5878,-285 500.5878,-285 506.5878,-291 506.5878,-297 506.5878,-297 506.5878,-351 506.5878,-351 506.5878,-357 500.5878,-363 494.5878,-363 494.5878,-363 448.5878,-363 448.5878,-363 442.5878,-363 436.5878,-357 436.5878,-351 436.5878,-351 436.5878,-297 436.5878,-297 436.5878,-291 442.5878,-285 448.5878,-285"/>
<text text-anchor="middle" x="471.5878" y="-293.5" font-family="Arial" font-size="15.00" fill="#222222">(Date)</text>
</a>
</g>
</g>
<g id="clust3" class="cluster">
<title>cluster_*github.com/sirupsen/logrus.Logger</title>
<g id="a_clust3"><a xlink:title="type: *github.com/sirupsen/logrus.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M444.9272,-571C444.9272,-571 499.2484,-571 499.2484,-571 505.2484,-571 511.2484,-577 511.2484,-583 511.2484,-583 511.2484,-637 511.2484,-637 511.2484,-643 505.2484,-649 499.2484,-649 499.2484,-649 444.9272,-649 444.9272,-649 438.9272,-649 432.9272,-643 432.9272,-637 432.9272,-637 432.9272,-583 432.9272,-583 432.9272,-577 438.9272,-571 444.9272,-571"/>
<text text-anchor="middle" x="472.0878" y="-579.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/logger.Logger</title>
<g id="a_clust2"><a xlink:title="type: *github.com/go&#45;i2p/logger.Logger">
<path fill="#eed8ae" stroke="#000000" stroke-width=".5" d="M432.4784,-16C432.4784,-16 510.6972,-16 510.6972,-16 516.6972,-16 522.6972,-22 522.6972,-28 522.6972,-28 522.6972,-265 522.6972,-265 522.6972,-271 516.6972,-277 510.6972,-277 510.6972,-277 432.4784,-277 432.4784,-277 426.4784,-277 420.4784,-271 420.4784,-265 420.4784,-265 420.4784,-28 420.4784,-28 420.4784,-22 426.4784,-16 432.4784,-16"/>
<text text-anchor="middle" x="471.5878" y="-24.5" font-family="Arial" font-size="15.00" fill="#222222">(*Logger)</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.init -->
<g id="node1" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.init</title>
<g id="a_node1"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.init | defined in .:0&#10;at lease.go:59: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="#add8e6" stroke="#000000" stroke-width=".5" d="M103.6445,-649C103.6445,-649 73.6445,-649 73.6445,-649 67.6445,-649 61.6445,-643 61.6445,-637 61.6445,-637 61.6445,-625 61.6445,-625 61.6445,-619 67.6445,-613 73.6445,-613 73.6445,-613 103.6445,-613 103.6445,-613 109.6445,-613 115.6445,-619 115.6445,-625 115.6445,-625 115.6445,-637 115.6445,-637 115.6445,-643 109.6445,-649 103.6445,-649"/>
<text text-anchor="middle" x="88.6445" y="-626.8" font-family="Verdana" font-size="14.00" fill="#000000">init</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="node2" class="node">
<title>github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_node2"><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="M343.5732,-649C343.5732,-649 246.1942,-649 246.1942,-649 240.1942,-649 234.1942,-643 234.1942,-637 234.1942,-637 234.1942,-625 234.1942,-625 234.1942,-619 240.1942,-613 246.1942,-613 246.1942,-613 343.5732,-613 343.5732,-613 349.5732,-613 355.5732,-619 355.5732,-625 355.5732,-625 355.5732,-637 355.5732,-637 355.5732,-643 349.5732,-649 343.5732,-649"/>
<text text-anchor="middle" x="294.8837" y="-635.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="294.8837" y="-618.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/lease.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger -->
<g id="edge15" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.init&#45;&gt;github.com/go&#45;i2p/logger.GetGoI2PLogger</title>
<g id="a_edge15"><a xlink:title="at lease.go:59: calling [github.com/go&#45;i2p/logger.GetGoI2PLogger]">
<path fill="none" stroke="#8b4513" d="M116.0315,-631C143.3741,-631 186.5488,-631 223.628,-631"/>
<polygon fill="#8b4513" stroke="#8b4513" points="223.9065,-634.5001 233.9064,-631 223.9064,-627.5001 223.9065,-634.5001"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLease -->
<g id="node3" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLease</title>
<g id="a_node3"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLease | defined in lease.go:111&#10;at lease.go:130: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at lease.go:112: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:133: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M324.4525,-560C324.4525,-560 265.3149,-560 265.3149,-560 259.3149,-560 253.3149,-554 253.3149,-548 253.3149,-548 253.3149,-536 253.3149,-536 253.3149,-530 259.3149,-524 265.3149,-524 265.3149,-524 324.4525,-524 324.4525,-524 330.4525,-524 336.4525,-530 336.4525,-536 336.4525,-536 336.4525,-548 336.4525,-548 336.4525,-554 330.4525,-560 324.4525,-560"/>
<text text-anchor="middle" x="294.8837" y="-537.8" font-family="Verdana" font-size="14.00" fill="#000000">NewLease</text>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="node7" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_node7"><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="M502.8069,-269C502.8069,-269 440.3687,-269 440.3687,-269 434.3687,-269 428.3687,-263 428.3687,-257 428.3687,-257 428.3687,-245 428.3687,-245 428.3687,-239 434.3687,-233 440.3687,-233 440.3687,-233 502.8069,-233 502.8069,-233 508.8069,-233 514.8069,-239 514.8069,-245 514.8069,-245 514.8069,-257 514.8069,-257 514.8069,-263 508.8069,-269 502.8069,-269"/>
<text text-anchor="middle" x="471.5878" y="-255.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="471.5878" y="-238.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/lease.NewLease&#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/lease.NewLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge10"><a xlink:title="at lease.go:130: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M302.7566,-523.8891C327.3124,-467.6446 401.9637,-298.575 420.4784,-279 421.6733,-277.7366 422.9382,-276.5167 424.2582,-275.3401"/>
<polygon fill="#8b4513" stroke="#8b4513" points="426.572,-277.9746 432.3185,-269.0735 422.2754,-272.4482 426.572,-277.9746"/>
</a>
</g>
</g>
<!-- (*github.com/sirupsen/logrus.Logger).Debug -->
<g id="node11" class="node">
<title>(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_node11"><a xlink:title="(*github.com/sirupsen/logrus.Logger).Debug | defined in logger.go:221">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M490.4098,-641C490.4098,-641 452.7658,-641 452.7658,-641 446.7658,-641 440.7658,-635 440.7658,-629 440.7658,-629 440.7658,-617 440.7658,-617 440.7658,-611 446.7658,-605 452.7658,-605 452.7658,-605 490.4098,-605 490.4098,-605 496.4098,-605 502.4098,-611 502.4098,-617 502.4098,-617 502.4098,-629 502.4098,-629 502.4098,-635 496.4098,-641 490.4098,-641"/>
<text text-anchor="middle" x="471.5878" y="-627.2" font-family="Verdana" font-size="14.00" fill="#000000">logrus</text>
<text text-anchor="middle" x="471.5878" y="-610.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/lease.NewLease&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge19" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLease&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge19"><a xlink:title="at lease.go:112: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:133: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M334.5395,-560.178C363.4283,-573.4204 402.4181,-591.293 431.4242,-604.5893"/>
<polygon fill="#8b4513" stroke="#8b4513" points="430.3004,-607.9243 440.8493,-608.9097 433.2173,-601.561 430.3004,-607.9243"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease -->
<g id="node4" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease</title>
<g id="a_node4"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease | defined in lease.go:86&#10;at lease.go:87: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:105: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:94: calling [(*github.com/go&#45;i2p/logger.Logger).Error]&#10;at lease.go:102: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID]&#10;at lease.go:90: calling [github.com/samber/oops.Errorf]&#10;at lease.go:91: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at lease.go:101: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at lease.go:87: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]&#10;at lease.go:103: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time]&#10;at lease.go:103: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M325.7915,-387C325.7915,-387 263.9759,-387 263.9759,-387 257.9759,-387 251.9759,-381 251.9759,-375 251.9759,-375 251.9759,-363 251.9759,-363 251.9759,-357 257.9759,-351 263.9759,-351 263.9759,-351 325.7915,-351 325.7915,-351 331.7915,-351 337.7915,-357 337.7915,-363 337.7915,-363 337.7915,-375 337.7915,-375 337.7915,-381 331.7915,-387 325.7915,-387"/>
<text text-anchor="middle" x="294.8837" y="-364.8" font-family="Verdana" font-size="14.00" fill="#000000">ReadLease</text>
</a>
</g>
</g>
<!-- github.com/samber/oops.Errorf -->
<g id="node5" class="node">
<title>github.com/samber/oops.Errorf</title>
<g id="a_node5"><a xlink:title="github.com/samber/oops.Errorf | defined in oops.go:34">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M488.7831,-416C488.7831,-416 454.3925,-416 454.3925,-416 448.3925,-416 442.3925,-410 442.3925,-404 442.3925,-404 442.3925,-392 442.3925,-392 442.3925,-386 448.3925,-380 454.3925,-380 454.3925,-380 488.7831,-380 488.7831,-380 494.7831,-380 500.7831,-386 500.7831,-392 500.7831,-392 500.7831,-404 500.7831,-404 500.7831,-410 494.7831,-416 488.7831,-416"/>
<text text-anchor="middle" x="471.5878" y="-402.2" font-family="Verdana" font-size="14.00" fill="#000000">oops</text>
<text text-anchor="middle" x="471.5878" y="-385.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/lease.ReadLease&#45;&gt;github.com/samber/oops.Errorf -->
<g id="edge11" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;github.com/samber/oops.Errorf</title>
<g id="a_edge11"><a xlink:title="at lease.go:90: calling [github.com/samber/oops.Errorf]">
<path fill="none" stroke="#8b4513" d="M337.6588,-376.0201C366.587,-380.7677 404.4919,-386.9885 432.5907,-391.5999"/>
<polygon fill="#8b4513" stroke="#8b4513" points="432.0296,-395.0546 442.4644,-393.2204 433.1633,-388.147 432.0296,-395.0546"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#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/lease.ReadLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge12"><a xlink:title="at lease.go:91: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at lease.go:101: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M318.3701,-350.8669C343.1701,-332.0326 383.6938,-302.138 420.4784,-279 423.0503,-277.3822 425.7221,-275.7587 428.4351,-274.153"/>
<polygon fill="#8b4513" stroke="#8b4513" points="430.2552,-277.1437 437.1676,-269.1144 426.7568,-271.0806 430.2552,-277.1437"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithField -->
<g id="node8" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithField</title>
<g id="a_node8"><a xlink:title="(*github.com/go&#45;i2p/logger.Logger).WithField | defined in log.go:54">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M499.8623,-208C499.8623,-208 443.3133,-208 443.3133,-208 437.3133,-208 431.3133,-202 431.3133,-196 431.3133,-196 431.3133,-184 431.3133,-184 431.3133,-178 437.3133,-172 443.3133,-172 443.3133,-172 499.8623,-172 499.8623,-172 505.8623,-172 511.8623,-178 511.8623,-184 511.8623,-184 511.8623,-196 511.8623,-196 511.8623,-202 505.8623,-208 499.8623,-208"/>
<text text-anchor="middle" x="471.5878" y="-194.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="471.5878" y="-177.4" font-family="Verdana" font-size="14.00" fill="#000000">WithField</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField -->
<g id="edge16" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField</title>
<g id="a_edge16"><a xlink:title="at lease.go:87: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]">
<path fill="none" stroke="#8b4513" d="M307.2224,-350.978C328.0967,-321.3722 372.7872,-261.6747 420.4784,-221 423.4579,-218.4588 426.6695,-215.9933 429.98,-213.6363"/>
<polygon fill="#8b4513" stroke="#8b4513" points="431.9897,-216.5027 438.337,-208.0196 428.085,-210.6929 431.9897,-216.5027"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="node9" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_node9"><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="M489.3541,-147C489.3541,-147 453.8215,-147 453.8215,-147 447.8215,-147 441.8215,-141 441.8215,-135 441.8215,-135 441.8215,-123 441.8215,-123 441.8215,-117 447.8215,-111 453.8215,-111 453.8215,-111 489.3541,-111 489.3541,-111 495.3541,-111 501.3541,-117 501.3541,-123 501.3541,-123 501.3541,-135 501.3541,-135 501.3541,-141 495.3541,-147 489.3541,-147"/>
<text text-anchor="middle" x="471.5878" y="-133.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="471.5878" y="-116.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/lease.ReadLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge5" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge5"><a xlink:title="at lease.go:94: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M302.195,-350.8225C318.5463,-311.936 361.3321,-219.39 420.4784,-160 424.323,-156.1395 428.7403,-152.5587 433.3336,-149.3051"/>
<polygon fill="#8b4513" stroke="#8b4513" points="435.2645,-152.2244 441.706,-143.8125 431.4248,-146.3714 435.2645,-152.2244"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge4" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge4"><a xlink:title="at lease.go:87: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:105: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M304.6883,-387.1684C324.5082,-423.266 371.6272,-505.9674 420.4784,-569 428.062,-578.7851 437.1367,-588.8175 445.5209,-597.5385"/>
<polygon fill="#8b4513" stroke="#8b4513" points="443.1592,-600.1293 452.6562,-604.8257 448.1608,-595.2319 443.1592,-600.1293"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time -->
<g id="node12" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time</title>
<g id="a_node12"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time | defined in date.go:47">
<path fill="#ffe4b5" stroke="#000000" stroke-width="1.5" d="M486.5878,-355C486.5878,-355 456.5878,-355 456.5878,-355 450.5878,-355 444.5878,-349 444.5878,-343 444.5878,-343 444.5878,-331 444.5878,-331 444.5878,-325 450.5878,-319 456.5878,-319 456.5878,-319 486.5878,-319 486.5878,-319 492.5878,-319 498.5878,-325 498.5878,-331 498.5878,-331 498.5878,-343 498.5878,-343 498.5878,-349 492.5878,-355 486.5878,-355"/>
<text text-anchor="middle" x="471.5878" y="-341.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="471.5878" y="-324.4" font-family="Verdana" font-size="14.00" fill="#000000">Time</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time -->
<g id="edge17" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time</title>
<g id="a_edge17"><a xlink:title="at lease.go:103: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time]">
<path fill="none" stroke="#8b4513" d="M337.6588,-361.2537C367.2238,-355.8997 406.165,-348.8477 434.4318,-343.7287"/>
<polygon fill="#8b4513" stroke="#8b4513" points="435.1096,-347.163 444.3258,-341.937 433.8621,-340.275 435.1096,-347.163"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID -->
<g id="node14" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID</title>
<g id="a_node14"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID | defined in lease.go:70&#10;at lease.go:73: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M499.014,-494C499.014,-494 444.1616,-494 444.1616,-494 438.1616,-494 432.1616,-488 432.1616,-482 432.1616,-482 432.1616,-470 432.1616,-470 432.1616,-464 438.1616,-458 444.1616,-458 444.1616,-458 499.014,-458 499.014,-458 505.014,-458 511.014,-464 511.014,-470 511.014,-470 511.014,-482 511.014,-482 511.014,-488 505.014,-494 499.014,-494"/>
<text text-anchor="middle" x="471.5878" y="-471.8" font-family="Verdana" font-size="14.00" fill="#000000">TunnelID</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID -->
<g id="edge7" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID</title>
<g id="a_edge7"><a xlink:title="at lease.go:102: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID]">
<path fill="none" stroke="#000000" d="M331.0643,-387.2334C350.0917,-397.5256 373.3679,-411.2598 392.4784,-426 406.4138,-436.7486 405.913,-444.1219 420.4784,-454 421.3978,-454.6235 422.3378,-455.2355 423.2946,-455.8356"/>
<polygon fill="#000000" stroke="#000000" points="421.8337,-459.0304 432.2603,-460.9108 425.2821,-452.9387 421.8337,-459.0304"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date -->
<g id="node15" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date</title>
<g id="a_node15"><a xlink:title="(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date | defined in lease.go:78">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M486.5878,-555C486.5878,-555 456.5878,-555 456.5878,-555 450.5878,-555 444.5878,-549 444.5878,-543 444.5878,-543 444.5878,-531 444.5878,-531 444.5878,-525 450.5878,-519 456.5878,-519 456.5878,-519 486.5878,-519 486.5878,-519 492.5878,-519 498.5878,-525 498.5878,-531 498.5878,-531 498.5878,-543 498.5878,-543 498.5878,-549 492.5878,-555 486.5878,-555"/>
<text text-anchor="middle" x="471.5878" y="-532.8" font-family="Verdana" font-size="14.00" fill="#000000">Date</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date -->
<g id="edge20" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date</title>
<g id="a_edge20"><a xlink:title="at lease.go:103: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date]">
<path fill="none" stroke="#000000" d="M310.1973,-387.1448C338.0609,-419.931 396.3908,-487.4572 420.4784,-507 425.1874,-510.8206 430.4372,-514.472 435.7291,-517.8298"/>
<polygon fill="#000000" stroke="#000000" points="434.2176,-521.0058 444.5867,-523.1814 437.8375,-515.0144 434.2176,-521.0058"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes -->
<g id="node6" class="node">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes</title>
<g id="a_node6"><a xlink:title="github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes | defined in lease.go:140&#10;at lease.go:153: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID]&#10;at lease.go:154: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date]&#10;at lease.go:152: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]&#10;at lease.go:144: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease]&#10;at lease.go:154: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time]&#10;at lease.go:141: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:156: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]&#10;at lease.go:141: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]&#10;at lease.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="#add8e6" stroke="#000000" stroke-width="1.5" d="M149.4338,-343C149.4338,-343 27.8552,-343 27.8552,-343 21.8552,-343 15.8552,-337 15.8552,-331 15.8552,-331 15.8552,-319 15.8552,-319 15.8552,-313 21.8552,-307 27.8552,-307 27.8552,-307 149.4338,-307 149.4338,-307 155.4338,-307 161.4338,-313 161.4338,-319 161.4338,-319 161.4338,-331 161.4338,-331 161.4338,-337 155.4338,-343 149.4338,-343"/>
<text text-anchor="middle" x="88.6445" y="-320.8" font-family="Verdana" font-size="14.00" fill="#000000">NewLeaseFromBytes</text>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease -->
<g id="edge8" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease</title>
<g id="a_edge8"><a xlink:title="at lease.go:144: calling [github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.ReadLease]">
<path fill="none" stroke="#000000" d="M161.3567,-340.5128C187.96,-346.1884 217.5285,-352.4967 242.065,-357.7314"/>
<polygon fill="#000000" stroke="#000000" points="241.3891,-361.1659 251.8993,-359.8295 242.8497,-354.32 241.3891,-361.1659"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields -->
<g id="edge3" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithFields</title>
<g id="a_edge3"><a xlink:title="at lease.go:152: calling [(*github.com/go&#45;i2p/logger.Logger).WithFields]">
<path fill="none" stroke="#8b4513" d="M161.5746,-310.907C236.6049,-296.4081 351.6733,-274.1723 418.4891,-261.2608"/>
<polygon fill="#8b4513" stroke="#8b4513" points="419.2313,-264.6822 428.3856,-259.3484 417.9032,-257.8093 419.2313,-264.6822"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField -->
<g id="edge18" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithField</title>
<g id="a_edge18"><a xlink:title="at lease.go:141: calling [(*github.com/go&#45;i2p/logger.Logger).WithField]">
<path fill="none" stroke="#8b4513" d="M131.6983,-306.9985C160.5438,-295.1498 199.4725,-279.5661 234.289,-267 298.3208,-243.8894 373.1745,-220.1322 421.4259,-205.2336"/>
<polygon fill="#8b4513" stroke="#8b4513" points="422.4801,-208.5713 431.0074,-202.2837 420.4203,-201.8812 422.4801,-208.5713"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error -->
<g id="edge21" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).Error</title>
<g id="a_edge21"><a xlink:title="at lease.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).Error]">
<path fill="none" stroke="#8b4513" d="M110.1613,-306.7367C137.5881,-284.1253 187.1201,-245.4882 234.289,-220 300.4279,-184.2611 383.6425,-155.7852 431.9066,-140.7353"/>
<polygon fill="#8b4513" stroke="#8b4513" points="433.1312,-144.0204 441.6564,-137.7298 431.0691,-137.331 433.1312,-144.0204"/>
</a>
</g>
</g>
<!-- (*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="node10" class="node">
<title>(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_node10"><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="M500.1193,-86C500.1193,-86 443.0563,-86 443.0563,-86 437.0563,-86 431.0563,-80 431.0563,-74 431.0563,-74 431.0563,-62 431.0563,-62 431.0563,-56 437.0563,-50 443.0563,-50 443.0563,-50 500.1193,-50 500.1193,-50 506.1193,-50 512.1193,-56 512.1193,-62 512.1193,-62 512.1193,-74 512.1193,-74 512.1193,-80 506.1193,-86 500.1193,-86"/>
<text text-anchor="middle" x="471.5878" y="-72.2" font-family="Verdana" font-size="14.00" fill="#000000">logger</text>
<text text-anchor="middle" x="471.5878" y="-55.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/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError -->
<g id="edge14" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/go&#45;i2p/logger.Logger).WithError</title>
<g id="a_edge14"><a xlink:title="at lease.go:146: calling [(*github.com/go&#45;i2p/logger.Logger).WithError]">
<path fill="none" stroke="#8b4513" d="M100.3322,-306.9586C122.6518,-273.7923 174.4797,-202.7183 234.289,-161 292.4697,-120.4177 370.8398,-94.1922 421.2975,-80.2568"/>
<polygon fill="#8b4513" stroke="#8b4513" points="422.2627,-83.6217 431.0026,-77.633 420.4357,-76.8642 422.2627,-83.6217"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug -->
<g id="edge13" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(*github.com/sirupsen/logrus.Logger).Debug</title>
<g id="a_edge13"><a xlink:title="at lease.go:141: calling [(*github.com/sirupsen/logrus.Logger).Debug]&#10;at lease.go:156: calling [(*github.com/sirupsen/logrus.Logger).Debug]">
<path fill="none" stroke="#8b4513" d="M93.688,-343.148C107.5783,-389.5488 151.0006,-513.0699 234.289,-573 242.2772,-578.7479 365.2091,-602.7768 430.9004,-615.3129"/>
<polygon fill="#8b4513" stroke="#8b4513" points="430.4474,-618.7895 440.9256,-617.2217 431.7567,-611.913 430.4474,-618.7895"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time -->
<g id="edge9" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time</title>
<g id="a_edge9"><a xlink:title="at lease.go:154: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Date).Time]">
<path fill="none" stroke="#8b4513" d="M161.5746,-327.2854C242.8097,-329.831 370.9788,-333.8473 434.0257,-335.8229"/>
<polygon fill="#8b4513" stroke="#8b4513" points="434.1875,-339.3296 444.2922,-336.1447 434.4068,-332.3331 434.1875,-339.3296"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID -->
<g id="edge1" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID</title>
<g id="a_edge1"><a xlink:title="at lease.go:153: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID]">
<path fill="none" stroke="#000000" d="M120.0301,-343.0897C149.0494,-359.3469 193.693,-383.1825 234.289,-400 297.7185,-426.2766 373.7071,-449.1832 422.303,-462.7987"/>
<polygon fill="#000000" stroke="#000000" points="421.6706,-466.2555 432.2426,-465.561 423.5449,-459.5111 421.6706,-466.2555"/>
</a>
</g>
</g>
<!-- github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date -->
<g id="edge2" class="edge">
<title>github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.NewLeaseFromBytes&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date</title>
<g id="a_edge2"><a xlink:title="at lease.go:154: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).Date]">
<path fill="none" stroke="#000000" d="M111.4694,-343.1579C139.4194,-364.9089 188.6801,-401.7 234.289,-428 302.488,-467.3264 387.3499,-503.4535 434.8903,-522.6271"/>
<polygon fill="#000000" stroke="#000000" points="433.8645,-525.9865 444.449,-526.4562 436.4676,-519.4885 433.8645,-525.9865"/>
</a>
</g>
</g>
<!-- (github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="node13" class="node">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_node13"><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="M638.6972,-494C638.6972,-494 608.6972,-494 608.6972,-494 602.6972,-494 596.6972,-488 596.6972,-482 596.6972,-482 596.6972,-470 596.6972,-470 596.6972,-464 602.6972,-458 608.6972,-458 608.6972,-458 638.6972,-458 638.6972,-458 644.6972,-458 650.6972,-464 650.6972,-470 650.6972,-470 650.6972,-482 650.6972,-482 650.6972,-488 644.6972,-494 638.6972,-494"/>
<text text-anchor="middle" x="623.6972" y="-480.2" font-family="Verdana" font-size="14.00" fill="#000000">data</text>
<text text-anchor="middle" x="623.6972" y="-463.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/lease.Lease).TunnelID&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int -->
<g id="edge6" class="edge">
<title>(github.com/go&#45;i2p/go&#45;i2p/lib/common/lease.Lease).TunnelID&#45;&gt;(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int</title>
<g id="a_edge6"><a xlink:title="at lease.go:73: calling [(github.com/go&#45;i2p/go&#45;i2p/lib/common/data.Integer).Int]">
<path fill="none" stroke="#8b4513" d="M511.1557,-476C534.257,-476 563.2443,-476 586.0141,-476"/>
<polygon fill="#8b4513" stroke="#8b4513" points="586.3165,-479.5001 596.3164,-476 586.3164,-472.5001 586.3165,-479.5001"/>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,52 @@
package lease
import (
"testing"
"github.com/stretchr/testify/assert"
. "github.com/go-i2p/go-i2p/lib/common/data"
)
func TestTunnelGateway(t *testing.T) {
assert := assert.New(t)
expectedTunnelGatewayBytes := []byte("example_32_bytes_hash_to_test_00")
var lease_bytes []byte
lease_bytes = append(lease_bytes, expectedTunnelGatewayBytes...)
lease_bytes = append(lease_bytes, make([]byte, LEASE_SIZE-LEASE_TUNNEL_GW_SIZE)...)
lease := Lease(lease_bytes)
tunnelGateway := lease.TunnelGateway()
assert.ElementsMatch(tunnelGateway.Bytes(), expectedTunnelGatewayBytes)
}
func TestTunnelID(t *testing.T) {
assert := assert.New(t)
expectedTunnelIDBytes := []byte{0x21, 0x37, 0x31, 0x33}
var lease_bytes []byte
lease_bytes = append(lease_bytes, make([]byte, LEASE_TUNNEL_GW_SIZE)...)
lease_bytes = append(lease_bytes, expectedTunnelIDBytes...)
lease_bytes = append(lease_bytes, make([]byte, LEASE_SIZE-LEASE_TUNNEL_ID_SIZE-LEASE_TUNNEL_GW_SIZE)...)
lease := Lease(lease_bytes)
tunnelID := lease.TunnelID()
assert.Equal(tunnelID, uint32(Integer(expectedTunnelIDBytes).Int()))
}
func TestDate(t *testing.T) {
assert := assert.New(t)
expectedDateBytes := []byte{0x21, 0x37, 0x31, 0x33, 0x16, 0x93, 0x13, 0x28}
var lease_bytes []byte
lease_bytes = append(lease_bytes, make([]byte, LEASE_TUNNEL_GW_SIZE+LEASE_TUNNEL_ID_SIZE)...)
lease_bytes = append(lease_bytes, expectedDateBytes...)
lease := Lease(lease_bytes)
date := lease.Date()
assert.ElementsMatch(date.Bytes(), expectedDateBytes)
}

View File

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

View File

@ -2,19 +2,27 @@
package lease_set
import (
"errors"
"fmt"
. "github.com/go-i2p/go-i2p/lib/common/certificate"
. "github.com/go-i2p/go-i2p/lib/common/data"
. "github.com/go-i2p/go-i2p/lib/common/destination"
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
. "github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
. "github.com/go-i2p/go-i2p/lib/common/lease"
. "github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/go-i2p/go-i2p/lib/crypto"
log "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/common/destination"
"github.com/go-i2p/go-i2p/lib/common/key_certificate"
"github.com/go-i2p/go-i2p/lib/common/lease"
"github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/go-i2p/go-i2p/lib/crypto/dsa"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/samber/oops"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
"github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
)
var log = logger.GetGoI2PLogger()
// Sizes of various structures in an I2P LeaseSet
const (
LEASE_SET_PUBKEY_SIZE = 256
@ -28,13 +36,13 @@ Accurate for version 0.9.49
Description
Contains all of the currently authorized Leases for a particular Destination, the
PublicKey to which garlic messages can be encrypted, and then the SigningPublicKey
publicKey to which garlic messages can be encrypted, and then the signingPublicKey
that can be used to revoke this particular version of the structure. The LeaseSet is one
of the two structures stored in the network database (the other being RouterInfo), and
is kered under the SHA256 of the contained Destination.
Contents
Destination, followed by a PublicKey for encryption, then a SigningPublicKey which
Destination, followed by a publicKey for encryption, then a signingPublicKey which
can be used to revoke this version of the LeaseSet, then a 1 byte Integer specifying how
many Lease structures are in the set, followed by the actual Lease structures and
finally a Signature of the previous bytes signed by the Destination's SigningPrivateKey.
@ -96,10 +104,10 @@ finally a Signature of the previous bytes signed by the Destination's SigningPri
destination :: Destination
length -> >= 387 bytes
encryption_key :: PublicKey
encryption_key :: publicKey
length -> 256 bytes
signing_key :: SigningPublicKey
signing_key :: signingPublicKey
length -> 128 bytes or as specified in destination's key certificate
num :: Integer
@ -130,84 +138,171 @@ type LeaseSet struct {
}
*/
func (lease_set LeaseSet) Bytes() ([]byte, error) {
return []byte(lease_set), nil
}
// Destination returns the Destination as []byte.
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
keys_and_cert, _, err := NewKeysAndCert(lease_set)
func (lease_set LeaseSet) Destination() (dest destination.Destination, err error) {
keys_and_cert, _, err := keys_and_cert.ReadKeysAndCertElgAndEd25519(lease_set)
if err != nil {
log.WithError(err).Error("Failed to read KeysAndCert from LeaseSet")
return
}
destination, _, err = ReadDestination(keys_and_cert.Bytes())
dest, _, err = destination.ReadDestination(keys_and_cert.Bytes())
if err != nil {
log.WithError(err).Error("Failed to read Destination from KeysAndCert")
} else {
log.Debug("Successfully retrieved Destination from LeaseSet")
}
return
}
func (lease_set LeaseSet) DestinationDeux() (dest destination.Destination, err error) {
data := lease_set
fmt.Printf("Starting DestinationDeux, lease_set_length=%d\n", len(data))
// Read the Destination (KeysAndCert) from the LeaseSet
dest, remainder, err := ReadDestinationFromLeaseSet(data)
if err != nil {
fmt.Printf("Failed to read Destination from LeaseSet: %v\n", err)
return
}
fmt.Printf("Successfully retrieved Destination from LeaseSet\n")
fmt.Printf(" destination_length: %d\n", len(data)-len(remainder))
fmt.Printf(" remainder_length: %d\n", len(remainder))
return
}
func ReadDestinationFromLeaseSet(data []byte) (dest destination.Destination, remainder []byte, err error) {
fmt.Printf("Reading Destination from LeaseSet, input_length=%d\n", len(data))
if len(data) < 387 { // Minimum size of Destination (384 keys + 3 bytes for minimum certificate)
err = oops.Errorf("LeaseSet data too short to contain Destination")
fmt.Printf("Error: %v\n", err)
return
}
certDataStart := 384
certData := data[certDataStart:]
cert, _, err := certificate.ReadCertificate(certData)
if err != nil {
fmt.Printf("Failed to read Certificate from LeaseSet: %v\n", err)
return
}
certTotalLength := 3 + int(cert.Length())
destinationLength := certDataStart + certTotalLength
fmt.Printf("Certificate details:\n")
fmt.Printf(" certType: %d\n", cert.Type())
fmt.Printf(" certLength: %d\n", cert.Length())
fmt.Printf(" certTotalLength: %d\n", certTotalLength)
fmt.Printf(" destinationLength: %d\n", destinationLength)
if len(data) < destinationLength {
err = oops.Errorf("LeaseSet data too short to contain full Destination")
fmt.Printf("Error: %v\n", err)
return
}
destinationData := data[:destinationLength]
keysAndCert, _, err := keys_and_cert.ReadKeysAndCert(destinationData)
if err != nil {
fmt.Printf("Failed to read KeysAndCert: %v\n", err) // 32 / 0 error
return
}
dest = destination.Destination{
KeysAndCert: keysAndCert,
}
remainder = data[destinationLength:]
return
}
// PublicKey returns the public key as crypto.ElgPublicKey.
// Returns errors encountered during parsing.
func (lease_set LeaseSet) PublicKey() (public_key crypto.ElgPublicKey, err error) {
_, remainder, err := NewKeysAndCert(lease_set)
func (lease_set LeaseSet) PublicKey() (public_key elgamal.ElgPublicKey, err error) {
_, remainder, err := keys_and_cert.ReadKeysAndCert(lease_set)
remainder_len := len(remainder)
if remainder_len < LEASE_SET_PUBKEY_SIZE {
log.WithFields(log.Fields{
"at": "(LeaseSet) PublicKey",
"data_len": remainder_len,
"required_len": LEASE_SET_PUBKEY_SIZE,
"reason": "not enough data",
}).Error("error parsing public key")
err = errors.New("error parsing public key: not enough data")
err = oops.Errorf("error parsing public key: not enough data")
copy(public_key[:], remainder)
return
}
copy(public_key[:], remainder[:LEASE_SET_PUBKEY_SIZE])
log.Debug("Successfully retrieved publicKey from LeaseSet")
return
}
// SigningKey returns the signing public key as crypto.SigningPublicKey.
// returns errors encountered during parsing.
func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicKey, err error) {
func (lease_set LeaseSet) SigningKey() (signing_public_key types.SigningPublicKey, err error) {
log.Debug("Retrieving SigningKey from LeaseSet")
destination, err := lease_set.Destination()
if err != nil {
log.WithError(err).Error("Failed to retrieve Destination for SigningKey")
return
}
offset := len(destination.Bytes()) + LEASE_SET_PUBKEY_SIZE
cert := destination.Certificate()
cert_len := cert.Length()
if err != nil {
log.WithError(err).Error("Failed to get Certificate length")
return
}
lease_set_len := len(lease_set)
if lease_set_len < offset+LEASE_SET_SPK_SIZE {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(LeaseSet) SigningKey",
"data_len": lease_set_len,
"required_len": offset + LEASE_SET_SPK_SIZE,
"reason": "not enough data",
}).Error("error parsing signing public key")
err = errors.New("error parsing signing public key: not enough data")
err = oops.Errorf("error parsing signing public key: not enough data")
return
}
if cert_len == 0 {
// No Certificate is present, return the LEASE_SET_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
var dsa_pk crypto.DSAPublicKey
// signingPublicKey space as legacy DSA SHA1 signingPublicKey.
var dsa_pk dsa.DSAPublicKey
copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE])
signing_public_key = dsa_pk
log.Debug("Retrieved legacy DSA SHA1 signingPublicKey")
} else {
// A Certificate is present in this LeaseSet's Destination
cert_type := cert.Type()
if cert_type == CERT_KEY {
if cert_type == certificate.CERT_KEY {
// This LeaseSet's Destination's Certificate is a Key Certificate,
// create the signing publickey key using any data that might be
// contained in the key certificate.
signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey(
keyCert, err := key_certificate.KeyCertificateFromCertificate(cert)
if err != nil {
log.WithError(err).Error("Failed to create keyCert")
}
signing_public_key, err = keyCert.ConstructSigningPublicKey(
lease_set[offset : offset+LEASE_SET_SPK_SIZE],
)
if err != nil {
log.WithError(err).Error("Failed to construct signingPublicKey from keyCertificate")
} else {
log.Debug("Retrieved signingPublicKey from keyCertificate")
}
} else {
// No Certificate is present, return the LEASE_SET_SPK_SIZE byte
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
var dsa_pk crypto.DSAPublicKey
// signingPublicKey space as legacy DSA SHA1 signingPublicKey.
var dsa_pk dsa.DSAPublicKey
copy(dsa_pk[:], lease_set[offset:offset+LEASE_SET_SPK_SIZE])
signing_public_key = dsa_pk
log.Debug("Retrieved legacy DSA SHA1 signingPublicKey (Certificate present but not Key Certificate)")
}
}
return
}
@ -215,108 +310,125 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK
// LeaseCount returns the numbert of leases specified by the LeaseCount value as int.
// returns errors encountered during parsing.
func (lease_set LeaseSet) LeaseCount() (count int, err error) {
_, remainder, err := NewKeysAndCert(lease_set)
log.Debug("Retrieving LeaseCount from LeaseSet")
_, remainder, err := keys_and_cert.ReadKeysAndCert(lease_set)
if err != nil {
log.WithError(err).Error("Failed to read KeysAndCert for LeaseCount")
return
}
remainder_len := len(remainder)
if remainder_len < LEASE_SET_PUBKEY_SIZE+LEASE_SET_SPK_SIZE+1 {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(LeaseSet) LeaseCount",
"data_len": remainder_len,
"required_len": LEASE_SET_PUBKEY_SIZE + LEASE_SET_SPK_SIZE + 1,
"reason": "not enough data",
}).Error("error parsing lease count")
err = errors.New("error parsing lease count: not enough data")
err = oops.Errorf("error parsing lease count: not enough data")
return
}
c := Integer([]byte{remainder[LEASE_SET_PUBKEY_SIZE+LEASE_SET_SPK_SIZE]})
c := data.Integer([]byte{remainder[LEASE_SET_PUBKEY_SIZE+LEASE_SET_SPK_SIZE]})
count = c.Int()
if count > 16 {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(LeaseSet) LeaseCount",
"lease_count": count,
"reason": "more than 16 leases",
}).Warn("invalid lease set")
err = errors.New("invalid lease set: more than 16 leases")
err = oops.Errorf("invalid lease set: more than 16 leases")
} else {
log.WithField("lease_count", count).Debug("Retrieved LeaseCount from LeaseSet")
}
return
}
// Leases returns the leases as []Lease.
// returns errors encountered during parsing.
func (lease_set LeaseSet) Leases() (leases []Lease, err error) {
func (lease_set LeaseSet) Leases() (leases []lease.Lease, err error) {
log.Debug("Retrieving Leases from LeaseSet")
destination, err := lease_set.Destination()
if err != nil {
log.WithError(err).Error("Failed to retrieve Destination for Leases")
return
}
offset := len(destination.Bytes()) + LEASE_SET_PUBKEY_SIZE + LEASE_SET_SPK_SIZE + 1
count, err := lease_set.LeaseCount()
if err != nil {
log.WithError(err).Error("Failed to retrieve LeaseCount for Leases")
return
}
for i := 0; i < count; i++ {
start := offset + (i * LEASE_SIZE)
end := start + LEASE_SIZE
start := offset + (i * lease.LEASE_SIZE)
end := start + lease.LEASE_SIZE
lease_set_len := len(lease_set)
if lease_set_len < end {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(LeaseSet) Leases",
"data_len": lease_set_len,
"required_len": end,
"reason": "some leases missing",
}).Error("error parsnig lease set")
err = errors.New("error parsing lease set: some leases missing")
err = oops.Errorf("error parsing lease set: some leases missing")
return
}
var lease Lease
var lease lease.Lease
copy(lease[:], lease_set[start:end])
leases = append(leases, lease)
}
log.WithField("lease_count", len(leases)).Debug("Retrieved Leases from LeaseSet")
return
}
// Signature returns the signature as Signature.
// returns errors encountered during parsing.
func (lease_set LeaseSet) Signature() (signature Signature, err error) {
func (lease_set LeaseSet) Signature() (signature signature.Signature, err error) {
log.Debug("Retrieving Signature from LeaseSet")
destination, err := lease_set.Destination()
if err != nil {
log.WithError(err).Error("Failed to retrieve Destination for Signature")
return
}
lease_count, err := lease_set.LeaseCount()
if err != nil {
log.WithError(err).Error("Failed to retrieve LeaseCount for Signature")
return
}
start := len(destination.Bytes()) +
LEASE_SET_PUBKEY_SIZE +
LEASE_SET_SPK_SIZE +
1 +
(LEASE_SIZE * lease_count)
(lease.LEASE_SIZE * lease_count)
cert := destination.Certificate()
cert_type := cert.Type()
var end int
if cert_type == CERT_KEY {
end = start + KeyCertificateFromCertificate(cert).SignatureSize()
if cert_type == certificate.CERT_KEY {
keyCert, err := key_certificate.KeyCertificateFromCertificate(cert)
if err != nil {
log.WithError(err).Error("Failed to create keyCert")
}
end = start + keyCert.SignatureSize()
} else {
end = start + LEASE_SET_SIG_SIZE
}
lease_set_len := len(lease_set)
if lease_set_len < end {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(LeaseSet) Signature",
"data_len": lease_set_len,
"required_len": end,
"reason": "not enough data",
}).Error("error parsing signatre")
err = errors.New("error parsing signature: not enough data")
err = oops.Errorf("error parsing signature: not enough data")
return
}
signature = []byte(lease_set[start:end])
log.WithField("signature_length", len(signature)).Debug("Retrieved Signature from LeaseSet")
return
}
// Verify returns nil
func (lease_set LeaseSet) Verify() error {
log.Debug("Verifying LeaseSet")
//data_end := len(destination) +
// LEASE_SET_PUBKEY_SIZE +
// LEASE_SET_SPK_SIZE +
@ -325,44 +437,151 @@ func (lease_set LeaseSet) Verify() error {
//data := lease_set[:data_end]
//spk, _ := lease_set.
// Destination().
// SigningPublicKey()
// signingPublicKey()
//verifier, err := spk.NewVerifier()
//if err != nil {
// return err
//}
log.Warn("LeaseSet verification not implemented")
return nil // verifier.Verify(data, lease_set.Signature())
}
// NewestExpiration returns the newest lease expiration as an I2P Date.
// Returns errors encountered during parsing.
func (lease_set LeaseSet) NewestExpiration() (newest Date, err error) {
func (lease_set LeaseSet) NewestExpiration() (newest data.Date, err error) {
log.Debug("Finding newest expiration in LeaseSet")
leases, err := lease_set.Leases()
if err != nil {
log.WithError(err).Error("Failed to retrieve Leases for NewestExpiration")
return
}
newest = Date{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
newest = data.Date{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
for _, lease := range leases {
date := lease.Date()
if date.Time().After(newest.Time()) {
newest = date
}
}
log.WithField("newest_expiration", newest.Time()).Debug("Found newest expiration in LeaseSet")
return
}
// OldestExpiration returns the oldest lease expiration as an I2P Date.
// Returns errors encountered during parsing.
func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) {
func (lease_set LeaseSet) OldestExpiration() (earliest data.Date, err error) {
log.Debug("Finding oldest expiration in LeaseSet")
leases, err := lease_set.Leases()
if err != nil {
log.WithError(err).Error("Failed to retrieve Leases for OldestExpiration")
return
}
earliest = Date{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
earliest = data.Date{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
for _, lease := range leases {
date := lease.Date()
if date.Time().Before(earliest.Time()) {
earliest = date
}
}
log.WithField("oldest_expiration", earliest.Time()).Debug("Found oldest expiration in LeaseSet")
return
}
func NewLeaseSet(
dest destination.Destination,
encryptionKey types.RecievingPublicKey,
signingKey types.SigningPublicKey,
leases []lease.Lease,
signingPrivateKey types.SigningPrivateKey,
) (LeaseSet, error) {
log.Debug("Creating new LeaseSet")
// Validate destination size
if len(dest.KeysAndCert.Bytes()) < 387 {
return nil, oops.Errorf("invalid destination: minimum size is 387 bytes")
}
// Validate encryption key size
if len(encryptionKey.Bytes()) != LEASE_SET_PUBKEY_SIZE {
return nil, oops.Errorf("invalid encryption key size")
}
// Validate inputs
if len(leases) > 16 {
return nil, oops.Errorf("invalid lease set: more than 16 leases")
}
// Validate signing key size matches certificate
cert := dest.Certificate()
if cert.Type() == certificate.CERT_KEY {
// Get expected size from key certificate
keyCert, err := key_certificate.KeyCertificateFromCertificate(cert)
if err != nil {
log.WithError(err).Error("Failed to create keyCert")
}
expectedSize := keyCert.SignatureSize()
if len(signingKey.Bytes()) != expectedSize {
return nil, oops.Errorf("invalid signing key size: got %d, expected %d",
len(signingKey.Bytes()), expectedSize)
}
} else {
// Default DSA size
if len(signingKey.Bytes()) != LEASE_SET_SPK_SIZE {
return nil, oops.Errorf("invalid signing key size")
}
}
// Build LeaseSet dbytes
dbytes := make([]byte, 0)
// Add Destination
dbytes = append(dbytes, dest.KeysAndCert.Bytes()...)
// Add encryption key
dbytes = append(dbytes, encryptionKey.Bytes()...)
// Add signing key
dbytes = append(dbytes, signingKey.Bytes()...)
// Add lease count
leaseCount, err := data.NewIntegerFromInt(len(leases), 1)
if err != nil {
log.WithError(err).Error("Failed to create lease count")
return nil, err
}
dbytes = append(dbytes, leaseCount.Bytes()...)
// Add leases
for _, lease := range leases {
dbytes = append(dbytes, lease[:]...)
}
// Create signature for all data up to this point
signer, err := signingPrivateKey.NewSigner()
if err != nil {
log.WithError(err).Error("Failed to create signer")
return nil, err
}
signature, err := signer.Sign(dbytes)
if err != nil {
log.WithError(err).Error("Failed to sign LeaseSet")
return nil, err
}
// Add signature
dbytes = append(dbytes, signature...)
log.WithFields(logrus.Fields{
"destination_length": len(dest.KeysAndCert.Bytes()),
"encryption_key_length": len(encryptionKey.Bytes()),
"signing_key_length": len(signingKey.Bytes()),
"lease_count": len(leases),
"total_length": len(dbytes),
}).Debug("Successfully created new LeaseSet")
return LeaseSet(dbytes), nil
}
func ReadLeaseSet(data []byte) (LeaseSet, error) {
log.Debug("Reading LeaseSet")
lease_set := LeaseSet(data)
if len(lease_set) < 387 {
return nil, oops.Errorf("LeaseSet data too short to contain Destination")
}
return lease_set, nil
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 135 KiB

View File

@ -2,211 +2,442 @@ package lease_set
import (
"bytes"
"crypto/rand"
"testing"
"time"
"github.com/go-i2p/go-i2p/lib/common/destination"
"github.com/go-i2p/go-i2p/lib/common/key_certificate"
"github.com/go-i2p/go-i2p/lib/common/router_address"
"github.com/go-i2p/go-i2p/lib/common/router_info"
"github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/samber/oops"
"github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/keys_and_cert"
"github.com/go-i2p/go-i2p/lib/crypto/ed25519"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/go-i2p/go-i2p/lib/common/certificate"
common "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/lease"
"github.com/go-i2p/go-i2p/lib/common/router_identity"
"github.com/stretchr/testify/assert"
)
func buildDestination() *router_identity.RouterIdentity {
router_ident_data := make([]byte, 128+256)
router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
ident, _, err := router_identity.NewRouterIdentity(router_ident_data)
panic(err)
return ident
}
func buildPublicKey() []byte {
pk := make([]byte, 256)
for i := range pk {
pk[i] = 0x01
func generateTestRouterInfo(t *testing.T) (*router_info.RouterInfo, types.RecievingPublicKey, types.SigningPublicKey, types.SigningPublicKey, types.SigningPublicKey, error) {
// Generate signing key pair (Ed25519)
var ed25519_privkey ed25519.Ed25519PrivateKey
ed25519_signingprivkey, err := ed25519.GenerateEd25519Key() // Use direct key generation
if err != nil {
t.Fatalf("Failed to generate Ed25519 private key: %v\n", err)
}
return pk
}
ed25519_privkey = ed25519_signingprivkey.(ed25519.Ed25519PrivateKey) // Store the generated key
func buildSigningKey() []byte {
sk := make([]byte, 128)
for i := range sk {
sk[i] = 0x02
// Verify key size
if len(ed25519_privkey) != 64 {
t.Fatalf("Generated Ed25519 private key has wrong size: got %d, want 64", len(ed25519_privkey))
}
return sk
}
func buildLease(n int) []byte {
data := make([]byte, 0)
for i := 0; i < n; i++ {
l := make([]byte, lease.LEASE_SIZE)
for p := range l {
l[p] = byte(i)
}
for q := lease.LEASE_SIZE - 9; q < lease.LEASE_SIZE-1; q++ {
l[q] = 0x00
}
l[lease.LEASE_SIZE-1] = byte(i + 10)
data = append(data, l...)
ed25519_pubkey_raw, err := ed25519_privkey.Public()
if err != nil {
t.Fatalf("Failed to derive Ed25519 public key: %v\n", err)
}
return data
}
func buildSignature(size int) []byte {
sig := make([]byte, size)
for i := range sig {
sig[i] = 0x08
ed25519_pubkey, ok := ed25519_pubkey_raw.(types.SigningPublicKey)
if !ok {
t.Fatalf("Failed to get SigningPublicKey from Ed25519 public key")
}
return sig
}
func buildFullLeaseSet(n int) LeaseSet {
lease_set_data := make([]byte, 0)
lease_set_data = append(lease_set_data, buildDestination().KeysAndCert.KeyCertificate.RawBytes()...)
lease_set_data = append(lease_set_data, buildPublicKey()...)
lease_set_data = append(lease_set_data, buildSigningKey()...)
lease_set_data = append(lease_set_data, byte(n))
lease_set_data = append(lease_set_data, buildLease(n)...)
lease_set_data = append(lease_set_data, buildSignature(64)...)
return LeaseSet(lease_set_data)
}
func TestDestinationIsCorrect(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(1)
dest, err := lease_set.Destination()
assert.Nil(err)
dest_cert := dest.Certificate()
//assert.Nil(err)
cert_type := dest_cert.Type()
assert.Nil(err)
assert.Equal(certificate.CERT_KEY, cert_type)
}
func TestPublicKeyIsCorrect(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(1)
pk, err := lease_set.PublicKey()
if assert.Nil(err) {
assert.Equal(
0,
bytes.Compare(
[]byte(buildPublicKey()),
pk[:],
),
)
// Generate encryption key pair (ElGamal)
var elgamal_privkey elgamal.PrivateKey
err = elgamal.ElgamalGenerate(&elgamal_privkey.PrivateKey, rand.Reader)
if err != nil {
t.Fatalf("Failed to generate ElGamal private key: %v\n", err)
}
}
func TestSigningKeyIsCorrect(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(1)
sk, err := lease_set.SigningKey()
if assert.Nil(err) {
assert.Equal(128, sk.Len())
// Convert elgamal private key to elgamal.ElgPrivateKey
var elg_privkey elgamal.ElgPrivateKey
xBytes := elgamal_privkey.X.Bytes()
if len(xBytes) > 256 {
t.Fatalf("ElGamal private key X too large")
}
}
copy(elg_privkey[256-len(xBytes):], xBytes)
func TestLeaseCountCorrect(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(1)
count, err := lease_set.LeaseCount()
if assert.Nil(err) {
assert.Equal(1, count)
// Convert elgamal public key to elgamal.ElgPublicKey
var elg_pubkey elgamal.ElgPublicKey
yBytes := elgamal_privkey.PublicKey.Y.Bytes()
if len(yBytes) > 256 {
t.Fatalf("ElGamal public key Y too large")
}
}
copy(elg_pubkey[256-len(yBytes):], yBytes)
func TestLeaseCountCorrectWithMultiple(t *testing.T) {
assert := assert.New(t)
// Ensure that elg_pubkey implements crypto.PublicKey interface
var _ types.RecievingPublicKey = elg_pubkey
lease_set := buildFullLeaseSet(3)
count, err := lease_set.LeaseCount()
if assert.Nil(err) {
assert.Equal(3, count)
// Create KeyCertificate specifying key types
var payload bytes.Buffer
signingPublicKeyType, err := data.NewIntegerFromInt(key_certificate.KEYCERT_SIGN_ED25519, 2)
if err != nil {
t.Fatalf("Failed to create signing public key type integer: %v", err)
}
}
func TestLeaseCountErrorWithTooMany(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(17)
count, err := lease_set.LeaseCount()
if assert.NotNil(err) {
assert.Equal("invalid lease set: more than 16 leases", err.Error())
cryptoPublicKeyType, err := data.NewIntegerFromInt(key_certificate.KEYCERT_CRYPTO_ELG, 2)
if err != nil {
t.Fatalf("Failed to create crypto public key type integer: %v", err)
}
assert.Equal(17, count)
}
func TestLeasesHaveCorrectData(t *testing.T) {
assert := assert.New(t)
payload.Write(*cryptoPublicKeyType)
payload.Write(*signingPublicKeyType)
lease_set := buildFullLeaseSet(3)
count, err := lease_set.LeaseCount()
if assert.Nil(err) && assert.Equal(3, count) {
leases, err := lease_set.Leases()
if assert.Nil(err) {
for i := 0; i < count; i++ {
l := make([]byte, lease.LEASE_SIZE)
for p := range l {
l[p] = byte(i)
}
for q := lease.LEASE_SIZE - 9; q < lease.LEASE_SIZE-1; q++ {
l[q] = 0x00
}
l[lease.LEASE_SIZE-1] = byte(i + 10)
assert.Equal(
0,
bytes.Compare(
l,
leases[i][:],
),
)
}
}
cert, err := certificate.NewCertificateWithType(certificate.CERT_KEY, payload.Bytes())
if err != nil {
t.Fatalf("Failed to create new certificate: %v\n", err)
}
}
func TestSignatureIsCorrect(t *testing.T) {
assert := assert.New(t)
t.Logf("Key Certificate Payload Length: %d bytes", len(payload.Bytes()))
t.Logf("Certificate Type: %d", cert.Type())
t.Logf("Certificate Length Field: %d", cert.Length())
t.Logf("Certificate Bytes Length: %d", len(cert.Bytes()))
t.Logf("Certificate Bytes: %d", cert.Bytes())
lease_set := buildFullLeaseSet(1)
sig, err := lease_set.Signature()
if assert.Nil(err) {
assert.Equal(
0,
bytes.Compare(
buildSignature(64),
sig,
),
)
if cert.Length() != len(cert.Bytes()) {
t.Logf("Certificate length (%d) does not match with bytes length (%d)", cert.Length(), cert.Bytes())
}
certBytes := cert.Bytes()
t.Logf("Serialized Certificate Size: %d bytes", len(certBytes))
keyCert, err := key_certificate.KeyCertificateFromCertificate(*cert)
if err != nil {
log.Fatalf("KeyCertificateFromCertificate failed: %v\n", err)
}
pubKeySize := keyCert.CryptoSize()
sigKeySize := keyCert.SignatureSize()
paddingSize := keys_and_cert.KEYS_AND_CERT_DATA_SIZE - (pubKeySize + sigKeySize)
if paddingSize < 0 {
t.Fatalf("Padding size is negative: %d", paddingSize)
}
padding := make([]byte, paddingSize)
_, err = rand.Read(padding)
if err != nil {
t.Fatalf("Failed to generate random padding: %v\n", err)
}
// Create RouterIdentity
routerIdentity, err := router_identity.NewRouterIdentity(elg_pubkey, ed25519_pubkey, *cert, padding)
if err != nil {
t.Fatalf("Failed to create router identity: %v\n", err)
}
// create some dummy addresses
options := map[string]string{}
routerAddress, err := router_address.NewRouterAddress(3, <-time.After(1*time.Second), "NTCP2", options)
if err != nil {
t.Fatalf("Failed to create router address: %v\n", err)
}
routerAddresses := []*router_address.RouterAddress{routerAddress}
// create router info
routerInfo, err := router_info.NewRouterInfo(routerIdentity, time.Now(), routerAddresses, nil, &ed25519_privkey, signature.SIGNATURE_TYPE_EDDSA_SHA512_ED25519)
if err != nil {
t.Fatalf("Failed to create router info: %v\n", err)
}
// Generate signing key pair for the LeaseSet (Ed25519)
var leaseSetSigningPrivKey ed25519.Ed25519PrivateKey
leaseSetSigningPrivkey, err := ed25519.GenerateEd25519Key() // Use direct key generation
if err != nil {
t.Fatalf("Failed to generate lease set Ed25519 private key: %v", err)
}
leaseSetSigningPrivKey = leaseSetSigningPrivkey.(ed25519.Ed25519PrivateKey) // Store the generated key
// Verify key size
if len(leaseSetSigningPrivKey) != 64 {
t.Fatalf("Generated Ed25519 private key has wrong size: got %d, want 64", len(leaseSetSigningPrivKey))
}
leaseSetSigningPubKeyRaw, err := leaseSetSigningPrivKey.Public()
if err != nil {
t.Fatalf("Failed to derive lease set Ed25519 public key: %v", err)
}
leaseSetSigningPubKey, ok := leaseSetSigningPubKeyRaw.(types.SigningPublicKey)
if !ok {
t.Fatalf("Failed to get lease set SigningPublicKey from Ed25519 public key")
}
var identityPrivKey ed25519.Ed25519PrivateKey
_, err = identityPrivKey.Generate()
if err != nil {
t.Fatalf("Failed to generate identity Ed25519 private key: %v", err)
}
return routerInfo, elg_pubkey, leaseSetSigningPubKey, &leaseSetSigningPrivKey, &identityPrivKey, nil
}
func TestNewestExpirationIsCorrect(t *testing.T) {
assert := assert.New(t)
func createTestLease(t *testing.T, index int, routerInfo *router_info.RouterInfo) (*lease.Lease, error) {
// Use the provided routerInfo instead of generating a new one
tunnelGatewayHash := types.SHA256(routerInfo.RouterIdentity().KeysAndCert.Bytes())
lease_set := buildFullLeaseSet(5)
latest, err := lease_set.NewestExpiration()
assert.Nil(err)
Date, _, err := common.NewDate([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, byte(4 + 10)})
assert.Equal(
Date,
latest,
// Create expiration time
expiration := time.Now().Add(time.Hour * time.Duration(index+1)) // Different times for each lease
// Create lease
testLease, err := lease.NewLease(tunnelGatewayHash, uint32(1000+index), expiration)
if err != nil {
return nil, err
}
return testLease, nil
}
func generateTestDestination(t *testing.T) (*destination.Destination, types.RecievingPublicKey, types.SigningPublicKey, types.SigningPrivateKey, error) {
// Generate client signing key pair (Ed25519)
var ed25519_privkey ed25519.Ed25519PrivateKey
ed25519_signingprivkey, err := ed25519.GenerateEd25519Key() // Use direct key generation
if err != nil {
t.Fatalf("Failed to generate Ed25519 private key: %v\n", err)
}
ed25519_privkey = ed25519_signingprivkey.(ed25519.Ed25519PrivateKey) // Store the generated key
// Verify key size
if len(ed25519_privkey) != 64 {
t.Fatalf("Generated Ed25519 private key has wrong size: got %d, want 64", len(ed25519_privkey))
}
ed25519_pubkey_raw, err := ed25519_privkey.Public()
if err != nil {
t.Fatalf("Failed to derive Ed25519 public key: %v\n", err)
}
ed25519_pubkey, ok := ed25519_pubkey_raw.(types.SigningPublicKey)
if !ok {
t.Fatalf("Failed to get SigningPublicKey from Ed25519 public key")
}
// Generate client encryption key pair (ElGamal)
var elgamal_privkey elgamal.PrivateKey
err = elgamal.ElgamalGenerate(&elgamal_privkey.PrivateKey, rand.Reader)
if err != nil {
t.Fatalf("Failed to generate ElGamal private key: %v\n", err)
}
// Convert ElGamal public key to elgamal.ElgPublicKey
var elg_pubkey elgamal.ElgPublicKey
yBytes := elgamal_privkey.PublicKey.Y.Bytes()
if len(yBytes) > 256 {
t.Fatalf("ElGamal public key Y too large")
}
copy(elg_pubkey[256-len(yBytes):], yBytes)
// Create KeyCertificate specifying key types
var payload bytes.Buffer
cryptoPublicKeyType, err := data.NewIntegerFromInt(0, 2) // ElGamal
if err != nil {
t.Fatalf("Failed to create crypto public key type integer: %v", err)
}
signingPublicKeyType, err := data.NewIntegerFromInt(7, 2) // Ed25519
if err != nil {
t.Fatalf("Failed to create signing public key type integer: %v", err)
}
payload.Write(*cryptoPublicKeyType)
payload.Write(*signingPublicKeyType)
// Create Certificate
cert, err := certificate.NewCertificateWithType(certificate.CERT_KEY, payload.Bytes())
if err != nil {
t.Fatalf("Failed to create new certificate: %v\n", err)
}
// Convert Certificate to KeyCertificate
keyCert, err := key_certificate.KeyCertificateFromCertificate(*cert)
if err != nil {
t.Fatalf("Failed to create KeyCertificate from Certificate: %v", err)
}
// Create padding
paddingSize := keys_and_cert.KEYS_AND_CERT_DATA_SIZE - (elg_pubkey.Len() + ed25519_pubkey.Len())
if paddingSize < 0 {
t.Fatalf("Padding size is negative: %d", paddingSize)
}
padding := make([]byte, paddingSize)
_, err = rand.Read(padding)
if err != nil {
t.Fatalf("Failed to generate random padding: %v\n", err)
}
// Correctly call NewKeysAndCert with parameters in the right order
kac, err := keys_and_cert.NewKeysAndCert(
keyCert,
elg_pubkey,
padding,
ed25519_pubkey,
)
t.Logf("Signing Public Key Type: %d", signingPublicKeyType.Int())
t.Logf("Crypto Public Key Type: %d", cryptoPublicKeyType.Int())
t.Logf("Expected Signing Public Key Size: %d", keyCert.SignatureSize())
t.Logf("Expected Crypto Public Key Size: %d", keyCert.CryptoSize())
t.Logf("Actual Signing Public Key Size: %d", ed25519_pubkey.Len())
t.Logf("Actual Crypto Public Key Size: %d", elg_pubkey.Len())
if err != nil {
t.Fatalf("Failed to create KeysAndCert: %v", err)
}
// Create Destination
dest := &destination.Destination{
KeysAndCert: kac,
}
return dest, elg_pubkey, ed25519_pubkey, &ed25519_privkey, nil
}
func TestOldestExpirationIsCorrect(t *testing.T) {
// (*router_info.RouterInfo, crypto.PublicKey, types.SigningPublicKey, types.SigningPublicKey, types.SigningPublicKey, error) {
func createTestLeaseSet(t *testing.T, routerInfo *router_info.RouterInfo, leaseCount int) (LeaseSet, error) {
// Generate test Destination and client keys
dest, encryptionKey, signingKey, signingPrivKey, err := generateTestDestination(t)
if err != nil {
return nil, oops.Errorf("failed to generate test destination: %v", err)
}
destBytes := dest.KeysAndCert.Bytes()
t.Logf("Destination size: %d bytes", len(destBytes))
// Ensure the destination size is at least 387 bytes
if len(destBytes) < 387 {
t.Fatalf("Destination size %d is less than required 387 bytes", len(destBytes))
}
// Create leases using the routerInfo
var leases []lease.Lease
for i := 0; i < leaseCount; i++ {
testLease, err := createTestLease(t, i, routerInfo)
if err != nil {
return nil, err
}
leases = append(leases, *testLease)
}
// Create LeaseSet
leaseSet, err := NewLeaseSet(
*dest,
encryptionKey,
signingKey,
leases,
signingPrivKey,
)
if err != nil {
t.Logf("Failed to create lease set: %v", err)
}
return leaseSet, err
}
func TestLeaseSetCreation(t *testing.T) {
assert := assert.New(t)
lease_set := buildFullLeaseSet(5)
latest, err := lease_set.OldestExpiration()
// Generate test router info and keys
routerInfo, _, _, _, _, err := generateTestRouterInfo(t)
assert.Nil(err)
Date, _, err := common.NewDate([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a})
assert.Equal(
Date,
latest,
)
leaseSet, err := createTestLeaseSet(t, routerInfo, 1)
assert.Nil(err)
assert.NotNil(leaseSet)
// Check the size of the LeaseSet's Destination KeysAndCert
dest, err := leaseSet.DestinationDeux()
assert.Nil(err)
assert.NotNil(dest)
// Verify individual key sizes
keysAndCert := dest.KeysAndCert
pubKeySize := keysAndCert.KeyCertificate.CryptoSize()
assert.Equal(256, pubKeySize, "CryptoPublicKeySize should be 256 bytes for ElGamal")
sigKeySize := keysAndCert.KeyCertificate.SignatureSize()
assert.Equal(32, sigKeySize, "SignatureSize should be 32 bytes for Ed25519")
}
func TestLeaseSetValidation(t *testing.T) {
assert := assert.New(t)
// Generate test router info and keys
routerInfo, _, _, _, _, err := generateTestRouterInfo(t)
assert.Nil(err)
// Test with too many leases
_, err = createTestLeaseSet(t, routerInfo, 17)
assert.NotNil(err)
assert.Equal("invalid lease set: more than 16 leases", err.Error())
}
/*
func TestLeaseSetComponents(t *testing.T) {
assert := assert.New(t)
// Generate test router info and keys
routerInfo, _, _, _, _, err := generateTestRouterInfo(t)
assert.Nil(err)
// Create the test lease set with 3 leases
leaseSet, err := createTestLeaseSet(t, routerInfo, 3)
assert.Nil(err)
dest, err := leaseSet.Destination()
assert.Nil(err)
assert.NotNil(dest)
count, err := leaseSet.LeaseCount()
assert.Nil(err)
assert.Equal(3, count)
leases, err := leaseSet.Leases()
assert.Nil(err)
assert.Equal(3, len(leases))
pubKey, err := leaseSet.PublicKey()
assert.Nil(err)
assert.Equal(LEASE_SET_PUBKEY_SIZE, len(pubKey.Bytes()))
signKey, err := leaseSet.SigningKey()
assert.Nil(err)
assert.NotNil(signKey)
}
func TestExpirations(t *testing.T) {
assert := assert.New(t)
// Generate test router info and keys
routerInfo, _, _, _, _, err := generateTestRouterInfo(t)
assert.Nil(err)
// Create the test lease set with 3 leases
leaseSet, err := createTestLeaseSet(t, routerInfo, 3)
assert.Nil(err)
newest, err := leaseSet.NewestExpiration()
assert.Nil(err)
assert.NotNil(newest)
oldest, err := leaseSet.OldestExpiration()
assert.Nil(err)
assert.NotNil(oldest)
assert.True(oldest.Time().Before(newest.Time()) || oldest.Time().Equal(newest.Time()))
}
func TestSignatureVerification(t *testing.T) {
assert := assert.New(t)
// Generate test router info and keys
routerInfo, _, _, _, _, err := generateTestRouterInfo(t)
assert.Nil(err)
// Create the test lease set
leaseSet, err := createTestLeaseSet(t, routerInfo, 1)
assert.Nil(err)
sig, err := leaseSet.Signature()
assert.Nil(err)
assert.NotNil(sig)
}
*/

View File

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

View File

@ -2,10 +2,17 @@
package router_address
import (
"errors"
"encoding/binary"
"net"
"strconv"
"strings"
"time"
"github.com/go-i2p/logger"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
. "github.com/go-i2p/go-i2p/lib/common/data"
log "github.com/sirupsen/logrus"
)
// Minimum number of bytes in a valid RouterAddress
@ -13,6 +20,8 @@ const (
ROUTER_ADDRESS_MIN_SIZE = 9
)
var log = logger.GetGoI2PLogger()
/*
[RouterAddress]
Accurate for version 0.9.49
@ -63,100 +72,366 @@ options :: Mapping
//
// https://geti2p.net/spec/common-structures#routeraddress
type RouterAddress struct {
cost *Integer
expiration *Date
transport_style *I2PString
options *Mapping
TransportCost *Integer
ExpirationDate *Date
TransportType I2PString
TransportOptions *Mapping
}
// Network implements net.Addr. It returns the transport type plus 4 or 6
func (router_address *RouterAddress) Network() string {
log.Debug("Getting network for RouterAddress")
if router_address.TransportType == nil {
log.Warn("TransportType is nil in RouterAddress")
return ""
}
str, err := router_address.TransportType.Data()
if err != nil {
log.WithError(err).Error("Failed to get TransportType data")
return ""
}
network := string(str) + router_address.IPVersion()
log.WithField("network", network).Debug("Retrieved network for RouterAddress")
return network
}
// IPVersion returns a string "4" for IPv4 or 6 for IPv6
func (router_address *RouterAddress) IPVersion() string {
log.Debug("Getting IP version for RouterAddress")
str, err := router_address.CapsString().Data()
if err != nil {
log.WithError(err).Error("Failed to get CapsString data")
return ""
}
if strings.HasSuffix(str, "6") {
log.Debug("IP version is IPv6")
return "6"
}
log.Debug("IP version is IPv4")
return "4"
}
func (router_address *RouterAddress) UDP() bool {
// return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
log.Debug("Checking if RouterAddress is UDP")
isUDP := strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
log.WithField("is_udp", isUDP).Debug("Checked if RouterAddress is UDP")
return isUDP
}
// String implements net.Addr. It returns the IP address, followed by the options
func (router_address *RouterAddress) String() string {
log.Debug("Converting RouterAddress to string")
var rv []string
rv = append(rv, string(router_address.TransportStyle()))
rv = append(rv, string(router_address.HostString()))
rv = append(rv, string(router_address.PortString()))
rv = append(rv, string(router_address.StaticKeyString()))
rv = append(rv, string(router_address.InitializationVectorString()))
rv = append(rv, string(router_address.ProtocolVersionString()))
if router_address.UDP() {
rv = append(rv, string(router_address.IntroducerHashString(0)))
rv = append(rv, string(router_address.IntroducerExpirationString(0)))
rv = append(rv, string(router_address.IntroducerTagString(0)))
rv = append(rv, string(router_address.IntroducerHashString(1)))
rv = append(rv, string(router_address.IntroducerExpirationString(1)))
rv = append(rv, string(router_address.IntroducerTagString(1)))
rv = append(rv, string(router_address.IntroducerHashString(2)))
rv = append(rv, string(router_address.IntroducerExpirationString(2)))
rv = append(rv, string(router_address.IntroducerTagString(2)))
}
str := strings.TrimSpace(strings.Join(rv, " "))
log.WithField("router_address_string", str).Debug("Converted RouterAddress to string")
return str
}
var ex_addr net.Addr = &RouterAddress{}
// Bytes returns the router address as a []byte.
func (router_address RouterAddress) Bytes() []byte {
log.Debug("Converting RouterAddress to bytes")
bytes := make([]byte, 0)
bytes = append(bytes, router_address.cost.Bytes()...)
bytes = append(bytes, router_address.expiration.Bytes()...)
strData, err := router_address.transport_style.Data()
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
} else {
bytes = append(bytes, strData...)
}
bytes = append(bytes, router_address.options.Data()...)
bytes = append(bytes, router_address.TransportCost.Bytes()...)
bytes = append(bytes, router_address.ExpirationDate.Bytes()...)
bytes = append(bytes, router_address.TransportType...)
bytes = append(bytes, router_address.TransportOptions.Data()...)
log.WithField("bytes_length", len(bytes)).Debug("Converted RouterAddress to bytes")
return bytes
}
// Cost returns the cost for this RouterAddress as a Go integer.
func (router_address RouterAddress) Cost() int {
return router_address.cost.Int()
return router_address.TransportCost.Int()
}
// Expiration returns the expiration for this RouterAddress as an I2P Date.
func (router_address RouterAddress) Expiration() Date {
return *router_address.expiration
return *router_address.ExpirationDate
}
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
func (router_address RouterAddress) TransportStyle() I2PString {
return *router_address.transport_style
return router_address.TransportType
}
// GetOption returns the value of the option specified by the key
func (router_address RouterAddress) GetOption(key I2PString) I2PString {
return router_address.Options().Values().Get(key)
}
func (router_address RouterAddress) HasOption(key I2PString) bool {
opt := router_address.GetOption(key)
return opt != nil
}
func (router_address RouterAddress) CheckOption(key string) bool {
keyv, _ := ToI2PString(key)
return router_address.HasOption(keyv)
}
func (router_address RouterAddress) HostString() I2PString {
host, _ := ToI2PString("host")
return router_address.GetOption(host)
}
func (router_address RouterAddress) PortString() I2PString {
port, _ := ToI2PString("port")
return router_address.GetOption(port)
}
func (router_address RouterAddress) CapsString() I2PString {
caps, _ := ToI2PString("caps")
return router_address.GetOption(caps)
}
func (router_address RouterAddress) StaticKeyString() I2PString {
sk, _ := ToI2PString("s")
return router_address.GetOption(sk)
}
func (router_address RouterAddress) InitializationVectorString() I2PString {
iv, _ := ToI2PString("i")
return router_address.GetOption(iv)
}
func (router_address RouterAddress) ProtocolVersionString() I2PString {
v, _ := ToI2PString("v")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerHashString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("ih" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("ih0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("iexp" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("iexp0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) IntroducerTagString(num int) I2PString {
if num >= 0 && num <= 2 {
val := strconv.Itoa(num)
v, _ := ToI2PString("itag" + val)
return router_address.GetOption(v)
}
v, _ := ToI2PString("itag0")
return router_address.GetOption(v)
}
func (router_address RouterAddress) Host() (net.Addr, error) {
log.Debug("Getting host from RouterAddress")
host := router_address.HostString()
hostBytes, err := host.Data()
if err != nil {
log.WithError(err).Error("Failed to get host data")
return nil, err
}
ip := net.ParseIP(hostBytes)
if ip == nil {
log.Error("Failed to parse IP address")
return nil, oops.Errorf("null host error")
}
// return net.ResolveIPAddr("", ip.String())
addr, err := net.ResolveIPAddr("", ip.String())
if err != nil {
log.WithError(err).Error("Failed to resolve IP address")
} else {
log.WithField("addr", addr).Debug("Retrieved host from RouterAddress")
}
return addr, err
}
func (router_address RouterAddress) Port() (string, error) {
log.Debug("Getting port from RouterAddress")
port := router_address.PortString()
portBytes, err := port.Data()
if err != nil {
log.WithError(err).Error("Failed to get port data")
return "", err
}
val, err := strconv.Atoi(portBytes)
if err != nil {
log.WithError(err).Error("Failed to convert port to integer")
return "", err
}
// return strconv.Itoa(val), nil
portStr := strconv.Itoa(val)
log.WithField("port", portStr).Debug("Retrieved port from RouterAddress")
return portStr, nil
}
func (routerAddress RouterAddress) StaticKey() ([32]byte, error) {
sk := routerAddress.StaticKeyString()
if sk == nil {
return [32]byte{}, oops.Errorf("error: static key not found")
}
skBytes := []byte(sk)
if len(skBytes) != 32 {
return [32]byte{}, oops.Errorf("error: invalid static key length: %d, expected 32", len(skBytes))
}
var result [32]byte
copy(result[:], skBytes)
return result, nil
}
func (router_address RouterAddress) InitializationVector() ([16]byte, error) {
iv := router_address.InitializationVectorString()
if len([]byte(iv)) != 16 {
return [16]byte{}, oops.Errorf("error: invalid IV")
}
return [16]byte(iv), nil
}
func (router_address RouterAddress) ProtocolVersion() (string, error) {
return router_address.ProtocolVersionString().Data()
}
// Options returns the options for this RouterAddress as an I2P Mapping.
func (router_address RouterAddress) Options() Mapping {
return *router_address.options
func (routerAddress RouterAddress) Options() Mapping {
if routerAddress.TransportOptions == nil {
log.Warn("TransportOptions is nil in RouterAddress")
return Mapping{}
}
return *routerAddress.TransportOptions
}
// Check if the RouterAddress is empty or if it is too small to contain valid data.
func (router_address RouterAddress) checkValid() (err error, exit bool) {
return
func (routerAddress RouterAddress) checkValid() (err error, exit bool) {
if routerAddress.TransportType == nil {
return oops.Errorf("invalid router address: nil transport type"), true
}
if routerAddress.TransportOptions == nil {
return oops.Errorf("invalid router address: nil transport options"), true
}
return nil, false
}
// ReadRouterAddress returns RouterAddress from a []byte.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
log.WithField("data_length", len(data)).Debug("Reading RouterAddress from data")
if len(data) == 0 {
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
err = errors.New("error parsing RouterAddress: no data")
err = oops.Errorf("error parsing RouterAddress: no data")
return
}
router_address.cost, remainder, err = NewInteger(data, 1)
router_address.TransportCost, remainder, err = NewInteger(data, 1)
if err != nil {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing cost",
}).Warn("error parsing RouterAddress")
}
router_address.expiration, remainder, err = NewDate(remainder)
router_address.ExpirationDate, remainder, err = NewDate(remainder)
if err != nil {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing expiration",
}).Error("error parsing RouterAddress")
}
router_address.transport_style, remainder, err = NewI2PString(remainder)
router_address.TransportType, remainder, err = ReadI2PString(remainder)
if err != nil {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing transport_style",
}).Error("error parsing RouterAddress")
}
var errs []error
router_address.options, remainder, errs = NewMapping(remainder)
router_address.TransportOptions, remainder, errs = NewMapping(remainder)
for _, err := range errs {
log.WithFields(log.Fields{
log.WithFields(logrus.Fields{
"at": "(RouterAddress) ReadNewRouterAddress",
"reason": "error parsing options",
"error": err,
}).Error("error parsing RouterAddress")
"error": err,
}).Error("error parsing RozuterAddress")
}
return
}
// NewRouterAddress creates a new *RouterAddress from []byte using ReadRouterAddress.
// Returns a pointer to RouterAddress unlike ReadRouterAddress.
func NewRouterAddress(data []byte) (router_address *RouterAddress, remainder []byte, err error) {
objrouteraddress, remainder, err := ReadRouterAddress(data)
router_address = &objrouteraddress
return
// NewRouterAddress creates a new RouterAddress with the provided parameters.
// Returns a pointer to RouterAddress.
func NewRouterAddress(cost uint8, expiration time.Time, transportType string, options map[string]string) (*RouterAddress, error) {
log.Debug("Creating new RouterAddress")
// Create TransportCost as an Integer (1 byte)
transportCost, err := NewIntegerFromInt(int(cost), 1)
if err != nil {
log.WithError(err).Error("Failed to create TransportCost Integer")
return nil, err
}
// Create ExpirationDate as a Date
millis := expiration.UnixNano() / int64(time.Millisecond)
dateBytes := make([]byte, DATE_SIZE)
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
expirationDate, _, err := NewDate(dateBytes)
if err != nil {
log.WithError(err).Error("Failed to create ExpirationDate")
return nil, err
}
// Create TransportType as an I2PString
transportTypeStr, err := ToI2PString(transportType)
if err != nil {
log.WithError(err).Error("Failed to create TransportType I2PString")
return nil, err
}
// Create TransportOptions as a Mapping
transportOptions, err := GoMapToMapping(options)
if err != nil {
log.WithError(err).Error("Failed to create TransportOptions Mapping")
return nil, err
}
// Create RouterAddress
ra := &RouterAddress{
TransportCost: transportCost,
ExpirationDate: expirationDate,
TransportType: transportTypeStr,
TransportOptions: transportOptions,
}
log.WithFields(logrus.Fields{
"cost": cost,
"expiration": expiration,
"transportType": transportType,
"options": options,
}).Debug("Successfully created new RouterAddress")
return ra, nil
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 156 KiB

View File

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

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