From 8af9546e60a996d18b9cbeb43f44875d24b8cdcd Mon Sep 17 00:00:00 2001
From: Timotej Lazar <timotej.lazar@araneo.si>
Date: Tue, 16 Jan 2024 21:51:45 +0100
Subject: [PATCH] Minor tweaks

---
 README.md | 13 +++++--------
 margfools | 34 +++++++++++++++-------------------
 2 files changed, 20 insertions(+), 27 deletions(-)

diff --git a/README.md b/README.md
index b0a9e13..79eb765 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,18 @@ Python script to replace [MargTools](https://businessconnect.margis.si/output/#o
 
 ## Usage
 
-
-### Configure certificates and sites
-
 Create the configuration file `~/.margfools`. The contents are described in the sections below.
 
-#### Certificates in files
+### Certificates in files
+
 If you are using certificate files, add the paths to your TLS private key and certificate in PEM format:
 
     [https://gcsign.example.com/BCSign/]
     user-key = <path/to/key.pem>
     user-cert = <path/to/cert.pem>
 
-#### Certificates on smartcards
+### Certificates on smartcards
+
 If you have your certificate on a PIV-II smart card (e.g. Yubikey), first determine the slot on your card which contains the certificate you wish to use:
 
     pkcs11-tool -O
@@ -25,12 +24,10 @@ Look for "ID:" in the output.
 
 Assuming the ID of your certificate was 07, specify the engine and certificate slot in your config file:
 
-
     [https://gcsign.example.com/BCSign/]
-    engine=pkcs11
+    engine = pkcs11
     user-key = 07
 
-
 You will be asked for your pin during signing.
 
 ### Add URL schema
diff --git a/margfools b/margfools
index 5df99a2..7f6adfa 100755
--- a/margfools
+++ b/margfools
@@ -15,14 +15,16 @@ import getpass
 # use requests instead of urllib.request for keep-alive connection
 import requests
 
-def sign(data, keyfile, unlock_key=None, engine=None):
-    #  pkcs11-tool --id 02 -s -p $PIN -m RSA-PKCS
+def sign(data, key, pin=None, engine=None):
     if engine is None:
-        cmd = ['openssl', 'pkeyutl', '-sign', '-inkey', keyfile, '-pkeyopt', 'digest:sha256']
+        # key in file
+        cmd = ['openssl', 'pkeyutl', '-sign', '-inkey', key, '-pkeyopt', 'digest:sha256']
         raw_data = base64.b64decode(data)
         env = None
     elif engine == 'pkcs11':
-        env = {'PIN': unlock_key}
+        # key on smartcard
+        cmd = ['pkcs11-tool', '--id', key, '-s', '-m', 'RSA-PKCS', '-p', 'env:PIN']
+        env = {'PIN': pin}
         """magic_prefix is ASN.1 DER for
            DigestInfo ::= SEQUENCE {
                digestAlgorithm DigestAlgorithm,
@@ -31,13 +33,7 @@ def sign(data, keyfile, unlock_key=None, engine=None):
         """
         magic_prefix = bytes.fromhex("3031300d060960864801650304020105000420")
         raw_data = magic_prefix + base64.b64decode(data)
-        cmd = ['pkcs11-tool', '--id', keyfile, '-s', '-m', 'RSA-PKCS', '-p', 'env:PIN']
-        # cmd = ['openssl', 'pkeyutl', '-sign', '-pkeyopt', 'digest:sha256', '-engine', 'pkcs11', '-keyform', 'engine', '-inkey', keyfile]
-    p = subprocess.run(
-        cmd,
-        env=env,
-        input=raw_data,
-        capture_output=True)
+    p = subprocess.run(cmd, env=env, input=raw_data, capture_output=True)
     return base64.b64encode(p.stdout).decode()
 
 if __name__ == '__main__':
@@ -66,20 +62,21 @@ if __name__ == '__main__':
             sys.exit(1)
         if not args.engine:
             args.engine = config.get(url, 'engine')
+
         engine = args.engine
         user_keyfile = args.user_key
-        # base64.b64encode
-        unlock_key = None
+        pin = None
+
         if engine is None:
             if not args.user_cert:
                 print('user cert not specified', file=sys.stderr)
                 sys.exit(1)
             user_cert = ''.join(line.strip() for line in open(args.user_cert) if not line.startswith('-----'))
         elif engine == 'pkcs11':
-            user_cert = base64.b64encode(subprocess.run(["pkcs11-tool", "--read-object", "--type", "cert", "--id", user_keyfile], capture_output=True).stdout).decode()
-            unlock_key = getpass.getpass("PIN:")
+            user_cert = base64.b64encode(subprocess.run(['pkcs11-tool', '--read-object', '--type', 'cert', '--id', user_keyfile], capture_output=True).stdout).decode()
+            pin = getpass.getpass('PIN: ')
         session = requests.Session()
-        headers={'Authorization': f'Bearer {token}'}
+        headers = {'Authorization': f'Bearer {token}'}
 
         # delete old signing session
         r = session.delete(f'{url}/signatures/{params["startSigningToken"][0]}', headers=headers)
@@ -100,7 +97,7 @@ if __name__ == '__main__':
         while True:
             for name in ('AttachmentHashes', 'XmlHashes'):
                 if request.get(name) is not None:
-                    request[f'Signed{name}'] = [sign(e, user_keyfile, unlock_key, engine=engine) for e in request[name]]
+                    request[f'Signed{name}'] = [sign(e, user_keyfile, pin, engine=engine) for e in request[name]]
             d = json.dumps(request)
             d = d.encode()
             r = session.put(f'{url}signatures/{request["SignatureRequestId"]}',
@@ -111,5 +108,4 @@ if __name__ == '__main__':
             request |= json.loads(r.text)
     except:
         traceback.print_exc()
-        # Don't close terminal immediately on fail
-        input()
+        input('press enter to exit') # don’t close terminal immediately on fail