From 3df4ae2fa4279ce3000c175bb3fd965328870a85 Mon Sep 17 00:00:00 2001 From: Artem Los Date: Thu, 8 Feb 2024 00:54:43 +1100 Subject: [PATCH] Add support for Metadata property in Key.Activate (#67) * First commit * Update * Update internal.py * Update internal.py * Update models.py * Update setup.py --- licensing/internal.py | 30 ++++++++++++++++++++++++++---- licensing/methods.py | 16 +++++++++++++++- licensing/models.py | 11 +++++++++-- setup.py | 4 ++-- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/licensing/internal.py b/licensing/internal.py index 37e3ff3..3f3c86e 100644 --- a/licensing/internal.py +++ b/licensing/internal.py @@ -70,28 +70,33 @@ def RSAVP1(pair, s): return pow(s, e, n) @staticmethod - def EMSA_PKCS1_V15_ENCODE(M, emLen): + def EMSA_PKCS1_V15_ENCODE(M, emLen, hlen = 256): import hashlib h = hashlib.sha256() + if hlen == 512: + h = hashlib.sha512() h.update(M) H = h.digest() T = bytes([0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]) + H + if hlen == 512: + T = bytes([0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]) + H + tLen = len(T) if emLen < tLen + 11: return None PS = bytes([0xff for _ in range(emLen - tLen - 3)]) return b"".join([b"\x00\x01", PS, b"\x00", T]) - + @staticmethod - def RSAASSA_PKCS1_V15_VERIFY(pair, M, S): + def RSAASSA_PKCS1_V15_VERIFY(pair, M, S, l=256): n, e = pair s = HelperMethods.OS2IP(S) m = HelperMethods.RSAVP1((n,e), s) if m is None: return False EM = HelperMethods.I2OSP(m, 256) if EM is None: return False - EM2 = HelperMethods.EMSA_PKCS1_V15_ENCODE(M, 256) + EM2 = HelperMethods.EMSA_PKCS1_V15_ENCODE(M, 256, l) if EM2 is None: return False try: @@ -114,6 +119,23 @@ def verify_signature(response, rsaPublicKey): return HelperMethods.RSAASSA_PKCS1_V15_VERIFY((n,e), m, r) + @staticmethod + def verify_signature_metadata(signature, rsaPublicKey): + + import base64 + import json + + n = HelperMethods.OS2IP(base64.b64decode(rsaPublicKey.modulus)) + e = HelperMethods.OS2IP(base64.b64decode(rsaPublicKey.exponent)) + + data = json.loads(base64.b64decode(signature)) + + d = base64.b64decode(data["Data"]) + s = base64.b64decode(data["Signature"]) + + return [HelperMethods.RSAASSA_PKCS1_V15_VERIFY((n,e), d,s, l=512), d] + + @staticmethod def int2base64(num): return base64.b64encode(int.to_bytes(num), byteorder='big') diff --git a/licensing/methods.py b/licensing/methods.py index 7fb7675..72918d0 100644 --- a/licensing/methods.py +++ b/licensing/methods.py @@ -61,7 +61,21 @@ def activate(token, rsa_pub_key, product_id, key, machine_code, fields_to_return else: try: if HelperMethods.verify_signature(response, pubkey): - return (LicenseKey.from_response(response), response.message) + if metadata: + + try: + metadata_s = HelperMethods.verify_signature_metadata(response.metadata["signature"], pubkey) + + if metadata_s[0]: + return (LicenseKey.from_response(response), response.message, json.loads(metadata_s[1])) + else: + return (LicenseKey.from_response(response), response.message, "Signature check for metadata object failed.") + except: + return (LicenseKey.from_response(response), response.message, "Signature check for metadata object failed.") + + + else: + return (LicenseKey.from_response(response), response.message) else: return (None, "The signature check failed.") except Exception as ex: diff --git a/licensing/models.py b/licensing/models.py index a6108ad..5d1df47 100644 --- a/licensing/models.py +++ b/licensing/models.py @@ -164,11 +164,12 @@ def __load_activated_machines(obj): class Response: - def __init__(self, license_key, signature, result, message): + def __init__(self, license_key, signature, result, message, metadata=None): self.license_key = license_key self.signature = signature self.result = result self.message = message + self.metadata = metadata @staticmethod def from_string(responseString): @@ -178,6 +179,7 @@ def from_string(responseString): signature = "" result = 0 message = "" + metadata = None if "licensekey" in obj: licenseKey = obj["licensekey"] @@ -192,8 +194,13 @@ def from_string(responseString): result = obj["result"] else: result = 1 + + if "metadata" in obj: + metadata = obj["metadata"] + + - return Response(licenseKey, signature, result, message) + return Response(licenseKey, signature, result, message, metadata) class RSAPublicKey: diff --git a/setup.py b/setup.py index 55176da..bf59adc 100644 --- a/setup.py +++ b/setup.py @@ -2,13 +2,13 @@ setup( name = 'licensing', # How you named your package folder (MyLib) packages = ['licensing'], # Chose the same as "name" - version = '0.41', # Start with a small number and increase it with every change you make + version = '0.42', # Start with a small number and increase it with every change you make license='MIT', # Chose a license from here: https://help.github.com/articles/licensing-a-repository description = 'Client library for Cryptolens licensing Web API.', # Give a short description about your library author = 'Cryptolens AB', # Type in your name author_email = 'support@cryptolens.io', # Type in your E-Mail url = 'https://cryptolens.io', # Provide either the link to your github or to your website - download_url = 'https://github.com/Cryptolens/cryptolens-python/archive/v_41.tar.gz', # I explain this later on + download_url = 'https://github.com/Cryptolens/cryptolens-python/archive/v_42.tar.gz', # I explain this later on keywords = ['software licensing', 'licensing library', 'cryptolens'], # Keywords that define your package best classifiers=[ #'Development Status :: 5 - Stable', # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package