Enable checking of json signatures on inbox posts

merge-requests/8/head
Bob Mottram 2021-01-03 18:20:25 +00:00
parent b9d33296a1
commit 77f965162c
5 changed files with 51 additions and 24 deletions

View File

@ -1079,6 +1079,8 @@ class PubServer(BaseHTTPRequestHandler):
elif self.headers.get('content-length'):
headersDict['content-length'] = self.headers['content-length']
originalMessageJson = messageJson.copy()
# For follow activities add a 'to' field, which is a copy
# of the object field
messageJson, toFieldExists = \
@ -1097,7 +1099,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix,
nickname,
self.server.domainFull,
messageJson,
messageJson, originalMessageJson,
messageBytesDecoded,
headersDict,
self.path,

View File

@ -313,6 +313,7 @@ def inboxPermittedMessage(domain: str, messageJson: {},
def savePostToInboxQueue(baseDir: str, httpPrefix: str,
nickname: str, domain: str,
postJsonObject: {},
originalPostJsonObject: {},
messageBytes: str,
httpHeaders: {},
postPath: str, debug: bool) -> str:
@ -437,6 +438,7 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
'httpHeaders': httpHeaders,
'path': postPath,
'post': postJsonObject,
'original': originalPostJsonObject,
'digest': digest,
'filename': filename,
'destination': destination
@ -2703,24 +2705,30 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
if debug:
print('DEBUG: http header signature check success')
if not queueJson['post'].get('signature'):
print('WARN: jsonld inbox signature signature missing from ' +
keyId)
# else:
# if not jsonldVerify(queueJson['post'], pubKey):
# hasJsonSig = False
# if debug:
# print('**************************************')
# print('WARN: jsonld signature check failed ' +
# str(queueJson['post']))
# print('--------------------------------------')
# print(keyId)
# print(pubKey)
# print('**************************************')
# else:
# if debug:
# print('jsonld inbox signature check success')
#
# should the json signature be checked?
checkJsonSignature = False
if queueJson['original'].get('@context'):
checkJsonSignature = True
if not queueJson['original'].get('signature'):
print('WARN: jsonld inbox signature signature missing from ' +
keyId)
checkJsonSignature = False
# check json signature
if checkJsonSignature:
# use the original json message received, not one which may have
# been modified along the way
if not jsonldVerify(queueJson['original'], pubKey):
print('WARN: jsonld signature check failed ' +
keyId + ' ' + pubKey + ' ' +
str(queueJson['original']))
if os.path.isfile(queueFilename):
os.remove(queueFilename)
if len(queue) > 0:
queue.pop(0)
continue
else:
print('jsonld inbox signature check success')
# set the id to the same as the post filename
# This makes the filename and the id consistent

View File

@ -116,6 +116,9 @@ def jsonldSign(jldDocument: {}, privateKeyPem: str) -> {}:
"""
Produces a signed JSON-LD document with a Json Web Signature
"""
if not jldDocument.get('@context'):
print('WARN: json document must have @context to sign')
return jldDocument
jldDocument = deepcopy(jldDocument)
normalizedJldHash = _jsonldNormalize(jldDocument)
jwsSignature = _signJws(normalizedJldHash, privateKeyPem)
@ -135,6 +138,11 @@ def jsonldVerify(signedJldDocument: {}, publicKeyPem: str) -> bool:
"""
Verifies the Json Web Signature of a signed JSON-LD Document
"""
if not isinstance(signedJldDocument, dict):
return False
if not signedJldDocument.get('@context'):
print('json document must have @context')
return False
signedJldDocument = deepcopy(signedJldDocument)
signature = signedJldDocument.pop('signature')
jwsSignature = signature['signatureValue'].encode('utf-8')

View File

@ -234,7 +234,7 @@ def link(input_, ctx, options=None):
return frame(input, frame, options)
def normalize(input_, options=None):
def normalize(input_: {}, options=None):
"""
Performs JSON-LD normalization.
@ -1016,6 +1016,13 @@ class JsonLdProcessor(object):
'Could not convert input to RDF dataset before normalization.',
'jsonld.NormalizeError', cause=cause)
# check that the data is not empty
if '@default' in dataset:
if not dataset['@default']:
raise JsonLdError(
'Could not convert input to RDF dataset.',
'jsonld.NormalizeError', cause=None)
# do normalization
return self._normalize(dataset, options)

View File

@ -1978,6 +1978,7 @@ def testRemoveTextFormatting():
def testJsonld():
print("testJsonld")
jldDocument = {
"@context": "https://www.w3.org/ns/activitystreams",
"description": "My json document",
"numberField": 83582,
"object": {
@ -2031,10 +2032,11 @@ def testJsonld():
assert(signedDocument['signature']['type'] == 'RsaSignatureSuite2017')
assert(jsonldVerify(signedDocument, publicKeyPem))
# alter the signed document
# signedDocument['object']['content'] = 'forged content'
# assert(not jsonldVerify(signedDocument, publicKeyPem))
signedDocument['object']['content'] = 'forged content'
assert(not jsonldVerify(signedDocument, publicKeyPem))
jldDocument2 = {
"@context": "https://www.w3.org/ns/activitystreams",
"description": "Another json document",
"numberField": 13353,
"object": {
@ -2049,8 +2051,8 @@ def testJsonld():
if signedDocument['signature']['signatureValue'] == \
signedDocument2['signature']['signatureValue']:
print('json signature has not changed for different documents')
# assert(signedDocument['signature']['signatureValue'] !=
# signedDocument2['signature']['signatureValue'])
assert(signedDocument['signature']['signatureValue'] !=
signedDocument2['signature']['signatureValue'])
def testSiteIsActive():