pypida 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pypida-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.4
2
+ Name: pypida
3
+ Version: 0.1.0
4
+ Summary: PIDA Protocol - Private Inbox Data API for Python
5
+ Home-page: https://github.com/yourusername/pypida
6
+ Author: Your Name
7
+ Author-email: Sigmapages <thilan89757@gmail.com>
8
+ Project-URL: Homepage, https://github.com/sigmapages/pida
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: requests
15
+ Requires-Dist: cryptography
16
+ Dynamic: author
17
+ Dynamic: home-page
18
+ Dynamic: requires-python
19
+
20
+ # pypida
21
+ PIDA Protocol (Private Inbox Data API) implementation for Python.
22
+
23
+ ## Installation
24
+ ```bash
25
+ pip install pypida
26
+
27
+ Quick start
28
+ from pypida import PIDA
29
+ client = PIDA("[https://your-worker.workers.dev](https://your-worker.workers.dev)")
30
+ print(client.id)
31
+
pypida-0.1.0/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # pypida
2
+ PIDA Protocol (Private Inbox Data API) implementation for Python.
3
+
4
+ ## Installation
5
+ ```bash
6
+ pip install pypida
7
+
8
+ Quick start
9
+ from pypida import PIDA
10
+ client = PIDA("[https://your-worker.workers.dev](https://your-worker.workers.dev)")
11
+ print(client.id)
12
+
@@ -0,0 +1 @@
1
+ from pypida.core import PIDA
@@ -0,0 +1,114 @@
1
+ import requests
2
+ import uuid
3
+ import time
4
+ import hashlib
5
+ import json
6
+ import base64
7
+ import os
8
+ from cryptography.hazmat.primitives import hashes, serialization
9
+ from cryptography.hazmat.primitives.asymmetric import ec
10
+ from cryptography.hazmat.primitives.kdf.hkdf import HKDF
11
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
12
+
13
+ class PIDA:
14
+ def __init__(self, relay_url, identity_data=None):
15
+ self.relay = relay_url.rstrip('/')
16
+ if identity_data:
17
+ self.load_identity(identity_data)
18
+ else:
19
+ self.create_identity()
20
+
21
+ self.block_list = set()
22
+ self.inbox = []
23
+
24
+ # --- IDENTITY & UUIDv8 ---
25
+ def create_identity(self):
26
+ # Tạo cặp khóa ECDSA (p256)
27
+ self.priv_key = ec.generate_private_key(ec.SECP256R1())
28
+ self.pub_key = self.priv_key.public_key()
29
+
30
+ # UUIDv8 giả lập (Custom bits): 48 bit timestamp + random
31
+ # Trong Python, uuid.uuid8() có trong bản 3.12+, tui viết custom cho tương thích
32
+ self.id = str(uuid.uuid4()) # Thay bằng logic UUIDv8 nếu cần sortable
33
+ self.priv_key_pem = self.priv_key.private_bytes(
34
+ encoding=serialization.Encoding.PEM,
35
+ format=serialization.PrivateFormat.PKCS8,
36
+ encryption_algorithm=serialization.NoEncryption()
37
+ ).decode()
38
+ self.pub_key_pem = self.pub_key.public_bytes(
39
+ encoding=serialization.Encoding.PEM,
40
+ format=serialization.PublicFormat.SubjectPublicKeyInfo
41
+ ).decode()
42
+
43
+ def load_identity(self, data):
44
+ self.id = data['id']
45
+ self.priv_key = serialization.load_pem_private_key(data['priv'].encode(), password=None)
46
+ self.pub_key = self.priv_key.public_key()
47
+
48
+ # --- CRYPTO: E2EE & ECDH ---
49
+ def _get_shared_secret(self, peer_pub_pem):
50
+ peer_pub = serialization.load_pem_public_key(peer_pub_pem.encode())
51
+ shared_key = self.priv_key.exchange(ec.ECDH(), peer_pub)
52
+ return HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'pida-e2ee').derive(shared_key)
53
+
54
+ def encrypt_msg(self, peer_pub_pem, plaintext):
55
+ key = self._get_shared_secret(peer_pub_pem)
56
+ aesgcm = AESGCM(key)
57
+ nonce = os.urandom(12)
58
+ ct = aesgcm.encrypt(nonce, plaintext.encode(), None)
59
+ return base64.b64encode(nonce + ct).decode()
60
+
61
+ def decrypt_msg(self, peer_pub_pem, ciphertext):
62
+ key = self._get_shared_secret(peer_pub_pem)
63
+ data = base64.b64decode(ciphertext)
64
+ nonce, ct = data[:12], data[12:]
65
+ return AESGCM(key).decrypt(nonce, ct, None).decode()
66
+
67
+ # --- PROTOCOL: PoW & SYNC ---
68
+ def _compute_pow(self, data, diff=4):
69
+ nonce = 0
70
+ while True:
71
+ h = hashlib.sha256(f"{data}{nonce}".encode()).hexdigest()
72
+ if h.startswith('0' * diff): return {"nonce": nonce, "hash": h}
73
+ nonce += 1
74
+
75
+ def send_message(self, to_id, peer_pub_pem, content, is_file=False):
76
+ encrypted_content = self.encrypt_msg(peer_pub_pem, content)
77
+ msg_id = str(uuid.uuid4())
78
+ msg = {
79
+ "id": msg_id, "from": self.id, "to": to_id,
80
+ "content": encrypted_content, "type": "file" if is_file else "text",
81
+ "timestamp": int(time.time() * 1000), "sender_pub": self.pub_key_pem
82
+ }
83
+ pow_data = self._compute_pow(msg_id)
84
+ return requests.post(f"{self.relay}/send", json={"msg": msg, "pow": pow_data}).json()
85
+
86
+ def sync(self):
87
+ # Challenge-Response
88
+ res = requests.get(f"{self.relay}/challenge?address={self.id}").json()
89
+ challenge = res['challenge']
90
+ signature = self.priv_key.sign(challenge.encode(), ec.ECDSA(hashes.SHA256()))
91
+
92
+ payload = {
93
+ "address": self.id, "challenge": challenge,
94
+ "signature": base64.b64encode(signature).decode()
95
+ }
96
+ msgs = requests.post(f"{self.relay}/get", json=payload).json().get('messages', [])
97
+
98
+ for m in msgs:
99
+ if m['from'] in self.block_list:
100
+ self.ack(m['id'])
101
+ continue
102
+ # Thử giải mã nếu có sender_pub
103
+ try:
104
+ m['body'] = self.decrypt_msg(m['sender_pub'], m['content'])
105
+ except: m['body'] = "[Decryption Failed]"
106
+ self.inbox.append(m)
107
+ return self.inbox
108
+
109
+ def ack(self, msg_id):
110
+ requests.post(f"{self.relay}/ack", json={"id": msg_id, "address": self.id})
111
+
112
+ def backup_inbox(self, filename="inbox_backup.json"):
113
+ with open(filename, 'w') as f:
114
+ json.dump(self.inbox, f)
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.4
2
+ Name: pypida
3
+ Version: 0.1.0
4
+ Summary: PIDA Protocol - Private Inbox Data API for Python
5
+ Home-page: https://github.com/yourusername/pypida
6
+ Author: Your Name
7
+ Author-email: Sigmapages <thilan89757@gmail.com>
8
+ Project-URL: Homepage, https://github.com/sigmapages/pida
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: requests
15
+ Requires-Dist: cryptography
16
+ Dynamic: author
17
+ Dynamic: home-page
18
+ Dynamic: requires-python
19
+
20
+ # pypida
21
+ PIDA Protocol (Private Inbox Data API) implementation for Python.
22
+
23
+ ## Installation
24
+ ```bash
25
+ pip install pypida
26
+
27
+ Quick start
28
+ from pypida import PIDA
29
+ client = PIDA("[https://your-worker.workers.dev](https://your-worker.workers.dev)")
30
+ print(client.id)
31
+
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ pypida/__init__.py
5
+ pypida/core.py
6
+ pypida.egg-info/PKG-INFO
7
+ pypida.egg-info/SOURCES.txt
8
+ pypida.egg-info/dependency_links.txt
9
+ pypida.egg-info/requires.txt
10
+ pypida.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ requests
2
+ cryptography
@@ -0,0 +1 @@
1
+ pypida
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pypida"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name="Sigmapages", email="thilan89757@gmail.com" },
10
+ ]
11
+ description = "PIDA Protocol - Private Inbox Data API for Python"
12
+ readme = "README.md"
13
+ requires-python = ">=3.7"
14
+ dependencies = [
15
+ "requests",
16
+ "cryptography"
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ [project.urls]
25
+ "Homepage" = "https://github.com/sigmapages/pida"
pypida-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
pypida-0.1.0/setup.py ADDED
@@ -0,0 +1,25 @@
1
+ import os
2
+ from setuptools import setup, find_packages
3
+
4
+ setup(
5
+ name="pypida",
6
+ version="0.1.0",
7
+ author="Your Name",
8
+ author_email="your@email.com",
9
+ description="PIDA Protocol - Private Inbox Data API for Python",
10
+ long_description=open("README.md").read() if os.path.exists("README.md") else "PIDA Protocol",
11
+ long_description_content_type="text/markdown",
12
+ url="https://github.com/yourusername/pypida",
13
+ packages=find_packages(),
14
+ install_requires=[
15
+ "requests",
16
+ "cryptography",
17
+ "ecdsa"
18
+ ],
19
+ classifiers=[
20
+ "Programming Language :: Python :: 3",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ ],
24
+ python_requires='>=3.7',
25
+ )