Skip to main content

Security: PKI, X.509, TLS, GPG

Lab Setup

  • We will be using a virtual machine in the faculty's cloud.
  • When creating a virtual machine in the Launch Instance window:
    • Name your VM using the following convention: scgc_lab<no>_<username>, where <no> is the lab number and <username> is your institutional account.
    • Select Boot from image in Instance Boot Source section
    • Select SCGC Template in Image Name section
    • Select a flavor that is at least m1.medium.
  • The username for connecting to the VM is student.
  • For the following exercises, the resources can be found in the laboratory archive:
$ cd work/
$ wget https://repository.grid.pub.ro/cs/scgc/laboratoare/lab-cert.zip
$ unzip lab-cert.zip

Creating and inspecting certificates

TLS (Transport Layer Security) is a cryptographic protocol that provides communication security between a client and a server. Usually, the identity of the server is verified through a certificate. This certificate contains a public key, the identity of the server and a signature which verifies that the key belongs to the entity in the certificate.

A certificate is valid if it is signed by a Certificate Authority (CA). The CA is considered trustworthy by the communication client. The client has access to the certificate of the CA, with which the signature in the certificate belonging to the server can be verified and, consequently, the identity of the server can be verified.

Inspecting local certificate files

Begin by inspecting the certificate found in the houdini.cs.pub.ro.crt-roedunet file.

$ cd cert-inspect
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -text

In the output you can find information about:

  • the issuer
  • the validity
    • start date
    • end date
  • the public key
    • algorithm
    • modulus
    • exponent
  • certificate extensions
  • signature

Specific information regarding the certificate can be printed by replacing the -text argument with the one or more of the following:

$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -pubkey
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -startdate
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -enddate
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -dates
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -issuer
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -subject
$ openssl x509 -in houdini.cs.pub.ro.crt-roedunet -noout -modulus

To verify the certificate using a certificate chain, use the following command:

$ openssl verify -CAfile terena-ca-chain.pem houdini.cs.pub.ro.crt-roedunet
houdini.cs.pub.ro.crt-roedunet: OU = Domain Control Validated, CN = houdini.cs.pub.ro
error 10 at 0 depth lookup:certificate has expired
OK

The certificate is expired, but has otherwise been verified.

tip

Use man openssl-verify to check other error codes.

Check the information in certificate chain:

$ cat terena-ca-chain.pem
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Notice there are multiple certificates in the file. Although openssl does not provide direct support for printing information about each certificate in the chain, the following workaround can be used:

$ openssl crl2pkcs7 -nocrl -certfile terena-ca-chain.pem | openssl pkcs7 -print_certs -noout
subject=/C=NL/ST=Noord-Holland/L=Amsterdam/O=TERENA/CN=TERENA SSL CA 2
issuer=/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority

subject=/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
issuer=/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

subject=/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
issuer=/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

Verify open-source.cs.pub.ro.crt-roedunet and security.cs.pub.ro.crt-roedunet using the two certificate chains present in the resources archive.

tip

Find the ''issuer'' for each of the certificates and use the appropriate certificate chain.

Inspecting remote certificates

Connect to aero.curs.pub.ro using a secure connection to obtain its certificate.

$ echo | openssl s_client -connect aero.curs.pub.ro:443
CONNECTED(00000003)
depth=2 C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
verify return:1
depth=1 C = NL, O = GEANT Vereniging, CN = GEANT OV RSA CA 4
verify return:1
depth=0 C = RO, postalCode = 060042, L = Bucure\C8\99ti, street = Sectorul 6, street = "Independentei Street, No.313", O = Universitatea Politehnica din Bucure\C8\99ti, OU = NCIT Cluster, CN = *.curs.pub.ro
verify return:1
---
Certificate chain
0 s:C = RO, postalCode = 060042, L = Bucure\C8\99ti, street = Sectorul 6, street = "Independentei Street, No.313", O = Universitatea Politehnica din Bucure\C8\99ti, OU = NCIT Cluster, CN = *.curs.pub.ro
i:C = NL, O = GEANT Vereniging, CN = GEANT OV RSA CA 4
1 s:C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
i:C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
2 s:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
i:C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
3 s:C = NL, O = GEANT Vereniging, CN = GEANT OV RSA CA 4
i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
...

The received certificate appears to be for *.curs.pub.ro. This is a wildcard certificate that is available for all subdomains of curs.pub.ro. Such certificates can be used when all subdomains are secured by the same server (web server or load balancer). Let's inspect the certificate:

$ echo | openssl s_client -connect aero.curs.pub.ro:443 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
3c:e8:ca:7b:24:34:0e:23:33:d2:ec:4d:3e:de:d0:03
Signature Algorithm: sha384WithRSAEncryption
Issuer: C = NL, O = GEANT Vereniging, CN = GEANT OV RSA CA 4
Validity
Not Before: Feb 30 00:00:00 20XX GMT
Not After : Feb 30 23:59:59 20XY GMT
Subject: C = RO, postalCode = 060042, L = Bucure\C8\99ti, street = Sectorul 6, street = "Independentei Street, No.313", O = Universitatea Politehnica din Bucure\C8\99ti, OU = NCIT Cluster, CN = *.curs.pub.ro
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:ce:7b:17:7b:8f:c3:be:00:b5:a4:7f:28:db:53:
db:a2:27:c2:62:6d:a4:75:7b:10:b7:81:3e:1d:5c:
6d:48:18:77:3f:f8:d6:5e:93:e8:50:fd:16:fb:a2:
79:ae:4b:12:39:22:df:28:9c:b7:82:b2:89:9c:7e:
09:7a:43:b5:51:10:77:a3:c2:ec:bd:03:f6:b1:40:
f2:c1:82:ca:3b:53:fa:3a:5a:61:20:25:10:03:d6:
cc:eb:67:da:0a:3a:5b:f5:95:5e:15:5d:7e:b8:9d:
e5:9e:d5:0e:5b:4d:77:7b:eb:4f:e7:e6:ad:d4:7c:
20:dc:82:cc:d0:cf:63:5d:b3:8b:41:e4:3a:4e:70:
f6:18:75:a4:90:1a:b3:18:ad:b2:51:53:92:9f:bf:
ed:c1:c3:8e:ea:e0:8e:ef:68:fa:36:d2:c9:ed:8d:
34:24:4b:d5:9d:18:ab:42:c3:0d:38:71:1b:ea:a9:
ca:28:ff:cf:f5:9d:e1:cd:53:69:7a:c8:f2:82:af:
48:72:e9:96:db:16:00:7a:c0:fc:7a:7b:01:eb:d4:
66:9a:6c:4c:66:7d:de:f7:bc:9d:43:90:c0:03:4a:
a6:42:98:e0:cc:44:58:85:00:6b:f2:76:cd:59:dc:
df:d0:83:88:eb:28:5c:c9:3a:1b:b2:0d:61:27:1f:
ed:a9:63:0e:4a:f7:3e:25:b3:ab:30:92:15:b6:b2:
89:53:50:48:b2:77:39:6a:43:42:47:0d:d2:b6:c7:
27:40:f9:77:1b:55:44:7e:67:81:5e:cf:7e:8e:65:
1c:a4:0b:05:b6:ff:0a:91:70:79:40:f9:be:e8:17:
74:81:3a:c1:f2:be:51:2e:3a:0b:d2:a9:55:1c:37:
3b:2b:76:eb:2c:7b:64:fc:e7:0f:6c:c4:28:f7:7c:
2c:d0:61:31:a8:f6:db:fd:89:08:c6:9d:c5:98:ec:
cd:55:4b:e9:7b:3c:95:45:68:ca:fe:f0:45:75:2f:
6b:65:53:c2:44:b0:44:16:af:e8:d2:5b:d5:e0:1d:
57:45:6f:43:02:80:62:0d:d8:5a:75:ac:fd:ae:a0:
6b:b0:52:7c:00:cf:65:57:2e:ce:0a:8d:ec:24:68:
75:ce:62:92:0b:bf:b1:02:65:b9:6f:fe:a9:fa:77:
24:7f:5a:2b:7d:aa:bb:42:50:8e:d4:91:f0:94:3d:
3c:42:47:64:c7:92:c7:4f:ce:0b:43:01:f6:92:c2:
4e:d0:2c:9b:ee:9f:b0:6b:d2:14:84:54:0c:ad:53:
74:01:0e:b4:2b:63:95:cc:51:1e:44:ce:ef:9c:c0:
9d:a7:98:41:1a:c4:3b:97:75:f5:eb:84:00:22:8e:
b9:66:37
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:6F:1D:35:49:10:6C:32:FA:59:A0:9E:BC:8A:E8:1F:95:BE:71:7A:0C

X509v3 Subject Key Identifier:
F9:09:37:51:7C:1D:EC:62:7A:9E:F9:4C:23:98:9E:FB:14:3F:52:D9
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Certificate Policies:
Policy: 1.3.6.1.4.1.6449.1.2.2.79
CPS: https://sectigo.com/CPS
Policy: 2.23.140.1.2.2

X509v3 CRL Distribution Points:

Full Name:
URI:http://GEANT.crl.sectigo.com/GEANTOVRSACA4.crl

Authority Information Access:
CA Issuers - URI:http://GEANT.crt.sectigo.com/GEANTOVRSACA4.crt
OCSP - URI:http://GEANT.ocsp.sectigo.com

X509v3 Subject Alternative Name:
DNS:*.curs.pub.ro, DNS:curs.pub.ro
...

As you can see, all the Subject Alternative Names (SAN) can be found under in the certificate, under DNS entries.

tip

Within a browser, inspect the certificate for aero.curs.pub.ro and find the field that specifies the Subject Alternative Names for the certificate. To avoid automatic redirecting to curs.upb.ro, go to aero.curs.pub.ro/2019.

Generating certificates

The steps required when generating a certificate are as follows:

  • generate a private key
  • generate a certificate signing request (CSR) with the key and identification data
  • send the CSR to a CA in order to have it signed

We will generate a CSR for server.tld. Use the cert-gen directory.

$ cd cert-gen

First, generate a private key:

$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...............................................+++
.....................................................................................+++
e is 65537 (0x10001)

Then, generate the signing request:

$ openssl req -new -key server.key -out server.csr
...
tip

Supply the following information in the request:

  • Organization Name: Cloud courses.
  • Organizational Unit: Development.
  • Common Name: server.tld.

The other fields can be completed as desired.

Usually, at this point, the request would be sent to a trusted CA in order to be signed. Instead, we will sign the certificate using the ca.crt certificate from the resource archive.

$ openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -in server.csr -out server.crt
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
...
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
tip

Inspect the ca.cnf file, in particular the signing_policy section.

A more complex OpenSSL configuration file can be found at /etc/ssl/openssl.cnf.

Verify that the signed certificate matches the generated key.

$ openssl x509 -in server.crt -noout -modulus | md5sum
d80db122c02c6ef6eabb3b4cbd8b8f40 -
$ openssl rsa -in server.key -noout -modulus | md5sum
d80db122c02c6ef6eabb3b4cbd8b8f40 -

Furthermore, verify the certificate using the ca.crt certificate.

$ openssl verify -CAfile ca/ca.crt server.crt
server.crt: OK

Client/server communication

Unencrypted client/server communication

First, in a separate terminal, start a tcpdump session to dump traffic on the loopback interface. We will also use this for the next task.

$ sudo tcpdump -A -i lo port 12345

Now, start a simple server listening on the port tcpdump is monitoring.

$ nc -l 12345

To connect to the server, run the following in another terminal.

$ nc localhost 12345
tip

Notice that any text typed into the client shows in the server and vice-versa. Also, the messages can be seen in plaintext in the tcpdump log.

Client/server communication over SSL/TLS

Use openssl s_server to start a server listening on the same port as the previous exercise. Use the server.tld certificate previously generated.

$ openssl s_server -key server.key -cert server.crt -accept 12345
Using default temp DH parameters
ACCEPT

Connect to the server using openssl s_client.

$ openssl s_client -connect localhost:12345
CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 C = RO, ST = Bucharest, L = Bucharest, O = Cloud courses, OU = Development, CN = server.tld
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = RO, ST = Bucharest, L = Bucharest, O = Cloud courses, OU = Development, CN = server.tld
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:C = RO, ST = Bucharest, L = Bucharest, O = Cloud courses, OU = Development, CN = server.tld
i:C = RO, ST = Bucharest, O = Cloud & Grid Team, OU = Cloud Courses, CN = Cloud Courses CA
---
[...]
SSL handshake has read 1773 bytes and written 363 bytes
Verification error: unable to verify the first certificate

The validation of the server certificate has failed.

Attempt the connection again, this time specifying the CA certificate.

$ openssl s_client -CAfile ca/ca.crt -connect localhost:12345
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 C = RO, ST = Bucharest, O = Cloud & Grid Team, OU = Cloud Courses, CN = Cloud Courses CA
verify return:1
depth=0 C = RO, ST = Bucharest, L = Bucharest, O = Cloud courses, OU = Development, CN = server.tld
verify return:1
---
Certificate chain
0 s:C = RO, ST = Bucharest, L = Bucharest, O = Cloud courses, OU = Development, CN = server.tld
i:C = RO, ST = Bucharest, O = Cloud & Grid Team, OU = Cloud Courses, CN = Cloud Courses CA
---
[...]
SSL handshake has read 1773 bytes and written 363 bytes
Verification: OK
tip

The connection has been successfully established. Verify that messages exchanged between server and client are no longer displayed in the tcpdump log.

GPG

GPG (GNU Privacy Guard) is an open-source implementation of the OpenPGP Message Format that is used to secure the data that is transmitted from one entity to another through untrusted environments where one must assure that the data was not tampered by a third party.

GPG works using symmetric key encryption or a pair of public and private cryptographic keys.

GPG key setup

This step is done once, the first time you generate your GPG key. After that, you can exchange the GPG public key with your collaborators and start encrypting sensitive data or signing documents.

For this task, you will work on the VM.

danger

Most gpg commands will work with binary files and, by default, will output binary data to the terminal. Make sure to add the --output parameter or pipe the output to cat -v or another tool that can escape non-printable characters (gpg [...] |& cat -v).

student@lab:~$ gpg --full-generate-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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.

Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(14) Existing key from card
Your selection? <Enter>
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) <Enter>
Key does not expire at all
Is this correct? (y/N) y

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

Real name: Student User
Email address: user@stud.acs.upb.ro
Comment: SCGC Lab
You selected this USER-ID:
"Student User (SCGC Lab) <user@stud.acs.upb.ro>"

Change (N)ame, (C)omment, (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: /home/student/.gnupg/trustdb.gpg: trustdb created
gpg: key 29F1349EEE0E2B1E marked as ultimately trusted
gpg: directory '/home/student/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/student/.gnupg/openpgp-revocs.d/<FINGERPRINT>.rev'
public and secret key created and signed.

pub rsa4096 2026-02-24 [SC]
<FINGERPRINT>
uid Student User (SCGC Lab) <user@stud.acs.upb.ro>
sub rsa4096 2026-02-24 [E]
info

Depending on your GPG version, the prompt may be different. For example, you may have more key type options (Elliptic Curve). Always use a key type that provides good security guarantees.

Let's check the key we have created.

student@lab:~$ gpg --list-key --with-subkey-fingerprint
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
/home/student/.gnupg/pubring.kbx
--------------------------------
pub rsa4096 2026-02-24 [SC]
<FINGERPRINT>
uid [ultimate] Student User (SCGC Lab) <user@stud.acs.upb.ro>
sub rsa4096 2026-02-24 [E]
<E_FINGERPRINT>
Subkeys

GPG uses primary keys and subkeys. Under a primary key that is used only for signing, you can have multiple subkeys that are signed with the primary key and can be used for authentication, signing or encryption.

As you can see in the output above, you have two fingerprints. The first one (under pub) is associated with the key and is used for signing (S) and certification (C).

The second one (under sub) is associated with a subkey that was generated for encryption (E). In our case, when we created the primary key, the encryption subkey was automatically created.

Exercise - Share GPG encrypted data

For this task you have to work in pairs. The task is described for two students, but it can be extended to as many students as you want.

In the next sections we will present the scenario in which Bob wants to send encrypted data to Alice. For this task, one of you will be Alice and the other(s) will be Bob (for multiple senders, the steps must be repeated for each one):

  • the data you want to encrypt is up to you (e.g., Bob can create a plain text file with some important secrets he wants to share with Alice), be creative;
  • you can transmit the encrypted data using your favourite platform (scp, Teams, WhatsApp, email, homing pigeons).

Export Alice's public key

This task is for Alice.

The first thing we need to do is to export the public key in a format that can be sent to Bob.

For this task, pay attention to replace the text in <...>.

student@lab:~$ gpg --armour --output <alice>.gpg --export <Alice's email>

Send the public key to Bob.

info

The key validation steps can be omitted, but since GPG does not have a public root of trust (similar to root CAs for certificates), anyone can impersonate the sender/recipient.

It is always a good idea to check the key's fingerprint before trusting it.

Another important step is for Bob to verify that the key belongs to Alice. For that, we should also inform Bob (this time on a secure channel) about the key's fingerprint.

student@lab:~$ gpg -v --fingerprint <Alice's email>
gpg: using pgp trust model
pub rsa4096 2026-02-24 [SC]
14A9 DB7B 835B E2F0 743A BD24 0501 C489 B420 74DE
uid [ultimate] Alice (SCGC Lab) <alice@stud.acs.upb.ro>
sub rsa4096 2026-02-24 [E]

When the time comes, inform Bob of the key's fingerprint. Do not use the same communication channel as before.

Import Alice's public key

This task is for Bob.

Receive the public key from Alice and import it.

student2@lab:~$ gpg --import alice.gpg
[...]
gpg: key 0501C489B42074DE: public key "Alice (SCGC Lab) <alice@stud.acs.upb.ro>" imported
gpg: Total number processed: 1
gpg: imported: 1

student2@lab:~$ gpg --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
/home/student2/.gnupg/pubring.kbx
---------------------------------
pub rsa3072 2026-02-24 [SC]
1AD169FE836BF8B6A83DCF8A26E89A3E08202572
uid [ultimate] Bob (SCGC Lab) <bob@stud.acs.upb.ro>
sub rsa3072 2026-02-24 [E]

pub rsa4096 2026-02-24 [SC]
14A9DB7B835BE2F0743ABD240501C489B42074DE
uid [ unknown] Alice (SCGC Lab) <alice@stud.acs.upb.ro>
sub rsa4096 2026-02-24 [E]
info

Note that Bob's key is marked as ultimate (highly trusted), while Alice's key is marked as unknown (untrusted).

You can check all the trust values in man gpg, by searching for TRUST VALUES.

Now, let's check the fingerprint of the key and sign the key:

  • we need to look at the imported key's fingerprint (fpr);
  • compare it with the fingerprint received from Alice;
  • when we are sure that the fingerprint is correct, we can sign the key.
# Check if fingerprints match
student2@lab:~$ gpg --edit-key alice
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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.


pub rsa4096/0501C489B42074DE
created: 2026-02-24 expires: never usage: SC
trust: unknown validity: unknown
sub rsa4096/6FF781FA463A1F64
created: 2026-02-24 expires: never usage: E
[ unknown] (1). Alice (SCGC Lab) <alice@stud.acs.upb.ro>

gpg> fpr
pub rsa4096/0501C489B42074DE 2026-02-24 Alice (SCGC Lab) <alice@stud.acs.upb.ro>
Primary key fingerprint: 14A9 DB7B 835B E2F0 743A BD24 0501 C489 B420 74DE

gpg> sign

pub rsa4096/0501C489B42074DE
created: 2026-02-24 expires: never usage: SC
trust: unknown validity: unknown
Primary key fingerprint: 14A9 DB7B 835B E2F0 743A BD24 0501 C489 B420 74DE

Alice (SCGC Lab) <alice@stud.acs.upb.ro>

Are you sure that you want to sign this key with your
key "Bob <bob@stud.acs.upb.ro>" (26E89A3E08202572)

Really sign? (y/N) y

student2@lab:~$ gpg --list-keys
/home/student2/.gnupg/pubring.kbx
---------------------------------
...
pub rsa4096 2026-02-24 [SC]
14A9DB7B835BE2F0743ABD240501C489B42074DE
uid [ full ] Alice (SCGC Lab) <alice@stud.acs.upb.ro>
sub rsa4096 2026-02-24 [E]
info

After signing the key, its trust status is elevated to full.

Encrypt a file

This task is for Bob.

Create a file and encrypt it. Specify the recipient's (Alice's) email. You can only encrypt a file if you have the recipient's public key imported into your keyring.

student2@lab:~$ gpg --output doc.gpg --encrypt --recipient <Alice's email> doc

Send the doc.gpg file to Alice.

Decrypt the file

This task is for Alice.

Receive the file from Bob and decrypt it.

student@lab:~$ gpg --output doc --decrypt doc.gpg
gpg: encrypted with 4096-bit RSA key, ID 6FF781FA463A1F64, created 2026-02-24
"Alice (SCGC Lab) <alice@stud.acs.upb.ro>"
student@lab:~$ cat doc
[redacted]

Exercise: Send a response back to Bob

Create a new file, encrypt it and send it back to Bob.

Exercise - Verifying files with GPG

In the previous task we saw how we can use GPG to encrypt data. However, Alice cannot verify that the sender is, indeed, Bob since the public key can be used by anyone to encrypt data, not just Bob.

In this task, we will also sign the encrypted message before sending it to Alice. For this, make sure that Bob has imported Alice's key and vice-versa. Otherwise, we cannot sign and verify documents.

Encrypt and sign a document

This task is for Bob. Similar with the previous task, we encrypt the message for Alice, but we additionally create a detached signature (the signature is written in a separate file, doc.gpg.asc) that Alice can use to verify that the message came from Bob.

student2@lab:~$ gpg --output doc.gpg --encrypt --recipient alice@stud.acs.upb.ro doc
student2@lab:~$ gpg --armour --detach-sign doc.gpg
student2@lab:~$ ls -l
[...]
-rw-rw-r-- 1 student2 student2 609 Feb 24 10:44 doc.gpg
-rw-rw-r-- 1 student2 student2 659 Feb 24 10:44 doc.gpg.asc
-rw-rw-r-- 1 student2 student2 13 Feb 24 09:41 doc
[...]

Send both files to Alice.

Verify the signature

This task is for Alice.

student@lab:~$ gpg --verify doc.gpg.asc doc.gpg
gpg: Signature made Tue 24 Feb 2026 10:44:17 AM UTC
gpg: using RSA key 1AD169FE836BF8B6A83DCF8A26E89A3E08202572
gpg: Good signature from "Bob <bob@stud.acs.upb.ro>" [full]

Exercise - Verify ISO download

Usually, when you download something (like an ISO file) from the Internet, providers also add information that can be used to verify the integrity of the data. While some use only a checksum validation system (md5, sha256), others also use GPG signatures to validate authenticity of the checksums.

Access the Fedora Project Security page, download the Fedora GPG keyring and use the keys to validate the authenticity of the checksum file for one of the Fedora versions. Go to the download server, navigate to one of the released versions (e.g, 43/Workstation/x86_64/iso/), download only the checksum file and verify it using the GPG keys.