-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
decode_fingerprint()
and fingerprint_match()
functions #minor
Extended the functionality with two new functions and related tests. The `decode_fingerprint()` function takes jfp's as input, validates them and returns a 3-value tuple containing the version (int), hash function (str) and hash (str). The `fingerprint_match()` uses the `decode_fingerprint()` function internally to decode a `target_fingerprint`, then create a fingerprint with these value of the given JSON input data. If the fingerprint then matches the given `target_fingerprint` value, the function will return `True`, or otherwise `False` if they don't match. Refactoring: - Split all exceptions into a dedicated `_exceptions` module - Moved JSON loading into a new utility module `_utils` Other changes: - Updated README.md to reflect new functionality
- Loading branch information
Showing
14 changed files
with
274 additions
and
45 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 |
---|---|---|
@@ -1 +1,3 @@ | ||
from .decode_fingerprint import decode_fingerprint | ||
from .fingerprint_match import fingerprint_match | ||
from .json_fingerprint import json_fingerprint |
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,18 @@ | ||
class FingerprintHashFunctionError(Exception): | ||
pass | ||
|
||
|
||
class FingerprintInputDataTypeError(Exception): | ||
pass | ||
|
||
|
||
class FingerprintVersionError(Exception): | ||
pass | ||
|
||
|
||
class FingerprintStringFormatError(Exception): | ||
pass | ||
|
||
|
||
class FingerprintJSONLoadError(Exception): | ||
pass |
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,11 @@ | ||
import json | ||
|
||
from ._exceptions import FingerprintJSONLoadError | ||
|
||
|
||
def _load_json(data: str): | ||
try: | ||
return json.loads(data) | ||
except Exception: | ||
err = 'Unable to load JSON' | ||
raise FingerprintJSONLoadError(err) from None |
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,13 @@ | ||
from typing import Tuple | ||
from ._validators import _validate_fingerprint_format | ||
|
||
|
||
def decode_fingerprint(fingerprint: str) -> Tuple[int, str, str]: | ||
"""Decode json fingerprints into version, hash function and hash values.""" | ||
_validate_fingerprint_format(fingerprint) | ||
elements = fingerprint.split('$') | ||
version = int(elements[0][4:]) | ||
hash_function = elements[1] | ||
hash = elements[2] | ||
|
||
return version, hash_function, hash |
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,13 @@ | ||
from .decode_fingerprint import decode_fingerprint | ||
from .json_fingerprint import json_fingerprint | ||
|
||
|
||
def fingerprint_match(input: str, target_fingerprint: str) -> bool: | ||
"""Match raw json str input to target fingerprint. | ||
Decodes the target fingerprint and creates a fingerprint from the input with identical parameters.""" | ||
version, hash_function, _ = decode_fingerprint(fingerprint=target_fingerprint) | ||
input_fingerprint = json_fingerprint(input=input, hash_function=hash_function, version=version) | ||
if input_fingerprint == target_fingerprint: | ||
return True | ||
return False |
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 |
---|---|---|
@@ -1,27 +1,16 @@ | ||
import json | ||
|
||
from ._jfpv1 import _create_jfpv1_fingerprint | ||
from ._utils import _load_json | ||
from ._validators import ( | ||
_validate_hash_function, | ||
_validate_input_type, | ||
_validate_version, | ||
) | ||
|
||
|
||
class FingerprintJSONLoadError(Exception): | ||
pass | ||
|
||
|
||
def json_fingerprint(input: str, hash_function: str, version: int) -> str: | ||
"""Create json fingerprints with the selected hash function and jfp version.""" | ||
_validate_version(version=version) | ||
_validate_input_type(input=input) | ||
_validate_hash_function(hash_function=hash_function, version=version) | ||
|
||
try: | ||
loaded = json.loads(input) | ||
except Exception: | ||
err = 'Unable to load JSON' | ||
raise FingerprintJSONLoadError(err) from None | ||
|
||
loaded = _load_json(data=input) | ||
return _create_jfpv1_fingerprint(data=loaded, hash_function=hash_function, version=version) |
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 |
---|---|---|
@@ -1,3 +1,5 @@ | ||
from .test_json_fingerprint import TestJsonFingerprint | ||
from .test_decode_fingerprint import TestDecodeFingerprint | ||
from .test_fingerprint_match import TestFingerprintMatch | ||
from .test_jfpv1 import TestJfpv1 | ||
from .test_json_fingerprint import TestJsonFingerprint | ||
from .test_validators import TestValidators |
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,43 @@ | ||
import json | ||
import unittest | ||
|
||
from json_fingerprint import ( | ||
_exceptions, | ||
decode_fingerprint, | ||
json_fingerprint, | ||
) | ||
|
||
|
||
class TestDecodeFingerprint(unittest.TestCase): | ||
def test_decode_fingerprint(self): | ||
"""Test json fingerprint decoder. | ||
Verify that: | ||
- Fingerprints of all jfpv1 SHA-2 variants are properly decoded | ||
- Exception is properly raised with invalid fingerprint input""" | ||
input = json.dumps({'foo': 'bar'}) | ||
jfpv1_sha256 = json_fingerprint(input=input, hash_function='sha256', version=1) | ||
jfpv1_sha384 = json_fingerprint(input=input, hash_function='sha384', version=1) | ||
jfpv1_sha512 = json_fingerprint(input=input, hash_function='sha512', version=1) | ||
|
||
version, hash_function, hash = decode_fingerprint(fingerprint=jfpv1_sha256) | ||
self.assertEqual(version, 1) | ||
self.assertEqual(hash_function, 'sha256') | ||
self.assertEqual(hash, jfpv1_sha256.split('$')[-1]) | ||
|
||
version, hash_function, hash = decode_fingerprint(fingerprint=jfpv1_sha384) | ||
self.assertEqual(version, 1) | ||
self.assertEqual(hash_function, 'sha384') | ||
self.assertEqual(hash, jfpv1_sha384.split('$')[-1]) | ||
|
||
version, hash_function, hash = decode_fingerprint(fingerprint=jfpv1_sha512) | ||
self.assertEqual(version, 1) | ||
self.assertEqual(hash_function, 'sha512') | ||
self.assertEqual(hash, jfpv1_sha512.split('$')[-1]) | ||
|
||
with self.assertRaises(_exceptions.FingerprintStringFormatError): | ||
decode_fingerprint(fingerprint='invalid fingerprint') | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
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,40 @@ | ||
import json | ||
import unittest | ||
|
||
from json_fingerprint import ( | ||
_exceptions, | ||
fingerprint_match, | ||
json_fingerprint, | ||
) | ||
|
||
|
||
class TestFingerprintMatch(unittest.TestCase): | ||
def test_jfpv1_fingerprint_match(self): | ||
"""Test json fingerprint matcher. | ||
Verify that: | ||
- Fingerprints of all jfpv1 SHA-2 variants are properly matched | ||
- Exception is properly raised with invalid fingerprints and input types""" | ||
input = json.dumps({'foo': 'bar'}) | ||
jfpv1_sha256 = json_fingerprint(input=input, hash_function='sha256', version=1) | ||
jfpv1_sha384 = json_fingerprint(input=input, hash_function='sha384', version=1) | ||
jfpv1_sha512 = json_fingerprint(input=input, hash_function='sha512', version=1) | ||
|
||
match_sha256 = fingerprint_match(input=input, target_fingerprint=jfpv1_sha256) | ||
self.assertEqual(match_sha256, True) | ||
match_sha384 = fingerprint_match(input=input, target_fingerprint=jfpv1_sha384) | ||
self.assertEqual(match_sha384, True) | ||
match_sha512 = fingerprint_match(input=input, target_fingerprint=jfpv1_sha512) | ||
self.assertEqual(match_sha512, True) | ||
|
||
no_match = fingerprint_match(input=json.dumps('{"bar": "foo"}'), target_fingerprint=jfpv1_sha256) | ||
self.assertEqual(no_match, False) | ||
|
||
with self.assertRaises(_exceptions.FingerprintJSONLoadError): | ||
fingerprint_match(input='{"invalid": json string}', target_fingerprint=jfpv1_sha256) | ||
with self.assertRaises(_exceptions.FingerprintStringFormatError): | ||
fingerprint_match(input=input, target_fingerprint='invalid fingerprint string') | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
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
Oops, something went wrong.