diff --git a/linked_data_sig.py b/linked_data_sig.py index f36cc288f..abe4a9348 100644 --- a/linked_data_sig.py +++ b/linked_data_sig.py @@ -24,47 +24,65 @@ except ImportError: from pyjsonld import normalize -def _options_hash(doc): - doc = dict(doc["signature"]) +def _options_hash(doc: {}) -> str: + """Returns a hash of the signature, with a few fields removed + """ + docSig = dict(doc["signature"]) + + # remove fields from signature for k in ["type", "id", "signatureValue"]: - if k in doc: - del doc[k] - doc["@context"] = "https://w3id.org/identity/v1" + if k in docSig: + del docSig[k] + + docSig["@context"] = "https://w3id.org/identity/v1" options = { "algorithm": "URDNA2015", "format": "application/nquads" } - normalized = normalize(doc, options) + + normalized = normalize(docSig, options) h = hashlib.new("sha256") h.update(normalized.encode("utf-8")) return h.hexdigest() -def _doc_hash(doc): +def _doc_hash(doc: {}) -> str: + """Returns a hash of the ActivityPub post + """ doc = dict(doc) + + # remove the signature if "signature" in doc: del doc["signature"] + options = { "algorithm": "URDNA2015", "format": "application/nquads" } + normalized = normalize(doc, options) h = hashlib.new("sha256") h.update(normalized.encode("utf-8")) return h.hexdigest() -def verifyJsonSignature(doc: {}, publicKeyPem: str): +def verifyJsonSignature(doc: {}, publicKeyPem: str) -> bool: + """Returns True if the given ActivityPub post was sent + by an actor having the given public key + """ key = RSA.importKey(publicKeyPem) to_be_signed = _options_hash(doc) + _doc_hash(doc) signature = doc["signature"]["signatureValue"] signer = PKCS1_v1_5.new(key) # type: ignore digest = SHA256.new() digest.update(to_be_signed.encode("utf-8")) - return signer.verify(digest, base64.b64decode(signature)) # type: ignore + base64sig = base64.b64decode(signature) + return signer.verify(digest, base64sig) # type: ignore -def generateJsonSignature(doc: {}, privateKeyPem: str): +def generateJsonSignature(doc: {}, privateKeyPem: str) -> None: + """Adds a json signature to the given ActivityPub post + """ if not doc.get('actor'): return