Check that the date in the signature isn't too old.
This commit is contained in:
parent
52eeabc5bb
commit
b1516f18be
|
@ -1,5 +1,6 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
import datetime
|
||||||
from base64 import b64encode, b64decode
|
from base64 import b64encode, b64decode
|
||||||
|
|
||||||
from Crypto import Random
|
from Crypto import Random
|
||||||
|
@ -7,6 +8,7 @@ from Crypto.PublicKey import RSA
|
||||||
from Crypto.Signature import pkcs1_15 #pylint: disable=no-name-in-module
|
from Crypto.Signature import pkcs1_15 #pylint: disable=no-name-in-module
|
||||||
from Crypto.Hash import SHA256
|
from Crypto.Hash import SHA256
|
||||||
|
|
||||||
|
MAX_SIGNATURE_AGE = 300
|
||||||
|
|
||||||
def create_key_pair():
|
def create_key_pair():
|
||||||
random_generator = Random.new().read
|
random_generator = Random.new().read
|
||||||
|
@ -77,6 +79,9 @@ class Signature:
|
||||||
|
|
||||||
def verify(self, public_key, request):
|
def verify(self, public_key, request):
|
||||||
''' verify rsa signature '''
|
''' verify rsa signature '''
|
||||||
|
if http_date_age(request.headers['date']) > MAX_SIGNATURE_AGE:
|
||||||
|
raise ValueError(
|
||||||
|
"Request too old: %s" % (request.headers['date'],))
|
||||||
public_key = RSA.import_key(public_key)
|
public_key = RSA.import_key(public_key)
|
||||||
|
|
||||||
comparison_string = []
|
comparison_string = []
|
||||||
|
@ -99,3 +104,8 @@ class Signature:
|
||||||
|
|
||||||
# raises a ValueError if it fails
|
# raises a ValueError if it fails
|
||||||
signer.verify(digest, self.signature)
|
signer.verify(digest, self.signature)
|
||||||
|
|
||||||
|
def http_date_age(datestr):
|
||||||
|
parsed = datetime.datetime.strptime(datestr, '%a, %d %b %Y %H:%M:%S GMT')
|
||||||
|
delta = datetime.datetime.utcnow() - parsed
|
||||||
|
return delta.total_seconds()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import time
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from urllib.parse import urlsplit
|
from urllib.parse import urlsplit
|
||||||
|
|
||||||
|
@ -51,8 +52,9 @@ class Signature(TestCase):
|
||||||
sender,
|
sender,
|
||||||
signer=None,
|
signer=None,
|
||||||
send_data=None,
|
send_data=None,
|
||||||
digest=None):
|
digest=None,
|
||||||
now = http_date()
|
date=None):
|
||||||
|
now = date or http_date()
|
||||||
data = get_follow_data(sender, self.rat)
|
data = get_follow_data(sender, self.rat)
|
||||||
signature = make_signature(
|
signature = make_signature(
|
||||||
signer or sender, self.rat.inbox, now, digest or make_digest(data))
|
signer or sender, self.rat.inbox, now, digest or make_digest(data))
|
||||||
|
@ -105,3 +107,11 @@ class Signature(TestCase):
|
||||||
self.mouse,
|
self.mouse,
|
||||||
digest='SHA-256=AAAAAAAAAAAAAAAAAA')
|
digest='SHA-256=AAAAAAAAAAAAAAAAAA')
|
||||||
self.assertEqual(response.status_code, 401)
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
||||||
|
def test_old_message(self):
|
||||||
|
'''Old messages should be rejected to prevent replay attacks.'''
|
||||||
|
response = self.send_test_request(
|
||||||
|
self.mouse,
|
||||||
|
date=http_date(time.time() - 301)
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 401)
|
||||||
|
|
Loading…
Reference in New Issue