Alpine Linux Docker 镜像上的 GPG 密钥生成失败

Alpine Linux Docker 镜像上的 GPG 密钥生成失败

我在 docker alpine linux 上执行了以下测试:

ole@MKI:~$ docker run --rm -it alpine /bin/ash
/ # apk add --update duplicity
fetch http://dl-4.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-4.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
(1/28) Installing libbz2 (1.0.6-r4)
(2/28) Installing expat (2.1.0-r2)
...
(28/28) Installing duplicity (0.7.05-r0)
Executing busybox-1.24.1-r7.trigger
OK: 72 MiB in 39 packages
/ # gpg --list-keys
gpg: directory '/root/.gnupg' created
gpg: new configuration file '/root/.gnupg/dirmngr.conf' created
gpg: new configuration file '/root/.gnupg/gpg.conf' created
gpg: WARNING: options in '/root/.gnupg' are not yet active during this run
gpg: keybox '/root/.gnupg/pubring.kbx' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
/ # gpg --list-keys
/ # gpg --gen-key
gpg (GnuPG) 2.1.10; Copyright (C) 2015 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.

Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog.

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

Real name: Testing
Email address: testing@test
You selected this USER-ID:
"Testing <testing@test>"

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.
gpg: agent_genkey failed: No such file or directory
Key generation failed: No such file or directory
/ # ls /root/.gnupg/
S.gpg-agent dirmngr.conf gpg.conf private-keys-v1.d pubring.kbx trustdb.gpg
/ #

知道密钥生成失败的原因吗?

[编辑] 我总是可以使用 ubuntu 映像生成密钥并将它们安装在卷中。无论如何,这最终就是我正在做的事情,但我认为将其与高山图像一起使用会很好,所以我strace按照建议粘贴了以下内容:

/ # strace -f gpg --gen-key
execve("/usr/bin/gpg", ["gpg", "--gen-key"], [/* 6 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f75271edda8) = 0
set_tid_address(0x7f75271edde0)         = 17
open("/etc/ld-musl-x86_64.path", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=87976, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0!\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2187264, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526d4f000
mmap(0x7f7526f63000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x14000) = 0x7f7526f63000
close(3)                                = 0
open("/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=856824, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\214\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2957312, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526a7d000
mmap(0x7f7526d45000, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xc8000) = 0x7f7526d45000
mmap(0x7f7526d4e000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7526d4e000
close(3)                                = 0
open("/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=67520, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p'\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752686c000
mmap(0x7f7526a7b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f7526a7b000
close(3)                                = 0
open("/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=67616, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\2204\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752665b000
mmap(0x7f752686a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f752686a000
close(3)                                = 0
mprotect(0x7f7526f63000, 4096, PROT_READ) = 0
mprotect(0x7f7526d45000, 4096, PROT_READ) = 0
mprotect(0x7f7526a7b000, 4096, PROT_READ) = 0
mprotect(0x7f752686a000, 4096, PROT_READ) = 0
mprotect(0x7f75271ec000, 4096, PROT_READ) = 0
mprotect(0x7f752749a000, 8192, PROT_READ) = 0
fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
fstat(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
access("/etc/gcrypt/fips_enabled", F_OK) = -1 ENOENT (No such file or directory)
open("/proc/sys/crypto/fips_enabled", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/gcrypt/hwf.deny", O_RDONLY)  = -1 ENOENT (No such file or directory)
prlimit64(0, RLIMIT_CORE, NULL, {rlim_cur=0, rlim_max=RLIM64_INFINITY}) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
prlimit64(0, RLIMIT_CORE, {rlim_cur=0, rlim_max=RLIM64_INFINITY}, NULL) = 0
futex(0x7f75271f011c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0
rt_sigaction(SIGINT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGSEGV, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSEGV, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGUSR1, {0x7f752726a0d4, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
mmap(NULL, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7527492000
getuid()                                = 0
mlock(0x7f7527492000, 32768)            = 0
access("/root/.gnupg/gpg.conf-2.1.10", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf-2.1", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf-2", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf", R_OK)   = -1 ENOENT (No such file or directory)
access("/root/.gnupg/options", R_OK)    = -1 ENOENT (No such file or directory)
stat("~/.gnupg", 0x7fff3556cc38)        = -1 ENOENT (No such file or directory)
stat("/root/.gnupg/gpg.conf", 0x7fff3556cc38) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/gpg.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
writev(2, [{"", 0}, {"gpg (GnuPG) 2.1.10; Copyright (C"..., 69}], 2gpg (GnuPG) 2.1.10; Copyright (C) 2015 Free Software Foundation, Inc.) = 69
writev(2, [{"", 0}, {"\n", 1}], 2
)      = 1
writev(2, [{"", 0}, {"This is free software: you are f"..., 121}], 2This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
) = 121
writev(2, [{"", 0}, {"\n", 1}], 2
)      = 1
access("/root/.gnupg/random_seed", F_OK) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/pubring.gpg", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/pubring.kbx", O_RDONLY) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg", F_OK)            = -1 ENOENT (No such file or directory)
mkdir("/root/.gnupg", 0700)             = 0
write(2, "gpg: directory '/root/.gnupg", 28gpg: directory '/root/.gnupg) = 28
write(2, "' created\n", 10' created
)             = 10
open("/usr/share/gnupg/dirmngr-conf.skel", O_RDONLY) = 3
umask(077)                              = 022
open("/root/.gnupg/dirmngr.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
ioctl(4, TIOCGWINSZ, 0x7fff3556c908)    = -1 ENOTTY (Not a tty)
umask(022)                              = 077
readv(3, [{"", 0}, {"# dirmngr-conf.skel - Skeleton t"..., 1024}], 2) = 1024
readv(3, [{"", 0}, {"nd receive keys to and from a ke"..., 1024}], 2) = 1024
writev(4, [{"# dirmngr.conf - Options for Dir"..., 1024}, {"L", 1}], 2) = 1025
readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 704
writev(4, [{"DAP\n# support).\n#\n# Example HKP "..., 1024}, {"c", 1}], 2) = 1025
readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 0
writev(4, [{"ally running or not (on a per se"..., 593}, {NULL, 0}], 2) = 593
close(4)                                = 0
close(3)                                = 0
write(2, "gpg: new configuration file '/ro"..., 54gpg: new configuration file '/root/.gnupg/dirmngr.conf) = 54
write(2, "' created\n", 10' created
)             = 10
open("/usr/share/gnupg/gpg-conf.skel", O_RDONLY) = 3
umask(077)                              = 022
open("/root/.gnupg/gpg.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
ioctl(4, TIOCGWINSZ, 0x7fff3556c908)    = -1 ENOTTY (Not a tty)
umask(022)                              = 077
readv(3, [{"", 0}, {"# These first three lines are no"..., 1024}], 2) = 1024
readv(3, [{"", 0}, {"\n\n# Uncomment the following opti"..., 1024}], 2) = 1024
writev(4, [{"# Options for GnuPG\n# Copyright "..., 1024}, {"o", 1}], 2) = 1025
readv(3, [{"", 0}, {"nce you may want to use this opt"..., 1024}], 2) = 1024
writev(4, [{"re than 1 secret key in your key"..., 1024}, {" ", 1}], 2) = 1025
readv(3, [{"", 0}, {"\n# \"0x12345678\".  Note there is "..., 1024}], 2) = 1024
writev(4, [{"subkey, ensure that the cross\n# "..., 1024}, {"o", 1}], 2) = 1025
readv(3, [{"", 0}, {"r.\n#\n# verbose = show more infor"..., 1024}], 2) = 1024
writev(4, [{" another group.  Note also that\n"..., 1024}, {"t", 1}], 2) = 1025
readv(3, [{"", 0}, {"ys to the keyserver.\n\n#keyserver"..., 1024}], 2) = 1024
writev(4, [{"o increase the amount\n#         "..., 1024}, {"I", 1}], 2) = 1025
readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 413
writev(4, [{"Ds in key listings and\n# when a "..., 1024}, {"t", 1}], 2) = 1025
readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 0
writev(4, [{"o-viewer \"qiv %i\"\n# photo-viewer"..., 307}, {NULL, 0}], 2) = 307
close(4)                                = 0
close(3)                                = 0
write(2, "gpg: new configuration file '/ro"..., 50gpg: new configuration file '/root/.gnupg/gpg.conf) = 50
write(2, "' created\n", 10' created
)             = 10
write(2, "gpg: WARNING: options in '/root/"..., 38gpg: WARNING: options in '/root/.gnupg) = 38
write(2, "' are not yet active during this"..., 37' are not yet active during this run
) = 37
access("/root/.gnupg", F_OK)            = 0
getpid()                                = 17
uname({sysname="Linux", nodename="60fbb80a7ebb", ...}) = 0
getpid()                                = 17
open("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", O_WRONLY|O_CREAT|O_EXCL, 0644) = 3
write(3, "        17\n", 11)            = 11
write(3, "60fbb80a7ebb", 12)            = 12
write(3, "\n", 1)                       = 1
close(3)                                = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0
link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/pubring.kbx.lock") = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory)
umask(077)                              = 022
open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
brk(0)                                  = 0x7f7528fc5000
brk(0x7f7528fc8000)                     = 0x7f7528fc8000
umask(022)                              = 077
close(3)                                = 0
open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
ioctl(3, TIOCGWINSZ, 0x7fff3556c968)    = -1 ENOTTY (Not a tty)
writev(3, [{"\0\0\0 \1\1\0\2KBXf\0\0\0\0W\30+\243W\30+\243\0\0\0\0\0\0\0\0", 32}, {NULL, 0}], 2) = 32
close(3)                                = 0
write(2, "gpg: keybox '/root/.gnupg/pubrin"..., 37gpg: keybox '/root/.gnupg/pubring.kbx) = 37
write(2, "' created\n", 10' created
)             = 10
open("/root/.gnupg/pubring.kbx.lock", O_RDONLY) = 3
read(3, "        17\n60fbb80a7ebb\n", 24) = 24
close(3)                                = 0
getpid()                                = 17
unlink("/root/.gnupg/pubring.kbx.lock") = 0
unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17") = 0
access("/root/.gnupg/secring.gpg", F_OK) = -1 ENOENT (No such file or directory)
open("/dev/tty", O_RDWR)                = 3
ioctl(3, TIOCGWINSZ, {ws_row=43, ws_col=174, ws_xpixel=0, ws_ypixel=0}) = 0
writev(3, [{"Note: Use \"gpg2 --full-gen-key", 30}, {"\" for a full featured key genera"..., 45}], 2Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog.
) = 75
writev(3, [{"", 0}, {"\nGnuPG needs to construct a user"..., 59}], 2
GnuPG needs to construct a user ID to identify your key.

) = 59
writev(3, [{"Real name: ", 11}, {NULL, 0}], 2Real name: ) = 11
read(3,

答案1

该问题似乎与 pinentry 和 tty 有关。相同的命令在 Ubuntu 上完美运行。tty在 Alpine Linux 容器中显示/0,而tty在 Ubuntu 容器中显示/dev/console

通过首先为 gpg ( ) 导出正确的 tty,export GPG_TTY=/dev/console该命令将起作用并显示密码对话框。

答案2

连接到 Alpine Linux 容器或裸机时,重要的是:不是 su -到另一个$USER,因为这也会导致密钥生成失败。

添加到您的远程 Alpine~/.profile~/.bashrc如果使用bash

export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null

unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
        export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
  • &再次登录
  • 用于gpg --full-generate-key生成4096gpg密钥

相关内容