How to use GPG for git commit?

What is the goal

After you read this article, you can sign by GPG when you commit on git and create signed tag by GPG.

What is GPG?

GPG stands for GnuPG. GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC4880. GnuPG allows you to encrypt and sign your data and communication. And you can use it to sign commit and tag on git.

Generate GPG key pair

If you don’t have GPG key pair, you need to generate GPG key pair at first as below. During this command you need to input pass phrase for this master key. Don’t forget this pass phrase otherwise you can’t use this key anymore.

${Bob Test} should be replaced by your name. ${bob@test.local} should be replaced by your email address.

% gpg --gen-key
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keybox 'pubring.kbx' created
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Bob Test
Email address: bob@test.local
You selected this USER-ID:
    "Bob Test <bob@test.local>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: trustdb.gpg: trustdb created
gpg: key D21E6661A260DAE4 marked as ultimately trusted
gpg: revocation certificate stored as 'openpgp-revocs.d/D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4.rev'
public and secret key created and signed.

pub   rsa3072 2019-07-07 [SC] [expires: 2021-07-06]
      D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
uid                      Bob Test <bob@test.local>
sub   rsa3072 2019-07-07 [E] [expires: 2021-07-06]

The rsa3072 means key algorithm. This key is generated using rsa.

The [expires: 2021-07-06] means key expiry date. You can change it anytime.

This command generates RSA algorithm key.

The ‘[SC]’ means key type. The S means that this key can sign and the C means that this key can certify key.

The D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4 is key id.

And you can see sub rsa3072 2019-07-07 [E] [expires: 2021-07-06]. It means one sub key was created at the same time. I will explain it later.

If you want to generate different encryption algorithm key, please use the below command to chose other encryption algorithm.

% gpg --full-generate-key

Generate revoke key

It is better to generate revoke key because you need to revoke key when you lost your pass phrase. When you lost your pass phrase, but you need revoke this key because you lost pass phrase and some one stole your private key and someone pretends to be you.

% gpg --output revoke.asc --gen-revoke bob@test.local
sec  rsa3072/DEF9179376D25D37 2019-05-26 Bob Test <bob@test.local>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

Then revoke key `revoke.asc** was generated. Please keep this file some secret place. Anyone can revoke your GPG key using this revoke key.

How to use revoke key

CAUTION!! DON’T RUN THIS COMMAND. THIS COMMAND REVOKE YOUR GPG KEY.

% gpg --import revoke.asc

Then your PGP key was revoked.

Generate sub key to sign

Let’s create sub key to sign. You can use master key for sign, but if you lost private key of this or this key will be compromised, you lost your identification in internet. Therefore it is better to create sub key for sign, and remove master private key from your PC and store it in offline place.

Change master key type

At first change master key type from sign and create to create only.

The edit key command is as blow.

$ gpg edit_key ${key_id}

So in this case, you can type below command to edit key.

$ gpg --edit-key D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa3072/D21E6661A260DAE4
     created: 2019-07-07  expires: 2021-07-06  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/C3C1E8861689E952
     created: 2019-07-07  expires: 2021-07-06  usage: E
[ultimate] (1). Bob Test <bob@test.local>

gpg> change-usage
Changing usage of the primary key.

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify


   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q

sec  rsa3072/D21E6661A260DAE4
     created: 2019-07-07  expires: 2021-07-06  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa3072/C3C1E8861689E952
     created: 2019-07-07  expires: 2021-07-06  usage: E
[ultimate] (1). Bob Test <bob@test.local>

gpg> save

The primary key usage was changed from SC to C. It means this key can certify only.

Change sub key type

Currently auto generated sub key usage is E. It means encryption only. So we need to add sign capability.

$ gpg --edit-key D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa3072/D21E6661A260DAE4
     created: 2019-07-07  expires: 2021-07-06  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa3072/C3C1E8861689E952
     created: 2019-07-07  expires: 2021-07-06  usage: E
[ultimate] (1). Bob Test <bob@test.local>

Select first sub key.

gpg> key 1

sec  rsa3072/D21E6661A260DAE4
     created: 2019-07-07  expires: 2021-07-06  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa3072/C3C1E8861689E952
     created: 2019-07-07  expires: 2021-07-06  usage: E
[ultimate] (1). Bob Test <bob@test.local>

Please check * is added right of target sub key. Then change usage.

gpg> change-usage
Changing usage of a subkey.

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q

sec  rsa3072/D21E6661A260DAE4
     created: 2019-07-07  expires: 2021-07-06  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa3072/C3C1E8861689E952
     created: 2019-07-07  expires: 2021-07-06  usage: SE
[ultimate] (1). Bob Test <bob@test.local>

gpg> save

The sub key usage was changed from E to SE.

You can check usage anytime below command.

$ gpg --home ./gpg_test --list-keys
-----------------------------------------------------------------
pub   rsa3072 2019-07-07 [C] [expires: 2021-07-06]
      D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
uid           [ultimate] Bob Test <bob@test.local>
sub   rsa3072 2019-07-07 [SE] [expires: 2021-07-06]

Export all keys

Export all keys.

$ gpg --output public_keys.gpg --export D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
$ gpg --output secret_subkeys.gpg --export-secret-subkeys D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
$ gpg --output secret_keys.gpg --export-secret-keys D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4

Store those .gpg files to secure place.

Check private key list

$ gpg --list-secret-keys
---------------------------------------------------------------
sec   rsa3072 2019-07-07 [C] [expires: 2021-07-06]
      D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
uid           [ultimate] Bob Test <bob@test.local>
ssb   rsa3072 2019-07-07 [SE] [expires: 2021-07-06]

You can see master key and sub key information.

Then remove private key to remove master private key.

$ gpg --delete-secret-key D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec  rsa3072/D21E6661A260DAE4 2019-07-07 Bob Test <bob@test.local>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

Check private keys.

$ gpg --list-secret-keys

You can’t see any keys, because you deleted key already. Then import sub key only.

$ gpg --import ./secret_subkeys.gpg
gpg: key D21E6661A260DAE4: "Bob Test <bob@test.local>" not changed
gpg: To migrate 'secring.gpg', with each smartcard, run: gpg --card-status
gpg: key D21E6661A260DAE4: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Check private keys.

$ gpg --list-secret-keys --keyid-format LONG
---------------------------------------------------------------
sec#  rsa3072/D21E6661A260DAE4 2019-07-07 [C] [expires: 2021-07-06]
      D8AC8EA5B4FEB3EFD93EE5AED21E6661A260DAE4
uid                 [ultimate] Bob Test <bob@test.local>
ssb   rsa3072/C3C1E8861689E952 2019-07-07 [SE] [expires: 2021-07-06]

You can see # after sec. It means this master key hasn’t been imported, but private sub key was imported.

Let’s test sign using this private key

$ echo "test" | gpg --clearsign
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

test
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE3DshCz6YxdrlVDw7w8HohhaJ6VIFAl0hajEACgkQw8HohhaJ
6VJ2rAv8DPH6+cSs8k7ENJ7ygr2lk0LAZCcnplnITxkVZkvQ52cZarMug3bC89Eh
nvamwqk7TobpcYWkCTOfQxNQquWM/IznFLWCHPdzWwcCVNFPnV1QLS98bXK5BJJo
iRW5WxZn4nhFIHHeDKKX9P+z2xuRRZD16GPRRDYQ9L2NEVwvMwOJx2Kj5HzYIkZL
Xe5VjuxEg6GTQHUDzel+mxcYepD0/Fs2HXhZvQ1Sst+qq+1pBVw9lDOZdn+3wsM3
c8LtFd7zybW8+c9zZDWMlbgvQN+WUBbqpxteTlfE5P+jpbHXvZWLB+dW2T1swqnE
ZVIhijVgM/TzXZXSOePBWviVq6nOdiinH+zNPxe14SDVoEDTrQM14ULQ3lntD+OJ
dVQkfZfaSwri9Pa9wmK8ea9Uwe+fYedRtcI3Ph/4oblXxasbth48A8phCWeZBmcS
r46K2oDUpuYPrY0j+9AmIXqzn/uUidBdPCmjlJrsVJz5WEX5jyuP/bftHej2UqvK
+EHReVOw
=Ljn0
-----END PGP SIGNATURE-----

Congratulation, you prepared to sign! Last part is set git configuration to sign commit and tag.

$ gpg --list-secret-keys --keyid-format LONG

Set git configuration

Set global configuration for git to sign always.

$ git config --global user.signingkey C3C1E8861689E952
$ git config --global commit.gpgsign true

You need to set subkey id to signingkey. You can sign all commit if you set commit.gpgsign true.

Confirm signed commit

Then you can sign your commit automatically. And you can verify your sign using below command.

$ git verify-commit ${commmit_id}

Sign tag

If you want to sign the tag, you use below command.

$ git tag -s test

And you can verify tag using the below command.

$ git tag --verify test

Tags: ,

Updated: