Skip to content

Commit

Permalink
Merge pull request line#13 from charsyam/bugfix/hmac-compare-digest-f…
Browse files Browse the repository at this point in the history
…or-under-python277

hmac.compare_digest is not in earlier version python2.7.7
  • Loading branch information
be-hase authored Oct 19, 2016
2 parents a9b3f6e + 29759f7 commit b763069
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 4 deletions.
22 changes: 22 additions & 0 deletions linebot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,25 @@ def to_camel_case(text):
"""
split = text.split('_')
return split[0] + "".join(x.title() for x in split[1:])


def safe_compare_digest(val1, val2):
"""safe_compare_digest method.
:param val1: string or bytes for compare
:type val1: str | bytes
:param val2: string or bytes for compare
:type val2: str | bytes
"""
if len(val1) != len(val2):
return False

result = 0
if PY3 and isinstance(val1, bytes) and isinstance(val2, bytes):
for i, j in zip(val1, val2):
result |= i ^ j
else:
for i, j in zip(val1, val2):
result |= (ord(i) ^ ord(j))

return result == 0
32 changes: 29 additions & 3 deletions linebot/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,33 @@
PostbackEvent,
BeaconEvent
)
from .utils import LOGGER, PY3
from .utils import LOGGER, PY3, safe_compare_digest


if hasattr(hmac, "compare_digest"):
def compare_digest(val1, val2):
"""compare_digest method.
:param val1: string or bytes for compare
:type val1: str | bytes
:param val2: string or bytes for compare
:type val2: str | bytes
:rtype: bool
:return: result
"""
return hmac.compare_digest(val1, val2)
else:
def compare_digest(val1, val2):
"""compare_digest method.
:param val1: string or bytes for compare
:type val1: str | bytes
:param val2: string or bytes for compare
:type val2: str | bytes
:rtype: bool
:return: result
"""
return safe_compare_digest(val1, val2)


class SignatureValidator(object):
Expand Down Expand Up @@ -64,8 +90,8 @@ def validate(self, body, signature):
hashlib.sha256
).digest()

return hmac.compare_digest(
signature.encode('utf-8'), base64.b64encode(gen_signature)
return compare_digest(
signature.encode('utf-8'), base64.b64encode(gen_signature)
)


Expand Down
11 changes: 10 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import unittest

from linebot.utils import to_camel_case, to_snake_case
from linebot.utils import to_camel_case, to_snake_case, safe_compare_digest


class TestUtils(unittest.TestCase):
Expand All @@ -26,6 +26,15 @@ def test_to_snake_case(self):
def test_to_camel_case(self):
self.assertEqual(to_camel_case('hoge_bar'), 'hogeBar')

def test_safe_compare_digest_true(self):
self.assertTrue(safe_compare_digest('/gg9a+LvFevTH1sd7', '/gg9a+LvFevTH1sd7'))

def test_safe_compare_digest_false_same_size(self):
self.assertFalse(safe_compare_digest('/gg9a+LvFevTH1sd7', '/gg9a+LvFevTH1sd8'))

def test_safe_compare_digest_false_different_size(self):
self.assertFalse(safe_compare_digest('/gg9a+LvFevTH1sd7', '/gg9a+LvFevTH1sd78'))


if __name__ == '__main__':
unittest.main()

0 comments on commit b763069

Please sign in to comment.