[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Working onion-key-crosscert verification
commit ba1796674172f837e931033d8a060e435b768744
Author: Patrick O'Doherty <p@xxxxxxxxxxx>
Date: Sun Feb 5 17:08:58 2017 -0800
Working onion-key-crosscert verification
Compares the digest in the signature block provided with a calculated
onion-key-crosscert digest and raises a ValueError if they do not match.
---
stem/descriptor/certificate.py | 6 +++++-
stem/descriptor/server_descriptor.py | 38 ++++++++++++++++++++++++++----------
2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index e26992f..63ebace 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -162,7 +162,11 @@ class Ed25519KeyCertificate(Certificate):
signed_part = descriptor[:descriptor.index('router-sig-ed25519 ') + len('router-sig-ed25519 ')]
descriptor_with_prefix = ED25519_ROUTER_SIGNATURE_PREFIX + signed_part
descriptor_sha256_digest = hashlib.sha256(descriptor_with_prefix).digest()
- verify_key.verify(descriptor_sha256_digest, signature_bytes)
+
+ try:
+ verify_key.verify(descriptor_sha256_digest, signature_bytes)
+ except BadSignatureError:
+ raise ValueError('Descriptor Ed25519 certificate signature invalid')
def _verify_signature(self):
if self.identity_key:
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index c5bcaad..7d134dd 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -34,6 +34,7 @@ etc). This information is provided from a few sources...
import functools
import hashlib
import re
+import base64
import stem.descriptor.extrainfo_descriptor
import stem.exit_policy
@@ -760,23 +761,22 @@ class RelayDescriptor(ServerDescriptor):
if signed_digest != self.digest():
raise ValueError('Decrypted digest does not match local digest (calculated: %s, local: %s)' % (signed_digest, self.digest()))
+ if self.onion_key_crosscert:
+ onion_key_crosscert_digest = self._digest_for_signature(self.onion_key, self.onion_key_crosscert)
+ if onion_key_crosscert_digest != self.onion_key_crosscert_digest():
+ raise ValueError('Decrypted onion-key-crosscert digest does not match local digest (calculated: %s, local: %s)' % (onion_key_crosscert_digest, self.onion_key_crosscert_digest()))
+
if stem.prereq.is_nacl_available() and self.ed25519_certificate:
self.certificate = _parse_certificate(_bytes_for_block(self.ed25519_certificate),
self.ed25519_master_key,
validate)
- if self.ed25519_master_key is not None:
- if self.certificate.identity_key != self.ed25519_master_key:
- raise ValueError("master-key-ed25519 does not match ed25519 certificate identity key")
+ if self.certificate.identity_key != self.ed25519_master_key:
+ raise ValueError("master-key-ed25519 does not match ed25519 certificate identity key")
- self.certificate.verify_descriptor_signature(stem.util.str_tools._to_unicode(raw_contents),
+ self.certificate.verify_descriptor_signature(raw_contents,
self.ed25519_signature)
- onion_key_bytes = _bytes_for_block(self.onion_key)
- from Crypto.Util import asn1
- seq = asn1.DerSequence()
- seq.decode(onion_key_bytes)
- self._digest_for_signature(self.onion_key, self.onion_key_crosscert)
@lru_cache()
@@ -786,11 +786,29 @@ class RelayDescriptor(ServerDescriptor):
:returns: the digest string encoded in uppercase hex
- :raises: ValueError if the digest canot be calculated
+ :raises: ValueError if the digest cannot be calculated
"""
return self._digest_for_content(b'router ', b'\nrouter-signature\n')
+
+ @lru_cache()
+ def onion_key_crosscert_digest(self):
+ """
+ Provides the digest of the onion-key-crosscert data consisting of the following:
+
+ 1. SHA1 digest of the RSA identity key
+ 2. the ed25519 identity key
+
+ :returns: the digest encoded in uppercase hex
+
+ :raises: ValueError if the digest cannot be calculated
+ """
+ signing_key_digest = hashlib.sha1(_bytes_for_block(self.signing_key)).digest()
+ data = signing_key_digest + base64.b64decode(self.ed25519_master_key + b'=')
+ return data.encode("hex").upper()
+
+
def _compare(self, other, method):
if not isinstance(other, RelayDescriptor):
return False
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits