mirror of
https://github.com/PurpleI2P/pyseeder
synced 2025-03-13 05:41:23 +00:00
add support for NoneWithRSA signing
This commit is contained in:
parent
e5e39fe77e
commit
5eb614be66
@ -61,16 +61,30 @@ def keygen(pub_key, priv_key, user_id, priv_key_password=None):
|
|||||||
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
|
||||||
def append_signature(target_file, priv_key, priv_key_password=None):
|
def get_signature(contents, priv_key, priv_key_password=None):
|
||||||
"""Append signature to the end of file"""
|
"""Calculate signature for prepared reseed file"""
|
||||||
with open(target_file, "rb") as f:
|
"""Singing with NoneWithRSA algorithm: https://stackoverflow.com/a/68301530"""
|
||||||
contents = f.read()
|
import rsa as pyrsa
|
||||||
|
|
||||||
with open(priv_key, "rb") as kf:
|
with open(priv_key, "rb") as kf:
|
||||||
private_key = serialization.load_pem_private_key(
|
pk = pyrsa.PrivateKey.load_pkcs1(
|
||||||
kf.read(), password=priv_key_password, backend=default_backend())
|
serialization.load_pem_private_key(
|
||||||
|
kf.read(), password=priv_key_password, backend=default_backend()
|
||||||
|
).private_bytes(
|
||||||
|
serialization.Encoding.PEM,
|
||||||
|
serialization.PrivateFormat.TraditionalOpenSSL,
|
||||||
|
serialization.NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
signature = private_key.sign(contents, padding.PKCS1v15(), hashes.SHA512())
|
digest = hashes.Hash(hashes.SHA512())
|
||||||
|
digest.update(contents)
|
||||||
|
h = digest.finalize()
|
||||||
|
|
||||||
with open(target_file, "ab") as f:
|
keylength = pyrsa.pkcs1.common.byte_size(pk.n)
|
||||||
f.write(signature)
|
padded = pyrsa.pkcs1._pad_for_signing(h, keylength)
|
||||||
|
payload = pyrsa.pkcs1.transform.bytes2int(padded)
|
||||||
|
encrypted = pk.blinded_encrypt(payload)
|
||||||
|
sig = pyrsa.pkcs1.transform.int2bytes(encrypted, keylength)
|
||||||
|
|
||||||
|
return sig
|
||||||
|
@ -24,31 +24,43 @@ class SU3File:
|
|||||||
self.CONTENT_LENGTH = None
|
self.CONTENT_LENGTH = None
|
||||||
self.VERSION = str(int(time.time())).encode("utf-8")
|
self.VERSION = str(int(time.time())).encode("utf-8")
|
||||||
#self.keytype = "RSA_SHA512_4096"
|
#self.keytype = "RSA_SHA512_4096"
|
||||||
|
self.OUTPUT = None
|
||||||
|
|
||||||
def write(self, filename, priv_key, priv_key_password=None):
|
def write(self, filename, priv_key, priv_key_password=None):
|
||||||
"""Write file to disc"""
|
"""Write file to disc"""
|
||||||
nullbyte = bytes([0])
|
nullbyte = bytes([0])
|
||||||
with open(filename, "wb") as f:
|
|
||||||
f.write("I2Psu3".encode("utf-8"))
|
|
||||||
f.write(bytes([0,0]))
|
|
||||||
f.write(self.SIGNATURE_TYPE.to_bytes(2, "big"))
|
|
||||||
f.write(self.SIGNATURE_LENGTH.to_bytes(2, "big"))
|
|
||||||
f.write(nullbyte)
|
|
||||||
f.write(bytes([self.VERSION_LENGTH]))
|
|
||||||
f.write(nullbyte)
|
|
||||||
f.write(bytes([self.SIGNER_ID_LENGTH]))
|
|
||||||
f.write(self.CONTENT_LENGTH.to_bytes(8, "big"))
|
|
||||||
f.write(nullbyte)
|
|
||||||
f.write(bytes([self.FILE_TYPE]))
|
|
||||||
f.write(nullbyte)
|
|
||||||
f.write(bytes([self.CONTENT_TYPE]))
|
|
||||||
f.write(bytes([0 for _ in range(12)]))
|
|
||||||
f.write(self.VERSION + bytes(
|
|
||||||
[0 for _ in range(16 - len(self.VERSION))]))
|
|
||||||
f.write(self.SIGNER_ID.encode("utf-8"))
|
|
||||||
f.write(self.CONTENT)
|
|
||||||
|
|
||||||
pyseeder.crypto.append_signature(filename, priv_key, priv_key_password)
|
self.OUTPUT = "I2Psu3".encode("utf-8")
|
||||||
|
self.OUTPUT += bytes([0,0])
|
||||||
|
self.OUTPUT += self.SIGNATURE_TYPE.to_bytes(2, "big")
|
||||||
|
self.OUTPUT += self.SIGNATURE_LENGTH.to_bytes(2, "big")
|
||||||
|
self.OUTPUT += nullbyte
|
||||||
|
self.OUTPUT += bytes([self.VERSION_LENGTH])
|
||||||
|
self.OUTPUT += nullbyte
|
||||||
|
self.OUTPUT += bytes([self.SIGNER_ID_LENGTH])
|
||||||
|
self.OUTPUT += self.CONTENT_LENGTH.to_bytes(8, "big")
|
||||||
|
self.OUTPUT += nullbyte
|
||||||
|
self.OUTPUT += bytes([self.FILE_TYPE])
|
||||||
|
self.OUTPUT += nullbyte
|
||||||
|
self.OUTPUT += bytes([self.CONTENT_TYPE])
|
||||||
|
self.OUTPUT += bytes([0 for _ in range(12)])
|
||||||
|
self.OUTPUT += self.VERSION + bytes(
|
||||||
|
[0 for _ in range(16 - len(self.VERSION))])
|
||||||
|
self.OUTPUT += self.SIGNER_ID.encode("utf-8")
|
||||||
|
self.OUTPUT += self.CONTENT
|
||||||
|
|
||||||
|
with open(filename + "-data", "wb") as f:
|
||||||
|
f.write(self.OUTPUT)
|
||||||
|
|
||||||
|
signature = pyseeder.crypto.get_signature(self.OUTPUT, priv_key, priv_key_password)
|
||||||
|
|
||||||
|
with open(filename + "-sig", "wb") as f:
|
||||||
|
f.write(signature)
|
||||||
|
|
||||||
|
self.OUTPUT += signature
|
||||||
|
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
f.write(self.OUTPUT)
|
||||||
|
|
||||||
def reseed(self, netdb, yggseeds):
|
def reseed(self, netdb, yggseeds):
|
||||||
"""Compress netdb entries and set content"""
|
"""Compress netdb entries and set content"""
|
||||||
|
@ -21,22 +21,28 @@ def run(filename, config):
|
|||||||
|
|
||||||
# get release info
|
# get release info
|
||||||
try:
|
try:
|
||||||
resp = requests.get(release_info_url, auth=creds)
|
release = requests.get(release_info_url, auth=creds)
|
||||||
except:
|
except:
|
||||||
raise TransportException("Failed to connect to GitHub API")
|
raise TransportException("Failed to connect to GitHub API")
|
||||||
|
|
||||||
if resp.status_code is not 200:
|
if release.status_code is not 200:
|
||||||
raise TransportException("Check your GitHub API auth settings")
|
raise TransportException("Check your GitHub API auth settings")
|
||||||
|
|
||||||
|
# fetch release assets
|
||||||
|
try:
|
||||||
|
assets = requests.get(release.json()["assets_url"], auth=creds)
|
||||||
|
except:
|
||||||
|
raise TransportException("Unable get release assets")
|
||||||
|
|
||||||
# delete old asset
|
# delete old asset
|
||||||
for x in resp.json()["assets"]:
|
for x in assets.json():
|
||||||
if x["name"] == asset_name:
|
if x["name"] == asset_name:
|
||||||
r = requests.delete(x["url"], auth=creds)
|
r = requests.delete(x["url"], auth=creds)
|
||||||
if r.status_code is not 204:
|
if r.status_code is not 204:
|
||||||
raise TransportException("Failed to delete asset from GitHub")
|
raise TransportException("Failed to delete asset from GitHub")
|
||||||
|
|
||||||
# upload new asset
|
# upload new asset
|
||||||
upload_url = resp.json()["upload_url"].split("{")[0] # wat
|
upload_url = release.json()["upload_url"].split("{")[0] # wat
|
||||||
headers = {'Content-Type': content_type}
|
headers = {'Content-Type': content_type}
|
||||||
params = {'name': asset_name}
|
params = {'name': asset_name}
|
||||||
|
|
||||||
@ -45,5 +51,5 @@ def run(filename, config):
|
|||||||
data=data)
|
data=data)
|
||||||
|
|
||||||
if r.status_code is not 201:
|
if r.status_code is not 201:
|
||||||
raise TransportException("Failed to upload asset to GitHub API")
|
raise TransportException("Failed to upload asset to GitHub API : code %d" % (r.status_code))
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
cryptography>=1.4
|
cryptography>=1.4
|
||||||
|
rsa
|
||||||
requests
|
requests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user