Skip to content

Commit

Permalink
Add value dumper func
Browse files Browse the repository at this point in the history
  • Loading branch information
barseghyanartur committed Aug 17, 2021
1 parent c1f211d commit c743caf
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 24 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ 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`.

1.8.2
-----
2021-06-18
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
except:
readme = ""

version = "1.8.2"
version = "1.9"

exec_dirs = [
"src/ska/bin/",
Expand Down
2 changes: 1 addition & 1 deletion src/ska/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from .utils import RequestHelper

__title__ = "ska"
__version__ = "1.8.2"
__version__ = "1.9"
__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
__copyright__ = "2013-2021 Artur Barseghyan"
__license__ = "GPL 2.0/LGPL 2.1"
Expand Down
22 changes: 19 additions & 3 deletions src/ska/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from base64 import b64encode
from datetime import datetime, timedelta
import time
from typing import Any, Dict, List, Optional, Union
from typing import Any, Dict, List, Optional, Union, Callable

from . import error_codes
from .defaults import SIGNATURE_LIFETIME, TIMESTAMP_FORMAT
Expand Down Expand Up @@ -129,6 +129,7 @@ def validate_signature(
valid_until: Union[str, float],
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
return_object: bool = False,
value_dumper: Optional[Callable] = None,
) -> Union[SignatureValidationResult, bool]:
"""Validates the signature.
Expand All @@ -139,6 +140,7 @@ def validate_signature(
:param extra: Extra arguments to be validated.
:param return_object: If set to True, an instance of
``SignatureValidationResult`` is returned.
:param value_dumper:
:return:
:example:
Expand All @@ -162,6 +164,7 @@ def validate_signature(
secret_key=secret_key,
valid_until=valid_until,
extra=extra,
value_dumper=value_dumper,
)

if not return_object:
Expand Down Expand Up @@ -205,6 +208,7 @@ def get_base(
auth_user: str,
timestamp: Union[float, str],
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> bytes:
"""Get base string.
Expand All @@ -214,14 +218,17 @@ def get_base(
:param auth_user:
:param timestamp:
:param extra:
:param value_dumper:
"""
if not extra:
extra = {}

_base = [str(timestamp), auth_user]

if extra:
urlencoded_extra = sorted_urlencode(extra)
urlencoded_extra = sorted_urlencode(
extra, value_dumper=value_dumper
)
if urlencoded_extra:
_base.append(urlencoded_extra)

Expand All @@ -243,6 +250,7 @@ def make_hash(
secret_key: str,
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -252,6 +260,7 @@ def make_hash(
:param secret_key:
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:return:
"""
raise NotImplementedError("You should implement this method!")
Expand All @@ -264,6 +273,7 @@ def generate_signature(
valid_until: Optional[Union[float, str]] = None,
lifetime: int = SIGNATURE_LIFETIME,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> "AbstractSignature":
"""Generates the signature.
Expand Down Expand Up @@ -295,7 +305,13 @@ def generate_signature(
return None # Something went wrong

signature = b64encode(
cls.make_hash(auth_user, secret_key, valid_until, extra)
cls.make_hash(
auth_user,
secret_key,
valid_until,
extra,
value_dumper=value_dumper,
)
)

return cls(
Expand Down
15 changes: 13 additions & 2 deletions src/ska/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
__license__ = "GPL 2.0/LGPL 2.1"
__all__ = (
"get_callback_func",
"default_value_dumper",
"dict_keys",
"dict_to_ordered_list",
"sorted_urlencode",
Expand Down Expand Up @@ -87,17 +88,27 @@ def dict_to_ordered_list(
return items


def default_value_dumper(value):
return value


def sorted_urlencode(
data: Dict[str, Union[bytes, str, float, int]], quoted: bool = True
data: Dict[str, Union[bytes, str, float, int]],
quoted: bool = True,
value_dumper: Optional[Callable] = default_value_dumper,
) -> 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:
:return:
"""
_sorted = [f"{k}={v}" for k, v in dict_to_ordered_list(data)]
if not value_dumper:
value_dumper = default_value_dumper

_sorted = [f"{k}={value_dumper(v)}" for k, v in dict_to_ordered_list(data)]
res = "&".join(_sorted)
if quoted:
res = quote(res)
Expand Down
15 changes: 13 additions & 2 deletions src/ska/shortcuts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Optional, Type, Union
from typing import Dict, Optional, Type, Union, Callable

from .base import SignatureValidationResult, AbstractSignature
from .defaults import (
Expand Down Expand Up @@ -43,6 +43,7 @@ def sign_url(
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
extra_param: str = DEFAULT_EXTRA_PARAM,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
) -> str:
"""Sign the URL.
Expand All @@ -64,6 +65,7 @@ def sign_url(
:param extra_param: Name of the GET param name which would hold the
``extra_keys`` value.
:param signature_cls:
:param value_dumper:
:return:
:example:
Expand Down Expand Up @@ -101,6 +103,7 @@ def sign_url(
valid_until=valid_until,
lifetime=lifetime,
extra=extra,
value_dumper=value_dumper,
)

request_helper = RequestHelper(
Expand Down Expand Up @@ -131,6 +134,7 @@ def signature_to_dict(
extra: Optional[Dict[str, Union[str, int]]] = None,
extra_param: str = DEFAULT_EXTRA_PARAM,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
) -> Dict[str, Union[bytes, str, float, int]]:
"""Return a dictionary containing the signature data params.
Expand All @@ -149,6 +153,7 @@ def signature_to_dict(
:param extra_param: Name of the (for example POST) param name which
would hold the ``extra`` keys value.
:param signature_cls:
:param value_dumper:
:return:
:example:
Expand Down Expand Up @@ -184,6 +189,7 @@ def signature_to_dict(
valid_until=valid_until,
lifetime=lifetime,
extra=extra,
value_dumper=value_dumper,
)

request_helper = RequestHelper(
Expand All @@ -207,6 +213,7 @@ def validate_signed_request_data(
valid_until_param: str = DEFAULT_VALID_UNTIL_PARAM,
extra_param: str = DEFAULT_EXTRA_PARAM,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
) -> SignatureValidationResult:
"""Validate the signed request data.
Expand All @@ -222,6 +229,7 @@ def validate_signed_request_data(
:param extra_param: Name of the (foe example GET or POST) param
name which holds the ``extra`` keys value.
:param signature_cls:
:param value_dumper:
:return: A ``ska.SignatureValidationResult``
object with the following properties:
- `result` (bool): True if data is valid. False otherwise.
Expand All @@ -237,7 +245,7 @@ def validate_signed_request_data(
)

validation_result = request_helper.validate_request_data(
data=data, secret_key=secret_key
data=data, secret_key=secret_key, value_dumper=value_dumper,
)

return validation_result
Expand All @@ -253,6 +261,7 @@ def extract_signed_request_data(
validate: bool = False,
fail_silently: bool = False,
signature_cls: Type[AbstractSignature] = Signature,
value_dumper: Optional[Callable] = None,
) -> Dict[str, Union[bytes, str, float, int]]:
"""Validate the signed request data.
Expand All @@ -271,6 +280,7 @@ def extract_signed_request_data(
returning the result.
:param fail_silently: If set to True, exceptions are omitted.
:param signature_cls:
:param value_dumper:
:return: Dictionary with signed request data.
"""
request_helper = RequestHelper(
Expand All @@ -286,4 +296,5 @@ def extract_signed_request_data(
secret_key=secret_key,
validate=validate,
fail_silently=fail_silently,
value_dumper=value_dumper,
)
8 changes: 6 additions & 2 deletions src/ska/signatures/hmac_md5.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import hashlib
import hmac
from typing import Union, Optional, Dict
from typing import Union, Optional, Dict, Callable

from ..base import AbstractSignature

Expand All @@ -20,6 +20,7 @@ def make_hash(
secret_key: str,
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -29,14 +30,17 @@ def make_hash(
:param secret_key:
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:return:
"""
if not extra:
extra = {}

raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(auth_user, valid_until, extra=extra),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
),
hashlib.md5,
).digest()

Expand Down
8 changes: 6 additions & 2 deletions src/ska/signatures/hmac_sha1.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import hashlib
import hmac
from typing import Union, Optional, Dict
from typing import Union, Optional, Dict, Callable

from ..base import AbstractSignature

Expand All @@ -20,6 +20,7 @@ def make_hash(
secret_key: str,
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -29,14 +30,17 @@ def make_hash(
:param secret_key:
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:return:
"""
if not extra:
extra = {}

raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(auth_user, valid_until, extra=extra),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
),
hashlib.sha1,
).digest()

Expand Down
8 changes: 6 additions & 2 deletions src/ska/signatures/hmac_sha224.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import hashlib
import hmac
from typing import Union, Optional, Dict
from typing import Union, Optional, Dict, Callable

from ..base import AbstractSignature

Expand All @@ -20,6 +20,7 @@ def make_hash(
secret_key: str,
valid_until: Union[str, float] = None,
extra: Optional[Dict[str, Union[bytes, str, float, int]]] = None,
value_dumper: Optional[Callable] = None,
) -> bytes:
"""Make hash.
Expand All @@ -29,14 +30,17 @@ def make_hash(
:param secret_key:
:param valid_until: Unix timestamp, valid until.
:param extra: Additional variables to be added.
:param value_dumper:
:return:
"""
if not extra:
extra = {}

raw_hmac = hmac.new(
cls.make_secret_key(secret_key),
cls.get_base(auth_user, valid_until, extra=extra),
cls.get_base(
auth_user, valid_until, extra=extra, value_dumper=value_dumper
),
hashlib.sha224,
).digest()

Expand Down
Loading

0 comments on commit c743caf

Please sign in to comment.