Skip to content

Commit

Permalink
Add quoter
Browse files Browse the repository at this point in the history
  • Loading branch information
barseghyanartur committed Aug 17, 2021
1 parent 036cfe5 commit cb120e4
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ are used for versioning (schema follows below):
- Add `value_dumper` to most of the functions/methods related to signature
generation/validation. It's aimed to make signatures generated in languages
better compatible with `ska`.
- Add `quoter` to most of the functions/methods related to signature
generation/validation. It's aimed to make signatures generated in languages
better compatible with `ska`.

1.8.2
-----
Expand Down
11 changes: 11 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ are used for versioning (schema follows below):
0.3.4 to 0.4).
- All backwards incompatible changes are mentioned in this document.

1.9
-----
2021-08-17

- Add `value_dumper` to most of the functions/methods related to signature
generation/validation. It's aimed to make signatures generated in languages
better compatible with `ska`.
- Add `quoter` to most of the functions/methods related to signature
generation/validation. It's aimed to make signatures generated in languages
better compatible with `ska`.

1.8.2
-----
2021-06-18
Expand Down
15 changes: 14 additions & 1 deletion src/ska/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def validate_signature(
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
return_object: bool = False,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> Union[SignatureValidationResult, bool]:
"""Validates the signature.
Expand All @@ -141,6 +142,7 @@ def validate_signature(
:param return_object: If set to True, an instance of
``SignatureValidationResult`` is returned.
:param value_dumper:
:param quoter:
:return:
:example:
Expand All @@ -165,6 +167,7 @@ def validate_signature(
valid_until=valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
)

if not return_object:
Expand Down Expand Up @@ -209,6 +212,7 @@ def get_base(
timestamp: Union[float, str],
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Get base string.
Expand All @@ -219,6 +223,7 @@ def get_base(
:param timestamp:
:param extra:
:param value_dumper:
:param quoter:
"""
if not extra:
extra = {}
Expand All @@ -227,7 +232,9 @@ def get_base(

if extra:
urlencoded_extra = sorted_urlencode(
extra, value_dumper=value_dumper
extra,
value_dumper=value_dumper,
quoter=quoter,
)
if urlencoded_extra:
_base.append(urlencoded_extra)
Expand All @@ -251,6 +258,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -261,6 +269,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
raise NotImplementedError("You should implement this method!")
Expand All @@ -274,6 +283,7 @@ def generate_signature(
lifetime: int = SIGNATURE_LIFETIME,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> "AbstractSignature":
"""Generates the signature.
Expand All @@ -285,6 +295,8 @@ def generate_signature(
:param valid_until: Unix timestamp, valid until.
:param lifetime: Lifetime of the signature in seconds.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
:example:
Expand All @@ -311,6 +323,7 @@ def generate_signature(
valid_until,
extra,
value_dumper=value_dumper,
quoter=quoter,
)
)

Expand Down
23 changes: 19 additions & 4 deletions src/ska/helpers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from collections import OrderedDict
from datetime import datetime, timedelta
from importlib import import_module
import json
from uuid import UUID
import time
from typing import Callable, Dict, List, Tuple, Union, Optional
from urllib.parse import quote
Expand All @@ -21,6 +19,8 @@
"javascript_value_dumper",
"make_valid_until",
"sorted_urlencode",
"default_quoter",
"javascript_quoter",
)


Expand Down Expand Up @@ -121,27 +121,42 @@ def javascript_value_dumper(value):
return json.dumps(value, separators=(",", ":"))


def default_quoter(value):
return quote(value)


def javascript_quoter(value):
return quote(value, safe="~()*!.'")


def sorted_urlencode(
data: Dict[str, Union[bytes, str, float, int]],
quoted: bool = True,
value_dumper: Optional[Callable] = default_value_dumper,
quoter: Optional[Callable] = default_quoter,
) -> str:
"""Similar to built-in ``urlencode``, but always puts data in a sorted
constant way that stays the same between various python versions.
:param data:
:param quoted:
:param value_dumper:
:param quoter:
:return:
"""
if not value_dumper:
value_dumper = default_value_dumper

if not quoter:
quoter = default_quoter

# _sorted = [f"{k}={value_dumper(v)}" for k, v in dict_to_ordered_list(data)]
_sorted = [f"{k}={value_dumper(v)}" for k, v in dict_to_ordered_dict(data).items()]
_sorted = [
f"{k}={value_dumper(v)}" for k, v in dict_to_ordered_dict(data).items()
]
res = "&".join(_sorted)
if quoted:
res = quote(res)
res = quoter(res)
return res


Expand Down
9 changes: 9 additions & 0 deletions src/ska/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def signature_to_dict(
extra_param: str = DEFAULT_EXTRA_PARAM,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> Dict[str, Union[bytes, str, float, int]]:
"""Return a dictionary containing the signature data params.
Expand All @@ -154,6 +155,7 @@ def signature_to_dict(
would hold the ``extra`` keys value.
:param signature_cls:
:param value_dumper:
:param quoter:
:return:
:example:
Expand Down Expand Up @@ -190,6 +192,7 @@ def signature_to_dict(
lifetime=lifetime,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
)

request_helper = RequestHelper(
Expand All @@ -214,6 +217,7 @@ def validate_signed_request_data(
extra_param: str = DEFAULT_EXTRA_PARAM,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> SignatureValidationResult:
"""Validate the signed request data.
Expand All @@ -230,6 +234,7 @@ def validate_signed_request_data(
name which holds the ``extra`` keys value.
:param signature_cls:
:param value_dumper:
:param quoter:
:return: A ``ska.SignatureValidationResult``
object with the following properties:
- `result` (bool): True if data is valid. False otherwise.
Expand All @@ -248,6 +253,7 @@ def validate_signed_request_data(
data=data,
secret_key=secret_key,
value_dumper=value_dumper,
quoter=quoter,
)

return validation_result
Expand All @@ -264,6 +270,7 @@ def extract_signed_request_data(
fail_silently: bool = False,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> Dict[str, Union[bytes, str, float, int]]:
"""Validate the signed request data.
Expand All @@ -283,6 +290,7 @@ def extract_signed_request_data(
:param fail_silently: If set to True, exceptions are omitted.
:param signature_cls:
:param value_dumper:
:param quoter:
:return: Dictionary with signed request data.
"""
request_helper = RequestHelper(
Expand All @@ -299,4 +307,5 @@ def extract_signed_request_data(
validate=validate,
fail_silently=fail_silently,
value_dumper=value_dumper,
quoter=quoter,
)
8 changes: 7 additions & 1 deletion src/ska/signatures/hmac_md5.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -31,6 +32,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
if not extra:
Expand All @@ -39,7 +41,11 @@ def make_hash(
raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
auth_user,
valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
),
hashlib.md5,
).digest()
Expand Down
8 changes: 7 additions & 1 deletion src/ska/signatures/hmac_sha1.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -31,6 +32,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
if not extra:
Expand All @@ -39,7 +41,11 @@ def make_hash(
raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
auth_user,
valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
),
hashlib.sha1,
).digest()
Expand Down
8 changes: 7 additions & 1 deletion src/ska/signatures/hmac_sha224.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -31,6 +32,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
if not extra:
Expand All @@ -39,7 +41,11 @@ def make_hash(
raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
auth_user,
valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
),
hashlib.sha224,
).digest()
Expand Down
8 changes: 7 additions & 1 deletion src/ska/signatures/hmac_sha256.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -31,6 +32,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
if not extra:
Expand All @@ -39,7 +41,11 @@ def make_hash(
raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
auth_user,
valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
),
hashlib.sha256,
).digest()
Expand Down
8 changes: 7 additions & 1 deletion src/ska/signatures/hmac_sha384.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def make_hash(
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
quoter: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -31,6 +32,7 @@ def make_hash(
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:param quoter:
:return:
"""
if not extra:
Expand All @@ -39,7 +41,11 @@ def make_hash(
raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
auth_user,
valid_until,
extra=extra,
value_dumper=value_dumper,
quoter=quoter,
),
hashlib.sha384,
).digest()
Expand Down
Loading

0 comments on commit cb120e4

Please sign in to comment.