main
1{den, ...}: {
2 den.aspects.desktop.includes = [den.aspects.desktop.gnupg];
3 den.aspects.desktop.gnupg = {
4 nixos = {pkgs, ...}: {
5 programs.gnupg.agent = {
6 enable = true;
7 pinentryPackage = pkgs.pinentry-gnome3;
8 enableSSHSupport = false;
9 settings.default-cache-ttl = 4 * 60 * 60; # 4 hours
10 };
11 };
12
13 provides.to-users = {
14 includes = [
15 {
16 persistHome = {config, ...}: {
17 directories = [
18 {
19 directory = config.environment.sessionVariables.GNUPGHOME;
20 mode = "0700";
21 }
22 ];
23 };
24 }
25 ];
26
27 hjem = {
28 user,
29 pkgs,
30 lib,
31 config,
32 ...
33 }: let
34 # Port of home-manager's programs.gpg
35 # See https://github.com/nix-community/home-manager/blob/c53d643b3737e2fcd04e6cb3b3580ef50b2087a0/modules/programs/gpg.nix
36 gpgConfGenerator = value:
37 lib.generators.toKeyValue {
38 mkKeyValue = key: v:
39 if lib.isString v
40 then "${key} ${v}"
41 else lib.optionalString v key;
42 listsAsDuplicateKeys = true;
43 }
44 value;
45
46 # Managed public keys, all ultimately trusted.
47 publicKeys =
48 map (key: {
49 trust = 5;
50 source =
51 if builtins.isPath key
52 then key
53 else pkgs.writeText "gpg-pubkey" key;
54 })
55 user.identity.gpgKeys;
56
57 # Build the immutable keyring with the managed keys imported.
58 gpgKeyring = pkgs.runCommand "gpg-pubring" {buildInputs = [pkgs.gnupg];} (
59 let
60 gpg = "${pkgs.gnupg}/bin/gpg";
61
62 importKey = {
63 source,
64 trust,
65 ...
66 }: ''
67 ${gpg} --import ${source}
68 ${lib.optionalString (trust != null) ''importTrust "${source}" ${toString trust}''}
69 '';
70
71 importKeys = lib.concatMapStringsSep "\n" importKey publicKeys;
72 in ''
73 GNUPGHOME=$(mktemp -d)
74 export GNUPGHOME
75
76 function gpgKeyId() {
77 ${gpg} --show-key --with-colons "$1" \
78 | grep ^pub: \
79 | cut -d: -f5
80 }
81
82 function importTrust() {
83 local keyIds trust
84 mapfile -t keyIds <<< "$(gpgKeyId "$1")"
85 trust="$2"
86 for id in "''${keyIds[@]}"; do
87 { echo trust; echo "$trust"; (( trust == 5 )) && echo y; echo quit; } \
88 | ${gpg} --no-tty --command-fd 0 --edit-key "$id"
89 done
90 }
91
92 ${importKeys}
93
94 mkdir $out
95 cp $GNUPGHOME/pubring.kbx $out/pubring.kbx
96 if [[ -e $GNUPGHOME/trustdb.gpg ]] ; then
97 cp $GNUPGHOME/trustdb.gpg $out/trustdb.gpg
98 fi
99 ''
100 );
101 in {
102 packages = [pkgs.gnupg];
103
104 environment.sessionVariables.GNUPGHOME = "${config.directory}/.gnupg";
105
106 files =
107 {
108 # This configuration is based on the tutorial below, it allows for a robust setup
109 # https://blog.eleven-labs.com/en/openpgp-almost-perfect-key-pair-part-1
110 # ~/.gnupg/gpg.conf
111 ".gnupg/gpg.conf" = {
112 generator = gpgConfGenerator;
113 value = {
114 # Get rid of the copyright notice
115 no-greeting = true;
116
117 # --- Avoid information leaked --- #
118 # Disable inclusion of the version string in ASCII armored output
119 no-emit-version = true;
120 # Do not write comment packets
121 no-comments = false;
122 # Export the smallest key possible
123 # This removes all signatures except the most recent self-signature on each user ID
124 export-options = "export-minimal";
125
126 # Display long key IDs
127 keyid-format = "0xlong";
128 # List all keys (or the specified ones) along with their fingerprints
129 with-fingerprint = true;
130
131 # Display the calculated validity of user IDs during key listings
132 list-options = "show-uid-validity";
133 verify-options = "show-uid-validity show-keyserver-urls";
134
135 # Select the strongest cipher
136 personal-cipher-preferences = "AES256";
137 # Select the strongest digest
138 personal-digest-preferences = "SHA512";
139 # This preference list is used for new keys and becomes the default for "setpref" in the edit menu
140 default-preference-list = "SHA512 SHA384 SHA256 RIPEMD160 AES256 TWOFISH BLOWFISH ZLIB BZIP2 ZIP Uncompressed";
141
142 # Use the strongest cipher algorithm
143 cipher-algo = "AES256";
144 # Use the strongest digest algorithm
145 digest-algo = "SHA512";
146 # Message digest algorithm used when signing a key
147 cert-digest-algo = "SHA512";
148 # Use RFC-1950 ZLIB compression
149 compress-algo = "ZLIB";
150
151 # Disable weak algorithm
152 disable-cipher-algo = "3DES";
153 # Treat the specified digest algorithm as weak
154 weak-digest = "SHA1";
155
156 # The cipher algorithm for symmetric encryption for symmetric encryption with a passphrase
157 s2k-cipher-algo = "AES256";
158 # The digest algorithm used to mangle the passphrases for symmetric encryption
159 s2k-digest-algo = "SHA512";
160 # Selects how passphrases for symmetric encryption are mangled
161 s2k-mode = "3";
162 # Specify how many times the passphrases mangling for symmetric encryption is repeated
163 s2k-count = "65011712";
164 };
165 };
166 }
167 // lib.optionalAttrs (publicKeys != []) {
168 # Immutable keyring: managed keys/trust are linked from the store.
169 ".gnupg/pubring.kbx".source = "${gpgKeyring}/pubring.kbx";
170 ".gnupg/trustdb.gpg" = {
171 type = "copy";
172 source = "${gpgKeyring}/trustdb.gpg";
173 };
174 };
175 };
176 };
177 };
178}