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 re import sub
|
||||||
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
from cryptography.hazmat.primitives import serialization as crypto_serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
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 = {
|
defaults = {
|
||||||
|
@ -25,37 +26,21 @@ def keys(metadata):
|
||||||
keys = {}
|
keys = {}
|
||||||
|
|
||||||
for domain in metadata.get('mailserver/domains'):
|
for domain in metadata.get('mailserver/domains'):
|
||||||
if domain in metadata.get(f'opendkim/keys'):
|
privkey = repo.libs.rsa.generate_deterministic_rsa_private_key(
|
||||||
continue
|
b64decode(str(repo.vault.random_bytes_as_base64_for('dkim' + domain)))
|
||||||
|
)
|
||||||
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()))
|
|
||||||
|
|
||||||
keys[domain] = {
|
keys[domain] = {
|
||||||
|
'private': privkey.private_bytes(
|
||||||
|
crypto_serialization.Encoding.PEM,
|
||||||
|
crypto_serialization.PrivateFormat.PKCS8,
|
||||||
|
crypto_serialization.NoEncryption()
|
||||||
|
).decode(),
|
||||||
'public': ''.join(
|
'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.Encoding.PEM,
|
||||||
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
crypto_serialization.PublicFormat.SubjectPublicKeyInfo
|
||||||
).decode().split('\n')[1:-2]
|
).decode().split('\n')[1:-2]
|
||||||
),
|
),
|
||||||
'private': privkey,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
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