@@ -24,6 +24,7 @@ struct gpg_format {
2424 int (* sign_buffer )(struct strbuf * buffer , struct strbuf * signature ,
2525 const char * signing_key );
2626 const char * (* get_default_key )(void );
27+ const char * (* get_key_id )(void );
2728};
2829
2930static const char * openpgp_verify_args [] = {
@@ -61,6 +62,8 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
6162
6263static const char * get_default_ssh_signing_key (void );
6364
65+ static const char * get_ssh_key_id (void );
66+
6467static struct gpg_format gpg_format [] = {
6568 {
6669 .name = "openpgp" ,
@@ -70,6 +73,7 @@ static struct gpg_format gpg_format[] = {
7073 .verify_signed_buffer = verify_gpg_signed_buffer ,
7174 .sign_buffer = sign_buffer_gpg ,
7275 .get_default_key = NULL ,
76+ .get_key_id = NULL ,
7377 },
7478 {
7579 .name = "x509" ,
@@ -79,6 +83,7 @@ static struct gpg_format gpg_format[] = {
7983 .verify_signed_buffer = verify_gpg_signed_buffer ,
8084 .sign_buffer = sign_buffer_gpg ,
8185 .get_default_key = NULL ,
86+ .get_key_id = NULL ,
8287 },
8388 {
8489 .name = "ssh" ,
@@ -88,6 +93,7 @@ static struct gpg_format gpg_format[] = {
8893 .verify_signed_buffer = NULL , /* TODO */
8994 .sign_buffer = sign_buffer_ssh ,
9095 .get_default_key = get_default_ssh_signing_key ,
96+ .get_key_id = get_ssh_key_id ,
9197 },
9298};
9399
@@ -484,6 +490,41 @@ int git_gpg_config(const char *var, const char *value, void *cb)
484490 return 0 ;
485491}
486492
493+ static char * get_ssh_key_fingerprint (const char * signing_key )
494+ {
495+ struct child_process ssh_keygen = CHILD_PROCESS_INIT ;
496+ int ret = -1 ;
497+ struct strbuf fingerprint_stdout = STRBUF_INIT ;
498+ struct strbuf * * fingerprint ;
499+
500+ /*
501+ * With SSH Signing this can contain a filename or a public key
502+ * For textual representation we usually want a fingerprint
503+ */
504+ if (starts_with (signing_key , "ssh-" )) {
505+ strvec_pushl (& ssh_keygen .args , "ssh-keygen" , "-lf" , "-" , NULL );
506+ ret = pipe_command (& ssh_keygen , signing_key ,
507+ strlen (signing_key ), & fingerprint_stdout , 0 ,
508+ NULL , 0 );
509+ } else {
510+ strvec_pushl (& ssh_keygen .args , "ssh-keygen" , "-lf" ,
511+ configured_signing_key , NULL );
512+ ret = pipe_command (& ssh_keygen , NULL , 0 , & fingerprint_stdout , 0 ,
513+ NULL , 0 );
514+ }
515+
516+ if (!!ret )
517+ die_errno (_ ("failed to get the ssh fingerprint for key '%s'" ),
518+ signing_key );
519+
520+ fingerprint = strbuf_split_max (& fingerprint_stdout , ' ' , 3 );
521+ if (!fingerprint [1 ])
522+ die_errno (_ ("failed to get the ssh fingerprint for key '%s'" ),
523+ signing_key );
524+
525+ return strbuf_detach (fingerprint [1 ], NULL );
526+ }
527+
487528/* Returns the first public key from an ssh-agent to use for signing */
488529static const char * get_default_ssh_signing_key (void )
489530{
@@ -532,6 +573,21 @@ static const char *get_default_ssh_signing_key(void)
532573 return default_key ;
533574}
534575
576+ static const char * get_ssh_key_id (void ) {
577+ return get_ssh_key_fingerprint (get_signing_key ());
578+ }
579+
580+ /* Returns a textual but unique representation of the signing key */
581+ const char * get_signing_key_id (void )
582+ {
583+ if (use_format -> get_key_id ) {
584+ return use_format -> get_key_id ();
585+ }
586+
587+ /* GPG/GPGSM only store a key id on this variable */
588+ return get_signing_key ();
589+ }
590+
535591const char * get_signing_key (void )
536592{
537593 if (configured_signing_key )
0 commit comments