diff --git a/basic_ap.py b/basic_ap.py index 97f28a8..f4deaf6 100644 --- a/basic_ap.py +++ b/basic_ap.py @@ -30,6 +30,8 @@ from Crypto.Hash import SHA256 from Crypto.Signature import pkcs1_15 from Crypto.PublicKey import RSA +from httpsig import HTTPSigAuth + # import logging import http.client as http_client @@ -61,69 +63,69 @@ def public_key(): public_key() #generate public_key on first launch -def build_signing_string(headers, header_values): - return '\n'.join(map(lambda x: ': '.join([x.lower(), headers[x]]), header_values)) +# def build_signing_string(headers, header_values): +# return '\n'.join(map(lambda x: ': '.join([x.lower(), headers[x]]), header_values)) -def messageContentDigest(messageBodyJsonStr: str) -> str: - msg = messageBodyJsonStr.encode('utf-8') - digestStr = SHA256.new(msg).digest() - return base64.b64encode(digestStr).decode('utf-8') +# def messageContentDigest(messageBodyJsonStr: str) -> str: +# msg = messageBodyJsonStr.encode('utf-8') +# digestStr = SHA256.new(msg).digest() +# return base64.b64encode(digestStr).decode('utf-8') -def sign_header(private_key, keyID, host, messageBodyJsonStr): - """ - Sign HTTP headers - """ - date = strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) #RFC1123 Time format +# def sign_header(private_key, keyID, host, messageBodyJsonStr): +# """ +# Sign HTTP headers +# """ +# date = strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime()) #RFC1123 Time format - #Based on https://code.freedombone.net/bashrc/epicyon/src/main/httpsig.py - keyfile = open(private_key,'rb').read() - secret = RSA.import_key(keyfile) +# #Based on https://code.freedombone.net/bashrc/epicyon/src/main/httpsig.py +# keyfile = open(private_key,'rb').read() +# secret = RSA.import_key(keyfile) - bodyDigest = messageContentDigest(messageBodyJsonStr) - contentLength = len(messageBodyJsonStr) - print(contentLength) +# bodyDigest = messageContentDigest(messageBodyJsonStr) +# contentLength = len(messageBodyJsonStr) +# print(contentLength) - path = '/inbox' - - headers = { - '(request-target)': f'post {path}', - 'host': host, - 'date': date, - 'digest': f'SHA-256={bodyDigest}', - 'content-type': 'application/json', - 'content-length': str(contentLength) - } - - - signedHeaderKeys = headers.keys() - signedHeaderText = '' - - for headerKey in signedHeaderKeys: - signedHeaderText += f'{headerKey}: {headers[headerKey]}\n' - - signedHeaderText = signedHeaderText.strip() - headerDigest = SHA256.new(signedHeaderText.encode('ascii')) - - # Sign the digest - rawSignature = pkcs1_15.new(secret).sign(headerDigest) - signature = base64.b64encode(rawSignature).decode('ascii') - - # Put it into a valid HTTP signature format - signatureDict = { - 'keyId': keyID, - 'algorithm': 'rsa-sha256', - 'headers': ' '.join(signedHeaderKeys), - 'signature': signature - } - signatureHeader = ', '.join( - [f'{k}="{v}"' for k, v in signatureDict.items()]) +# path = '/inbox' + +# headers = { +# '(request-target)': f'post {path}', +# 'host': host, +# 'date': date, +# 'digest': f'SHA-256={bodyDigest}', +# 'content-type': 'application/json', +# 'content-length': str(contentLength) +# } + + +# signedHeaderKeys = headers.keys() +# signedHeaderText = '' + +# for headerKey in signedHeaderKeys: +# signedHeaderText += f'{headerKey}: {headers[headerKey]}\n' + +# signedHeaderText = signedHeaderText.strip() +# headerDigest = SHA256.new(signedHeaderText.encode('ascii')) + +# # Sign the digest +# rawSignature = pkcs1_15.new(secret).sign(headerDigest) +# signature = base64.b64encode(rawSignature).decode('ascii') + +# # Put it into a valid HTTP signature format +# signatureDict = { +# 'keyId': keyID, +# 'algorithm': 'rsa-sha256', +# 'headers': ' '.join(signedHeaderKeys), +# 'signature': signature +# } +# signatureHeader = ', '.join( +# [f'{k}="{v}"' for k, v in signatureDict.items()]) - headers['signature'] = signatureHeader +# headers['signature'] = signatureHeader - return headers +# return headers @@ -163,14 +165,28 @@ def profile(actor): @app.route('/post/', methods=['POST','GET']) def post(): - date = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime()) + + keyfile = open('private.pem','rb').read() + key = {'privkey': RSA.import_key(keyfile), 'keyId': DOMAIN+'/users/'+USERNAME+'#main-key'} + + headers = {"content-type": "application/activity+json", + "user-agent": f"test v:1"} json_message=json.loads(flask.render_template('create.json', - domain=DOMAIN,public_key=public_key(),actor=USERNAME,host='DOMAIN', date=date)) + domain=DOMAIN,public_key=public_key(),actor=USERNAME,host='DOMAIN')) - signed_headers = sign_header('private.pem', DOMAIN+'/users/'+USERNAME+'#main-key','https://post.lurk.org', json.dumps(json_message)) - r = requests.post('https://post.lurk.org/inbox', json=json_message, headers=signed_headers) + http_sig = HTTPSigAuth(key, headers) + + url = 'https://post.lurk.org/inbox' + + body = json.dumps(json_message) + + headers = http_sig.sign(url,body) + + #signed_headers = sign_header('private.pem', DOMAIN+'/users/'+USERNAME+'#main-key','https://post.lurk.org', json.dumps(json_message)) + + r = requests.post('https://post.lurk.org/inbox', json=body, headers=headers) html = f'Status code
{r.status_code}

Response Headers:
{r.headers}


json message:
{r.request.body}


Request headers:
{r.request.headers}
' html_headers = f'{html}' diff --git a/templates/create.json b/templates/create.json index e307384..df8c83f 100644 --- a/templates/create.json +++ b/templates/create.json @@ -8,7 +8,7 @@ "object": { "id": "{{domain}}/hello-world", "type": "Note", - "published": "{{date}}", + "published": "2018-06-23T17:17:11Z", "attributedTo": "{{domain}}/users/{{actor}}", "inReplyTo": "https://post.lurk.org/@rra/101224791711855553", "content": "

This is a test from a flask based implementation of the mastodon tutorial

",