-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtortools.py
More file actions
126 lines (100 loc) · 3.8 KB
/
Copy pathtortools.py
File metadata and controls
126 lines (100 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from config import sub_password
import base64
import hashlib
import os
from pathlib import Path
import time
from nacl.signing import SigningKey,VerifyKey
import random
random.seed(input(">")+sub_password)
k=SigningKey(random.randbytes(32))
sd="keys"
def sign(data):
return k.sign(data)[:64]
def expand_private_key(secret_key) -> bytes:
hash = hashlib.sha512(secret_key[:32]).digest()
hash = bytearray(hash)
hash[0] &= 248
hash[31] &= 127
hash[31] |= 64
return bytes(hash)
def onion_address_from_public_key(public_key: bytes) -> str:
version = b"\x03"
checksum = hashlib.sha3_256(b".onion checksum" + public_key + version).digest()[:2]
onion_address = "{}.onion".format(
base64.b32encode(public_key + checksum + version).decode().lower()
)
return onion_address
def verify_v3_onion_address(onion_address: str) -> list[bytes, bytes, bytes]:
# v3 spec https://gitweb.torproject.org/torspec.git/plain/rend-spec-v3.txt
try:
decoded = base64.b32decode(onion_address.replace(".onion", "").upper())
public_key = decoded[:32]
checksum = decoded[32:34]
version = decoded[34:]
if (
checksum
!= hashlib.sha3_256(b".onion checksum" + public_key + version).digest()[:2]
):
raise ValueError
return public_key, checksum, version
except:
raise ValueError("Invalid v3 onion address")
def create_hs_ed25519_secret_key_content(signing_key: bytes) -> bytes:
return b"== ed25519v1-secret: type0 ==\x00\x00\x00" + expand_private_key(
signing_key
)
def create_hs_ed25519_public_key_content(public_key: bytes) -> bytes:
assert len(public_key) == 32
return b"== ed25519v1-public: type0 ==\x00\x00\x00" + public_key
def store_bytes_to_file(
bytes: bytes, filename: str
) -> str:
with open(filename, "wb") as binary_file:
binary_file.write(bytes)
#if uid and gid:
# os.chown(filename, uid, gid)
return filename
def store_string_to_file(
string: str, filename: str
) -> str:
with open(filename, "w") as file:
file.write(string)
#if uid and gid:
# os.chown(filename, uid, gid)
return filename
def create_hidden_service_files(
private_key: bytes,
public_key: bytes
) -> None:
#path = Path(tor_data_directory)
#parent = path.parent.absolute()
# these are not strictly needed but takes care of the file permissions need by tor
#tor_user = parent.owner()
#tor_group = parent.group()
#uid = pwd.getpwnam(tor_user).pw_uid
#gid = grp.getgrnam(tor_group).gr_gid
#if not path.exists():
# os.mkdir(tor_data_directory)
# os.chmod(tor_data_directory, 0o700)
# os.chown(tor_data_directory, uid, gid)
file_content_secret = create_hs_ed25519_secret_key_content(private_key)
store_bytes_to_file(
file_content_secret, f"{sd}/hs_ed25519_secret_key"
)
file_content_public = create_hs_ed25519_public_key_content(public_key)
store_bytes_to_file(
file_content_public, f"{sd}/hs_ed25519_public_key"
)
onion_address = onion_address_from_public_key(public_key)
store_string_to_file(onion_address, f"{sd}/hostname")
try:
os.remove(f"{sd}/hs_ed25519_public_key")
except FileNotFoundError: pass
open(f"{sd}/hs_ed25519_secret_key","wb").write(b'== ed25519v1-secret: type0 ==\x00\x00\x00'+k._signing_key[:-32])
open(f"{sd}/hs_ed25519_public_key","wb").write(b'== ed25519v1-public: type0 ==\x00\x00\x00'+k.verify_key._key)
create_hidden_service_files(
k._signing_key[:-32], # the ed25519 private key often includes the public key, this does not
k.verify_key._key,
)
print(onion_address_from_public_key(k.verify_key._key))