opendkim deterministic rsa
This commit is contained in:
parent
b67e77ed6a
commit
fea2d96077
2 changed files with 40 additions and 26 deletions
|
@ -2,7 +2,8 @@ from os.path import join, exists
|
|||
from re import sub
|
||||
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||
from cryptography.hazmat.primitives.serialization import load_der_private_key
|
||||
from base64 import b64decode
|
||||
|
||||
|
||||
defaults = {
|
||||
|
@ -25,37 +26,21 @@ def keys(metadata):
|
|||
keys = {}
|
||||
|
||||
for domain in metadata.get('mailserver/domains'):
|
||||
if domain in metadata.get(f'opendkim/keys'):
|
||||
continue
|
||||
|
||||
privkey_path = join(repo.path, 'data', 'dkim', f'{domain}.privkey.enc')
|
||||
|
||||
if not exists(privkey_path):
|
||||
with open(privkey_path, 'w') as file:
|
||||
file.write(
|
||||
repo.vault.encrypt(
|
||||
rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=2048
|
||||
).private_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PrivateFormat.PKCS8,
|
||||
crypto_serialization.NoEncryption()
|
||||
).decode()
|
||||
)
|
||||
)
|
||||
|
||||
with open(privkey_path, 'r') as file:
|
||||
privkey = str(repo.vault.decrypt(file.read()))
|
||||
|
||||
privkey = repo.libs.rsa.generate_deterministic_rsa_private_key(
|
||||
b64decode(str(repo.vault.random_bytes_as_base64_for('dkim' + domain)))
|
||||
)
|
||||
keys[domain] = {
|
||||
'private': privkey.private_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PrivateFormat.PKCS8,
|
||||
crypto_serialization.NoEncryption()
|
||||
).decode(),
|
||||
'public': ''.join(
|
||||
load_pem_private_key(privkey.encode(), password=None).public_key().public_bytes(
|
||||
privkey.public_key().public_bytes(
|
||||
crypto_serialization.Encoding.PEM,
|
||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
).decode().split('\n')[1:-2]
|
||||
),
|
||||
'private': privkey,
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
29
libs/rsa.py
Normal file
29
libs/rsa.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# https://stackoverflow.com/a/18266970
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Hash import HMAC
|
||||
from struct import pack
|
||||
from hashlib import sha3_512
|
||||
from cryptography.hazmat.primitives.serialization import load_der_private_key
|
||||
from functools import cache
|
||||
|
||||
|
||||
class PRNG(object):
|
||||
def __init__(self, seed):
|
||||
self.index = 0
|
||||
self.seed = sha3_512(seed).digest()
|
||||
self.buffer = b""
|
||||
def __call__(self, n):
|
||||
while len(self.buffer) < n:
|
||||
self.buffer += sha3_512(self.seed + pack("<d", self.index)).digest()
|
||||
self.index += 1
|
||||
result, self.buffer = self.buffer[:n], self.buffer[n:]
|
||||
return result
|
||||
|
||||
|
||||
@cache
|
||||
def generate_deterministic_rsa_private_key(secret_bytes):
|
||||
return load_der_private_key(
|
||||
RSA.generate(2048, randfunc=PRNG(secret_bytes)).export_key('DER'),
|
||||
password=None,
|
||||
)
|
Loading…
Reference in a new issue