GPG基础使用

测试环境:alpine:3.22(docker)
基础软件:gpg gpg-agent openssl openssh-client monkeysphere bash

第一部分、第二部分相关的文章比较多,第三部分相对较少。这篇文章基本上都是代码,是一篇完全实操过程的记录。

GPGwindows对应版本是Kleopatra
文中的一些操作有对应的图形界面,有些没有,比如第三部分(也可能是我没有找到)

低版本可导入高版本,反过来不行,因此,第一步先确认使用的环境以及版本。

环境准备

/ # 是命令提示符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
f:/gpgtest> podman run -it -v ./:/app --name gpgtest alpine:3.22 sh
/ # apk add gpg gpg-agent openssl openssh-client monkeysphere bash
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/community/x86_64/APKINDEX.tar.gz
(1/46) Installing ncurses-terminfo-base (6.5_p20250503-r0)
...
(46/46) Installing openssh-client-default (10.0_p1-r10)
Executing busybox-1.37.0-r19.trigger
OK: 65 MiB in 62 packages
/ # exit
f:/gpgtest> podman start -i gpgtest
gpgtest
f:/gpgtest> podman exec -it gpgtest bash
d661cfbeb503:/#

第一部分(增删Key)

这部分将生成一个key
testa testa@exmaple.com
密码是: testa123456

生成Key(–generate-key)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
##
## 生成一个Key
## 这个Key可以用于 Sign Certify Encrypt Authenticate
##
d661cfbeb503:/# gpg --expert --full-generate-key
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory '/root/.gnupg' created
Please select what kind of key you want:
(1) RSA and RSA
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
(14) Existing key from card
Your selection? 8

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

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

Your selection? A

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

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

Your selection? Q
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)
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: testa
Email address: testa@example.com
Comment: testa
You selected this USER-ID:
"testa (testa) <testa@example.com>"

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.
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/C59DA9100483F2F71C4238464B3A00756CCA7091.rev'
public and secret key created and signed.

pub rsa4096 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
uid testa (testa) <testa@example.com>

d661cfbeb503:/#
d661cfbeb503:/# gpg --quiet --list-key --with-keygrip
[keyboxd]
---------
pub rsa4096 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>

导出Key(–export)

1
2
3
4
5
6
7
8
9
10
d661cfbeb503:/# cd /app/
d661cfbeb503:/app# ls
##
## 将Key导出,后面还有一种更加快速的方式
## 导出SECRET的时候会提示输入密码
##
d661cfbeb503:/app# gpg -o testa_public.gpg --export testa
d661cfbeb503:/app# gpg -o testa_SECRET.gpg --export-secret-keys testa
d661cfbeb503:/app# ls
testa_SECRET.gpg testa_public.gpg

导入Key(–import)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#
# 导入公钥
# 加密文件给别人的时候用到
#
d661cfbeb503:/app# gpg --import testa_public.gpg
gpg: key 4B3A00756CCA7091: public key "testa (testa) <testa@example.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
#
# 导入私钥
# 解密文件的时候用到
#
d661cfbeb503:/app# gpg --import testa_SECRET.gpg
gpg: key 4B3A00756CCA7091: "testa (testa) <testa@example.com>" not changed
gpg: key 4B3A00756CCA7091: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ unknown] testa (testa) <testa@example.com>

d661cfbeb503:/app#

列出所有的Key(–list-keys)

1
2
3
4
5
6
7
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>

信任Key(–edit-key > trust > save)

新导入的状态是unknown,将其设置为信任ultimately

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
d661cfbeb503:/app# gpg --edit-key testa
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
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 rsa4096/4B3A00756CCA7091
created: 2026-01-16 expires: never usage: SCEA
trust: unknown validity: unknown
[ unknown] (1). testa (testa) <testa@example.com>

gpg> trust
sec rsa4096/4B3A00756CCA7091
created: 2026-01-16 expires: never usage: SCEA
trust: unknown validity: unknown
[ unknown] (1). testa (testa) <testa@example.com>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

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
Do you really want to set this key to ultimate trust? (y/N) y

sec rsa4096/4B3A00756CCA7091
created: 2026-01-16 expires: never usage: SCEA
trust: ultimate validity: unknown
[ unknown] (1). testa (testa) <testa@example.com>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> save
Key not changed so no update needed.
d661cfbeb503:/app#

这时候 trust状态已经变成ultimate,不会再有烦人的提示了

1
2
3
4
5
6
7
8
9
10
11
d661cfbeb503:/app# 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
[keyboxd]
---------
pub rsa4096 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
uid [ultimate] testa (testa) <testa@example.com>

d661cfbeb503:/app#

删除Keys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
d661cfbeb503:/app# gpg --delete-secret-keys testa
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec rsa4096/4B3A00756CCA7091 2026-01-16 testa (testa) <testa@example.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>

d661cfbeb503:/app# gpg --delete-keys testa
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub rsa4096/4B3A00756CCA7091 2026-01-16 testa (testa) <testa@example.com>

Delete this key from the keyring? (y/N) y
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
gpg: checking the trustdb
gpg: no ultimately trusted keys found
d661cfbeb503:/app#

第二部分(文件文本加解密)

加密文件(–encrypt)

1
2
3
4
5
6
7
8
9
10
11
d661cfbeb503:/app# echo "abc" > in.txt
d661cfbeb503:/app# ls
in.txt
d661cfbeb503:/app# gpg -se -r testa -o out.txt.gpg in.txt
d661cfbeb503:/app# ls
in.txt out.txt.gpg
d661cfbeb503:/app# cat in.txt
abc
d661cfbeb503:/app# cat out.txt.gpg
....一堆乱码...
d661cfbeb503:/app#

-s sign
-e/–encrypt 加密
若加密文件夹的话,可以使用gpg-zip,也可以先压缩再加密

解密文件(–decrypt)

1
2
3
4
5
6
7
8
9
10
d661cfbeb503:/app# gpg -d -o in2.txt out.txt.gpg
gpg: encrypted with rsa4096 key, ID 4B3A00756CCA7091, created 2026-01-16
"testa (testa) <testa@example.com>"
gpg: Signature made Fri Jan 16 07:11:54 2026 UTC
gpg: using RSA key C59DA9100483F2F71C4238464B3A00756CCA7091
gpg: Good signature from "testa (testa) <testa@example.com>" [ultimate]
d661cfbeb503:/app# ls
in.txt in2.txt out.txt.gpg
d661cfbeb503:/app# cat in2.txt
abc

-d/–decrypt 解密

加密字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
d661cfbeb503:/app# echo "abc" | gpg -e -r testa --armour
-----BEGIN PGP MESSAGE-----

hQIMA0s6AHVsynCRAQ/9HnvG6yXhyAEqz/6GQvzMfYomHNmqJR4WJr3rHoqchzZk
aKvhcxsQINRqJbDVBVaoCyepx1lz+HVfDnr9SmtlqHrE74FyorAtoTXzmZZR/gtu
VsGevrmQdidnBmXox1+XjX6A+pBNjhNkcopjd5VASsDDtSPGrwdcZX7QFqId5vKl
x8v7p6sRs7bKyY1FK3UDDH7HpMj27enMXO/eqAW3ASBnuzOMc8YsWcGcNWvJT63E
6XB5jrSZBJff8zVLP1R1JXlhClsridlx3oqU4yZlVnW2OQTf77Yrbp+3zPuhH+5g
RbKfs5DL7hf0tBsvPx2WOuDJwg0twoxYZ0mdlUCwcNFqQ5n9PzIbtdSVB5NnDh/w
XaIQ+FJ+O9QT+ctJauNgcypGy0d7GQNBS/18cf2kseJkWsr+on1Q0Me+a4ofXsmT
LW6nPot/zlVyJSNGgWWTUFptP6M09E5qXyjuigBPZrZcHt+FK6GBCLcZTMq1jUJa
tteEyKdiyTLaAsuclbgqJyVdyN1xmzMcWATfvgUNbQJBWsjAHNV+fyBrBqPRqe0a
TjjV38eOftD0jgR4xxUJO26h7/Jc1bUJOZ5azJQU6G6oRLz/CD5XdTwIwRZdK9t7
Gofx3QBbHr9nkUawvhbHjHNPUMLFXnrwvNMYnSoLXYMXz40d4mSxdtCFUXmUdz3U
SQEJAhCQWknuErtqVOYuDOioU5DrmliXN/FvkiXoxUD3d4y5rHA4mCydsNRxsAz4
ktGS75ilpsmXpvKkiPpvowDfcLltkKN57f4=
=BcqG
-----END PGP MESSAGE-----

解密字符串

1
2
3
4
5
6
7
8
9
10
11
12
d661cfbeb503:/app# echo "abc" | gpg -e -r testa --armour > abc.str.txt
d661cfbeb503:/app# gpg -d abc.str.txt
gpg: encrypted with rsa4096 key, ID 4B3A00756CCA7091, created 2026-01-16
"testa (testa) <testa@example.com>"
abc
##
## 如果是第一次解密的话
## 可能会卡住,因为需要输入密码
d661cfbeb503:/app# cat abc.str.txt | gpg -d
gpg: encrypted with rsa4096 key, ID 4B3A00756CCA7091, created 2026-01-16
"testa (testa) <testa@example.com>"
abc

第三部分(替代ssh-agent)

前面的都是相对简单的,这部分才是这篇文章的重点

替代ssh-agent

1、导出ssh-public-key(公钥)

1
2
d661cfbeb503:/app# gpg --export-ssh-key testa
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDNxSVTIp0bjeb+3dmSjT1NMcTfcCzO0r+49IMqQvOYWvpQ+3uAUiy3Lq9394KDZWbV2UIP+7EKK+wKkcE+8AsptpnFKqjyuxbCUjrNDlAMUSeOD7tv4yuWlkGnueCkSnX5GKntiFjKihZ6P8ZBLyrIPRb4LUaRZthslstSV3dHVd8vW9I3d9hpKJQYknCNIWnmsgoA7pWn4cwFS4Jn0Zcdwk6Gpd2aRfC2o/6AewIRpHUDNgvOJP4zI6DbGwWHkUVox6QYUxNHf1O8ygKqi+BEnh2qxhFh1iOcB6gYpmD6CdiY4UEDvQitOdgfIbUXqyfswSy9xI4IFGjdjcy2+ACa7rrSdSlAbgoP4D/cBdXk9Rjh5UoqflRT879SfzFnlg71daT8EaDcHGS+0rrimby4KdczDqlJhYe5YMfTH6gknk0/HPN7TtDUvLUc/gE0Ur8OqAVhMVjLr05iDpR5HtTIxTSsUyGHuWJB32mF+uyIu58FxY0OQMWp75UfWAYdjTOT+FpRXu0jNAlZlepNoyTf7GYfnquiNNk33b8Lf4ZNzM+pF8K9pWtTWFMPVXJlcCI3OILLidaxRweUSSuWUh4zuRc2gys1Av6eNTL8D8WdqIpQbMX0m9nIFzGO6FeAWtzT2ezd+jDk/brk89QsAXtrt9l2eGF/FObF1cFPnERAhw== openpgp:0x6CCA7091

将ssh-rsa …添加到服务器上的~/.ssh/authorized_keys

2、配置sshcontrol

1
2
3
4
5
6
7
d661cfbeb503:/app# gpg --list-keys --with-keygrip
[keyboxd]
---------
pub rsa4096 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>

[A] 是Authenticate的意思
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4 就是指纹

将指纹添加到~/.gnupg/sshcontrol中

echo "BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4" >> ~/.gnupg/sshcontrol

3、启动gpg-agent

1
2
3
d661cfbeb503:/app# gpg-connect-agent --quiet /bye
d661cfbeb503:/app# export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
### eval $(gpg-agent --daemon --enable-ssh-support)

4、完成

1
2
d661cfbeb503:/app# ssh-add -l
4096 SHA256:TLIjaLIPgJ1D5ifJO6jZkCU0LppcGcnB6pNNgR811iA (none) (RSA)

这是已经是可以使用ssh user@host登录服务器了,似乎已经可以结束了
但是如果已经有了id_rsa怎么处理呢?
用这个新的替换掉旧的,不太合理吧
是不是可以把旧的key添加到gpg中呢?当然可以

将OPENSSH私钥作为subkey添加到gpg中

准备

假设我们已经有一个openssh key 名字是testb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
d661cfbeb503:/app# ssh-keygen -t rsa -b 4096 -C "testb@exmaple.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /app/testb
Enter passphrase for "/app/testb" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /app/testb
Your public key has been saved in /app/testb.pub
The key fingerprint is:
SHA256:wRwKd/0OVS93gZ/tRTU3uVbtVoDIeA2sjxGeTuu4wus testb@exmaple.com
The key's randomart image is:
+---[RSA 4096]----+
| . . o=.+ o+=*|
| o =o.* +. oX|
| ..+= o ooX|
| *.. . B*|
| oS= o .o.|
| + . . .|
| . o |
| o . . |
| .Eo.. |
+----[SHA256]-----+

将ssh私钥转换为gpg作为subkey添加到其他gpg中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
##
## 首先将其转换为pem
##
d661cfbeb503:/app# ssh-keygen -f testb -p -m pem
##
## 将testb导入gpg
## 如果有报错提示,可能是版本问题,降版本
## 比如 alpine3.23是有问题的,用alpine3.22先转换再在3.23中导入
##
d661cfbeb503:/app# pem2openpgp testb < testb | gpg --import
gpg: key C69ED8C1A9E1F9EF: public key "testb" imported
gpg: key C69ED8C1A9E1F9EF: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/A9E1F9EF 2026-01-16 [C]
A45945D8EE060145F5F4C1FEC69ED8C1A9E1F9EF
Keygrip = AD30946474C95802071D6A8CBEA8B9779FC8DEA5
uid [ unknown] testb

pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>

将testb作为testa的subkey,并且只用于[A]uthenticate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
d661cfbeb503:/app# gpg --expert --edit-key testa
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
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 rsa4096/4B3A00756CCA7091
created: 2026-01-16 expires: never usage: SCEA
trust: ultimate validity: ultimate
[ultimate] (1). testa (testa) <testa@example.com>

gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
(14) Existing key from card
Your selection? 13
Enter the keygrip: AD30946474C95802071D6A8CBEA8B9779FC8DEA5

Possible actions for this 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? A

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

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

Your selection? E

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

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

Your selection? S

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

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

Your selection? Q
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) 10y
Key expires at Mon Jan 14 08:39:48 2036 UTC
Is this correct? (y/N) y
Really create? (y/N) y

sec rsa4096/4B3A00756CCA7091
created: 2026-01-16 expires: never usage: SCEA
trust: ultimate validity: ultimate
ssb rsa4096/8E221B1DB894174B
created: 2026-01-16 expires: 2036-01-14 usage: A
[ultimate] (1). testa (testa) <testa@example.com>

gpg> save
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/446596D5 2026-01-16 [C]
372D316C8BF04BCA90883B9A13ADAE51446596D5
Keygrip = AD30946474C95802071D6A8CBEA8B9779FC8DEA5
uid [ unknown] testb

pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ultimate] testa (testa) <testa@example.com>
sub rsa4096/B894174B 2026-01-16 [A] [expires: 2036-01-14]
Keygrip = AD30946474C95802071D6A8CBEA8B9779FC8DEA5

已经添加完成了,备份下,然后重新导入看下是否真的有效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
##
## 导出最新的gpg
##
d661cfbeb503:/app# gpg -a --export-secret-keys -o testa_b_SECRET.gpg testa
d661cfbeb503:/app# gpg -a --export -o testa_b_public.gpg testa
##
## 删除旧的gpg
##
d661cfbeb503:/app# gpg --delete-secret-and-public-keys testa testb
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec rsa4096/4B3A00756CCA7091 2026-01-16 testa (testa) <testa@example.com>

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

pub rsa4096/4B3A00756CCA7091 2026-01-16 testa (testa) <testa@example.com>

Delete this key from the keyring? (y/N) y

pub rsa4096/13ADAE51446596D5 2026-01-16 testb

Delete this key from the keyring? (y/N) y
d661cfbeb503:/app#
##
## 重新导入testa
##
d661cfbeb503:/app# gpg --import testa_b_SECRET.gpg testa_b_public.gpg
gpg: key 4B3A00756CCA7091: public key "testa (testa) <testa@example.com>" imported
gpg: key 4B3A00756CCA7091: secret key imported
gpg: key 4B3A00756CCA7091: "testa (testa) <testa@example.com>" not changed
gpg: Total number processed: 2
gpg: imported: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
d661cfbeb503:/app#
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format SHORT
[keyboxd]
---------
pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ unknown] testa (testa) <testa@example.com>
sub rsa4096/B894174B 2026-01-16 [A] [expires: 2036-01-14]
Keygrip = AD30946474C95802071D6A8CBEA8B9779FC8DEA5

将testb用于登录验证

1
2
3
4
5
6
7
8
9
10
11
12
## 导出testb的公钥
d661cfbeb503:/app# gpg --export-ssh-key B894174B!
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCjV2tQTSqQm9G2guMRqsTIwHEmk5WvMSfQ7w6rOJfI+jzduJJh68i+Icr1FElTJAJ+yYtnZqAFgeA8kAKU3sbKWKK9CjFXZm/SeBMyeIcQqysTZ6dWSQpmkQm4YUJQusYPqCSiyxWsYe5tW9/9d/GkfzTceH/I0CM9OOzUgDzgZd8DL98AsLeW2mbhErG9yUvLoecP2P1crVc8K0/iLMb+PAg+twbo3hHhsWfF2N2ZVcq1oeKGs6WjqnmYCJcWXuIO6J5DcFx5681pErhrD4j7qbwKisEsqOcBIHUF+XcvQ6O5xm/Ua8P5h2oX0vFEt0kQxL7poX2GpKQ9WPBzvKnU8c4MS3gb0xvXj/1bZdO21V0FowDd+6cbavVPkB4S+98mHeJshyKzPRIWwA2tY7d2uFmbbWnu2qoE1ogAD157q5WTCPRlu9VRB6seCzunr5OF7PJ2yQMSWTqXcrXaIY+uPeGHeT3BcI4J/RxNR5QkSYWv8+BDvTPrX5miDrYrUSYRj4QrWrg5tX0nrv5UEzh2hyyld5fDpK8Hp7PAtjpEj3EA8Wxy38jihgOQ9uETb9Qj2MqyH5LTWHJW4vd1tJGA2MglYkBAqVDL1pF0IGHHXQ92b/RGG8oKr+cv0tkqF58MG9T5gPIjldc8xYk2/3QyZ5XggvP5xmHhChdx8oz/PQ== openpgp:0xB894174B
## 设置testb用于ssh登录验证
d661cfbeb503:/app# echo "AD30946474C95802071D6A8CBEA8B9779FC8DEA5" > ~/.gnupg/sshcontrol
d661cfbeb503:/app# cat ~/.gnupg/sshcontrol
AD30946474C95802071D6A8CBEA8B9779FC8DEA5
d661cfbeb503:/app# gpg-connect-agent --quiet /bye
d661cfbeb503:/app# export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
d661cfbeb503:/app# ssh-add -l
4096 SHA256:wRwKd/0OVS93gZ/tRTU3uVbtVoDIeA2sjxGeTuu4wus (none) (RSA)
d661cfbeb503:/app#

将GPG subkey(testb)转换为Openssh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
d661cfbeb503:/app# gpg --list-keys --with-keygrip --keyid-format short
[keyboxd]
---------
pub rsa4096/6CCA7091 2026-01-16 [SCEA]
C59DA9100483F2F71C4238464B3A00756CCA7091
Keygrip = BB5DEEF5B6EDA9C88276A101687AF84D328CC8F4
uid [ unknown] testa (testa) <testa@example.com>
sub rsa4096/B894174B 2026-01-16 [A] [expires: 2036-01-14]
Keygrip = AD30946474C95802071D6A8CBEA8B9779FC8DEA5

d661cfbeb503:/app# gpg --export-secret-keys B894174B! | openpgp2ssh B894174B
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAo1drUE0qkJvRtoLjEarEyMBxJpOVrzEn0O8OqziXyPo83biS
...
6x1wVPjwFe8Vvx4hJcWiaVO8Cgi2BxlY3cUxEbaSbBs1c/5dw+LUTc0tzdg=
-----END RSA PRIVATE KEY-----
d661cfbeb503:/app#
d661cfbeb503:/app# gpg --export-secret-keys B894174B! | openpgp2ssh B894174B > testb_rsa.pub
## 对比testb_rsa和原testb.pub 是一致的
d661cfbeb503:/app# ssh-keygen -y -f testb_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCjV2tQTSqQm9G2guMRqsTIwHEmk5WvMSfQ7w6rOJfI+jzduJJh68i+Icr1FElTJAJ+yYtnZqAFgeA8kAKU3sbKWKK9CjFXZm/SeBMyeIcQqysTZ6dWSQpmkQm4YUJQusYPqCSiyxWsYe5tW9/9d/GkfzTceH/I0CM9OOzUgDzgZd8DL98AsLeW2mbhErG9yUvLoecP2P1crVc8K0/iLMb+PAg+twbo3hHhsWfF2N2ZVcq1oeKGs6WjqnmYCJcWXuIO6J5DcFx5681pErhrD4j7qbwKisEsqOcBIHUF+XcvQ6O5xm/Ua8P5h2oX0vFEt0kQxL7poX2GpKQ9WPBzvKnU8c4MS3gb0xvXj/1bZdO21V0FowDd+6cbavVPkB4S+98mHeJshyKzPRIWwA2tY7d2uFmbbWnu2qoE1ogAD157q5WTCPRlu9VRB6seCzunr5OF7PJ2yQMSWTqXcrXaIY+uPeGHeT3BcI4J/RxNR5QkSYWv8+BDvTPrX5miDrYrUSYRj4QrWrg5tX0nrv5UEzh2hyyld5fDpK8Hp7PAtjpEj3EA8Wxy38jihgOQ9uETb9Qj2MqyH5LTWHJW4vd1tJGA2MglYkBAqVDL1pF0IGHHXQ92b/RGG8oKr+cv0tkqF58MG9T5gPIjldc8xYk2/3QyZ5XggvP5xmHhChdx8oz/PQ==
d661cfbeb503:/app# cat testb.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCjV2tQTSqQm9G2guMRqsTIwHEmk5WvMSfQ7w6rOJfI+jzduJJh68i+Icr1FElTJAJ+yYtnZqAFgeA8kAKU3sbKWKK9CjFXZm/SeBMyeIcQqysTZ6dWSQpmkQm4YUJQusYPqCSiyxWsYe5tW9/9d/GkfzTceH/I0CM9OOzUgDzgZd8DL98AsLeW2mbhErG9yUvLoecP2P1crVc8K0/iLMb+PAg+twbo3hHhsWfF2N2ZVcq1oeKGs6WjqnmYCJcWXuIO6J5DcFx5681pErhrD4j7qbwKisEsqOcBIHUF+XcvQ6O5xm/Ua8P5h2oX0vFEt0kQxL7poX2GpKQ9WPBzvKnU8c4MS3gb0xvXj/1bZdO21V0FowDd+6cbavVPkB4S+98mHeJshyKzPRIWwA2tY7d2uFmbbWnu2qoE1ogAD157q5WTCPRlu9VRB6seCzunr5OF7PJ2yQMSWTqXcrXaIY+uPeGHeT3BcI4J/RxNR5QkSYWv8+BDvTPrX5miDrYrUSYRj4QrWrg5tX0nrv5UEzh2hyyld5fDpK8Hp7PAtjpEj3EA8Wxy38jihgOQ9uETb9Qj2MqyH5LTWHJW4vd1tJGA2MglYkBAqVDL1pF0IGHHXQ92b/RGG8oKr+cv0tkqF58MG9T5gPIjldc8xYk2/3QyZ5XggvP5xmHhChdx8oz/PQ== testb@exmaple.com
d661cfbeb503:/app#

结束