Ghi chú về GPG


Giới thiệu

GnuPG là chương trình máy tính được lập trình theo chuẩn OpenGPG định nghĩa tại RFC4880. GnuGPG phép mã hóa dữ liệu hay thực hiện ký điện tử. Trên Ubuntu Linux, bạn có thể cài gpg bằng câu lệnh sudo apt install gpg. GnuPG được dùng ở rất nhiều nơi trong hệ điều hành Ubuntu:

GnuPG cung cấp các chức năng cho phép:

Khái quát mã công khai

Mã công khai bao gồm 2 chìa khóa: khóa bí mật và khóa công khai. Thuật toán mã công khai bí mật bảo đảm rằng rất khó để có thể biết được khóa bí mật từ khóa công khai trong khi đó không khó để biết khóa công khai từ khóa bí mật. Khóa công khai sẽ được thông báo với tất cả các bên tham gia truyền thông trong khi khóa bí mật chỉ được người sở hữu biết.

Cả khóa công khai và khóa bí mật đều có thể dùng để mã hóa dữ liệu.

Một số tính năng thông dụng của gpg

Nếu chương trình gpg chưa được cài đặt, dùng câu lệnh sudo apt install gpg để cài đặt. Nếu gpg chạy lần đầu tiên, kho khóa của user chạy câu lệnh sẽ được tạo tại ${HOME}/.gnupg/pubring.kbx.

Mặc định các câu lệnh gpg sẽ xuất ra dữ liệu binary. Để gpg xuất ra dữ liệu ascii, lựa chọn --armor cần được chỉ định khi chạy chương trình.

1) Tạo khóa

Trước khi bắt đầu mã hóa/giải mã/hay ký dữ liệu, một cặp khóa cần được tạo hay import vào kho khóa của gpg.

Tạo khóa. Chọn thuật toán RSA 4096 bits với thời hạn 1 năm, Realname là “GnuPG Testkey”. Sau khi nhập các dữ liệu trên, khóa sẽ được tạo với kết quả như dưới đây.

# gpg --full-generate-key
...
gpg: /home/ubuntu/.gnupg/trustdb.gpg: trustdb created
gpg: key AC9F02A2880FC94D marked as ultimately trusted
gpg: directory '/home/ubuntu/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/ubuntu/.gnupg/openpgp-revocs.d/A32AF7386251D58AF96CD7C5AC9F02A2880FC94D.rev'
public and secret key created and signed.

pub   rsa4096 2024-06-25 [SC] [expires: 2025-06-25]
      A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
uid                      GnuPG Testkey (Demo GnuPG) <testkey@local> 
sub   rsa4096 2024-06-25 [E] [expires: 2025-06-25]

2) Liệt kê khóa

Liệt kê khóa lưu trữ ở kho khóa bằng --list-keys hoặc chỉ định khóa công khai hay bí mật.

# gpg --list-keys 
# gpg --list-public-keys
# gpg --list-secret-keys

Với khóa được tạo ở trên, --list-keys cho kết quả như dưới đây:

# gpg --list-keys
/home/ubuntu/.gnupg/pubring.kbx
-------------------------------
pub   rsa4096 2024-06-25 [SC] [expires: 2025-06-25]
      A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
uid           [ultimate] GnuPG Testkey (Demo GnuPG) <testkey@local>
sub   rsa4096 2024-06-25 [E] [expires: 2025-06-25]

ID Khóa có thể được tham khảo bằng 8 ký tự cuối của chuỗi ID 880FC94D.

3) Export/Import khóa

Export

# gpg --export 880FC94D
# gpg --export -a 880FC94D

Import Khóa có thể được import từ file hay từ keyserver (là nơi để mọi người chia sẽ khóa).

# gpg --import /etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg 
gpg: key 871920D1991BC93C: 1 signature not checked due to a missing key
gpg: key 871920D1991BC93C: public key "Ubuntu Archive Automatic Signing Key (2018) <[email protected]>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2025-06-25

# gpg --list-keys
/home/ubuntu/.gnupg/pubring.kbx
-------------------------------
pub   rsa4096 2024-06-25 [SC] [expires: 2025-06-25]
      A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
uid           [ultimate] GnuPG Testkey (Demo GnuPG) <testkey@local>
sub   rsa4096 2024-06-25 [E] [expires: 2025-06-25]

pub   rsa4096 2018-09-17 [SC]
      F6ECB3762474EDA9D21B7022871920D1991BC93C
uid           [ unknown] Ubuntu Archive Automatic Signing Key (2018) <[email protected]>

Tìm kiếm và import từ keyserver.

# gpg --keyserver keyserver.ubuntu.com --search-keys 0547d020 
gpg: data source: http://[2620:2d:4000:1007::70c]:11371
(1)     Bui Hong Ha (Work email) <[email protected]>
        Bui Hong Ha <[email protected]>
          3072 bit RSA key 0C1E5DC50547D020, created: 2019-02-19
Keys 1-1 of 1 for "0547d020".  Enter number(s), N)ext, or Q)uit > Q
gpg: error searching keyserver: Operation cancelled
gpg: keyserver search failed: Operation cancelled

# gpg --keyserver keyserver.ubuntu.com --recv-keys 0547d020 
gpg: key 0C1E5DC50547D020: public key "Bui Hong Ha (Work email) <[email protected]>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Một số keyserver phổ biến:

4) Mã hóa/giải mã dữ liệu

Chuẩn bị dữ liệu.

# echo "Important messages" > data.txt
# cat data.txt 
Important messages

Mã hóa. File kết quả data.txt.gpg có thể được dùng để gửi cho người nhận. gpg sẽ mã hóa file data.txt sử dụng khóa công khai của user testkey@local.

# gpg --encrypt --recipient testkey@local data.txt
# ls
data.txt  data.txt.gpg
# file data.txt.gpg 
data.txt.gpg: PGP RSA encrypted session key - keyid: BD766384 26A0D34D RSA (Encrypt or Sign) 4096b .

Nếu bạn muốn file mã hóa có định dạng text ascii thay vì dữ liệu, dùng lựa chọn --armor.

# gpg --encrypt --armor  --recipient testkey@local data.txt
# ls
data.txt  data.txt.asc  data.txt.gpg
# cat data.txt.asc 
-----BEGIN PGP MESSAGE-----

hQIMA712Y4QmoNNNAQ/9FcJw17cRFzYytBMWkV+7ub2b88a/bUnqYm49xNsU36Sx
mHGnDUW9RwNoM7JzHzXljp/n2nBDv15xBVvWdujouhzKRKO3ieOr5fFF03VDT//h
8x38me0h6lTD1ENd5zgVEFX5h94uAp5gP5xZ7MPYh5Idpd5iGfY07YDXlEyEG325
inpBitcEUatfee6yqn00jot8ADfeqlQLC1hlOFOQrBmokxAHE6oemICwJByIDEsJ
Q9/IOFblIBAuqV3jrVb9nYpzdOTiWd6P6qJmUKFHpefjVm6ZLUlHcM2U3ck+GKRQ
1D1XwVrudIhrz1pYLTfFQFZMKhXPS2j93X+H7zxUn3oM1WaBGpYH+ZlyDq/XUkC6
lwz+K70LLHxrWGNKe3i1dJcvdLnTFNrwBmtdGDDFyVHyW7zCQVmLUwOV3SD9Hy9W
UnUXQGNf2iQU1+TYSCD9ZYiVaepEhvHIezWOy23nvO16+KVtrYgpGkpZta6Amm3J
PWp3CCzSKBJJVcib2EZAKkKm1oVL84fnmwpxZ81w3R9ZGDoQuzQAORjlCSOgTFX8
esU1/FVoiIttVZDO+HL5PKVuKue/2V5AA065sp7Vcgnmo8UuWcqVwNUWqtrJa+7Y
wu5+U2iWBEeTcLyIUvOlEdj0/dAvKpOpg/KKBTZRo0eQTJ1a9C1cQ2CjKG8x7DvS
VgEcN0ggDyhqOPWI7EDzke+UgGwT/Brhx6Mjq5Uw+yMmp/In8KzQcsgUg3f1CuLE
+RQKi91MB3xH0B+xUa4cRdHuJMSG/cgl8P3/kbdr048t2gAjPHj2
=Tn05
-----END PGP MESSAGE-----

Giải mã dùng lựa chọn --decrypt. Nếu khóa bí mật của bạn có passphrase, bạn phải nhập passphrase để có thể mở khóa bí mật.

# gpg --decrypt data.txt.gpg 
gpg: encrypted with 4096-bit RSA key, ID BD76638426A0D34D, created 2024-06-25
      "GnuPG Testkey (Demo GnuPG) <testkey@local>"
Important messages
# 
# gpg --decrypt data.txt.asc 
gpg: encrypted with 4096-bit RSA key, ID BD76638426A0D34D, created 2024-06-25
      "GnuPG Testkey (Demo GnuPG) <testkey@local>"
Important messages

5) Ký điện tử

Giả định thay vì bạn muốn gửi data.txt cho user testkey@local, bạn là user testkey@local muốn gửi data.txt cho tất cả mọi người trong khi muốn chứng minh người gửi chính là bạn. Trong trường hợp này, bạn cần gửi kèm data.txt kèm chữ ký điện tử. gpg cho phép bạn làm điều này.

# gpg --sign data.txt
# ls
data.txt  data.txt.gpg
# file data.txt.gpg 
data.txt.gpg: data
# gpg --sign -a data.txt
# ls
data.txt  data.txt.asc  data.txt.gpg
# cat data.txt.asc 
-----BEGIN PGP MESSAGE-----

owEBaAKX/ZANAwAKAayfAqKID8lNAawhYghkYXRhLnR4dGZ62IxJbXBvcnRhbnQg
bWVzc2FnZXMKiQIzBAABCgAdFiEEoyr3OGJR1Yr5bNfFrJ8CoogPyU0FAmZ62IwA
CgkQrJ8CoogPyU3ZmxAAjhDERfKRrlP5OxlqoAdaqsvtWP7A5p9jDbV5xCcrMjZW
kY5C7D3GNBhVpXjL3qnBRcjgDHEo3xcjMh84iiFKKlSUxpBQBfFvDEuJmHhPvVAr
k8aKpnqXecJ2zSGfiw6dAqw4TZVGmEoQd5ThBR/4eAKpBk+X4zDnIluDMkKHfT8e
DZFkU2FcYHNUFewUHgaA37svgOLf4lL+A7bONxFTNlawrVkbefcIIjYppwkVgioa
rbULDTCjLeKdO/x/dgh521G/wamobZlOaRta5UjYmSPR5uOYI9AHOm14UTkFE6uu
ZlkpIJhgjMndIdDi50qD9jRtAtyIf32HJW/ec/iSGK1/M1T0HDQPE7Z7DfShd0Pe
Ovg8Fkj7IHR8QLu9l7uN9+AX9RcZw9MQuzbbCmaI+7ihRvhBrm6Apw4gFyRRcy/5
eNJQJqVe61VqPf8akKRXthxv/BH4+ioHuzbetCNB9KsFt8fhMf9m6wiPTf2HHUaZ
GjvHEBOJk8uVGq5bFJ82NmLyL2vkFl/a7QShy734LnPPvQBDmOpkEJaMRiD/G18x
BLHtuLcUQUpZyItuLbCCDIlbU4COFHZNQRHvUpbm+8ulfGReOih2gSsxidMKB6V5
hBKkGWbt3v4RfkJLptse6jCFDI+PJXDRLBbo8ONbU3GiBGBc8nHdIcxjBNh48Mw=
=hb3d
-----END PGP MESSAGE-----

6) Kiểm tra chữ ký điện tử

# gpg --list-packets data.txt.gpg 
# off=0 ctb=a3 tag=8 hlen=1 plen=0 indeterminate
:compressed packet: algo=1
# off=2 ctb=90 tag=4 hlen=2 plen=13
:onepass_sig packet: keyid AC9F02A2880FC94D
        version 3, sigclass 0x00, digest 10, pubkey 1, last=1
# off=17 ctb=ac tag=11 hlen=2 plen=33
:literal data packet:
        mode b (62), created 1719326733, name="data.txt",
        raw data: 19 bytes
# off=52 ctb=89 tag=2 hlen=3 plen=563
:signature packet: algo 1, keyid AC9F02A2880FC94D
        version 4, created 1719326733, md5len 0, sigclass 0x00
        digest algo 10, begin of digest 01 e3
        hashed subpkt 33 len 21 (issuer fpr v4 A32AF7386251D58AF96CD7C5AC9F02A2880FC94D)
        hashed subpkt 2 len 4 (sig created 2024-06-25)
        subpkt 16 len 8 (issuer key ID AC9F02A2880FC94D)
        data: [4094 bits]
# gpg --verify data.txt.gpg
gpg: Signature made Tue Jun 25 14:45:33 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]

Kết quả “Good signature” cho thấy chữ ký này quả thực đến từ user testkey@local. Muốn đọc nội dung kèm trong chữ ký điện tử này, dùng gpg --decrypt.

# gpg --decrypt data.txt.asc 
Important messages
gpg: Signature made Tue Jun 25 14:47:40 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]

7) Ký chứng thực nhưng không mã hóa

gpg cho phép ký chứng thực mà không cần mã hóa. Người nhận có thể đọc nội dung trực tiếp trong khi vẫn có thể kiểm tra tính xác thưc của nội dung.

# gpg --clear-sign data.txt
File 'data.txt.asc' exists. Overwrite? (y/N) y
# cat data.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Important messages
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEoyr3OGJR1Yr5bNfFrJ8CoogPyU0FAmZ62kMACgkQrJ8CoogP
yU0THRAA0Ph/NiHuOiBb9qyiN0doBXoE8mTCKyBHPMWAK4J0aro48x9022icnmDy
+GGvulbg+bCQlxPzACa1MYux7dA1b/XqFOQ1yh3FQPqlY+JhygYsHAvUnd9yamFT
fCAcmDkaMSys5J3P0HQsYdMgNOR/+WL7cnAwMxeYsEy20oOh+7KxJHJqfQ4ScM5r
5/HPuhMnWalbPd8mkf739wuDw79bJHsm/E5DKMFOOrhWUjQ2sfCj1fHDYbAiCe5L
hF5W6hTPtB7RgLAoB7U+1Y6NFG3IxnwtUFjATXZE9lEhHi4lpsBDnFypF7TGzv/Z
347AbkKol4UCoQaUMSYeA4UkN8rN23DfssHYM3P4lSBW7hxpu49o+j2ovYZt/XqS
tx6pomgUE2e+MR+eVkqXfiCmHvKSQC7nHweOwTRRdFpTdvCEH0VGQThyI3s6Fgsf
chWl6PDXqF3LoNltMjzLwxBuVA590n+lFICIRLaAB2zs5nN8clKUxlH9x8Mq0/oY
T5DTxtmbHmI3m3X5uhnp19c+wDcliMmWad5nluonXFBVo9flD09UsmmoOUnid3Wx
p54V07ZRMzpXRpyJ4WQTwwd4sQJoYD/WR0OXe4aXNO6pje20Er7KSKc4Rqr8uCl9
Q0BvWDb3HQ11L+w/cgFLf2pjpr9l7JuYP6z8UokdpgcXgaR3U9U=
=jG0r
-----END PGP SIGNATURE-----

# gpg --verify  data.txt.asc
gpg: Signature made Tue Jun 25 14:54:59 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]
gpg: WARNING: not a detached signature; file 'data.txt' was NOT verified!

8) Ký chứng thực nhưng không kèm nội dung

Nội dung của file data.txt sẽ không được đính kèm trong chữ ký. Người gửi cần gửi kèm cả chữ ký cả nội dung data.txt. Sử dụng tính năng này nếu muốn gửi nội dung trong khi không bắt buộc người nhận nhất định phải chứng thực.

# gpg --detach-sign -a data.txt
File 'data.txt.asc' exists. Overwrite? (y/N) y
# cat data.txt.asc 
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEEoyr3OGJR1Yr5bNfFrJ8CoogPyU0FAmZ626EACgkQrJ8CoogP
yU0D6w/9HqmYPZy8H/sb5YGFX8nsylwSZTsk6mNy4dFaVNAOxK+xJFxXCFHh9fSc
C6MahN/IBqGd7YiBWbYapZ3JDcdh5Yc764AgtXaSPrTG0kklnDOYvcvB6QI8qz5Q
Nlcs9GIS4NpzbyBbWeEMBOIWJI7aVSeVi6DRxV4DJpTVc4S4BhcanQa2nBJq7/W7
tTFplYZq6ioiiLjdhDeflELwbwB75pldSAHFlzGXMsZFBbwaFKHKS+EhqXqkFHYZ
VuV1TtHfxatyPpQxqsivd0fllJp1Q6isoUEtf+F+cezpxfVs6UgZPNYd5sOhUYG1
Ph8XyS/nUygyYGh970ZC48iaFYRC+KBvjjeCRdahfc3Wr764c1ZzNbSUC+S8krgC
tiPK4rBou/L2ZEz6YkWmRrmbdCoFi8fMWu1WYT+PqE4iMilbSB3Kyemg4YCDQvH7
lHxJu6bWPJviRTDw8pWjxv4oymkPPuR7jxV9XzahaHgsxRe7XjRCXKM61/Hc30FW
jTAoBVlzjXQAxiGFLolOXjnTcJzZdbT8CHYE/cvjlB86KyF981KLMV17VJBlNh9N
OqSyK94n1YRTf2Qr9hPiI3ajwB7/XUV8LcA21Xp8t7NR6SJIA2yVmqvJEGoLpIoZ
30n40LSxr5HWsn6eTMhoQi0W0UBCTtMdaRet1GrNMPWtSFPd9bI=
=IfeT
-----END PGP SIGNATURE-----

# gpg --decrypt data.txt.asc
gpg: assuming signed data in 'data.txt'
gpg: Signature made Tue Jun 25 15:00:49 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]

Câu lệnh nói rằng nội dung cần được tham khảo ở file data.txt. Ta có thể kiểm tra tính xác thực của data.txt như sau.

gpg --verify  data.txt.asc data.txt
gpg: Signature made Tue Jun 25 15:00:49 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]

9) Phục hồi dữ liệu

Nếu chữ ký có đính kèm dữ liệu, bạn có thể phục hồi dữ liệu từ chữ ký.

# ls
data.txt  data.txt.asc  data.txt.gpg  data.txt.sig
# rm data.txt
# gpg data.txt.gpg 
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: Signature made Tue Jun 25 14:45:33 2024 UTC
gpg:                using RSA key A32AF7386251D58AF96CD7C5AC9F02A2880FC94D
gpg: Good signature from "GnuPG Testkey (Demo GnuPG) <testkey@local>" [ultimate]
# ls
data.txt  data.txt.asc  data.txt.gpg  data.txt.sig
# cat data.txt
Important messages

Tóm tắt phần mở rộng