-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdnssec2pem
More file actions
executable file
·112 lines (100 loc) · 3.53 KB
/
dnssec2pem
File metadata and controls
executable file
·112 lines (100 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/python3
#
# SPDX-License-Identifier: 0BSD
import argparse
import base64
import binascii
import pathlib
import re
import sys
from cryptography.hazmat.primitives.asymmetric import ec, ed448, ed25519, rsa
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
def errmsg(msg):
print(msg, file=sys.stderr)
def rec2key(rec):
o = rec.split(maxsplit=3)
keytype = int(o[2])
try:
key = base64.b64decode(o[3].replace(" ", "").encode())
except binascii.Error:
errmsg("Invalid base64")
return None
if keytype in {1, 5, 7, 8, 10}:
# RSA key format description in RFC 3110 Section 2
if len(key) < 3:
errmsg("RSA key too short")
return None
if key[0] == 0:
elen = int.from_bytes(key[1:3], byteorder="big")
else:
elen = key[0]
if len(key) < elen + 1:
errmsg("Invalid RSA exponent length")
return None
e = int.from_bytes(key[1:1 + elen], byteorder="big")
n = int.from_bytes(key[1 + elen:], byteorder="big")
try:
return rsa.RSAPublicNumbers(e, n).public_key()
except ValueError:
errmsg("Invalid RSA values")
return None
if keytype == 13:
if len(key) != 64:
errmsg(f"Wrong key size {len(key)} for ECDSA/P256, expected 64")
return None
x = int.from_bytes(key[0:32], byteorder="big")
y = int.from_bytes(key[32:64], byteorder="big")
try:
return ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()).public_key()
except ValueError as e:
errmsg("Invalid ECDSA/P256 key")
errmsg(f"{e!s}")
return None
if keytype == 14:
if len(key) != 96:
errmsg(f"Wrong key size {len(key)} for ECDSA/P384, expected 96")
return None
x = int.from_bytes(key[0:48], byteorder="big")
y = int.from_bytes(key[48:96], byteorder="big")
try:
return ec.EllipticCurvePublicNumbers(x, y, ec.SECP384R1()).public_key()
except ValueError as e:
errmsg("Invalid ECDSA/P384 key")
errmsg(f"{e!s}")
return None
if keytype == 15:
if len(key) != 32:
errmsg(f"Wrong key size {len(key)} for Ed25519, expected 32")
return None
return ed25519.Ed25519PublicKey.from_public_bytes(key)
if keytype == 16:
if len(key) != 57:
errmsg(f"Wrong key size {len(key)} for Ed448, expected 57")
return None
return ed448.Ed448PublicKey.from_public_bytes(key)
errmsg(f"Unsupported key type {keytype}")
return None
ap = argparse.ArgumentParser()
ap.add_argument("input", nargs="+")
ap.add_argument("-d", "--directory", help="Output directory")
args = ap.parse_args()
for fn in args.input:
if fn == "-":
content = sys.stdin.read()
else:
content = pathlib.Path(fn).read_text(encoding="ascii", errors="replace")
count = 0
for rec in re.findall(r"[0-9]{1,3}\s+[0-9]{1,3}\s+[0-9]{1,3}\s+[A-Za-z0-9/+= ]+", content):
key = rec2key(rec)
if not key:
errmsg(f"Parser error in {fn}")
continue
pem = key.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
if args.directory:
ofn = fn.split("/")[-1]
if count > 0:
ofn += f".{count}"
pathlib.Path(f"{args.directory}/{ofn}").write_bytes(pem)
else:
print(pem.decode(), end="")
count += 1