mirror of https://gitlab.com/bashrc2/epicyon
Calculate message body digest from incoming bytes to avoid any json conversion issues
parent
ffde81d909
commit
1b1810ff8a
15
daemon.py
15
daemon.py
|
@ -383,7 +383,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.projectVersion)
|
||||
return True
|
||||
|
||||
def _updateInboxQueue(self,nickname: str,messageJson: {}) -> int:
|
||||
def _updateInboxQueue(self,nickname: str,messageJson: {},messageBytes: str) -> int:
|
||||
"""Update the inbox queue
|
||||
"""
|
||||
# Check if the queue is full
|
||||
|
@ -410,11 +410,12 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
|
||||
# save the json for later queue processing
|
||||
queueFilename = \
|
||||
savePostToInboxQueue(self.server.baseDir, \
|
||||
self.server.httpPrefix, \
|
||||
nickname, \
|
||||
self.server.domainFull, \
|
||||
savePostToInboxQueue(self.server.baseDir,
|
||||
self.server.httpPrefix,
|
||||
nickname,
|
||||
self.server.domainFull,
|
||||
messageJson,
|
||||
messageBytes.decode('utf-8'),
|
||||
headersDict,
|
||||
self.path,
|
||||
self.server.debug)
|
||||
|
@ -2750,7 +2751,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
else:
|
||||
self.postToNickname=pathUsersSection.split('/')[0]
|
||||
if self.postToNickname:
|
||||
queueStatus=self._updateInboxQueue(self.postToNickname,messageJson)
|
||||
queueStatus=self._updateInboxQueue(self.postToNickname,messageJson,messageBytes)
|
||||
if queueStatus==0:
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
|
@ -2771,7 +2772,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
else:
|
||||
if self.path == '/sharedInbox' or self.path == '/inbox':
|
||||
print('DEBUG: POST to shared inbox')
|
||||
queueStatus=self._updateInboxQueue('inbox',messageJson)
|
||||
queueStatus=self._updateInboxQueue('inbox',messageJson,messageBytes)
|
||||
if queueStatus==0:
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
|
|
19
httpsig.py
19
httpsig.py
|
@ -19,12 +19,16 @@ import json
|
|||
from time import gmtime, strftime
|
||||
from pprint import pprint
|
||||
|
||||
def messageContentDigest(messageBodyJsonStr: str) -> str:
|
||||
return base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest()).decode('utf-8')
|
||||
|
||||
def signPostHeaders(dateStr: str,privateKeyPem: str, \
|
||||
nickname: str, \
|
||||
domain: str,port: int, \
|
||||
toDomain: str,toPort: int, \
|
||||
path: str, \
|
||||
httpPrefix: str, messageBodyJson: {}) -> str:
|
||||
httpPrefix: str, \
|
||||
messageBodyJson: {}) -> str:
|
||||
"""Returns a raw signature string that can be plugged into a header and
|
||||
used to verify the authenticity of an HTTP transmission.
|
||||
"""
|
||||
|
@ -45,8 +49,7 @@ def signPostHeaders(dateStr: str,privateKeyPem: str, \
|
|||
headers = {'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'content-type': 'application/json'}
|
||||
else:
|
||||
messageBodyJsonStr=json.dumps(messageBodyJson)
|
||||
bodyDigest = \
|
||||
base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest()).decode('utf-8')
|
||||
bodyDigest=messageContentDigest(messageBodyJsonStr)
|
||||
headers = {'(request-target)': f'post {path}','host': toDomain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': 'application/activity+json'}
|
||||
privateKeyPem = RSA.import_key(privateKeyPem)
|
||||
#headers.update({
|
||||
|
@ -101,8 +104,7 @@ def createSignedHeader(privateKeyPem: str,nickname: str, \
|
|||
path,httpPrefix,None)
|
||||
else:
|
||||
messageBodyJsonStr=json.dumps(messageBodyJson)
|
||||
bodyDigest = \
|
||||
base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest()).decode('utf-8')
|
||||
bodyDigest=messageContentDigest(messageBodyJsonStr)
|
||||
print('***************************Send (request-target): post '+path)
|
||||
print('***************************Send host: '+headerDomain)
|
||||
print('***************************Send date: '+dateStr)
|
||||
|
@ -120,6 +122,7 @@ def createSignedHeader(privateKeyPem: str,nickname: str, \
|
|||
|
||||
def verifyPostHeaders(httpPrefix: str,publicKeyPem: str,headers: dict, \
|
||||
path: str,GETmethod: bool, \
|
||||
messageBodyDigest: str, \
|
||||
messageBodyJsonStr: str) -> bool:
|
||||
"""Returns true or false depending on if the key that we plugged in here
|
||||
validates against the headers, method, and path.
|
||||
|
@ -153,8 +156,10 @@ def verifyPostHeaders(httpPrefix: str,publicKeyPem: str,headers: dict, \
|
|||
f'(request-target): {method.lower()} {path}')
|
||||
print('***************************Verify (request-target): '+method.lower()+' '+path)
|
||||
elif signedHeader == 'digest':
|
||||
bodyDigest = \
|
||||
base64.b64encode(SHA256.new(messageBodyJsonStr.strip().encode()).digest()).decode('utf-8')
|
||||
if messageBodyDigest:
|
||||
bodyDigest=messageBodyDigest
|
||||
else:
|
||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
||||
signedHeaderList.append(f'digest: SHA-256={bodyDigest}')
|
||||
print('***************************Verify digest: SHA-256='+bodyDigest)
|
||||
print('***************************Verify messageBodyJsonStr: '+messageBodyJsonStr)
|
||||
|
|
5
inbox.py
5
inbox.py
|
@ -41,6 +41,7 @@ from like import undoLikesCollectionEntry
|
|||
from blocking import isBlocked
|
||||
from filters import isFiltered
|
||||
from announce import updateAnnounceCollection
|
||||
from httpsig import messageContentDigest
|
||||
|
||||
def validInbox(baseDir: str,nickname: str,domain: str) -> bool:
|
||||
"""Checks whether files were correctly saved to the inbox
|
||||
|
@ -165,7 +166,7 @@ def validPublishedDate(published) -> bool:
|
|||
return False
|
||||
return True
|
||||
|
||||
def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str,postJsonObject: {},httpHeaders: {},postPath: str,debug: bool) -> str:
|
||||
def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str,postJsonObject: {},messageBytes: str,httpHeaders: {},postPath: str,debug: bool) -> str:
|
||||
"""Saves the give json to the inbox queue for the person
|
||||
keyId specifies the actor sending the post
|
||||
"""
|
||||
|
@ -241,6 +242,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str
|
|||
'httpHeaders': httpHeaders,
|
||||
'path': postPath,
|
||||
'post': postJsonObject,
|
||||
'digest': messageContentDigest(messageBytes),
|
||||
'filename': filename,
|
||||
'destination': destination
|
||||
}
|
||||
|
@ -1156,6 +1158,7 @@ def runInboxQueue(projectVersion: str, \
|
|||
pubKey, \
|
||||
queueJson['httpHeaders'], \
|
||||
queueJson['path'],False, \
|
||||
queueJson['digest'], \
|
||||
json.dumps(queueJson['post'])):
|
||||
if debug:
|
||||
print('DEBUG: Header signature check failed')
|
||||
|
|
14
tests.py
14
tests.py
|
@ -111,14 +111,14 @@ def testHttpsigBase(withDigest):
|
|||
boxpath, httpPrefix, messageBodyJson)
|
||||
|
||||
headers['signature'] = signatureHeader
|
||||
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, \
|
||||
boxpath,False, \
|
||||
assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \
|
||||
boxpath,False,None, \
|
||||
messageBodyJsonStr)
|
||||
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, \
|
||||
'/parambulator'+boxpath,False, \
|
||||
assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \
|
||||
'/parambulator'+boxpath,False,None, \
|
||||
messageBodyJsonStr) == False
|
||||
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, \
|
||||
boxpath,True, \
|
||||
assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \
|
||||
boxpath,True,None, \
|
||||
messageBodyJsonStr) == False
|
||||
if not withDigest:
|
||||
# fake domain
|
||||
|
@ -130,7 +130,7 @@ def testHttpsigBase(withDigest):
|
|||
headers = {'host': domain,'date': dateStr,'digest': f'SHA-256={bodyDigest}','content-type': contentType}
|
||||
headers['signature'] = signatureHeader
|
||||
assert verifyPostHeaders(httpPrefix,publicKeyPem,headers, \
|
||||
boxpath,True, \
|
||||
boxpath,True,None, \
|
||||
messageBodyJsonStr) == False
|
||||
os.chdir(baseDir)
|
||||
shutil.rmtree(path)
|
||||
|
|
Loading…
Reference in New Issue