addons-server/lib/crypto/receipt.py

78 строки
2.1 KiB
Python

import json
import urllib2
from django.conf import settings
from django_statsd.clients import statsd
import commonware.log
import jwt
log = commonware.log.getLogger('z.crypto')
class SigningError(Exception):
pass
def sign(receipt):
"""
Send the receipt to the signing service.
This could possibly be made async via celery.
"""
destination = settings.SIGNING_SERVER
# If no destination is set. Just ignore this request.
if not destination:
return
destination += '/1.0/sign'
timeout = settings.SIGNING_SERVER_TIMEOUT
receipt_json = json.dumps(receipt)
log.info('Calling service: %s' % destination)
log.info('Receipt contents: %s' % receipt_json)
headers = {'Content-Type': 'application/json'}
data = receipt if isinstance(receipt, basestring) else receipt_json
request = urllib2.Request(destination, data, headers)
try:
with statsd.timer('services.sign'):
response = urllib2.urlopen(request, timeout=timeout)
except urllib2.HTTPError, error:
# Will occur when a 3xx or greater code is returned
log.error('Posting to signing failed: %s, %s'
% (error.code, error.read().strip()))
raise SigningError
except:
# Will occur when some other error occurs.
log.error('Posting to signing failed', exc_info=True)
raise SigningError
if response.getcode() != 200:
log.error('Posting to signing failed: %s'
% (response.getcode()))
raise SigningError
return json.loads(response.read())['receipt']
def decode(receipt):
"""
Decode and verify that the receipt is sound from a crypto point of view.
Will raise errors if the receipt is not valid, returns receipt contents
if it is valid.
"""
raise NotImplementedError
def crack(receipt):
"""
Crack open the receipt, without checking that the crypto is valid.
Returns a list of all the elements of a receipt, which by default is
cert, receipt.
"""
return map(lambda x: jwt.decode(x.encode('ascii'), verify=False),
receipt.split('~'))