Digital signature and how the verification works

The Signing Requirement

You properly heard Commit Signature Verification or the Gradle Signing to publishing artifact to Maven Central. They’re all using the GPG to verify whether they receive files from a trusted source.

Recently, when I was trying to publish an Android library to Maven Central. One of the requirements is that all the files need to be signed with a GPG key.

Technically, I was able to generate the .asc files containing the signature and passed the verification process when publishing to Maven Central. But how does the verification work? Let’s see.

Installing GPG

First of all, we need to install GPG and then generate the key by following this tutorial.

Distribute Public Key

Now, we simulate the process of signing the file on a local computer and then sending the file included with the signature to the server emulator.

You can check your generated key id by using the command.

List all public keys:

gpg --list-keys --keyid-format LONG

List all private keys:

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

Both works, because you have a pair of public and private keys. The public key is used for verification or encrypting data and the private key is used for signing or decrypting data.

Here on my machine, the key id is 2E7FF7EDBF52BC1C, the one after the slash character.

sec   rsa4096/2E7FF7EDBF52BC1C 2021-03-07 [SC]
uid                 [ultimate] Justin Nguyen <>
ssb   rsa4096/99C6D46AAD3145E4 2021-03-07 [E]

Let’s distribute the public key to the server. There are several ways to share it, export ASCII format or sending to the keyserver. In this topic, I make it simple by sending it to a keyserver.

gpg --keyserver hkp:// --send-keys 2E7FF7EDBF52BC1C

Now, anyone can receive your public key from Assume that the server emulator is a Maven Central and it knows the configuration of our public key id 2E7FF7EDBF52BC1C.

We can run the command to receive the key on the server emulator to get the shared public key.

gpg --keyserver hkp:// --recv-keys 2E7FF7EDBF52BC1C

When the import is completed.

gpg: key 2E7FF7EDBF52BC1C: public key "Justin Nguyen <>" imported
gpg: Total number processed: 1
gpg:               imported: 1

We can check the public key by using the command --list-keys. Note that --list-secret-keys does not work, because the server does not own your private key.

Signing Method

Now, let’s sign a helloworld.txt for example.

gpg --armor --detach-sig -u 2E7FF7EDBF52BC1C helloworld.txt

It will generate a helloworld.txt.asc file, this is the signature file from helloworld.txt. We need to send both to the server. Note that signing is not encrypting data.

Then, to simulate the git push or maven publish process, we copy these files and paste them to the server.

Verification Method

On the server to verify whether helloworld.txt comes from a trusted source. We can run the verify command to check it.

gpg --verify helloworld.txt.asc

As a result, it’s a good signature. If you try to modify the helloworld.txt and run the verify command again, it prompts a bad signature message, indicating that the helloworld.txt is not original.

There is a warning “This key is not certified with a trusted signature!”. It indicates that you have not trusted the key. More information in the GNU Handbook

If you want to trust the key, on the server you can edit it.

gpg --edit-key 2E7FF7EDBF52BC1C
gpg> trust
  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
gpg> save

Now, if you run the --verify command again. The warning will disappear.

To recap, the person who holds the public key can verify whether it was signed by a private key. Only the person, who owns the private key can sign a file. That’s how the verification works.

This has nothing to do with encryption and decryption, you can check the GNU Handbook if you want to see how to implement it.