From 0756cac45415c20db394f851107411afe1448996 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Thu, 27 Jul 2023 13:10:26 +0200 Subject: [PATCH] acmecert: Replace the (apparently) deprecated Crypto library with cryptography. --- acmecert | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/acmecert b/acmecert index c8c05ff..84c212a 100755 --- a/acmecert +++ b/acmecert @@ -4,7 +4,6 @@ import sys, os, getopt, binascii, json, pprint, signal, time, calendar, threading import urllib.request -import Crypto.PublicKey.RSA, Crypto.Random, Crypto.Hash.SHA256, Crypto.Signature.PKCS1_v1_5 ### General utilities @@ -44,6 +43,14 @@ class maybeopen(object): ### Crypto utilities +_cryptobke = None +def cryptobke(): + global _cryptobke + if _cryptobke is None: + from cryptography.hazmat import backends + _cryptobke = backends.default_backend() + return _cryptobke + class dererror(Exception): pass @@ -382,12 +389,13 @@ class jwkauth(object): self.key = key def authdata(self): - return {"jwk": {"kty": "RSA", "e": ebignum(self.key.e), "n": ebignum(self.key.n)}} + pub = self.key.public_key().public_numbers() + return {"jwk": {"kty": "RSA", "e": ebignum(pub.e), "n": ebignum(pub.n)}} def sign(self, data): - dig = Crypto.Hash.SHA256.new() - dig.update(data) - return Crypto.Signature.PKCS1_v1_5.new(self.key).sign(dig) + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import padding + return self.key.sign(data, padding.PKCS1v15(), hashes.SHA256()) class account(object): def __init__(self, uri, key): @@ -398,9 +406,9 @@ class account(object): return {"kid": self.uri} def sign(self, data): - dig = Crypto.Hash.SHA256.new() - dig.update(data) - return Crypto.Signature.PKCS1_v1_5.new(self.key).sign(dig) + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import padding + return self.key.sign(data, padding.PKCS1v15(), hashes.SHA256()) def getinfo(self): data, headers = jreq(self.uri, None, self) @@ -412,16 +420,22 @@ class account(object): raise Exception("account is not valid: %s" % (data.get("status", "\"\""))) def write(self, out): + from cryptography.hazmat.primitives import serialization out.write("%s\n" % (self.uri,)) - out.write("%s\n" % (self.key.exportKey().decode("us-ascii"),)) + out.write("%s\n" % (self.key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption() + ).decode("us-ascii"),)) @classmethod def read(cls, fp): + from cryptography.hazmat.primitives import serialization uri = fp.readline() if uri == "": raise Exception("missing account URI") uri = uri.strip() - key = Crypto.PublicKey.RSA.importKey(fp.read()) + key = serialization.load_pem_private_key(fp.read().encode("us-ascii"), password=None, backend=cryptobke()) return cls(uri, key) ### ACME protocol @@ -436,7 +450,8 @@ def directory(): return _directory def register(keysize=4096): - key = Crypto.PublicKey.RSA.generate(keysize, Crypto.Random.new().read) + from cryptography.hazmat.primitives.asymmetric import rsa + key = rsa.generate_private_key(public_exponent=65537, key_size=keysize, backend=cryptobke()) data, headers = jreq(directory()["newAccount"], {"termsOfServiceAgreed": True}, jwkauth(key)) return account(headers["Location"], key) @@ -446,10 +461,11 @@ def mkorder(acct, csr): return data def httptoken(acct, ch): + from cryptography.hazmat.primitives import hashes jwk = {"kty": "RSA", "e": ebignum(acct.key.e), "n": ebignum(acct.key.n)} - dig = Crypto.Hash.SHA256.new() + dig = hashes.Hash(hashes.SHA256()) dig.update(json.dumps(jwk, separators=(',', ':'), sort_keys=True).encode("us-ascii")) - khash = base64url(dig.digest()) + khash = base64url(dig.finalize()) return ch["token"], ("%s.%s" % (ch["token"], khash)) def finalize(acct, csr, orderid): -- 2.11.0