68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
import base64
|
|
import hashlib
|
|
import Crypt.ed25519 as ed25519
|
|
import rsa
|
|
|
|
def sign(data, privatekey):
|
|
# !ONION v3!
|
|
if len(privatekey) == 88:
|
|
prv_key = base64.b64decode(privatekey)
|
|
pub_key = ed25519.publickey_unsafe(prv_key)
|
|
signed = ed25519.signature_unsafe(data, prv_key, pub_key)
|
|
return signed
|
|
|
|
# FIXME: doesn't look good
|
|
if "BEGIN RSA PRIVATE KEY" not in privatekey:
|
|
privatekey = "-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----" % privatekey
|
|
|
|
priv = rsa.PrivateKey.load_pkcs1(privatekey)
|
|
signed = rsa.pkcs1.sign(data, priv, 'SHA-256')
|
|
return signed
|
|
|
|
def verify(data, publickey, sign):
|
|
# !ONION v3!
|
|
if len(publickey) == 32:
|
|
try:
|
|
valid = ed25519.checkvalid(sign, data, publickey)
|
|
valid = 'SHA-256'
|
|
except Exception as err:
|
|
# TODO: traceback
|
|
print(err)
|
|
valid = False
|
|
return valid
|
|
|
|
pub = rsa.PublicKey.load_pkcs1(publickey, format="DER")
|
|
try:
|
|
valid = rsa.pkcs1.verify(data, sign, pub)
|
|
except rsa.pkcs1.VerificationError:
|
|
valid = False
|
|
return valid
|
|
|
|
def privatekeyToPublickey(privatekey):
|
|
# !ONION v3!
|
|
if len(privatekey) == 88:
|
|
prv_key = base64.b64decode(privatekey)
|
|
pub_key = ed25519.publickey_unsafe(prv_key)
|
|
return pub_key
|
|
|
|
if "BEGIN RSA PRIVATE KEY" not in privatekey:
|
|
privatekey = "-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----" % privatekey
|
|
|
|
priv = rsa.PrivateKey.load_pkcs1(privatekey)
|
|
pub = rsa.PublicKey(priv.n, priv.e)
|
|
return pub.save_pkcs1("DER")
|
|
|
|
# adopted by @anonymoose & @caryoscelus from https://gitweb.torproject.org/stem.git/tree/stem/descriptor/hidden_service.py @ address_from_identity_key
|
|
def publickeyToOnionV3Address(key):
|
|
CHECKSUM_CONSTANT = b'.onion checksum'
|
|
version = b'\x03' # v3
|
|
checksum = hashlib.sha3_256(CHECKSUM_CONSTANT + key + version).digest()[:2]
|
|
onion_address = base64.b32encode(key + checksum + version)
|
|
return onion_address.decode('utf-8', 'replace').lower()
|
|
|
|
def publickeyToOnion(publickey):
|
|
if len(publickey) == 32:
|
|
# !ONION v3!
|
|
return publickeyToOnionV3Address(publickey)
|
|
else:
|
|
return base64.b32encode(hashlib.sha1(publickey).digest()[:10]).lower().decode("ascii")
|