class DirKeyCertificateObject(TorDocumentObject): START_ITEM = ItemInt('dir-key-certificate-version') ITEMS = [ # fingerprint 14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 Item('fingerprint'), # dir-key-published 2019-06-01 00:00:00 ItemDate('dir-key-published'), # dir-key-expires 2019-11-01 00:00:00 ItemDate('dir-key-expires'), ItemMulti('dir-identity-key', 'rsa public key'), ItemMulti('dir-signing-key', 'rsa public key'), ItemMulti('dir-key-crosscert', 'id signature'), ItemMulti('dir-key-certification', 'signature'), ]
class NetworkStatusDocument(TorDocument): DOCUMENT_NAME = 'network_status' # "network-status-version" SP version NL # [At start, exactly once.] # network-status-version 3 START_ITEM = ItemInt('network-status-version') ITEMS = [ # "vote-status" SP type NL # [Exactly once.] # vote-status consensus Item('vote-status'), # "consensus-method" SP Integer NL # [At most once for consensuses; does not occur in votes.] # [No extra arguments] # consensus-method 28 ItemInt('consensus-method'), # "valid-after" SP YYYY-MM-DD SP HH:MM:SS NL # [Exactly once.] # valid-after 2019-07-20 21:00:00 ItemDate('valid-after'), # "fresh-until" SP YYYY-MM-DD SP HH:MM:SS NL # [Exactly once.] # fresh-until 2019-07-20 22:00:00 ItemDate('fresh-until'), # "valid-until" SP YYYY-MM-DD SP HH:MM:SS NL # [Exactly once.] # valid-until 2019-07-21 00:00:00 ItemDate('valid-until'), # "voting-delay" SP VoteSeconds SP DistSeconds NL # [Exactly once.] # voting-delay 300 300 Item('voting-delay'), # "client-versions" SP VersionList NL # [At most once.] # client-versions 0.2.9.16,0.2.9.17,0.3.5.7,0.3.5.8,0.4.0.5,0.4.0.6,0.4.1.2-alpha,0.4.1.3-alpha,0.4.1.4-rc Item('client-versions'), # "server-versions" SP VersionList NL # [At most once.] # server-versions 0.2.9.15,0.2.9.16,0.2.9.17,0.3.5.8,0.4.0.5,0.4.0.6,0.4.1.2-alpha,0.4.1.3-alpha,0.4.1.4-rc Item('server-versions'), # "package" SP PackageName SP Version SP URL SP DIGESTS NL # [Any number of times.] # Included in consensuses only for method 19 and later. # "known-flags" SP FlagList NL # [Exactly once.] # known-flags Authority BadExit Exit Fast Guard HSDir NoEdConsensus Running Stable StaleDesc V2Dir Valid Item('known-flags'), # "recommended-client-protocols" SP Entries NL # [At most once.] # recommended-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 ... Item('recommended-client-protocols'), # "recommended-relay-protocols" SP Entries NL # [At most once.] # recommended-relay-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 ... Item('recommended-relay-protocols'), # "required-client-protocols" SP Entries NL # [At most once.] # required-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 ...` Item('required-client-protocols'), # "required-relay-protocols" SP Entries NL # [At most once.] # required-relay-protocols Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4 ... Item('required-relay-protocols'), # "params" SP [Parameters] NL # [At most once] # params CircuitPriorityHalflifeMsec=30000 DoSCircuitCreationEnabled=1 DoSConnectionEnabled=1 ... Item('params'), # "shared-rand-previous-value" SP NumReveals SP Value NL # [At most once] # shared-rand-previous-value 9 ybFb42KVOFmJR/EMtjPJNJiTBDyiI0eefmebenN9EY0= Item('shared-rand-previous-value'), # "shared-rand-current-value" SP NumReveals SP Value NL # [At most once] # shared-rand-current-value 9 p4+CMGa6M7EhDqGNpofcJ2MeQ7f7qdF8QslK+AOnrQg= Item('shared-rand-current-value'), ItemObject(DirSourceObject, out_name='voters'), ItemObject(RouterObject, out_name='routers'), # "directory-signature" [SP Algorithm] SP identity SP signing-key-digest # NL Signature ItemSignature('directory-signature'), ] def __init__(self, raw_string): super().__init__( raw_string, digests_names=['sha1', 'sha3_256'], digest_start='network-status-version', digest_end='directory-signature ', ) def link_consensus(self, consensus): for router in self.routers: router._consensus = consensus @property def is_fresh(self): return self.valid_until > datetime.utcnow() @property def digest_sha1(self): return self.get_digest('sha1') @property def digest_sha3_256(self): return self.get_digest('sha3_256') def find_signature(self, identity): for sign in self.signatures: if sign['identity'] == identity: return sign def apply_diff(self, diff): logger.info('Apply network-status-diff for %s to %s', self.digest_sha3_256.hex(), diff.to_digest.lower()) assert self.digest_sha3_256.hex() == diff.from_digest.lower() lines = self.raw_string.split('\n') cur_line = 1 for action in diff.actions: cur_end = len(lines) cur_line = action.apply(lines, cur_line, cur_end) raw_string_new = '\n'.join(lines) + '\n' assert sha3_256( raw_string_new.encode()).hex() == diff.to_digest.lower() return NetworkStatusDocument(raw_string_new)