Jelajahi Sumber

optionally substitute '{keygrip_hex}' in arg --gpg-key-output-path (new default path: '{keygrip_hex}.key')

Fabian Peter Hammerle 6 tahun lalu
induk
melakukan
cfef3885da
2 mengubah file dengan 31 tambahan dan 9 penghapusan
  1. 0 1
      .gitignore
  2. 31 8
      create-gpg-shadow-key-from-x509-cert-req.py

+ 0 - 1
.gitignore

@@ -1,2 +1 @@
 /cert-request.pem
-/gpg-key.sexp

+ 31 - 8
create-gpg-shadow-key-from-x509-cert-req.py

@@ -1,13 +1,18 @@
 #!/usr/bin/env python3
 
+import binascii
 import cryptography.hazmat.backends
 import cryptography.hazmat.primitives.serialization
 import cryptography.x509
+import ctypes
 import math
 
-DEFAULT_KEY_OUTPUT_PATH = 'gpg-key.sexp'
+DEFAULT_KEY_OUTPUT_PATH_PATTERN = '{keygrip_hex}.key'
 DEFAULT_SMARTCARD_APP_ID_HEX = 'D2760001240102010001234567890000'
 
+gcrypt = ctypes.cdll.LoadLibrary('libgcrypt.so')
+gcrypt.gcry_pk_get_keygrip.restype = ctypes.POINTER(ctypes.c_char)
+
 
 def convert_to_sexp(data):
     if isinstance(data, int):
@@ -23,7 +28,20 @@ def convert_to_sexp(data):
         return b'(' + b''.join(convert_to_sexp(i) for i in data) + b')'
 
 
-def create_gpg_key(input_path, gpg_key_output_path, smartcard_app_id_hex):
+def keygrip_from_key_sexp(key_sexp_data):
+    sexp = ctypes.c_void_p()
+    assert not gcrypt.gcry_sexp_new(
+        ctypes.pointer(sexp),
+        key_sexp_data,
+        len(key_sexp_data),
+        0,
+    )
+    keygrip = gcrypt.gcry_pk_get_keygrip(sexp, None)[:20]
+    gcrypt.gcry_sexp_release(sexp)
+    return keygrip
+
+
+def create_gpg_key(input_path, gpg_key_output_path_pattern, smartcard_app_id_hex):
     backend = cryptography.hazmat.backends.default_backend()
     with open(input_path, 'rb') as f:
         req = cryptography.x509.load_pem_x509_csr(f.read(), backend)
@@ -35,9 +53,11 @@ def create_gpg_key(input_path, gpg_key_output_path, smartcard_app_id_hex):
         ['e', pubnums.e],
         ['shadowed', 't1-v1', [int(smartcard_app_id_hex, 16), 'OPENPGP.1']],
     ]]
-    key = convert_to_sexp(key_data)
-    with open(gpg_key_output_path, 'wb') as f:
-        f.write(key)
+    key_sexp_data = convert_to_sexp(key_data)
+    keygrip = keygrip_from_key_sexp(key_sexp_data)
+    keygrip_hex = binascii.hexlify(keygrip).upper().decode()
+    with open(gpg_key_output_path_pattern.format(keygrip_hex=keygrip_hex), 'wb') as f:
+        f.write(key_sexp_data)
 
 
 def _init_argparser():
@@ -52,9 +72,12 @@ def _init_argparser():
     )
     argparser.add_argument(
         '--gpg-key-output-path',
-        dest='gpg_key_output_path',
-        default=DEFAULT_KEY_OUTPUT_PATH,
-        help='path to sexp-encoded shadowed-private-key to be created (default: "%(default)s")',
+        dest='gpg_key_output_path_pattern',
+        metavar='path-pattern',
+        default=DEFAULT_KEY_OUTPUT_PATH_PATTERN,
+        help='path to sexp-encoded shadowed-private-key to be created.'
+            + ' if specified, {keygrip_hex} will be substituted.'
+            + ' (default: "%(default)s")',
     )
     argparser.add_argument(
         '--smartcard-app-id',