diff --git a/nostr/bech32.py b/nostr/bech32.py index 0ae6c80..b068de7 100644 --- a/nostr/bech32.py +++ b/nostr/bech32.py @@ -23,25 +23,21 @@ from enum import Enum - class Encoding(Enum): """Enumeration type to list the various supported encodings.""" - BECH32 = 1 BECH32M = 2 - CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" -BECH32M_CONST = 0x2BC830A3 - +BECH32M_CONST = 0x2bc830a3 def bech32_polymod(values): """Internal function that computes the Bech32 checksum.""" - generator = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3] + generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] chk = 1 for value in values: top = chk >> 25 - chk = (chk & 0x1FFFFFF) << 5 ^ value + chk = (chk & 0x1ffffff) << 5 ^ value for i in range(5): chk ^= generator[i] if ((top >> i) & 1) else 0 return chk @@ -61,7 +57,6 @@ def bech32_verify_checksum(hrp, data): return Encoding.BECH32M return None - def bech32_create_checksum(hrp, data, spec): """Compute the checksum values given HRP and data.""" values = bech32_hrp_expand(hrp) + data @@ -73,29 +68,26 @@ def bech32_create_checksum(hrp, data, spec): def bech32_encode(hrp, data, spec): """Compute a Bech32 string given HRP and data values.""" combined = data + bech32_create_checksum(hrp, data, spec) - return hrp + "1" + "".join([CHARSET[d] for d in combined]) - + return hrp + '1' + ''.join([CHARSET[d] for d in combined]) def bech32_decode(bech): """Validate a Bech32/Bech32m string, and determine HRP and data.""" - if (any(ord(x) < 33 or ord(x) > 126 for x in bech)) or ( - bech.lower() != bech and bech.upper() != bech - ): + if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or + (bech.lower() != bech and bech.upper() != bech)): return (None, None, None) bech = bech.lower() - pos = bech.rfind("1") + pos = bech.rfind('1') if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: return (None, None, None) - if not all(x in CHARSET for x in bech[pos + 1 :]): + if not all(x in CHARSET for x in bech[pos+1:]): return (None, None, None) hrp = bech[:pos] - data = [CHARSET.find(x) for x in bech[pos + 1 :]] + data = [CHARSET.find(x) for x in bech[pos+1:]] spec = bech32_verify_checksum(hrp, data) if spec is None: return (None, None, None) return (hrp, data[:-6], spec) - def convertbits(data, frombits, tobits, pad=True): """General power-of-2 base conversion.""" acc = 0 @@ -131,12 +123,7 @@ def decode(hrp, addr): return (None, None) if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32: return (None, None) - if ( - data[0] == 0 - and spec != Encoding.BECH32 - or data[0] != 0 - and spec != Encoding.BECH32M - ): + if data[0] == 0 and spec != Encoding.BECH32 or data[0] != 0 and spec != Encoding.BECH32M: return (None, None) return (data[0], decoded) diff --git a/nostr/client/cbc.py b/nostr/client/cbc.py index e69e8b5..a41dbc0 100644 --- a/nostr/client/cbc.py +++ b/nostr/client/cbc.py @@ -1,3 +1,4 @@ + from Cryptodome import Random from Cryptodome.Cipher import AES @@ -10,10 +11,10 @@ key = bytes.fromhex("3aa925cb69eb613e2928f8a18279c78b1dca04541dfd064df2eda66b598 BLOCK_SIZE = 16 - class AESCipher(object): - """This class is compatible with crypto.createCipheriv('aes-256-cbc')""" + """This class is compatible with crypto.createCipheriv('aes-256-cbc') + """ def __init__(self, key=None): self.key = key @@ -32,10 +33,9 @@ class AESCipher(object): def decrypt(self, iv, enc_text): cipher = AES.new(self.key, AES.MODE_CBC, iv=iv) return self.unpad(cipher.decrypt(enc_text).decode("UTF-8")) - - + if __name__ == "__main__": aes = AESCipher(key=key) iv, enc_text = aes.encrypt(plain_text) dec_text = aes.decrypt(iv, enc_text) - print(dec_text) + print(dec_text) \ No newline at end of file diff --git a/nostr/client/client.py b/nostr/client/client.py index 5be6089..6fb885f 100644 --- a/nostr/client/client.py +++ b/nostr/client/client.py @@ -1,15 +1,20 @@ -import base64 -import json -import os +from typing import * import ssl import time -from typing import * +import json +import os +import base64 -from ..event import EncryptedDirectMessage, Event, EventKind -from ..filter import Filter, Filters -from ..key import PrivateKey, PublicKey -from ..message_type import ClientMessageType +from ..event import Event from ..relay_manager import RelayManager +from ..message_type import ClientMessageType +from ..key import PrivateKey, PublicKey + +from ..filter import Filter, Filters +from ..event import Event, EventKind, EncryptedDirectMessage +from ..relay_manager import RelayManager +from ..message_type import ClientMessageType + # from aes import AESCipher from . import cbc diff --git a/nostr/delegation.py b/nostr/delegation.py index 8b1c311..94801f5 100644 --- a/nostr/delegation.py +++ b/nostr/delegation.py @@ -7,23 +7,23 @@ class Delegation: delegator_pubkey: str delegatee_pubkey: str event_kind: int - duration_secs: int = 30 * 24 * 60 # default to 30 days + duration_secs: int = 30*24*60 # default to 30 days signature: str = None # set in PrivateKey.sign_delegation @property def expires(self) -> int: return int(time.time()) + self.duration_secs - + @property def conditions(self) -> str: return f"kind={self.event_kind}&created_at<{self.expires}" - + @property def delegation_token(self) -> str: return f"nostr:delegation:{self.delegatee_pubkey}:{self.conditions}" def get_tag(self) -> list[str]: - """Called by Event""" + """ Called by Event """ return [ "delegation", self.delegator_pubkey, diff --git a/nostr/event.py b/nostr/event.py index 65b187d..b903e0e 100644 --- a/nostr/event.py +++ b/nostr/event.py @@ -1,11 +1,10 @@ -import json import time +import json from dataclasses import dataclass, field from enum import IntEnum -from hashlib import sha256 from typing import List - from secp256k1 import PublicKey +from hashlib import sha256 from .message_type import ClientMessageType diff --git a/nostr/key.py b/nostr/key.py index 8089e11..d34697f 100644 --- a/nostr/key.py +++ b/nostr/key.py @@ -1,15 +1,14 @@ -import base64 import secrets -from hashlib import sha256 - +import base64 import secp256k1 from cffi import FFI -from cryptography.hazmat.primitives import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives import padding +from hashlib import sha256 -from . import bech32 from .delegation import Delegation from .event import EncryptedDirectMessage, Event, EventKind +from . import bech32 class PublicKey: diff --git a/nostr/message_pool.py b/nostr/message_pool.py index 373d9fc..d364cf2 100644 --- a/nostr/message_pool.py +++ b/nostr/message_pool.py @@ -1,9 +1,8 @@ import json from queue import Queue from threading import Lock - -from .event import Event from .message_type import RelayMessageType +from .event import Event class EventMessage: diff --git a/nostr/message_type.py b/nostr/message_type.py index 9f3be78..3f5206b 100644 --- a/nostr/message_type.py +++ b/nostr/message_type.py @@ -3,7 +3,6 @@ class ClientMessageType: REQUEST = "REQ" CLOSE = "CLOSE" - class RelayMessageType: EVENT = "EVENT" NOTICE = "NOTICE" @@ -11,10 +10,6 @@ class RelayMessageType: @staticmethod def is_valid(type: str) -> bool: - if ( - type == RelayMessageType.EVENT - or type == RelayMessageType.NOTICE - or type == RelayMessageType.END_OF_STORED_EVENTS - ): + if type == RelayMessageType.EVENT or type == RelayMessageType.NOTICE or type == RelayMessageType.END_OF_STORED_EVENTS: return True - return False + return False \ No newline at end of file diff --git a/nostr/pow.py b/nostr/pow.py index 034ad9a..e006288 100644 --- a/nostr/pow.py +++ b/nostr/pow.py @@ -1,9 +1,7 @@ import time - from .event import Event from .key import PrivateKey - def zero_bits(b: int) -> int: n = 0 @@ -16,11 +14,10 @@ def zero_bits(b: int) -> int: return 7 - n - def count_leading_zero_bits(hex_str: str) -> int: total = 0 for i in range(0, len(hex_str) - 2, 2): - bits = zero_bits(int(hex_str[i : i + 2], 16)) + bits = zero_bits(int(hex_str[i:i+2], 16)) total += bits if bits != 8: @@ -28,10 +25,7 @@ def count_leading_zero_bits(hex_str: str) -> int: return total - -def mine_event( - content: str, difficulty: int, public_key: str, kind: int, tags: list = [] -) -> Event: +def mine_event(content: str, difficulty: int, public_key: str, kind: int, tags: list=[]) -> Event: all_tags = [["nonce", "1", str(difficulty)]] all_tags.extend(tags) @@ -49,7 +43,6 @@ def mine_event( return Event(public_key, content, created_at, kind, all_tags, event_id) - def mine_key(difficulty: int) -> PrivateKey: sk = PrivateKey() num_leading_zero_bits = count_leading_zero_bits(sk.public_key.hex()) diff --git a/nostr/relay.py b/nostr/relay.py index 0851c02..ee78baa 100644 --- a/nostr/relay.py +++ b/nostr/relay.py @@ -2,9 +2,7 @@ import json import time from queue import Queue from threading import Lock - from websocket import WebSocketApp - from .event import Event from .filter import Filters from .message_pool import MessagePool diff --git a/nostr/subscription.py b/nostr/subscription.py index 10b5363..7afba20 100644 --- a/nostr/subscription.py +++ b/nostr/subscription.py @@ -1,10 +1,12 @@ from .filter import Filters - class Subscription: - def __init__(self, id: str, filters: Filters = None) -> None: + def __init__(self, id: str, filters: Filters=None) -> None: self.id = id self.filters = filters def to_json_object(self): - return {"id": self.id, "filters": self.filters.to_json_array()} + return { + "id": self.id, + "filters": self.filters.to_json_array() + }