-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #240 from akhait/ocsp_sign
Add OCSP signature verification
- Loading branch information
Showing
4 changed files
with
245 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
"""Base class that represents any signed object""" | ||
|
||
from .utils.cryptomath import numBytes | ||
|
||
RSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"] | ||
ALL_RSA_SIGNATURE_HASHES = RSA_SIGNATURE_HASHES + ["md5"] | ||
RSA_SCHEMES = ["pss", "pkcs1"] | ||
|
||
|
||
class SignatureSettings(object): | ||
def __init__(self, min_key_size=None, max_key_size=None, | ||
rsa_sig_hashes=None, rsa_schemes=None): | ||
"""Create default variables for key-related settings.""" | ||
self.min_key_size = min_key_size or 1023 | ||
self.max_key_size = max_key_size or 8193 | ||
self.rsa_sig_hashes = rsa_sig_hashes or list(RSA_SIGNATURE_HASHES) | ||
self.rsa_schemes = rsa_schemes or list(RSA_SCHEMES) | ||
|
||
def _copy_settings(self, other): | ||
other.min_key_size = self.min_key_size | ||
other.max_key_size = self.max_key_size | ||
other.rsa_sig_hashes = self.rsa_sig_hashes | ||
other.rsa_schemes = self.rsa_schemes | ||
|
||
@staticmethod | ||
def _sanityCheckKeySizes(other): | ||
if other.min_key_size < 512: | ||
raise ValueError("min_key_size too small") | ||
if other.min_key_size > 16384: | ||
raise ValueError("min_key_size too large") | ||
if other.max_key_size < 512: | ||
raise ValueError("max_key_size too small") | ||
if other.max_key_size > 16384: | ||
raise ValueError("max_key_size too large") | ||
if other.max_key_size < other.min_key_size: | ||
raise ValueError("max_key_size smaller than min_key_size") | ||
|
||
@staticmethod | ||
def _sanityCheckSignatureAlgs(other): | ||
not_allowed = [alg for alg in other.rsa_sig_hashes | ||
if alg not in ALL_RSA_SIGNATURE_HASHES] | ||
if len(not_allowed) > 0: | ||
raise ValueError("Following signature algorithms are not allowed: " | ||
"{0}".format(", ".join(not_allowed))) | ||
|
||
def validate(self): | ||
other = SignatureSettings() | ||
self._copy_settings(other) | ||
self._sanityCheckKeySizes(other) | ||
self._sanityCheckSignatureAlgs(other) | ||
return other | ||
|
||
|
||
class SignedObject(object): | ||
def __init__(self): | ||
self.tbs_data = None | ||
self.signature = None | ||
self.signature_alg = None | ||
|
||
_hash_algs_OIDs = { | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x4]): 'md5', | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x5]): 'sha1', | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xe]): 'sha224', | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xc]): 'sha384', | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb]): 'sha256', | ||
tuple([0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xd]): 'sha512' | ||
} | ||
|
||
def verify_signature(self, publicKey, settings=None): | ||
""" Verify signature in a reponse""" | ||
offset = 0 | ||
settings = settings or SignatureSettings() | ||
|
||
# workaround as some signature encodings could be zero left-padded | ||
if (self.signature[0] == 0 and | ||
numBytes(publicKey.n) + 1 == len(self.signature)): | ||
offset = 1 | ||
|
||
alg = self._hash_algs_OIDs[tuple(self.signature_alg)] | ||
if alg not in settings.rsa_sig_hashes: | ||
raise ValueError("Invalid signature algorithm: {0}".format(alg)) | ||
verified = publicKey.hashAndVerify(self.signature[offset:], | ||
self.tbs_data, hAlg=alg) | ||
if not verified: | ||
raise ValueError("Signature could not be verified for {0}" | ||
.format(alg)) | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Author: Anna Khaitovich (c) 2018 | ||
# see LICENCE file for legal information regarding use of this file | ||
|
||
# compatibility with Python 2.6, for that we need unittest2 package, | ||
# which is not available on 3.3 or 3.4 | ||
try: | ||
import unittest2 as unittest | ||
except ImportError: | ||
import unittest | ||
|
||
from tlslite.signed import SignatureSettings, SignedObject, RSA_SIGNATURE_HASHES, RSA_SCHEMES | ||
|
||
|
||
class TestSignatureSettings(unittest.TestCase): | ||
def test_signature_settings_validate(self): | ||
settings = SignatureSettings() | ||
validated = settings.validate() | ||
self.assertEqual(validated.min_key_size, 1023) | ||
self.assertEqual(validated.max_key_size, 8193) | ||
self.assertEqual(validated.rsa_sig_hashes, RSA_SIGNATURE_HASHES) | ||
self.assertEqual(validated.rsa_schemes, RSA_SCHEMES) | ||
|
||
def test_signature_settings_min_key_size_small(self): | ||
settings = SignatureSettings(min_key_size=256) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("min_key_size too small", str(ctx.exception)) | ||
|
||
def test_signature_settings_min_key_size_large(self): | ||
settings = SignatureSettings(min_key_size=17000) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("min_key_size too large", str(ctx.exception)) | ||
|
||
def test_signature_settings_max_key_size_small(self): | ||
settings = SignatureSettings(max_key_size=256) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("max_key_size too small", str(ctx.exception)) | ||
|
||
def test_signature_settings_max_key_size_large(self): | ||
settings = SignatureSettings(max_key_size=17000) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("max_key_size too large", str(ctx.exception)) | ||
|
||
def test_signature_settings_min_key_bigger_max_key(self): | ||
settings = SignatureSettings(min_key_size=2048, max_key_size=1024) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("max_key_size smaller than min_key_size", str(ctx.exception)) | ||
|
||
def test_signature_settings_invalid_sig_alg(self): | ||
settings = SignatureSettings(rsa_sig_hashes=list(['sha1', 'sha128', 'sha129'])) | ||
with self.assertRaises(ValueError) as ctx: | ||
settings.validate() | ||
self.assertIn("Following signature algorithms are not allowed: sha128, sha129", | ||
str(ctx.exception)) | ||
#TODO: verify_signature method testing |