Browse Source

add support for NoneWithRSA signing

master
R4SAS 3 years ago
parent
commit
5eb614be66
  1. 32
      pyseeder/crypto.py
  2. 52
      pyseeder/su3file.py
  3. 16
      pyseeder/transports/github.py
  4. 1
      requirements.txt

32
pyseeder/crypto.py

@ -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

52
pyseeder/su3file.py

@ -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])
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: with open(filename, "wb") as f:
f.write("I2Psu3".encode("utf-8")) f.write(self.OUTPUT)
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)
def reseed(self, netdb, yggseeds): def reseed(self, netdb, yggseeds):
"""Compress netdb entries and set content""" """Compress netdb entries and set content"""

16
pyseeder/transports/github.py

@ -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
requirements.txt

@ -1,2 +1,3 @@
cryptography>=1.4 cryptography>=1.4
rsa
requests requests

Loading…
Cancel
Save