pki: Add different output options for --keyid
authorTobias Brunner <tobias@strongswan.org>
Thu, 18 Apr 2019 14:14:16 +0000 (16:14 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 May 2019 12:56:48 +0000 (14:56 +0200)
Makes machine-processing these identifiers easier.

src/pki/commands/keyid.c
src/pki/man/pki---keyid.1.in

index 001b9ff..10651f5 100644 (file)
 #include <credentials/certificates/certificate.h>
 #include <credentials/certificates/x509.h>
 
+typedef enum {
+               FORMAT_PRETTY,
+               FORMAT_HEX,
+               FORMAT_BASE64,
+               FORMAT_BINARY,
+} format_t;
+
+/**
+ * Print a single keyid in the requested format
+ */
+static bool print_id(chunk_t id, format_t format, char *desc)
+{
+       chunk_t chunk;
+
+       switch (format)
+       {
+               case FORMAT_PRETTY:
+                       printf("%s:\n             %#B\n", desc, &id);
+                       break;
+               case FORMAT_HEX:
+                       chunk = chunk_to_hex(id, NULL, FALSE);
+                       printf("%.*s\n", (int)chunk.len, chunk.ptr);
+                       chunk_free(&chunk);
+                       break;
+               case FORMAT_BASE64:
+                       chunk = chunk_to_base64(id, NULL);
+                       printf("%.*s\n", (int)chunk.len, chunk.ptr);
+                       chunk_free(&chunk);
+                       break;
+               case FORMAT_BINARY:
+                       if (fwrite(id.ptr, id.len, 1, stdout) != 1)
+                       {
+                               fprintf(stderr, "writing %s failed\n", desc);
+                               return FALSE;
+                       }
+                       break;
+       }
+       return TRUE;
+}
+
 /**
  * Calculate the keyid of a key/certificate
  */
@@ -31,9 +71,15 @@ static int keyid()
        certificate_t *cert;
        private_key_t *private;
        public_key_t *public;
+       format_t format = FORMAT_PRETTY;
+       enum {
+               ID_TYPE_ALL,
+               ID_TYPE_SPK,
+               ID_TYPE_SPKI,
+       } id_type = FORMAT_PRETTY;
        char *file = NULL, *keyid = NULL;
        void *cred;
-       chunk_t id;
+       chunk_t id, spk = chunk_empty, spki = chunk_empty;
        char *arg;
 
        while (TRUE)
@@ -86,6 +132,38 @@ static int keyid()
                                        return command_usage( "invalid input type");
                                }
                                continue;
+                       case 'I':
+                               if (streq(arg, "spk"))
+                               {
+                                       id_type = ID_TYPE_SPK;
+                               }
+                               else if (streq(arg, "spki"))
+                               {
+                                       id_type = ID_TYPE_SPKI;
+                               }
+                               else if (!streq(arg, "all"))
+                               {
+                                       return command_usage( "invalid id type");
+                               }
+                               continue;
+                       case 'f':
+                               if (streq(arg, "hex"))
+                               {
+                                       format = FORMAT_HEX;
+                               }
+                               else if (streq(arg, "base64"))
+                               {
+                                       format = FORMAT_BASE64;
+                               }
+                               else if (streq(arg, "bin"))
+                               {
+                                       format = FORMAT_BINARY;
+                               }
+                               else if (!streq(arg, "pretty"))
+                               {
+                                       return command_usage( "invalid output format");
+                               }
+                               continue;
                        case 'i':
                                file = arg;
                                continue;
@@ -138,11 +216,11 @@ static int keyid()
                private = cred;
                if (private->get_fingerprint(private, KEYID_PUBKEY_SHA1, &id))
                {
-                       printf("subjectKeyIdentifier:      %#B\n", &id);
+                       spk = chunk_clone(id);
                }
                if (private->get_fingerprint(private, KEYID_PUBKEY_INFO_SHA1, &id))
                {
-                       printf("subjectPublicKeyInfo hash: %#B\n", &id);
+                       spki = chunk_clone(id);
                }
                private->destroy(private);
        }
@@ -151,11 +229,11 @@ static int keyid()
                public = cred;
                if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &id))
                {
-                       printf("subjectKeyIdentifier:      %#B\n", &id);
+                       spk = chunk_clone(id);
                }
                if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &id))
                {
-                       printf("subjectPublicKeyInfo hash: %#B\n", &id);
+                       spki = chunk_clone(id);
                }
                public->destroy(public);
        }
@@ -170,15 +248,34 @@ static int keyid()
                }
                if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &id))
                {
-                       printf("subjectKeyIdentifier:      %#B\n", &id);
+                       spk = chunk_clone(id);
                }
                if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &id))
                {
-                       printf("subjectPublicKeyInfo hash: %#B\n", &id);
+                       spki = chunk_clone(id);
                }
                public->destroy(public);
                cert->destroy(cert);
        }
+
+       if (id_type == ID_TYPE_ALL || id_type == ID_TYPE_SPK)
+       {
+               if (!spk.len ||
+                       !print_id(spk, format, "subjkey (SHA-1 of subjectPublicKey)"))
+               {
+                       return 1;
+               }
+       }
+       if (id_type == ID_TYPE_ALL || id_type == ID_TYPE_SPKI)
+       {
+               if (!spki.len ||
+                       !print_id(spki, format, "keyid (SHA-1 of subjectPublicKeyInfo)"))
+               {
+                       return 1;
+               }
+       }
+       chunk_free(&spk);
+       chunk_free(&spki);
        return 0;
 }
 
@@ -190,12 +287,15 @@ static void __attribute__ ((constructor))reg()
        command_register((command_t)
                { keyid, 'k', "keyid",
                "calculate key identifiers of a key/certificate",
-               {"[--in file|--keyid hex] [--type priv|rsa|ecdsa|bliss|pub|pkcs10|x509]"},
+               {"[--in file|--keyid hex] [--type priv|rsa|ecdsa|bliss|pub|pkcs10|x509]",
+                "[--id all|spk|spki] [--format pretty|hex|base64|bin]"},
                {
                        {"help",        'h', 0, "show usage information"},
                        {"in",          'i', 1, "input file, default: stdin"},
                        {"keyid",       'x', 1, "smartcard or TPM private key object handle"},
                        {"type",        't', 1, "type of key, default: priv"},
+                       {"id",          'I', 1, "type of identifier, default: all"},
+                       {"format",      'f', 1, "output format, default: pretty"},
                }
        });
 }
index 148b95e..594643a 100644 (file)
@@ -1,4 +1,4 @@
-.TH "PKI \-\-KEYID" 1 "2013-07-31" "@PACKAGE_VERSION@" "strongSwan"
+.TH "PKI \-\-KEYID" 1 "2019-04-29" "@PACKAGE_VERSION@" "strongSwan"
 .
 .SH "NAME"
 .
@@ -11,6 +11,8 @@ pki \-\-keyid \- Calculate key identifiers of a key or certificate
 .IR file | \fB\-\-keyid\fR
 .IR hex ]
 .OP \-\-type type
+.OP \-\-id id-type
+.OP \-\-format format
 .OP \-\-debug level
 .YS
 .
@@ -54,23 +56,44 @@ Type of input. One of \fIpriv\fR (private key), \fIrsa\fR (RSA private key),
 \fIecdsa\fR (ECDSA private key), \fIbliss\fR (BLISS private key),
 \fIpub\fR (public key), \fIpkcs10\fR (PKCS#10 certificate request),
 \fIx509\fR (X.509 certificate), defaults to \fIpriv\fR.
+.TP
+.BI "\-I, \-\-id " id-type
+Type of identifier. One of \fIall\fR (all identifiers), \fIspk\fR (SHA-1 hash
+of subjectPublicKey), \fIspki\fR (SHA-1 hash of subjectPublicKeyInfo), defaults
+to \fIall\fR.
+.TP
+.BI "\-f, \-\-format " format
+Output format. One of \fIpretty\fR (user-readable output), \fIhex\fR
+(hexadecimal encoding), \fIbase64\fR (Base64 encoding), \fIbin\fR (raw binary
+data), defaults to \fIpretty\fR.
 .
 .SH "EXAMPLES"
 .
 Calculate key identifiers of an RSA private key:
 .PP
 .EX
-  pki --keyid --in key.der
-  subjectKeyIdentifier:      6a:9c:74:d1:f8:89:79:89:f6:5a:94:e9:89:f1...
-  subjectPublicKeyInfo hash: 6e:55:dc:7e:9c:a5:58:d9:5b:e3:c7:13:14:e1...
+  $ pki --keyid --in key.der
+  subjkey (SHA-1 of subjectPublicKey):
+               6a:9c:74:d1:f8:89:79:89:f6:5a:94:e9:89:f1...
+  keyid (SHA-1 of subjectPublicKeyInfo):
+               6e:55:dc:7e:9c:a5:58:d9:5b:e3:c7:13:14:e1...
 .EE
 .PP
 Calculate key identifiers of an X.509 certificate:
 .PP
 .EX
-  pki --keyid --in cert.der --type x509
-  subjectKeyIdentifier:      6a:9c:74:d1:f8:89:79:89:f6:5a:94:e9:89:f1...
-  subjectPublicKeyInfo hash: 6e:55:dc:7e:9c:a5:58:d9:5b:e3:c7:13:14:e1...
+  $ pki --keyid --in cert.der --type x509
+  subjkey (SHA-1 of subjectPublicKey):
+               6a:9c:74:d1:f8:89:79:89:f6:5a:94:e9:89:f1...
+  keyid (SHA-1 of subjectPublicKeyInfo):
+               6e:55:dc:7e:9c:a5:58:d9:5b:e3:c7:13:14:e1...
+.EE
+.PP
+Calculate keyid in simple hex encoding of an X.509 certificate:
+.PP
+.EX
+  $ pki --keyid --in cert.der --type x509 --id spki --format hex
+  6e55dc7e9ca558d95be3c71314e1...
 .EE
 .PP
 .