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 +31 -0
- pypida-0.1.0/README.md +12 -0
- pypida-0.1.0/pypida/__init__.py +1 -0
- pypida-0.1.0/pypida/core.py +114 -0
- pypida-0.1.0/pypida.egg-info/PKG-INFO +31 -0
- pypida-0.1.0/pypida.egg-info/SOURCES.txt +10 -0
- pypida-0.1.0/pypida.egg-info/dependency_links.txt +1 -0
- pypida-0.1.0/pypida.egg-info/requires.txt +2 -0
- pypida-0.1.0/pypida.egg-info/top_level.txt +1 -0
- pypida-0.1.0/pyproject.toml +25 -0
- pypida-0.1.0/setup.cfg +4 -0
- pypida-0.1.0/setup.py +25 -0
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 @@
|
|
|
1
|
+
|
|
@@ -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
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
|
+
)
|