From 44c19872408db84d5768e7f71bf4c94eb6636578 Mon Sep 17 00:00:00 2001 From: JJTech0130 Date: Sat, 23 Sep 2023 21:20:26 -0400 Subject: [PATCH] wow that was annoying --- ids/_helpers.py | 4 ++- ids/encryption.py | 18 +++++++++-- ids/identity.py | 46 +++++++++++++-------------- ids/test.js | 80 +++++++++++++++++++++++++++++++++++++++++++++++ ids/test.py | 32 +++++++++++++++++++ 5 files changed, 154 insertions(+), 26 deletions(-) create mode 100644 ids/test.js create mode 100644 ids/test.py diff --git a/ids/_helpers.py b/ids/_helpers.py index 58f3c52..0202f14 100644 --- a/ids/_helpers.py +++ b/ids/_helpers.py @@ -81,7 +81,9 @@ def create_compact_key(): def compact_key(key: ec.EllipticCurvePrivateKey): from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat - return key.public_key().public_bytes(Encoding.X962, PublicFormat.CompressedPoint)[1:] + k = key.public_key().public_bytes(Encoding.X962, PublicFormat.CompressedPoint) + assert k[0] == 0x02 + return k[1:] def create_compactable_key(): diff --git a/ids/encryption.py b/ids/encryption.py index 368f236..8580729 100644 --- a/ids/encryption.py +++ b/ids/encryption.py @@ -4,6 +4,8 @@ import struct,time from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature + import logging logger = logging.getLogger("ids") @@ -18,11 +20,23 @@ class NGMIdentity: def sign_prekey(self): timestamp = time.time() + # Set decimal to 0 + timestamp = float(int(timestamp)) to_sign = b"NGMPrekeySignature" + _helpers.compact_key(_helpers.parse_key(self.pre_key)) + struct.pack("\x9f\xae\xd9\xf9\xd1\x9c*\x8dU\xe0\xd2\xdeo\xb2\xcb\xd8\xf8i\xd4\xd0a^\t!\x0fa\xb2\xddI\xfc_*\x19\xb2\xf0#\x12\xe0@\xd9A", - # "supports-avless": True, - # "public-message-identity-key": b"0\x81\xf6\x81C\x00A\x04\x87\x1e\xeb\xe4u\x0b\xa3\x9e\x9c\xbc\xf8rK\x1e\xfe44%f$\x1d\xe8\xbb\xc6\xbdCD\x9ckv K\xc1\x1e\xb1\xdf4\xc8S6\x0f\x92\xd0=\x1e\x84\x9c\xc5\xa5\xb6\xb7}\xdd\xec\x1e\x1e\xd8Q\xd8\xca\xdb\x07'\xc7\x82\x81\xae\x00\xac0\x81\xa9\x02\x81\xa1\x00\xa8 \xfc\x9f\xa6\xb0V2\xce\x1c\xa7\x13\x9e\x03\xd1\xd8\x97a\xbb\xdd\xac\x86\xb8\x10(\x89\x13QP\x8f\xf0+EP\xd1\xb06\xee\x94\xcd\xa8\x9e\xf1\xedp\xa4\x9726\x1e\xe9\xab\xd4\xcb\xac\x05\xd7\x8c?\xbb\xa2\xde,\xfe\r\x1a\xb9\x88W@\x99\xec\xa0]\r\x1a>dV\xb2@\xc5P\xf3m\x80y\xf5\xa0G\xae\xd8h\x92\xef\xca\x85\xcbB\xed\xa9W\x8c\x13\xd4O\xdbYI2\xdcM\x1f\xf6c\x17\x1c\xd1v\xdd\xbcc\xac,&V\xfd\x07\xa0\xc3\x9f\x00\x1f\xc6\xe4\x02u\x12p\x8f\xe2\xb0\x14\xfai\x12\xbb\xa6\x9a6Q\xa5\xde+\x9e{\xcf\xc8\x1b}\x02\x03\x01\x00\x01", - # "supports-gft-calls": True, - # "public-message-identity-version": 2.0, - # "supports-co": True, - # "supports-gft-errors": True, - # "supports-self-one-to-one-invites": True, - # "supports-modern-gft": True, - # "public-message-identity-ngm-version": 12.0, - # "device-key-signature": b"0a\x04\x14\x1d\xb02~\xefk&\xf8\r;R\xa4\x95c~\x8a\x90H\x85\xb0\x02\x01\x01\x04F0D\x02 @\xce\xa7P6\x89\x92Wf\x87\xc9\xc5M-\xb1\xe5Q\x9f\x7fKi\x1bp\xd5\x12\x1c,:\xdb\xed\x08\x12\x02 l\xfd\\\xe2\xd3:,\xc1\xd8\x08|\xbe\x05M\x12\xee@\xc2=eR8:\xa7h3u|\x83ia\x19", - # }, - # "kt-loggable-data": b'\n"\n \rl\xbe\xca\xf7\xe8\xb2\x89k\x18\x1e\xb9,d\xf8\xe2\n\xbf\x8d\xe1E\xd6\xf3T\xcb\xd9\x99d\xd1mk\xeb\x10\x0c\x18\x05', + "public-message-ngm-device-prekey-data-key": ngm.sign_prekey(), + "supports-avless": True, + "public-message-identity-key": identity.encode(), + "supports-gft-calls": True, + "public-message-identity-version": 2.0, + "supports-co": True, + "supports-gft-errors": True, + "supports-self-one-to-one-invites": True, + "supports-modern-gft": True, + "public-message-identity-ngm-version": 12.0, + #"device-key-signature": b"0a\x04\x14\x1d\xb02~\xefk&\xf8\r;R\xa4\x95c~\x8a\x90H\x85\xb0\x02\x01\x01\x04F0D\x02 @\xce\xa7P6\x89\x92Wf\x87\xc9\xc5M-\xb1\xe5Q\x9f\x7fKi\x1bp\xd5\x12\x1c,:\xdb\xed\x08\x12\x02 l\xfd\\\xe2\xd3:,\xc1\xd8\x08|\xbe\x05M\x12\xee@\xc2=eR8:\xa7h3u|\x83ia\x19", + }, + "kt-loggable-data": ngm.generate_loggable_data(), "uris": uris, "user-id": user_id, diff --git a/ids/test.js b/ids/test.js new file mode 100644 index 0000000..b112368 --- /dev/null +++ b/ids/test.js @@ -0,0 +1,80 @@ +const { subtle } = globalThis.crypto; + +const fromHexString = (hexString) => + Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); + +function hexToBytes(hex) { + let bytes = []; + for (let c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +// Convert a byte array to a hex string +function bytesToHex(bytes) { + let hex = []; + for (let i = 0; i < bytes.length; i++) { + let current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i]; + hex.push((current >>> 4).toString(16)); + hex.push((current & 0xF).toString(16)); + } + return hex.join(""); +} +function byteToUint8Array(byteArray) { + var uint8Array = new Uint8Array(byteArray.length); + for(var i = 0; i < uint8Array.length; i++) { + uint8Array[i] = byteArray[i]; + } + + return uint8Array; +} + +const EXPECTED = "4e474d5072656b65795369676e6174757265e6565a7b37344b65f695db4f80d4515532a075cbb27a3d4dcbda949e9a571a640000c068e343d941" +const SIGNED = "54e0dc4956f7ce0e559b83e0d93d3a2d41074b59992100ab8a71c807fa50d6d2053da7f16621c799486f821a6ac627ffc76b4d63c11b9c75ef8c85d15c54aff4" +const DEV_KEY = "04ab72d39f38cbadfc8914e45726ec9a41732fad9eb6e6e536ea6ef6b954328a030fe1ed4c3332c98f91d4c079d43163e865d6c23b33394c69a131f51415ff0eda" + +async function test() { + let key = await subtle.importKey("raw",byteToUint8Array(hexToBytes(DEV_KEY)),{ + name: "ECDSA", + namedCurve: "P-256", + }, + true, + ["verify"], + ); + let signature = byteToUint8Array(hexToBytes(SIGNED)) + + let expected = byteToUint8Array(hexToBytes(EXPECTED)); + console.log(key); + let t = await subtle.verify({ + name: "ECDSA", + hash: "SHA-256" + }, key, signature, expected) + console.log(t) +} + +const DEV_PRIV_KEY = "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420a1b2ef67c92859ae7677c7bcc657c33fac4059448aff9602b8e6a313aa0d17caa144034200044eaf956b8619406cfd506232ded21fd5349f1ac8acc28b3b73bc8e293bc56ee0e4cfb4c9baf3c7603baa7716d0fe9c781e48f4bba5f90167f68d7f6c0e4b8cd8" +async function test2() { + //console.log(Uint8Array.from(Buffer.from(DEV_PRIV_KEY, 'hex'))) + let key = await subtle.importKey("pkcs8",fromHexString(DEV_PRIV_KEY),{ + name: "ECDSA", + namedCurve: "P-256", + }, + true, + ["sign"], + ); + let to_sign = byteToUint8Array(hexToBytes(EXPECTED)); + + let signature = await subtle.sign({ + name: "ECDSA", + hash: "SHA-256" + }, key, to_sign) + console.log(signature) +} +(async() => { + console.log('before start'); + + await test(); + await test2(); + + console.log('after start'); +})(); \ No newline at end of file diff --git a/ids/test.py b/ids/test.py new file mode 100644 index 0000000..e5f6285 --- /dev/null +++ b/ids/test.py @@ -0,0 +1,32 @@ +import time +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives import hashes +import _helpers +import struct +from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat, PrivateFormat, NoEncryption +from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature + +def sign_prekey(): + pre_key = _helpers.create_compactable_key() + device_key = _helpers.create_compactable_key() + print("DEV PRIV KEY: " + _helpers.parse_key(device_key).private_bytes(Encoding.DER, PrivateFormat.PKCS8, NoEncryption()).hex()) + timestamp = time.time() + # Set decimal to 0 + timestamp = float(int(timestamp)) + to_sign = b"NGMPrekeySignature" + _helpers.compact_key(_helpers.parse_key(pre_key)) + struct.pack("