Merge branch 'main' of gitlab.com:bashrc2/epicyon

merge-requests/30/head
Bob Mottram 2021-11-22 23:07:05 +00:00
commit ff3fba4c79
6 changed files with 269 additions and 133 deletions

View File

@ -242,7 +242,6 @@ from like import updateLikesCollection
from reaction import updateReactionCollection
from utils import undoReactionCollectionEntry
from utils import getNewPostEndpoints
from utils import malformedCiphertext
from utils import hasActor
from utils import setReplyIntervalHours
from utils import canReplyTo
@ -451,6 +450,8 @@ class PubServer(BaseHTTPRequestHandler):
# https://tools.ietf.org/html/
# draft-ietf-httpbis-message-signatures-01
return self.headers['Signature-Input']
elif self.headers.get('signature-input'):
return self.headers['signature-input']
elif self.headers.get('signature'):
# Ye olde Masto http sig
return self.headers['signature']
@ -728,7 +729,9 @@ class PubServer(BaseHTTPRequestHandler):
return False
# verify the GET request without any digest
if verifyPostHeaders(self.server.httpPrefix, pubKey, self.headers,
if verifyPostHeaders(self.server.httpPrefix,
self.server.domainFull,
pubKey, self.headers,
self.path, True, None, '', self.server.debug):
return True
@ -1503,11 +1506,6 @@ class PubServer(BaseHTTPRequestHandler):
# save the json for later queue processing
messageBytesDecoded = messageBytes.decode('utf-8')
if malformedCiphertext(messageBytesDecoded):
print('WARN: post contains malformed ciphertext ' +
str(originalMessageJson))
return 4
if containsInvalidLocalLinks(messageBytesDecoded):
print('WARN: post contains invalid local links ' +
str(originalMessageJson))

View File

@ -11,7 +11,7 @@ __module_group__ = "Security"
# see https://tools.ietf.org/html/draft-cavage-http-signatures-06
#
# This might change in future
# see https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01
# see https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_private_key
@ -116,11 +116,11 @@ def signPostHeadersNew(dateStr: str, privateKeyPem: str,
path: str,
httpPrefix: str,
messageBodyJsonStr: str,
algorithm: str) -> (str, str):
algorithm: str, debug: bool) -> (str, str):
"""Returns a raw signature strings that can be plugged into a header
as "Signature-Input" and "Signature"
used to verify the authenticity of an HTTP transmission.
See https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-01
See https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures
"""
domain = getFullDomain(domain, port)
@ -137,18 +137,17 @@ def signPostHeadersNew(dateStr: str, privateKeyPem: str,
keyID = localActorUrl(httpPrefix, nickname, domain) + '#main-key'
if not messageBodyJsonStr:
headers = {
'*request-target': f'post {path}',
'*created': str(secondsSinceEpoch),
'@request-target': f'get {path}',
'@created': str(secondsSinceEpoch),
'host': toDomain,
'date': dateStr,
'content-type': 'application/json'
'date': dateStr
}
else:
bodyDigest = messageContentDigest(messageBodyJsonStr)
contentLength = len(messageBodyJsonStr)
headers = {
'*request-target': f'post {path}',
'*created': str(secondsSinceEpoch),
'@request-target': f'post {path}',
'@created': str(secondsSinceEpoch),
'host': toDomain,
'date': dateStr,
'digest': f'SHA-256={bodyDigest}',
@ -164,6 +163,10 @@ def signPostHeadersNew(dateStr: str, privateKeyPem: str,
signedHeaderText += f'{headerKey}: {headers[headerKey]}\n'
signedHeaderText = signedHeaderText.strip()
if debug:
print('\nsignPostHeadersNew signedHeaderText:\n' +
signedHeaderText + '\nEND\n')
# Sign the digest. Potentially other signing algorithms can be added here.
signature = ''
if algorithm == 'rsa-sha512':
@ -269,7 +272,8 @@ def _verifyRecentSignature(signedDateStr: str) -> bool:
return True
def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
def verifyPostHeaders(httpPrefix: str,
publicKeyPem: str, headers: dict,
path: str, GETmethod: bool,
messageBodyDigest: str,
messageBodyJsonStr: str, debug: bool,
@ -298,8 +302,11 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
pubkey = load_pem_public_key(publicKeyPem.encode('utf-8'),
backend=default_backend())
# Build a dictionary of the signature values
if headers.get('Signature-Input'):
signatureHeader = headers['Signature-Input']
if headers.get('Signature-Input') or headers.get('signature-input'):
if headers.get('Signature-Input'):
signatureHeader = headers['Signature-Input']
else:
signatureHeader = headers['signature-input']
fieldSep2 = ','
# split the signature input into separate fields
signatureDict = {
@ -312,7 +319,8 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
if v.startswith('('):
requestTargetKey = k
requestTargetStr = v[1:-1]
break
elif v.startswith('"'):
signatureDict[k] = v[1:-1]
if not requestTargetKey:
return False
signatureDict[requestTargetKey] = requestTargetStr
@ -341,19 +349,40 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
# original Mastodon http signature
appendStr = f'(request-target): {method.lower()} {path}'
signedHeaderList.append(appendStr)
elif '*request-target' in signedHeader:
elif '@request-target' in signedHeader:
# https://tools.ietf.org/html/
# draft-ietf-httpbis-message-signatures-01
appendStr = f'*request-target: {method.lower()} {path}'
# remove ()
# if appendStr.startswith('('):
# appendStr = appendStr.split('(')[1]
# if ')' in appendStr:
# appendStr = appendStr.split(')')[0]
# draft-ietf-httpbis-message-signatures
appendStr = f'@request-target: {method.lower()} {path}'
signedHeaderList.append(appendStr)
elif '@created' in signedHeader:
if signatureDict.get('created'):
createdStr = str(signatureDict['created'])
appendStr = f'@created: {createdStr}'
signedHeaderList.append(appendStr)
elif '@expires' in signedHeader:
if signatureDict.get('expires'):
expiresStr = str(signatureDict['expires'])
appendStr = f'@expires: {expiresStr}'
signedHeaderList.append(appendStr)
elif '@method' in signedHeader:
appendStr = f'@expires: {method}'
signedHeaderList.append(appendStr)
elif '@scheme' in signedHeader:
signedHeaderList.append('@scheme: http')
elif '@authority' in signedHeader:
authorityStr = None
if signatureDict.get('authority'):
authorityStr = str(signatureDict['authority'])
elif signatureDict.get('Authority'):
authorityStr = str(signatureDict['Authority'])
if authorityStr:
appendStr = f'@authority: {authorityStr}'
signedHeaderList.append(appendStr)
elif signedHeader == 'algorithm':
if headers.get(signedHeader):
algorithm = headers[signedHeader]
if debug:
print('http signature algorithm: ' + algorithm)
elif signedHeader == 'digest':
if messageBodyDigest:
bodyDigest = messageBodyDigest
@ -427,14 +456,18 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
# Now we have our header data digest
signedHeaderText = '\n'.join(signedHeaderList)
if debug:
print('signedHeaderText:\n' + signedHeaderText + 'END')
print('\nverifyPostHeaders signedHeaderText:\n' +
signedHeaderText + '\nEND\n')
# Get the signature, verify with public key, return result
signature = None
if headers.get('Signature-Input') and headers.get('Signature'):
if (headers.get('Signature-Input') and headers.get('Signature')) or \
(headers.get('signature-input') and headers.get('signature')):
# https://tools.ietf.org/html/
# draft-ietf-httpbis-message-signatures-01
headersSig = headers['Signature']
# draft-ietf-httpbis-message-signatures
if headers.get('Signature'):
headersSig = headers['Signature']
else:
headersSig = headers['signature']
# remove sig1=:
if requestTargetKey + '=:' in headersSig:
headersSig = headersSig.split(requestTargetKey + '=:')[1]
@ -442,25 +475,36 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
signature = base64.b64decode(headersSig)
else:
# Original Mastodon signature
signature = base64.b64decode(signatureDict['signature'])
if debug:
print('signature: ' + algorithm + ' ' +
signatureDict['signature'])
headersSig = signatureDict['signature']
signature = base64.b64decode(headersSig)
if debug:
print('signature: ' + algorithm + ' ' + headersSig)
# log unusual signing algorithms
if signatureDict.get('alg'):
print('http signature algorithm: ' + signatureDict['alg'])
# If extra signing algorithms need to be added then do it here
if algorithm == 'rsa-sha256':
headerDigest = getSHA256(signedHeaderText.encode('ascii'))
paddingStr = padding.PKCS1v15()
if not signatureDict.get('alg'):
alg = hazutils.Prehashed(hashes.SHA256())
elif algorithm == 'rsa-sha512':
headerDigest = getSHA512(signedHeaderText.encode('ascii'))
paddingStr = padding.PKCS1v15()
elif (signatureDict['alg'] == 'rsa-sha256' or
signatureDict['alg'] == 'rsa-v1_5-sha256' or
signatureDict['alg'] == 'hs2019'):
alg = hazutils.Prehashed(hashes.SHA256())
elif (signatureDict['alg'] == 'rsa-sha512' or
signatureDict['alg'] == 'rsa-pss-sha512'):
alg = hazutils.Prehashed(hashes.SHA512())
else:
print('Unknown http signature algorithm: ' + algorithm)
paddingStr = padding.PKCS1v15()
alg = hazutils.Prehashed(hashes.SHA256())
if algorithm == 'rsa-sha256' or algorithm == 'hs2019':
headerDigest = getSHA256(signedHeaderText.encode('ascii'))
elif algorithm == 'rsa-sha512':
headerDigest = getSHA512(signedHeaderText.encode('ascii'))
else:
print('Unknown http signature algorithm: ' + algorithm)
headerDigest = ''
paddingStr = padding.PKCS1v15()
try:
pubkey.verify(signature, headerDigest, paddingStr, alg)

View File

@ -17,6 +17,7 @@ from languages import understoodPostLanguage
from like import updateLikesCollection
from reaction import updateReactionCollection
from reaction import validEmojiContent
from utils import invalidCiphertext
from utils import removeHtml
from utils import fileLastModified
from utils import hasObjectString
@ -2258,6 +2259,9 @@ def _validPostContent(baseDir: str, nickname: str, domain: str,
print('REJECT: reply to post which does not ' +
'allow comments: ' + originalPostId)
return False
if invalidCiphertext(messageJson['object']['content']):
print('REJECT: malformed ciphertext in content')
return False
if debug:
print('ACCEPT: post content is valid')
return True

View File

@ -32,6 +32,7 @@ from webfinger import webfingerHandle
from httpsig import createSignedHeader
from siteactive import siteIsActive
from languages import understoodPostLanguage
from utils import invalidCiphertext
from utils import hasObjectStringType
from utils import removeIdEnding
from utils import replaceUsersWithAt
@ -4602,6 +4603,14 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
recentPostsCache)
return None
if invalidCiphertext(contentStr):
_rejectAnnounce(announceFilename,
baseDir, nickname, domain, postId,
recentPostsCache)
print('WARN: Invalid ciphertext within announce ' +
str(announcedJson))
return None
# remove any long words
contentStr = removeLongWords(contentStr, 40, [])

253
tests.py
View File

@ -392,8 +392,20 @@ def _testSignAndVerify() -> None:
def _testHttpSigNew():
print('testHttpSigNew')
httpPrefix = 'https'
port = 443
debug = True
messageBodyJson = {"hello": "world"}
messageBodyJsonStr = json.dumps(messageBodyJson)
nickname = 'foo'
pathStr = "/" + nickname + "?param=value&pet=dog HTTP/1.1"
domain = 'example.com'
dateStr = 'Tue, 20 Apr 2021 02:07:55 GMT'
digestStr = 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE='
bodyDigest = messageContentDigest(messageBodyJsonStr)
assert bodyDigest in digestStr
contentLength = 18
contentType = 'application/activity+json'
publicKeyPem = \
'-----BEGIN RSA PUBLIC KEY-----\n' + \
'MIIBCgKCAQEAhAKYdtoeoy8zcAcR874L8' + \
@ -462,101 +474,49 @@ def _testHttpSigNew():
'EQeNC8fHGg4UXU8mhHnSBt3EA10qQJfRD' + \
's15M38eG2cYwB1PZpDHScDnDA0=\n' + \
'-----END RSA PRIVATE KEY-----'
sigInput = \
'sig1=(date); alg=rsa-sha256; keyId="test-key-b"'
sig = \
'sig1=:HtXycCl97RBVkZi66ADKnC9c5eSSlb57GnQ4KFqNZplOpNfxqk62' + \
'JzZ484jXgLvoOTRaKfR4hwyxlcyb+BWkVasApQovBSdit9Ml/YmN2IvJDPncrlhPD' + \
'VDv36Z9/DiSO+RNHD7iLXugdXo1+MGRimW1RmYdenl/ITeb7rjfLZ4b9VNnLFtVWw' + \
'rjhAiwIqeLjodVImzVc5srrk19HMZNuUejK6I3/MyN3+3U8tIRW4LWzx6ZgGZUaEE' + \
'P0aBlBkt7Fj0Tt5/P5HNW/Sa/m8smxbOHnwzAJDa10PyjzdIbywlnWIIWtZKPPsoV' + \
'oKVopUWEU3TNhpWmaVhFrUL/O6SN3w==:'
# "hs2019", using RSASSA-PSS [RFC8017] and SHA-512 [RFC6234]
# sigInput = \
# 'sig1=(*request-target, *created, host, date, ' + \
# 'cache-control, x-empty-header, x-example); keyId="test-key-a"; ' + \
# 'alg=hs2019; created=1402170695; expires=1402170995'
# sig = \
# 'sig1=:K2qGT5srn2OGbOIDzQ6kYT+ruaycnDAAUpKv+ePFfD0RAxn/1BUe' + \
# 'Zx/Kdrq32DrfakQ6bPsvB9aqZqognNT6be4olHROIkeV879RrsrObury8L9SCEibe' + \
# 'oHyqU/yCjphSmEdd7WD+zrchK57quskKwRefy2iEC5S2uAH0EPyOZKWlvbKmKu5q4' + \
# 'CaB8X/I5/+HLZLGvDiezqi6/7p2Gngf5hwZ0lSdy39vyNMaaAT0tKo6nuVw0S1MVg' + \
# '1Q7MpWYZs0soHjttq0uLIA3DIbQfLiIvK6/l0BdWTU7+2uQj7lBkQAsFZHoA96ZZg' + \
# 'FquQrXRlmYOh+Hx5D9fJkXcXe5tmAg==:'
nickname = 'foo'
boxpath = '/' + nickname
# headers = {
# "*request-target": "get " + boxpath,
# "*created": "1402170695",
# "host": "example.org",
# "date": "Tue, 07 Jun 2014 20:51:35 GMT",
# "cache-control": "max-age=60, must-revalidate",
# "x-emptyheader": "",
# "x-example": "Example header with some whitespace.",
# "x-dictionary": "b=2",
# "x-dictionary": "a=1",
# "x-list": "(a, b, c)",
# "Signature-Input": sigInput,
# "Signature": sig
# }
dateStr = "Tue, 07 Jun 2014 20:51:35 GMT"
secondsSinceEpoch = 1402174295
domain = "example.com"
port = 443
headers = {
"*created": str(secondsSinceEpoch),
"*request-target": "post /foo?param=value&pet=dog",
"host": domain,
"date": dateStr,
"content-type": "application/json",
"digest": "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=",
"content-length": "18",
"Signature-Input": sigInput,
"Signature": sig
}
httpPrefix = 'https'
debug = False
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, False, None,
messageBodyJsonStr, debug, True)
# make a deliberate mistake
headers['Signature'] = headers['Signature'].replace('V', 'B')
assert not verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, False, None,
messageBodyJsonStr, debug, True)
# test signing
bodyDigest = messageContentDigest(messageBodyJsonStr)
contentLength = len(messageBodyJsonStr)
headers = {
"host": domain,
"date": dateStr,
"digest": f'SHA-256={bodyDigest}',
"content-type": "application/json",
"content-type": contentType,
"content-length": str(contentLength)
}
signatureIndexHeader, signatureHeader = \
signPostHeadersNew(dateStr, privateKeyPem, nickname,
domain, port,
domain, port,
boxpath, httpPrefix, messageBodyJsonStr,
'rsa-sha256')
expectedIndexHeader = \
'keyId="https://example.com/users/foo#main-key"; ' + \
'alg=hs2019; created=' + str(secondsSinceEpoch) + '; ' + \
'sig1=(*request-target, *created, host, date, ' + \
'digest, content-type, content-length)'
if signatureIndexHeader != expectedIndexHeader:
print('Unexpected new http header: ' + signatureIndexHeader)
print('Should be: ' + expectedIndexHeader)
assert signatureIndexHeader == expectedIndexHeader
assert signatureHeader == \
'sig1=:euX3O1KSTYXN9/oR2qFezswWm9FbrjtRymK7xBpXNQvTs' + \
'XehtrNdD8nELZKzPXMvMz7PaJd6V+fjzpHoZ9upTdqqQLK2Iwml' + \
'p4BlHqW6Aopd7sZFCWFq7/Amm5oaizpp3e0jb5XISS5m3cRKuoi' + \
'LM0x+OudmAoYGi0TEEJk8bpnJAXfVCDfmOyL3XNqQeShQHeOANG' + \
'okiKktj8ff+KLYLaPTAJkob1k/EhoPIkbw/YzAY8IZjWQNMkf+F' + \
'JChApQ5HnDCQPwD5xV9eGzBpAf6D0G19xiTmQye4Hn6tAs3fy3V' + \
'/aYa/GhW2pSrctDnAKIi4imj9joppr3CB8gqgXZOPQ==:'
pathStr, httpPrefix, messageBodyJsonStr,
'rsa-sha256', debug)
print('signatureIndexHeader1: ' + str(signatureIndexHeader))
print('signatureHeader1: ' + str(signatureHeader))
sigInput = "keyId=\"https://example.com/users/foo#main-key\"; " + \
"alg=hs2019; created=1618884475; " + \
"sig1=(@request-target, @created, host, date, digest, " + \
"content-type, content-length)"
assert signatureIndexHeader == sigInput
sig = "sig1=:NXAQ7AtDMR2iwhmH1qCwiZw5PVTjOw5+5kSu0Tsx/3gqz0D" + \
"py7OQbWqFHrNB7MmS4TukX/vDyQOFdElY5yxnEhbgRwKACq0AP4QH9H" + \
"CiRyCE8UXDdAkY4VUd6jrWjRHKRoqQN7I+Q5tb2Fu5cDfifw/PQc86Z" + \
"NmMhPrg3OjUJ9Q2Gj29NhgJ+4el1ECg0cAy4yG1M9AQ3KvQooQFvlg1" + \
"vp0H2xfbJQjv8FsR/lKiRdaVHqGR2CKrvxvPRPaOsFANp2wzEtiMk3O" + \
"TrBTYU+Zb53mIspfEeLxsNtcGmBDmQKZ9Pud8f99XGJrP+uDd3zKtnr" + \
"f3fUnRRqy37yhB7WVwkg==:"
assert signatureHeader == sig
debug = True
headers['path'] = pathStr
headers['signature'] = sig
headers['signature-input'] = sigInput
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
pathStr, False, None,
messageBodyJsonStr, debug, True)
# make a deliberate mistake
debug = False
headers['signature'] = headers['signature'].replace('V', 'B')
assert not verifyPostHeaders(httpPrefix, publicKeyPem, headers,
pathStr, False, None,
messageBodyJsonStr, debug, True)
def _testHttpsigBase(withDigest: bool, baseDir: str):
@ -623,9 +583,10 @@ def _testHttpsigBase(withDigest: bool, baseDir: str):
headers['signature'] = signatureHeader
GETmethod = not withDigest
debug = True
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, GETmethod, None,
messageBodyJsonStr, False)
messageBodyJsonStr, debug)
if withDigest:
# everything correct except for content-length
headers['content-length'] = str(contentLength + 2)
@ -5919,6 +5880,124 @@ def _testValidEmojiContent() -> None:
assert validEmojiContent('😄')
def _testHttpsigBaseNew(withDigest: bool, baseDir: str):
print('testHttpsigNew(' + str(withDigest) + ')')
debug = True
path = baseDir + '/.testHttpsigBaseNew'
if os.path.isdir(path):
shutil.rmtree(path, ignore_errors=False, onerror=None)
os.mkdir(path)
os.chdir(path)
contentType = 'application/activity+json'
nickname = 'socrates'
hostDomain = 'someother.instance'
domain = 'argumentative.social'
httpPrefix = 'https'
port = 5576
password = 'SuperSecretPassword'
privateKeyPem, publicKeyPem, person, wfEndpoint = \
createPerson(path, nickname, domain, port, httpPrefix,
False, False, password)
assert privateKeyPem
if withDigest:
messageBodyJson = {
"a key": "a value",
"another key": "A string",
"yet another key": "Another string"
}
messageBodyJsonStr = json.dumps(messageBodyJson)
else:
messageBodyJsonStr = ''
headersDomain = getFullDomain(hostDomain, port)
dateStr = strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime())
boxpath = '/inbox'
if not withDigest:
headers = {
'host': headersDomain,
'date': dateStr,
'accept': contentType
}
signatureIndexHeader, signatureHeader = \
signPostHeadersNew(dateStr, privateKeyPem, nickname,
domain, port,
hostDomain, port,
boxpath, httpPrefix, messageBodyJsonStr,
'rsa-sha256', debug)
else:
bodyDigest = messageContentDigest(messageBodyJsonStr)
contentLength = len(messageBodyJsonStr)
headers = {
'host': headersDomain,
'date': dateStr,
'digest': f'SHA-256={bodyDigest}',
'content-type': contentType,
'content-length': str(contentLength)
}
signatureIndexHeader, signatureHeader = \
signPostHeadersNew(dateStr, privateKeyPem, nickname,
domain, port,
hostDomain, port,
boxpath, httpPrefix, messageBodyJsonStr,
'rsa-sha256', debug)
headers['signature'] = signatureHeader
headers['signature-input'] = signatureIndexHeader
print('headers: ' + str(headers))
GETmethod = not withDigest
debug = True
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, GETmethod, None,
messageBodyJsonStr, debug)
debug = False
if withDigest:
# everything correct except for content-length
headers['content-length'] = str(contentLength + 2)
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, GETmethod, None,
messageBodyJsonStr, debug) is False
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
'/parambulator' + boxpath, GETmethod, None,
messageBodyJsonStr, debug) is False
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, not GETmethod, None,
messageBodyJsonStr, debug) is False
if not withDigest:
# fake domain
headers = {
'host': 'bogon.domain',
'date': dateStr,
'content-type': contentType
}
else:
# correct domain but fake message
messageBodyJsonStr = \
'{"a key": "a value", "another key": "Fake GNUs", ' + \
'"yet another key": "More Fake GNUs"}'
contentLength = len(messageBodyJsonStr)
bodyDigest = messageContentDigest(messageBodyJsonStr)
headers = {
'host': domain,
'date': dateStr,
'digest': f'SHA-256={bodyDigest}',
'content-type': contentType,
'content-length': str(contentLength)
}
headers['signature'] = signatureHeader
headers['signature-input'] = signatureIndexHeader
pprint(headers)
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
boxpath, not GETmethod, None,
messageBodyJsonStr, False) is False
os.chdir(baseDir)
shutil.rmtree(path, ignore_errors=False, onerror=None)
def runAllTests():
baseDir = os.getcwd()
print('Running tests...')
@ -5990,6 +6069,8 @@ def runAllTests():
_testHttpsig(baseDir)
_testHttpSignedGET(baseDir)
_testHttpSigNew()
_testHttpsigBaseNew(True, baseDir)
_testHttpsigBaseNew(False, baseDir)
_testCache()
_testThreads()
_testCreatePerson(baseDir)

View File

@ -2653,8 +2653,8 @@ def isPGPEncrypted(content: str) -> bool:
return False
def malformedCiphertext(content: str) -> bool:
"""Returns true if the given content contains a malformed key
def invalidCiphertext(content: str) -> bool:
"""Returns true if the given content contains an invalid key
"""
if '----BEGIN ' in content or '----END ' in content:
if not containsPGPPublicKey(content) and \