mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of gitlab.com:bashrc2/epicyon
commit
5954306e43
69
deploy/i2p
69
deploy/i2p
|
|
@ -352,51 +352,32 @@ echo "Creating nginx virtual host for http://${I2P_DOMAIN}"
|
||||||
echo ' error_log /dev/null;';
|
echo ' error_log /dev/null;';
|
||||||
echo '';
|
echo '';
|
||||||
echo ' index index.html;';
|
echo ' index index.html;';
|
||||||
|
echo '';
|
||||||
|
echo ' location /newsmirror {';
|
||||||
|
echo " root /var/www/${I2P_DOMAIN}/htdocs;";
|
||||||
|
echo ' try_files $uri =404;';
|
||||||
|
echo ' }';
|
||||||
|
echo '';
|
||||||
echo ' location / {';
|
echo ' location / {';
|
||||||
echo ' proxy_http_version 1.1;';
|
echo ' proxy_http_version 1.1;';
|
||||||
echo ' client_max_body_size 31M;';
|
echo ' client_max_body_size 31M;';
|
||||||
echo " proxy_hide_header Upgrade;";
|
echo " proxy_set_header Host \$http_host;";
|
||||||
echo ' proxy_hide_header Connection;';
|
echo " proxy_set_header X-Real-IP \$remote_addr;";
|
||||||
echo " proxy_set_header Host \$http_host;";
|
echo " proxy_set_header X-Forward-For \$proxy_add_x_forwarded_for;";
|
||||||
echo " proxy_set_header X-Real-IP \$remote_addr;";
|
echo ' proxy_set_header X-Forward-Proto http;';
|
||||||
echo " proxy_set_header X-Forward-For \$proxy_add_x_forwarded_for;";
|
echo ' proxy_set_header X-Nginx-Proxy true;';
|
||||||
echo ' proxy_set_header X-Forward-Proto http;';
|
echo ' proxy_temp_file_write_size 64k;';
|
||||||
echo ' proxy_set_header X-Nginx-Proxy true;';
|
echo ' proxy_connect_timeout 10080s;';
|
||||||
echo ' proxy_set_header Upgrade-Insecure-Requests false;';
|
echo ' proxy_send_timeout 10080;';
|
||||||
echo ' expires epoch;';
|
echo ' proxy_read_timeout 10080;';
|
||||||
echo ' proxy_no_cache 1;';
|
echo ' proxy_buffer_size 64k;';
|
||||||
echo ' proxy_temp_file_write_size 64k;';
|
echo ' proxy_buffers 16 32k;';
|
||||||
echo ' proxy_connect_timeout 10080s;';
|
echo ' proxy_busy_buffers_size 64k;';
|
||||||
echo ' proxy_send_timeout 10080;';
|
echo ' proxy_redirect off;';
|
||||||
echo ' proxy_read_timeout 10080;';
|
echo ' proxy_request_buffering off;';
|
||||||
echo ' proxy_buffer_size 64k;';
|
echo ' proxy_buffering off;';
|
||||||
echo ' proxy_buffers 16 32k;';
|
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
||||||
echo ' proxy_busy_buffers_size 64k;';
|
echo ' tcp_nodelay on;';
|
||||||
echo ' proxy_redirect off;';
|
|
||||||
echo ' proxy_request_buffering off;';
|
|
||||||
echo ' proxy_buffering on;';
|
|
||||||
echo ' proxy_cache my_cache;';
|
|
||||||
echo ' proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;';
|
|
||||||
echo " location ~ ^/(icons|images|media|emoji)/(.*)/(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires 7d;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/icons/(.*)/(like|repeat|calendar)(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/icons/(like|repeat|calendar)(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/users/(.*)/(image|banner).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
echo ' }';
|
||||||
echo '}'; } > /etc/nginx/sites-available/epicyon-i2p
|
echo '}'; } > /etc/nginx/sites-available/epicyon-i2p
|
||||||
|
|
||||||
|
|
|
||||||
62
deploy/onion
62
deploy/onion
|
|
@ -281,49 +281,25 @@ echo "Creating nginx virtual host for ${ONION_DOMAIN}"
|
||||||
echo ' }';
|
echo ' }';
|
||||||
echo '';
|
echo '';
|
||||||
echo ' location / {';
|
echo ' location / {';
|
||||||
echo ' proxy_http_version 1.1;';
|
echo ' proxy_http_version 1.1;';
|
||||||
echo ' client_max_body_size 31M;';
|
echo ' client_max_body_size 31M;';
|
||||||
echo " proxy_hide_header Upgrade;";
|
echo " proxy_set_header Host \$http_host;";
|
||||||
echo ' proxy_hide_header Connection;';
|
echo " proxy_set_header X-Real-IP \$remote_addr;";
|
||||||
echo " proxy_set_header Host \$http_host;";
|
echo " proxy_set_header X-Forward-For \$proxy_add_x_forwarded_for;";
|
||||||
echo " proxy_set_header X-Real-IP \$remote_addr;";
|
echo ' proxy_set_header X-Forward-Proto http;';
|
||||||
echo " proxy_set_header X-Forward-For \$proxy_add_x_forwarded_for;";
|
echo ' proxy_set_header X-Nginx-Proxy true;';
|
||||||
echo ' proxy_set_header X-Forward-Proto http;';
|
echo ' proxy_temp_file_write_size 64k;';
|
||||||
echo ' proxy_set_header X-Nginx-Proxy true;';
|
echo ' proxy_connect_timeout 10080s;';
|
||||||
echo ' expires epoch;';
|
echo ' proxy_send_timeout 10080;';
|
||||||
echo ' proxy_no_cache 1;';
|
echo ' proxy_read_timeout 10080;';
|
||||||
echo ' proxy_temp_file_write_size 64k;';
|
echo ' proxy_buffer_size 64k;';
|
||||||
echo ' proxy_connect_timeout 10080s;';
|
echo ' proxy_buffers 16 32k;';
|
||||||
echo ' proxy_send_timeout 10080;';
|
echo ' proxy_busy_buffers_size 64k;';
|
||||||
echo ' proxy_read_timeout 10080;';
|
echo ' proxy_redirect off;';
|
||||||
echo ' proxy_buffer_size 64k;';
|
echo ' proxy_request_buffering off;';
|
||||||
echo ' proxy_buffers 16 32k;';
|
echo ' proxy_buffering off;';
|
||||||
echo ' proxy_busy_buffers_size 64k;';
|
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
||||||
echo ' proxy_redirect off;';
|
echo ' tcp_nodelay on;';
|
||||||
echo ' proxy_request_buffering off;';
|
|
||||||
echo ' proxy_buffering on;';
|
|
||||||
echo ' proxy_cache my_cache;';
|
|
||||||
echo ' proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;';
|
|
||||||
echo " location ~ ^/(icons|images|media|emoji)/(.*)/(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires 7d;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/icons/(.*)/(like|repeat|calendar)(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/icons/(like|repeat|calendar)(.*).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " location ~ ^/users/(.*)/(image|banner).(png|jpg|gif|webp|mp3|ogv|ogg|mp4) {";
|
|
||||||
echo ' expires epoch;';
|
|
||||||
echo ' proxy_no_cache 1;';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
|
||||||
echo " proxy_pass http://localhost:${EPICYON_PORT};";
|
|
||||||
echo ' }';
|
echo ' }';
|
||||||
echo '}'; } > "/etc/nginx/sites-available/${username}"
|
echo '}'; } > "/etc/nginx/sites-available/${username}"
|
||||||
|
|
||||||
|
|
|
||||||
75
httpsig.py
75
httpsig.py
|
|
@ -28,12 +28,41 @@ from utils import getSHA512
|
||||||
from utils import localActorUrl
|
from utils import localActorUrl
|
||||||
|
|
||||||
|
|
||||||
def messageContentDigest(messageBodyJsonStr: str) -> str:
|
def messageContentDigest(messageBodyJsonStr: str, digestAlgorithm: str) -> str:
|
||||||
|
"""Returns the digest for the message body
|
||||||
|
"""
|
||||||
msg = messageBodyJsonStr.encode('utf-8')
|
msg = messageBodyJsonStr.encode('utf-8')
|
||||||
hashResult = getSHA256(msg)
|
if digestAlgorithm == 'rsa-sha512' or \
|
||||||
|
digestAlgorithm == 'rsa-pss-sha512':
|
||||||
|
hashResult = getSHA512(msg)
|
||||||
|
else:
|
||||||
|
hashResult = getSHA256(msg)
|
||||||
return base64.b64encode(hashResult).decode('utf-8')
|
return base64.b64encode(hashResult).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def getDigestPrefix(digestAlgorithm: str) -> str:
|
||||||
|
"""Returns the prefix for the message body digest
|
||||||
|
"""
|
||||||
|
if digestAlgorithm == 'rsa-sha512' or \
|
||||||
|
digestAlgorithm == 'rsa-pss-sha512':
|
||||||
|
return 'SHA-512'
|
||||||
|
return 'SHA-256'
|
||||||
|
|
||||||
|
|
||||||
|
def getDigestAlgorithmFromHeaders(httpHeaders: {}) -> str:
|
||||||
|
"""Returns the digest algorithm from http headers
|
||||||
|
"""
|
||||||
|
digestStr = None
|
||||||
|
if httpHeaders.get('digest'):
|
||||||
|
digestStr = httpHeaders['digest']
|
||||||
|
elif httpHeaders.get('Digest'):
|
||||||
|
digestStr = httpHeaders['Digest']
|
||||||
|
if digestStr:
|
||||||
|
if digestStr.startswith('SHA-512'):
|
||||||
|
return 'rsa-sha512'
|
||||||
|
return 'rsa-sha256'
|
||||||
|
|
||||||
|
|
||||||
def signPostHeaders(dateStr: str, privateKeyPem: str,
|
def signPostHeaders(dateStr: str, privateKeyPem: str,
|
||||||
nickname: str,
|
nickname: str,
|
||||||
domain: str, port: int,
|
domain: str, port: int,
|
||||||
|
|
@ -41,7 +70,9 @@ def signPostHeaders(dateStr: str, privateKeyPem: str,
|
||||||
path: str,
|
path: str,
|
||||||
httpPrefix: str,
|
httpPrefix: str,
|
||||||
messageBodyJsonStr: str,
|
messageBodyJsonStr: str,
|
||||||
contentType: str) -> str:
|
contentType: str,
|
||||||
|
algorithm: str,
|
||||||
|
digestAlgorithm: str) -> str:
|
||||||
"""Returns a raw signature string that can be plugged into a header and
|
"""Returns a raw signature string that can be plugged into a header and
|
||||||
used to verify the authenticity of an HTTP transmission.
|
used to verify the authenticity of an HTTP transmission.
|
||||||
"""
|
"""
|
||||||
|
|
@ -65,13 +96,15 @@ def signPostHeaders(dateStr: str, privateKeyPem: str,
|
||||||
'accept': contentType
|
'accept': contentType
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
bodyDigest = \
|
||||||
|
messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
headers = {
|
headers = {
|
||||||
'(request-target)': f'post {path}',
|
'(request-target)': f'post {path}',
|
||||||
'host': toDomain,
|
'host': toDomain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': 'application/activity+json',
|
'content-type': 'application/activity+json',
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +133,7 @@ def signPostHeaders(dateStr: str, privateKeyPem: str,
|
||||||
# Put it into a valid HTTP signature format
|
# Put it into a valid HTTP signature format
|
||||||
signatureDict = {
|
signatureDict = {
|
||||||
'keyId': keyID,
|
'keyId': keyID,
|
||||||
'algorithm': 'rsa-sha256',
|
'algorithm': algorithm,
|
||||||
'headers': ' '.join(signedHeaderKeys),
|
'headers': ' '.join(signedHeaderKeys),
|
||||||
'signature': signature
|
'signature': signature
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +149,8 @@ def signPostHeadersNew(dateStr: str, privateKeyPem: str,
|
||||||
path: str,
|
path: str,
|
||||||
httpPrefix: str,
|
httpPrefix: str,
|
||||||
messageBodyJsonStr: str,
|
messageBodyJsonStr: str,
|
||||||
algorithm: str, debug: bool) -> (str, str):
|
algorithm: str, digestAlgorithm: str,
|
||||||
|
debug: bool) -> (str, str):
|
||||||
"""Returns a raw signature strings that can be plugged into a header
|
"""Returns a raw signature strings that can be plugged into a header
|
||||||
as "Signature-Input" and "Signature"
|
as "Signature-Input" and "Signature"
|
||||||
used to verify the authenticity of an HTTP transmission.
|
used to verify the authenticity of an HTTP transmission.
|
||||||
|
|
@ -143,14 +177,15 @@ def signPostHeadersNew(dateStr: str, privateKeyPem: str,
|
||||||
'date': dateStr
|
'date': dateStr
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
headers = {
|
headers = {
|
||||||
'@request-target': f'post {path}',
|
'@request-target': f'post {path}',
|
||||||
'@created': str(secondsSinceEpoch),
|
'@created': str(secondsSinceEpoch),
|
||||||
'host': toDomain,
|
'host': toDomain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': 'application/activity+json',
|
'content-type': 'application/activity+json',
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
|
@ -210,6 +245,8 @@ def createSignedHeader(dateStr: str, privateKeyPem: str, nickname: str,
|
||||||
contentType: str) -> {}:
|
contentType: str) -> {}:
|
||||||
"""Note that the domain is the destination, not the sender
|
"""Note that the domain is the destination, not the sender
|
||||||
"""
|
"""
|
||||||
|
algorithm = 'rsa-sha256'
|
||||||
|
digestAlgorithm = 'rsa-sha256'
|
||||||
headerDomain = getFullDomain(toDomain, toPort)
|
headerDomain = getFullDomain(toDomain, toPort)
|
||||||
|
|
||||||
# if no date is given then create one
|
# if no date is given then create one
|
||||||
|
|
@ -230,15 +267,17 @@ def createSignedHeader(dateStr: str, privateKeyPem: str, nickname: str,
|
||||||
signatureHeader = \
|
signatureHeader = \
|
||||||
signPostHeaders(dateStr, privateKeyPem, nickname,
|
signPostHeaders(dateStr, privateKeyPem, nickname,
|
||||||
domain, port, toDomain, toPort,
|
domain, port, toDomain, toPort,
|
||||||
path, httpPrefix, None, contentType)
|
path, httpPrefix, None, contentType,
|
||||||
|
algorithm, None)
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
headers = {
|
headers = {
|
||||||
'(request-target)': f'post {path}',
|
'(request-target)': f'post {path}',
|
||||||
'host': headerDomain,
|
'host': headerDomain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-length': str(contentLength),
|
'content-length': str(contentLength),
|
||||||
'content-type': contentType
|
'content-type': contentType
|
||||||
}
|
}
|
||||||
|
|
@ -247,7 +286,7 @@ def createSignedHeader(dateStr: str, privateKeyPem: str, nickname: str,
|
||||||
domain, port,
|
domain, port,
|
||||||
toDomain, toPort,
|
toDomain, toPort,
|
||||||
path, httpPrefix, messageBodyJsonStr,
|
path, httpPrefix, messageBodyJsonStr,
|
||||||
contentType)
|
contentType, algorithm, digestAlgorithm)
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
@ -341,6 +380,7 @@ def verifyPostHeaders(httpPrefix: str,
|
||||||
# body (if a digest was included)
|
# body (if a digest was included)
|
||||||
signedHeaderList = []
|
signedHeaderList = []
|
||||||
algorithm = 'rsa-sha256'
|
algorithm = 'rsa-sha256'
|
||||||
|
digestAlgorithm = 'rsa-sha256'
|
||||||
for signedHeader in signatureDict[requestTargetKey].split(fieldSep2):
|
for signedHeader in signatureDict[requestTargetKey].split(fieldSep2):
|
||||||
signedHeader = signedHeader.strip()
|
signedHeader = signedHeader.strip()
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -387,7 +427,8 @@ def verifyPostHeaders(httpPrefix: str,
|
||||||
if messageBodyDigest:
|
if messageBodyDigest:
|
||||||
bodyDigest = messageBodyDigest
|
bodyDigest = messageBodyDigest
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
bodyDigest = \
|
||||||
|
messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
signedHeaderList.append(f'digest: SHA-256={bodyDigest}')
|
signedHeaderList.append(f'digest: SHA-256={bodyDigest}')
|
||||||
elif signedHeader == 'content-length':
|
elif signedHeader == 'content-length':
|
||||||
if headers.get(signedHeader):
|
if headers.get(signedHeader):
|
||||||
|
|
@ -497,12 +538,12 @@ def verifyPostHeaders(httpPrefix: str,
|
||||||
else:
|
else:
|
||||||
alg = hazutils.Prehashed(hashes.SHA256())
|
alg = hazutils.Prehashed(hashes.SHA256())
|
||||||
|
|
||||||
if algorithm == 'rsa-sha256' or algorithm == 'hs2019':
|
if digestAlgorithm == 'rsa-sha256':
|
||||||
headerDigest = getSHA256(signedHeaderText.encode('ascii'))
|
headerDigest = getSHA256(signedHeaderText.encode('ascii'))
|
||||||
elif algorithm == 'rsa-sha512':
|
elif digestAlgorithm == 'rsa-sha512':
|
||||||
headerDigest = getSHA512(signedHeaderText.encode('ascii'))
|
headerDigest = getSHA512(signedHeaderText.encode('ascii'))
|
||||||
else:
|
else:
|
||||||
print('Unknown http signature algorithm: ' + algorithm)
|
print('Unknown http digest algorithm: ' + digestAlgorithm)
|
||||||
headerDigest = ''
|
headerDigest = ''
|
||||||
paddingStr = padding.PKCS1v15()
|
paddingStr = padding.PKCS1v15()
|
||||||
|
|
||||||
|
|
|
||||||
4
inbox.py
4
inbox.py
|
|
@ -60,6 +60,7 @@ from utils import localActorUrl
|
||||||
from utils import hasObjectStringType
|
from utils import hasObjectStringType
|
||||||
from categories import getHashtagCategories
|
from categories import getHashtagCategories
|
||||||
from categories import setHashtagCategory
|
from categories import setHashtagCategory
|
||||||
|
from httpsig import getDigestAlgorithmFromHeaders
|
||||||
from httpsig import verifyPostHeaders
|
from httpsig import verifyPostHeaders
|
||||||
from session import createSession
|
from session import createSession
|
||||||
from follow import followerApprovalActive
|
from follow import followerApprovalActive
|
||||||
|
|
@ -549,7 +550,8 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
|
||||||
sharedInboxItem = True
|
sharedInboxItem = True
|
||||||
|
|
||||||
digestStartTime = time.time()
|
digestStartTime = time.time()
|
||||||
digest = messageContentDigest(messageBytes)
|
digestAlgorithm = getDigestAlgorithmFromHeaders(httpHeaders)
|
||||||
|
digest = messageContentDigest(messageBytes, digestAlgorithm)
|
||||||
timeDiffStr = str(int((time.time() - digestStartTime) * 1000))
|
timeDiffStr = str(int((time.time() - digestStartTime) * 1000))
|
||||||
if debug:
|
if debug:
|
||||||
while len(timeDiffStr) < 6:
|
while len(timeDiffStr) < 6:
|
||||||
|
|
|
||||||
57
tests.py
57
tests.py
|
|
@ -23,6 +23,8 @@ from shutil import copyfile
|
||||||
from random import randint
|
from random import randint
|
||||||
from time import gmtime, strftime
|
from time import gmtime, strftime
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
from httpsig import getDigestAlgorithmFromHeaders
|
||||||
|
from httpsig import getDigestPrefix
|
||||||
from httpsig import createSignedHeader
|
from httpsig import createSignedHeader
|
||||||
from httpsig import signPostHeaders
|
from httpsig import signPostHeaders
|
||||||
from httpsig import signPostHeadersNew
|
from httpsig import signPostHeadersNew
|
||||||
|
|
@ -390,7 +392,7 @@ def _testSignAndVerify() -> None:
|
||||||
pubkey.verify(signature2, headerDigest, paddingStr, alg)
|
pubkey.verify(signature2, headerDigest, paddingStr, alg)
|
||||||
|
|
||||||
|
|
||||||
def _testHttpSigNew():
|
def _testHttpSigNew(algorithm: str, digestAlgorithm: str):
|
||||||
print('testHttpSigNew')
|
print('testHttpSigNew')
|
||||||
httpPrefix = 'https'
|
httpPrefix = 'https'
|
||||||
port = 443
|
port = 443
|
||||||
|
|
@ -401,8 +403,9 @@ def _testHttpSigNew():
|
||||||
pathStr = "/" + nickname + "?param=value&pet=dog HTTP/1.1"
|
pathStr = "/" + nickname + "?param=value&pet=dog HTTP/1.1"
|
||||||
domain = 'example.com'
|
domain = 'example.com'
|
||||||
dateStr = 'Tue, 20 Apr 2021 02:07:55 GMT'
|
dateStr = 'Tue, 20 Apr 2021 02:07:55 GMT'
|
||||||
digestStr = 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE='
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
digestStr = digestPrefix + '=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE='
|
||||||
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
assert bodyDigest in digestStr
|
assert bodyDigest in digestStr
|
||||||
contentLength = 18
|
contentLength = 18
|
||||||
contentType = 'application/activity+json'
|
contentType = 'application/activity+json'
|
||||||
|
|
@ -477,7 +480,7 @@ def _testHttpSigNew():
|
||||||
headers = {
|
headers = {
|
||||||
"host": domain,
|
"host": domain,
|
||||||
"date": dateStr,
|
"date": dateStr,
|
||||||
"digest": f'SHA-256={bodyDigest}',
|
"digest": f'{digestPrefix}={bodyDigest}',
|
||||||
"content-type": contentType,
|
"content-type": contentType,
|
||||||
"content-length": str(contentLength)
|
"content-length": str(contentLength)
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +489,7 @@ def _testHttpSigNew():
|
||||||
domain, port,
|
domain, port,
|
||||||
domain, port,
|
domain, port,
|
||||||
pathStr, httpPrefix, messageBodyJsonStr,
|
pathStr, httpPrefix, messageBodyJsonStr,
|
||||||
'rsa-sha256', debug)
|
algorithm, digestAlgorithm, debug)
|
||||||
print('signatureIndexHeader1: ' + str(signatureIndexHeader))
|
print('signatureIndexHeader1: ' + str(signatureIndexHeader))
|
||||||
print('signatureHeader1: ' + str(signatureHeader))
|
print('signatureHeader1: ' + str(signatureHeader))
|
||||||
sigInput = "keyId=\"https://example.com/users/foo#main-key\"; " + \
|
sigInput = "keyId=\"https://example.com/users/foo#main-key\"; " + \
|
||||||
|
|
@ -528,6 +531,8 @@ def _testHttpsigBase(withDigest: bool, baseDir: str):
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
|
|
||||||
|
algorithm = 'rsa-sha256'
|
||||||
|
digestAlgorithm = 'rsa-sha256'
|
||||||
contentType = 'application/activity+json'
|
contentType = 'application/activity+json'
|
||||||
nickname = 'socrates'
|
nickname = 'socrates'
|
||||||
hostDomain = 'someother.instance'
|
hostDomain = 'someother.instance'
|
||||||
|
|
@ -563,23 +568,26 @@ def _testHttpsigBase(withDigest: bool, baseDir: str):
|
||||||
signPostHeaders(dateStr, privateKeyPem, nickname,
|
signPostHeaders(dateStr, privateKeyPem, nickname,
|
||||||
domain, port,
|
domain, port,
|
||||||
hostDomain, port,
|
hostDomain, port,
|
||||||
boxpath, httpPrefix, None, contentType)
|
boxpath, httpPrefix, None, contentType,
|
||||||
|
algorithm, None)
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
headers = {
|
headers = {
|
||||||
'host': headersDomain,
|
'host': headersDomain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': contentType,
|
'content-type': contentType,
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
assert getDigestAlgorithmFromHeaders(headers) == digestAlgorithm
|
||||||
signatureHeader = \
|
signatureHeader = \
|
||||||
signPostHeaders(dateStr, privateKeyPem, nickname,
|
signPostHeaders(dateStr, privateKeyPem, nickname,
|
||||||
domain, port,
|
domain, port,
|
||||||
hostDomain, port,
|
hostDomain, port,
|
||||||
boxpath, httpPrefix, messageBodyJsonStr,
|
boxpath, httpPrefix, messageBodyJsonStr,
|
||||||
contentType)
|
contentType, algorithm, digestAlgorithm)
|
||||||
|
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
GETmethod = not withDigest
|
GETmethod = not withDigest
|
||||||
|
|
@ -612,14 +620,16 @@ def _testHttpsigBase(withDigest: bool, baseDir: str):
|
||||||
'{"a key": "a value", "another key": "Fake GNUs", ' + \
|
'{"a key": "a value", "another key": "Fake GNUs", ' + \
|
||||||
'"yet another key": "More Fake GNUs"}'
|
'"yet another key": "More Fake GNUs"}'
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
headers = {
|
headers = {
|
||||||
'host': domain,
|
'host': domain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': contentType,
|
'content-type': contentType,
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
assert getDigestAlgorithmFromHeaders(headers) == digestAlgorithm
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers,
|
||||||
boxpath, not GETmethod, None,
|
boxpath, not GETmethod, None,
|
||||||
|
|
@ -5880,7 +5890,8 @@ def _testValidEmojiContent() -> None:
|
||||||
assert validEmojiContent('😄')
|
assert validEmojiContent('😄')
|
||||||
|
|
||||||
|
|
||||||
def _testHttpsigBaseNew(withDigest: bool, baseDir: str):
|
def _testHttpsigBaseNew(withDigest: bool, baseDir: str,
|
||||||
|
algorithm: str, digestAlgorithm: str) -> None:
|
||||||
print('testHttpsigNew(' + str(withDigest) + ')')
|
print('testHttpsigNew(' + str(withDigest) + ')')
|
||||||
|
|
||||||
debug = True
|
debug = True
|
||||||
|
|
@ -5926,23 +5937,25 @@ def _testHttpsigBaseNew(withDigest: bool, baseDir: str):
|
||||||
domain, port,
|
domain, port,
|
||||||
hostDomain, port,
|
hostDomain, port,
|
||||||
boxpath, httpPrefix, messageBodyJsonStr,
|
boxpath, httpPrefix, messageBodyJsonStr,
|
||||||
'rsa-sha256', debug)
|
algorithm, digestAlgorithm, debug)
|
||||||
else:
|
else:
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
headers = {
|
headers = {
|
||||||
'host': headersDomain,
|
'host': headersDomain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': contentType,
|
'content-type': contentType,
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
assert getDigestAlgorithmFromHeaders(headers) == digestAlgorithm
|
||||||
signatureIndexHeader, signatureHeader = \
|
signatureIndexHeader, signatureHeader = \
|
||||||
signPostHeadersNew(dateStr, privateKeyPem, nickname,
|
signPostHeadersNew(dateStr, privateKeyPem, nickname,
|
||||||
domain, port,
|
domain, port,
|
||||||
hostDomain, port,
|
hostDomain, port,
|
||||||
boxpath, httpPrefix, messageBodyJsonStr,
|
boxpath, httpPrefix, messageBodyJsonStr,
|
||||||
'rsa-sha256', debug)
|
algorithm, digestAlgorithm, debug)
|
||||||
|
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
headers['signature-input'] = signatureIndexHeader
|
headers['signature-input'] = signatureIndexHeader
|
||||||
|
|
@ -5979,14 +5992,16 @@ def _testHttpsigBaseNew(withDigest: bool, baseDir: str):
|
||||||
'{"a key": "a value", "another key": "Fake GNUs", ' + \
|
'{"a key": "a value", "another key": "Fake GNUs", ' + \
|
||||||
'"yet another key": "More Fake GNUs"}'
|
'"yet another key": "More Fake GNUs"}'
|
||||||
contentLength = len(messageBodyJsonStr)
|
contentLength = len(messageBodyJsonStr)
|
||||||
bodyDigest = messageContentDigest(messageBodyJsonStr)
|
digestPrefix = getDigestPrefix(digestAlgorithm)
|
||||||
|
bodyDigest = messageContentDigest(messageBodyJsonStr, digestAlgorithm)
|
||||||
headers = {
|
headers = {
|
||||||
'host': domain,
|
'host': domain,
|
||||||
'date': dateStr,
|
'date': dateStr,
|
||||||
'digest': f'SHA-256={bodyDigest}',
|
'digest': f'{digestPrefix}={bodyDigest}',
|
||||||
'content-type': contentType,
|
'content-type': contentType,
|
||||||
'content-length': str(contentLength)
|
'content-length': str(contentLength)
|
||||||
}
|
}
|
||||||
|
assert getDigestAlgorithmFromHeaders(headers) == digestAlgorithm
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
headers['signature-input'] = signatureIndexHeader
|
headers['signature-input'] = signatureIndexHeader
|
||||||
pprint(headers)
|
pprint(headers)
|
||||||
|
|
@ -6068,9 +6083,9 @@ def runAllTests():
|
||||||
_testActorParsing()
|
_testActorParsing()
|
||||||
_testHttpsig(baseDir)
|
_testHttpsig(baseDir)
|
||||||
_testHttpSignedGET(baseDir)
|
_testHttpSignedGET(baseDir)
|
||||||
_testHttpSigNew()
|
_testHttpSigNew('rsa-sha256', 'rsa-sha256')
|
||||||
_testHttpsigBaseNew(True, baseDir)
|
_testHttpsigBaseNew(True, baseDir, 'rsa-sha256', 'rsa-sha256')
|
||||||
_testHttpsigBaseNew(False, baseDir)
|
_testHttpsigBaseNew(False, baseDir, 'rsa-sha256', 'rsa-sha256')
|
||||||
_testCache()
|
_testCache()
|
||||||
_testThreads()
|
_testThreads()
|
||||||
_testCreatePerson(baseDir)
|
_testCreatePerson(baseDir)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue