From c7be266c8e5a4cfc862ae741a7c2355a36bc3e1b Mon Sep 17 00:00:00 2001 From: Dan Loewenherz Date: Thu, 26 Oct 2017 13:01:53 -0500 Subject: [PATCH] add ability to sign response payload --- .ruby-version | 1 + app/views.py | 36 +++++++++++++++++++++++++++++++++--- requirements.txt | 1 + settings.py | 1 + 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 .ruby-version diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..8e8299d --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.4.2 diff --git a/app/views.py b/app/views.py index 9487e04..19a8ed5 100644 --- a/app/views.py +++ b/app/views.py @@ -1,24 +1,54 @@ import json import logging +import base64 from django.conf import settings from django.shortcuts import get_object_or_404 from django.views.decorators.csrf import csrf_exempt from lionheart.decorators import render_json +from lionheart.utils import JSONResponse import requests +from Crypto.PublicKey import RSA +from Crypto.Signature import PKCS1_v1_5 +from Crypto.Hash import SHA256 +from Crypto import Random + logger = logging.getLogger(__name__) -@render_json @csrf_exempt def verify_receipt(request): data = { 'receipt-data': request.body.strip().decode("utf-8"), 'password': settings.APP_SPECIFIC_SHARED_SECRET } - print(data['receipt-data']) response = requests.post(settings.RECEIPT_VERIFICATION_URL, data=json.dumps(data)) payload = response.json() - return payload + response = JSONResponse(payload) + + # If signing key is available, sign the payload to detect potential tampering. + if settings.B64_ENCODED_SIGNING_KEY: + key_data = base64.b64decode(settings.B64_ENCODED_SIGNING_KEY) + key = RSA.importKey(key_data) + + data = json.dumps(payload).encode("utf8") + + digest = SHA256.new() + digest.update(data) + + use_salt = False + if use_salt: + rndfile = Random.new() + salt_data = rndfile.read(64) + salt = base64.b64encode(nonce_data) + + digest.update(salt_data) + response['X-Salt'] = nonce + + signer = PKCS1_v1_5.new(key) + signature = signer.sign(digest) + response['X-Signature'] = base64.b64encode(signature) + + return response diff --git a/requirements.txt b/requirements.txt index 6c13981..a417a41 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,3 +28,4 @@ foreman==0.9.7 rerun==1.0.28 gevent requests +pycrypto diff --git a/settings.py b/settings.py index 2d99985..2a49a46 100644 --- a/settings.py +++ b/settings.py @@ -204,6 +204,7 @@ APP_SPECIFIC_SHARED_SECRET = os.environ.get("APP_SPECIFIC_SHARED_SECRET") RECEIPT_VERIFICATION_ENVIRONMENT = os.environ.get("RECEIPT_VERIFICATION_ENVIRONMENT") +B64_ENCODED_SIGNING_KEY = os.environ.get("B64_ENCODED_SIGNING_KEY") if RECEIPT_VERIFICATION_ENVIRONMENT == "production": RECEIPT_VERIFICATION_URL = "https://buy.itunes.apple.com/verifyReceipt"