Index: creddy/attribute.c
===================================================================
--- creddy/attribute.c	(revision ec06cb6d0dc78f7e83e6592e312e2666e05704a7)
+++ creddy/attribute.c	(revision ee5afdd2fe33a1ae6fc25d5da9dcb295eea251b5)
@@ -4,14 +4,45 @@
 
 #define ROLE_SEPARATOR " <- "
+#define SHA1_LENGTH 40
 
 void attribute_main(options_t *opts) {
+    char *subject_id = NULL;
+
     if (
         opts->issuer == NULL ||
         opts->key == NULL ||
         opts->role == NULL ||
-        opts->subject == NULL ||
         opts->out == NULL
     )
         usage(opts);
+
+    // make sure we have exactly one of --subject-cert / --subject-id
+    if (opts->subject_cert == NULL && opts->subject_id == NULL)
+        usage(opts);
+    if (opts->subject_cert && opts->subject_id) {
+        printf("Need exactly one of --subject-cert / --subject-id");
+        usage(opts);
+    }
+
+    // if we have an ID, make sure it's SHA1 and lowercase
+    if (opts->subject_id) {
+        int i;
+        subject_id = opts->subject_id;
+
+        // hex chars (also convert to lowercase)
+        for (i = 0; subject_id[i]; ++i) {
+            subject_id[i] = tolower(subject_id[i]);
+            if (!isxdigit(subject_id[i])) {
+                printf("Invalid subject ID: must be SHA1\n");
+                usage(opts);
+            }
+        }
+
+        // correct length
+        if (i != SHA1_LENGTH) {
+            printf("Invalid subject ID: must be SHA1 (too long)\n");
+            usage(opts);
+        }
+    }
 
     if (!clean_name(opts->role)) {
@@ -66,6 +97,10 @@
     char *issuer_id = cert_keyid(issuer);
 
-    certificate_t *subject = cert_from_file(opts->subject);
-    char *subject_id = cert_keyid(subject);
+    // subject keyid from cert if it wasn't passed in
+    if (opts->subject_cert) {
+        certificate_t *subject = cert_from_file(opts->subject_cert);
+        subject_id = cert_keyid(subject);
+        DESTROY_IF(subject);
+    }
 
     // build the role encoding
@@ -87,5 +122,8 @@
 
     free(issuer_id);
-    free(subject_id);
+
+    // if opts->subject_id, the memory will be freed in main
+    if (opts->subject_cert)
+        free(subject_id);
 
     // create attribute cert
@@ -121,5 +159,4 @@
     DESTROY_IF(attr_cert);
     DESTROY_IF(issuer);
-    DESTROY_IF(subject);
     DESTROY_IF(key);
 }
Index: creddy/creddy.c
===================================================================
--- creddy/creddy.c	(revision ec06cb6d0dc78f7e83e6592e312e2666e05704a7)
+++ creddy/creddy.c	(revision ee5afdd2fe33a1ae6fc25d5da9dcb295eea251b5)
@@ -13,8 +13,9 @@
 #define OPT_KEY             5
 #define OPT_ROLE            6
-#define OPT_SUBJECT         7
+#define OPT_SUBJECT_CERT    7
 #define OPT_SUBJECT_ROLE    8
 #define OPT_OUT             9 // the world oughta be opt-in only :(
 #define OPT_ATTRCERT        10
+#define OPT_SUBJECT_ID      11
 
 int main(int argc, char **argv) {
@@ -40,5 +41,6 @@
         { "key",        1, 0, OPT_KEY },
         { "role",       1, 0, OPT_ROLE },
-        { "subject",    1, 0, OPT_SUBJECT },
+        { "subject-cert", 1, 0, OPT_SUBJECT_CERT },
+        { "subject-id", 1, 0, OPT_SUBJECT_ID },
         { "subject-role", 1, 0, OPT_SUBJECT_ROLE },
         { "out",          1, 0, OPT_OUT },
@@ -82,6 +84,9 @@
                 options.role = xstrdup(optarg);
                 break;
-            case OPT_SUBJECT:
-                options.subject = xstrdup(optarg);
+            case OPT_SUBJECT_CERT:
+                options.subject_cert = xstrdup(optarg);
+                break;
+            case OPT_SUBJECT_ID:
+                options.subject_id = xstrdup(optarg);
                 break;
             case OPT_SUBJECT_ROLE:
@@ -180,7 +185,9 @@
             "Usage: identity --attribute \\\n"
             "                --issuer <cert> --key <key> --role <role> \\\n"
-            "                --subject <cert> [ --subject-role <role> ] \\\n"
+            "                --subject-cert <cert> | --subject-id <sha1> \\\n"
+            "                [ --subject-role <role> ] \\\n"
             "                [ --validity <days> ] --out <file>\n"
             "    default validity: 365 days\n"
+            "    provide exactly one of --subject-cert / --subject-id\n"
         );
 
Index: creddy/creddy.h
===================================================================
--- creddy/creddy.h	(revision ec06cb6d0dc78f7e83e6592e312e2666e05704a7)
+++ creddy/creddy.h	(revision ee5afdd2fe33a1ae6fc25d5da9dcb295eea251b5)
@@ -20,5 +20,6 @@
     char *key;
     char *role;
-    char *subject;
+    char *subject_cert;
+    char *subject_id;
     char *subject_role;
     char *out;
