asn-d6 / stem Public
forked from torproject/stemNew issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HSv3 review #2
base: hsv3_encoding_review
Are you sure you want to change the base?
HSv3 review #2
Conversation
Dropping the redundant '_descriptor' suffix from this module name. The old name still works as an alias.
Common parent for v2 and v3 hidden service descriptors. I'm not yet sure what (if anything) they'll share, but this class is proper regardless for object orientation (see router status entries for what this will exemplify). Existing usage of the HiddenServiceDescriptor class name is unfortunate since that is what our common base class should be called. Oh well - yet another thing to correct when we break backward compatibility in Stem 2.x.
Doesn't do anything yet - just getting the class and such wired up.
Trivial parsing for the first field. Mostly still just wiring things up.
Trivial from a parsing perspective but I gotta admit, I'm kinda confused how this is useful since unlike v2 the descriptor doesn't note its publication time.
We've done this in quite a few spots, so time for a helper.
Support for the outer later of v3 hidden service descriptors... https://trac.torproject.org/projects/tor/ticket/31369 https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n1046 This does *not* include support for reading HS-DESC-ENC (superencrypted blobs) nor validating the signature. Patches welcome for both!
Stem has a soft dependency on the cryptography module. If unavailable we should
gracefully degrade or explicitly error with a message saying that cryptography
is required.
Also, cryptography's ed25519 class is pretty new, so folks will have outdated
module versions for a while...
======================================================================
ERROR: test_for_decrypt
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 43, in test_for_decrypt
onion_address="sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion"))
File "/home/atagar/Desktop/stem/stem/descriptor/__init__.py", line 442, in parse_file
for desc in parse(descriptor_file):
File "/home/atagar/Desktop/stem/stem/descriptor/__init__.py", line 545, in _parse_metrics_file
for desc in stem.descriptor.hidden_service._parse_file(descriptor_file, desc_type, validate = validate, **kwargs):
File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 156, in _parse_file
yield desc_type(bytes.join(b'', descriptor_content), validate, **kwargs)
File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 571, in __init__
plaintext = self.decrypt_descriptor(desc_signing_cert)
File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 579, in decrypt_descriptor
identity_public_key = stem.descriptor.hsv3_crypto.decode_address(self.onion_address)
File "/home/atagar/Desktop/stem/stem/descriptor/hsv3_crypto.py", line 30, in decode_address
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
ImportError: No module named ed25519
Minor tweek so a few of our tests can pass...
======================================================================
ERROR: test_invalid_lifetime
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 110, in test_invalid_lifetime
expect_invalid_attr(self, {'descriptor-lifetime': test_value}, 'lifetime')
File "/home/atagar/Desktop/stem/test/unit/descriptor/__init__.py", line 41, in base_expect_invalid_attr
return base_expect_invalid_attr_for_text(cls, default_attr, default_value, test, cls.content(desc_attrs), attr, expected_value)
File "/home/atagar/Desktop/stem/test/unit/descriptor/__init__.py", line 52, in base_expect_invalid_attr_for_text
desc = cls(desc_text, validate = False)
File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 540, in __init__
raise ValueError("The onion address MUST be provided to parse a V3 descriptor")
ValueError: The onion address MUST be provided to parse a V3 descriptor
Fix remaining test failures so unit tests once again pass. Stylistic checks still report issues so that's next.
The ed25519 module itself does not say when it was added [1], but the changelog [2] indicates that support was added in version 2.6... 2.6 - 2019-02-27 Added support for Ed25519 signing when using OpenSSL 1.1.1b or newer. [1] https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ed25519/ [2] https://cryptography.io/en/latest/changelog/
Quick handful of corrections so our stylistic checks once again pass...
STATIC CHECKS
* /home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py
line 48 - use single rather than double quotes | onion_address="sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion"))
* /home/atagar/Desktop/stem/stem/descriptor/certificate.py
line 77 - use single rather than double quotes | "HS_V3_DESC_SIGNING_KEY", "HS_V3_INTRO_POINT_AUTH_KEY", "HS_V3_INTRO_POINT_ENC_KEY")
line 165 - E261 at least two spaces before inline comment | elif cert_type == 8: # see rend-spec-v3.txt appendix E for these defintions
line 172 - use single rather than double quotes | raise ValueError("Ed25519 certificate type is an unknown value %i." % cert_type)
line 311 - W391 blank line at end of file
* /home/atagar/Desktop/stem/stem/prereq.py
line 142 - 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey' imported but unused | from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
* /home/atagar/Desktop/stem/stem/descriptor/hsv3_crypto.py
line 19 - use single rather than double quotes | CHECKSUM_CONSTANT = b".onion checksum"
line 21 - E302 expected 2 blank lines, found 1 | def decode_address(onion_address_str):
line 38 - use single rather than double quotes | if (len(onion_address_str) != 56 + len(".onion")):
line 39 - use single rather than double quotes | raise ValueError("Wrong address length")
line 54 - use single rather than double quotes | my_checksum_body = b"%s%s%s" % (CHECKSUM_CONSTANT, pubkey, bytes([version]))
line 58 - use single rather than double quotes | raise ValueError("Bad checksum")
line 62 - E305 expected 2 blank lines after class or function definition, found 1 | """
line 81 - E302 expected 2 blank lines, found 0 | def get_subcredential(public_identity_key, blinded_key):
line 82 - use single rather than double quotes | cred_bytes_constant = "credential".encode()
line 83 - use single rather than double quotes | subcred_bytes_constant = "subcredential".encode()
line 85 - use single rather than double quotes | credential = hashlib.sha3_256(b"%s%s" % (cred_bytes_constant, public_identity_key)).digest()
line 86 - use single rather than double quotes | subcredential = hashlib.sha3_256(b"%s%s%s" % (subcred_bytes_constant, credential, blinded_key)).digest()
line 88 - use single rather than double quotes | print("public_identity_key: %s" % (public_identity_key.hex()))
line 89 - use single rather than double quotes | print("credential: %s" % (credential.hex()))
line 90 - use single rather than double quotes | print("blinded_key: %s" % (blinded_key.hex()))
line 91 - use single rather than double quotes | print("subcredential: %s" % (subcredential.hex()))
line 93 - use single rather than double quotes | print("===")
line 97 - E305 expected 2 blank lines after class or function definition, found 1 | """
line 131 - E302 expected 2 blank lines, found 1 | def _ciphertext_mac_is_valid(key, salt, ciphertext, mac):
line 142 - use single rather than double quotes | my_mac_body = b"%s%s%s%s%s" % (key_len, key, salt_len, salt, ciphertext)
line 145 - use single rather than double quotes | print("===")
line 146 - use single rather than double quotes | print("my mac: %s" % my_mac.hex())
line 147 - use single rather than double quotes | print("their mac: %s" % mac.hex())
line 152 - E302 expected 2 blank lines, found 1 | def _decrypt_descriptor_layer(ciphertext_blob_b64, revision_counter,
line 162 - use single rather than double quotes | raise ValueError("bad encrypted blob")
line 168 - use single rather than double quotes | print("encrypted blob lenth :%s" % len(ciphertext_blob))
line 169 - use single rather than double quotes | print("salt: %s" % salt.hex())
line 170 - use single rather than double quotes | print("ciphertext length: %s" % len(ciphertext))
line 171 - use single rather than double quotes | print("mac: %s" % mac.hex())
line 172 - use single rather than double quotes | print("===")
line 176 - use single rather than double quotes | secret_input = b"%s%s%s" % (secret_data, subcredential, rev_counter_int_8)
line 179 - use single rather than double quotes | print("secret_data (%d): %s" % (len(secret_data), secret_data.hex()))
line 180 - use single rather than double quotes | print("subcredential (%d): %s" % (len(subcredential), subcredential.hex()))
line 181 - use single rather than double quotes | print("rev counter int 8 (%d): %s" % (len(rev_counter_int_8), rev_counter_int_8.hex()))
line 182 - use single rather than double quotes | print("secret_input (%s): %s" % (len(secret_input), secret_input.hex()))
line 183 - use single rather than double quotes | print("===")
line 185 - use single rather than double quotes | kdf = hashlib.shake_256(b"%s%s%s" % (secret_input, salt, string_constant))
line 186 - E226 missing whitespace around arithmetic operator | keys = kdf.digest(S_KEY_LEN+S_IV_LEN+MAC_KEY_LEN)
line 189 - E226 missing whitespace around arithmetic operator | secret_iv = keys[S_KEY_LEN:S_KEY_LEN+S_IV_LEN]
line 190 - E226 missing whitespace around arithmetic operator | mac_key = keys[S_KEY_LEN+S_IV_LEN:]
line 192 - use single rather than double quotes | print("secret_key: %s" % secret_key.hex())
line 193 - use single rather than double quotes | print("secret_iv: %s" % secret_iv.hex())
line 194 - use single rather than double quotes | print("mac_key: %s" % mac_key.hex())
line 203 - use single rather than double quotes | raise ValueError("Bad MAC!!!")
line 207 - E302 expected 2 blank lines, found 1 | def decrypt_outter_layer(superencrypted_blob_b64, revision_counter,
line 208 - E128 continuation line under-indented for visual indent | public_identity_key, blinded_key, subcredential):
line 210 - use single rather than double quotes | string_constant = b"hsdir-superencrypted-data"
line 218 - use single rather than double quotes | print("====== Decrypting outter layer =======")
line 221 - E128 continuation line under-indented for visual indent | public_identity_key, subcredential,
line 222 - E128 continuation line under-indented for visual indent | secret_data, string_constant)
line 224 - E302 expected 2 blank lines, found 1 | def decrypt_inner_layer(encrypted_blob_b64, revision_counter,
line 227 - use single rather than double quotes | string_constant = b"hsdir-encrypted-data"
line 229 - use single rather than double quotes | print("====== Decrypting inner layer =======")
line 235 - E302 expected 2 blank lines, found 1 | def parse_superencrypted_plaintext(outter_layer_plaintext):
line 237 - 're' imported but unused | import re
line 248 - W391 blank line at end of file
* /home/atagar/Desktop/stem/stem/descriptor/hidden_service.py
line 563 - use single rather than double quotes | raise ValueError("Onion address is required to decrypt v3 hidden service descriptors")
line 571 - local variable 'plaintext' is assigned to but never used | plaintext = self.decrypt_descriptor(desc_signing_cert)
line 587 - E266 too many leading '#' for block comment | ####################################### Do the decryption ###################################
line 590 - E128 continuation line under-indented for visual indent | identity_public_key_bytes, blinded_key_bytes, subcredential_bytes)
line 595 - E222 multiple spaces after operator | inner_layer_plaintext = stem.descriptor.hsv3_crypto.decrypt_inner_layer(inner_layer_ciphertext, self.revision_counter,
line 596 - E128 continuation line under-indented for visual indent | identity_public_key_bytes, blinded_key_bytes, subcredential_bytes)
line 602 - E305 expected 2 blank lines after class or function definition, found 1 | HiddenServiceDescriptor = HiddenServiceDescriptorV2
Stem uses two space indentations rather than four. Adjusting this new module to match the rest of the codebase.
Possible step back on my part, but we're attempting to keep enumeration names as short as possible (since stem users need to type these). Just minor tweaks.
Our validate() method already does this, but can't share the helper due to differing exception messages. This helper was tiny and did not need to check signing key size because our constructor already does so.
George is absolutely right that this method is too specific to server descriptors, but I cannot find the generic "validate()" method he's referring to. Just reached out to him on irc to discuss this. If we have a generic method that applies to both server and hidden service descriptors I'd be delighted to deprecate this, but for the moment at least I'm unsure how to proceed with this.
Moving hidden service description from the constructor into a method for a
couple reasons...
1. Wherever possible we lazy rather than eagerly evaluate descriptor content.
We do not know upfront what fields our user will want, so best to avoid
doing unnecessarily decryption (which is particularly cpu intensive)
unless our user indicates that they want this content.
2. We cannot modify constructor signatures without plumbing arguments through
several other methods. Not necessarily a no-go, but decryption requires an
onion_address whereas construction does not so separating this into its
own method sidesteps that headache.
Hashlib's sha3_256() method was only recently added in python 3.6... https://docs.python.org/3/library/hashlib.html ====================================================================== ERROR: test_for_decrypt ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 53, in test_for_decrypt desc._decrypt('sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion') File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 576, in _decrypt identity_public_key = stem.descriptor.hsv3_crypto.decode_address(onion_address) File "/home/atagar/Desktop/stem/stem/descriptor/hsv3_crypto.py", line 55, in decode_address my_checksum = hashlib.sha3_256(my_checksum_body).digest() AttributeError: 'module' object has no attribute 'sha3_256' ---------------------------------------------------------------------- If unavailable then falling back to pysha3, and if that's unavailable as well we'll need to raise an ImportError.
Python 3.5 added the hex() method. Prior to that binascii is used for hex conversion. https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3 ====================================================================== ERROR: test_for_decrypt ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 57, in test_for_decrypt desc._decrypt('sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion') File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 581, in _decrypt subcredential_bytes = stem.descriptor.hsv3_crypto.get_subcredential(identity_public_key_bytes, blinded_key_bytes) File "/home/atagar/Desktop/stem/stem/descriptor/hsv3_crypto.py", line 112, in get_subcredential print('public_identity_key: %s' % (public_identity_key.hex())) AttributeError: 'str' object has no attribute 'hex' ----------------------------------------------------------------------
Did I bugger something up? George's unit test fails for me with...
======================================================================
ERROR: test_for_decrypt
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 57, in test_for_decrypt
desc._decrypt('sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion')
File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 576, in _decrypt
identity_public_key = stem.descriptor.hsv3_crypto.decode_address(onion_address)
File "/home/atagar/Desktop/stem/stem/descriptor/hsv3_crypto.py", line 76, in decode_address
raise ValueError('Bad checksum (expected %s but was %s)' % (binascii.hexlify(checksum), binascii.hexlify(my_checksum)))
ValueError: Bad checksum (expected d3e8 but was c658fff6a9b3ba2e151d237641e9b50c74a93dc33a3dc149136b4e402ed79800)
----------------------------------------------------------------------
Checking with him on irc.
Neat! I didn't realize python 3.x added a to_bytes() method to the integer class. We can't use this just yet, but when we drop python 2.x support we will.
Oops, missed the 'descriptor' module part of these pydocs.
Our test's _helper_get_intro() provided a good recipie for creating introduction points. Productionizing this into a helper we can provide to make these without worrying about too many details.
Adapting a couple checks I disabled earlier.
Making all the arguments except address/port optional so callers can opt to skip them.
We convert keys to bytes in enough places that this warrants a helper. Oddly the HSv3PublicBlindedKey class didn't actually implement its public_bytes() method so replacing its calls.
This class' verify() method was never called, making it effectively a container for its single attribute.
Now that introduction points can encode themselves there's no value in this helper.
Moving the subset of ed25519_exts_ref that's used into hsv3_crypto to give myself one fewer modules to puzzle out.
I love that test_encode_decode_descriptor() exercises re-parsing a descriptor we create. Adding a more targeted test to do this only for introduction points. We can then add companion tests once the InnerLayer and OuterLayer classes have creation methods.
We already had a _decrypt_layer() helper from the last branch. While doing the same for encryption it became evedent that these helpers are mostly identical so refactoring the common crypto into a third function. Still not perfectly happy, but closer. :P
Maybe I'm missing something, but why not simply pad using the modulus?
InnerLayer creation, encryption, and test. While _get_superencrypted_blob() provided a great demo, it was limited to just introduction points. Now we'll support anything the layer does.
Similar approach as the inner layer. This will provide more flexibility once we propagate the attribute up HiddenServiceDescriptorV3.content().
Flattening the last content() helper so we can see all the remaining implementation in one spot. Getting close!
Now that we have all the building blocks in place we can tackle HSv3 descriptor
creation itself. Two main changes are...
1. More flexibility. All parameters are now customizable.
2. Simpler. All parameters have defaults so simply calling
HiddenServiceDescriptorV3.create() once again works.
This might *not* fully fix python3 support, but closer. I don't quite grok why but my openssl bindings have ed25519 support with python 2.7 but not 3.5. Oh well, fixing what I can for now. % python Python 2.7.12 (default, Oct 8 2019, 14:14:10) >>> import cryptography >>> cryptography.__version__ '2.7' >>> from cryptography.hazmat.backends.openssl.backend import backend >>> backend.ed25519_supported() True ------------------------------------------------------------ % python3 Python 3.5.2 (default, Oct 8 2019, 13:06:37) >>> import cryptography >>> cryptography.__version__ '2.8' >>> from cryptography.hazmat.backends.openssl.backend import backend >>> backend.ed25519_supported() False
Ooph, slow_ed25519.py warns that this shouldn't be run in production and now I see why. Each blinded key creation and signing takes three seconds, raising our unit test runtime from 6s to 51s. This complicates working on this branch so disabling these tests until I can sort this out. % ./run_tests.py --unit --test descriptor.hidden_service_v3 --verbose ====================================================================== test.unit.descriptor.hidden_service_v3.TestHiddenServiceDescriptorV3 ====================================================================== test_address_from_public_key 0 ms [SUCCESS] test_decryption 3 ms [SUCCESS] test_encode_decode_descriptor 2.94s [SUCCESS] test_inner_layer 0 ms [SUCCESS] test_inner_layer_creation 3 ms [SUCCESS] test_intro_point_creation 0 ms [SUCCESS] test_intro_point_crypto 0 ms [SUCCESS] test_intro_point_crypto_without_prereq 0 ms [SUCCESS] test_intro_point_encode 0 ms [SUCCESS] test_intro_point_parse 0 ms [SUCCESS] test_invalid_lifetime 9.05s [SUCCESS] test_invalid_revision_counter 9.12s [SUCCESS] test_invalid_version 8.98s [SUCCESS] test_outer_layer 0 ms [SUCCESS] test_outer_layer_creation 3 ms [SUCCESS] test_public_key_from_address 0 ms [SUCCESS] test_real_descriptor 1 ms [SUCCESS] test_required_fields 18.31s [SUCCESS] ----------------------------------------------------------------------
Now that we've revised HiddenServiceDescriptorV3.content() we can test it in a similar fashion to inner/outer layers. This provides the same coverage as test_encode_decode_descriptor() so that test is now redundant. Fixing a few bugs this spotted along the way and renaming the 'public_key_from_address' functions to specify that they take identity keys instead (we have so many key types I lost track of what these truly did when I originally tacked 'em on).
I won't pretend to understand this math. A smarter mind than mine (asn's) came up with this crypto. Just massaging it into a form I find easier to understand.
Resuming our HSv3 tests, with blinding mocked out so we don't negatively impact runtime (without these mocks the unit tests jump from 6s => 51s).
On reflection, why not simply disable blinding by default? Blinding parameters are unnecessary for the vast majority of use cases, and when needed the caller can simply provide a nonce (and by extension accept the lengthy runtime). We can always re-enable blinding as a default if/when we have a performant implementation.
Cryptographically valid support for hidden service creation... https://trac.torproject.org/projects/tor/ticket/31823 HSv3 descriptors consist of three parts: an inner layer, outer layer, and the descriptor itself. Callers of HiddenServiceDescriptorV3's create() and content() methods can supply these to specify that layer's parameters. For example, to supply custom introduction points with random key material simply call... HiddenServiceDescriptorV3.content( inner_layer = InnerLayer.create( introduction_points = [ IntroductionPointV3.create('1.1.1.1', 9001), IntroductionPointV3.create('2.2.2.2', 9001), IntroductionPointV3.create('3.3.3.3', 9001), ], ), )
Oops, turns out the cryptography module doesn't always supply this method...
Traceback (most recent call last):
File "./run_tests.py", line 36, in <module>
import test.runner
File "/srv/jenkins-workspace/workspace/stem-tor-ci/test/runner.py", line 44, in <module>
import stem.connection
File "/srv/jenkins-workspace/workspace/stem-tor-ci/stem/connection.py", line 136, in <module>
import stem.control
File "/srv/jenkins-workspace/workspace/stem-tor-ci/stem/control.py", line 271, in <module>
import stem.descriptor.microdescriptor
File "/srv/jenkins-workspace/workspace/stem-tor-ci/stem/descriptor/__init__.py", line 1544, in <module>
import stem.descriptor.hidden_service
File "/srv/jenkins-workspace/workspace/stem-tor-ci/stem/descriptor/hidden_service.py", line 81, in <module>
X25519_AVAILABLE = backend.x25519_supported()
AttributeError: 'Backend' object has no attribute 'x25519_supported'
Jenkins has long struggled with this assertion, and I see these failures
locally from time to time too...
======================================================================
FAIL: test_query_with_timeout
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/home/atagar/Desktop/stem/test/unit/descriptor/remote.py", line 387, in test_query_with_timeout
self.assertEqual(2, dirport_mock.call_count)
AssertionError: 2 != 3
----------------------------------------------------------------------
No assertion is better than a flaky one, so dropping this last bit.
Thanks to asn we now have an upstream ticket for the ed25519 blinding support we need.
| return _descriptor_content(attr, exclude, ( | ||
| ('desc-auth-type', 'x25519'), | ||
| ('desc-auth-ephemeral-key', base64.b64encode(os.urandom(32))), | ||
| ), ( |
Similar to the code above (but this more important), Tor will refuse to parse descriptors that don't contain at least one auth-client element. That was the purpose of my old _get_middle_descriptor_layer_body() function that got removed. We should output at least one such element since otherwise the descriptor is bogus, and we might want to consider adding 16 of them as Tor does to remain indistinguishable from it.
We still need to output an auth-client line here otherwise the descriptor is not parseable by Tor.
Hi asn. According to our spec 'auth-client' is not a mandatory field and as such, excluded when creating a minimal descriptor (defaults are only specified for required fields). Tor should be able to parse descriptors without auth-client lines - otherwise that's a bug either with the spec or tor.
Ouch! Yes you are absolutely right. This is a bug in the spec, because we definitely don't accept descriptors with zero auth-client fields right now. I opened ticket #32563 about fixing this part of the spec.
| return IntroductionPointV3(link_specifiers, onion_key, auth_key_cert, enc_key, enc_key_cert, legacy_key, legacy_key_cert) | ||
|
|
||
| @staticmethod | ||
| def create(address, port, expiration = None, onion_key = None, enc_key = None, auth_key = None, signing_key = None): |
Hmm, seems like the constructor here only allows us to specify address/port, but usually HSv3 descriptor introduction points contain other sorts of link specifiers too (particularly fingeprrint and ed25519). Would it be possible to support more kinds of link specifiers here?
Yup! I wasn't sure what API would be most useful for callers so I put this together as a demo. As the pydoc says...
"Simplified constructor. For more sophisticated use cases you can use this as a template for how introduction points are properly created."
What API would you like?
Hmm, I'm not quite sure. Perhaps we can pass a list of link specifiers directly to the simplfied constructor? Or allow more arguments like ed25519_identity and fingerprint to the simplified constructor? Or I can use the non-simplified constructor if this is possible?
I think I'm OK with all the above as long as the functionality is possible in the end. What would you prefer?
No description provided.
The text was updated successfully, but these errors were encountered: