generateKeys = keys: unlines (lib.mapAttrsToList generateKey keys);
generateKey =
- uid:
- { uid ? uid
- , algo ? "future-default"
- , usage ? ["default"]
- , expire ? "-"
- , passPath
- , subKeys ? {}
- , ...
- }@primary:
+ _uid:
+ { uid ? uid
+ , algo ? "future-default"
+ , usage ? [ "default" ]
+ , expire ? "-"
+ , passPath
+ , subKeys ? { }
+ , postRun ? ""
+ , ...
+ }@primary:
''
- info "generateKey uid=\"${uid}\""
- if ! ${gpg-with-home}/bin/gpg-with-home --list-secret-keys -- "=${uid}" >/dev/null 2>/dev/null
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --quick-generate-key "${uid}" "${algo}" "${unwords usage}" "${expire}"
- fi
- ${head1}
- fpr=$(${gpg-fingerprint}/bin/gpg-fingerprint -- "=${uid}" | head1)
- caps=$(${gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode --with-fingerprint \
- --list-secret-keys -- "=${uid}" |
- ${pkgs.gnugrep}/bin/grep '^ssb:' |
- ${pkgs.coreutils}/bin/cut -d : -f 12 || true)
+ info "generateKey uid=\"${uid}\""
+ if ! ${gpg-with-home}/bin/gpg-with-home --list-secret-keys -- "=${uid}" >/dev/null 2>/dev/null
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --quick-generate-key "${uid}" "${algo}" "${unwords usage}" "${expire}"
+ fi
+ ${head1}
+ fpr=$(${gpg-fingerprint}/bin/gpg-fingerprint -- "=${uid}" | head1)
+ caps=$(${gpg-with-home}/bin/gpg-with-home \
+ --with-colons --with-fingerprint \
+ --list-secret-keys -- "=${uid}" |
+ ${pkgs.gnugrep}/bin/grep '^ssb:' |
+ ${pkgs.coreutils}/bin/cut -d : -f 12 || true)
''
+ unlines (map (generateSubKey primary) subKeys)
+ generateBackupKey "$fpr" primary
- ;
+ + postRun
+ ;
generateSubKey =
- primary:
- { expire ? primary.expire
- , algo ? primary.algo
- , usage
- , ...
- }:
+ primary:
+ { expire ? primary.expire
+ , algo ? primary.algo
+ , usage
+ , ...
+ }:
''
- info " generateSubKey usage=[${unwords usage}]"
- if ! printf '%s\n' "$caps" | ${pkgs.gnugrep}/bin/grep -Fqx "${lettersKeyUsage usage}"
- then
- ${pkgs.pass}/bin/pass "${primary.passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --quick-add-key "$fpr" "${algo}" "${unwords usage}" "${expire}"
- fi
+ info " generateSubKey usage=[${unwords usage}]"
+ if ! printf '%s\n' "$caps" | ${pkgs.gnugrep}/bin/grep -Fqx "${lettersKeyUsage usage}"
+ then
+ ${if primary.passPath != "" then "${pkgs.pass}/bin/pass '${primary.passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --quick-add-key "$fpr" "${algo}" "${unwords usage}" "${expire}"
+ fi
'';
generateBackupKey =
- fpr:
- { passPath
- , backupRecipients ? []
- , uid
- , ...
- }:
- lib.optionalString (backupRecipients != [])
- ''
- info " generateBackupKey backupRecipients=[${unwords (map (s: "\\\"${s}\\\"") backupRecipients)}]"
- mkdir -p "${gnupg.gnupgHome}/backup/${uid}/"
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc"
- then
- ${gpg-with-home}/bin/gpg-with-home \
- --batch \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc" \
- --export-options export-backup \
- --export "${fpr}"
- fi
- '' + (if backupRecipients == [""] then
- ''
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc" \
- --gen-revoke "${fpr}"
- fi
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec" \
- --export-options export-backup \
- --export-secret-key "${fpr}"
- fi
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec" \
- --export-options export-backup \
- --export-secret-subkeys "${fpr}"
- fi
- '' else ''
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --pinentry-mode loopback --passphrase-fd 0 \
- --armor --gen-revoke "${fpr}" |
- gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
- fi
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --export-options export-backup \
- --export-secret-key "${fpr}" |
- gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
- fi
- if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
- then
- ${pkgs.pass}/bin/pass "${passPath}" |
- ${gpg-with-home}/bin/gpg-with-home \
- --batch --pinentry-mode loopback --passphrase-fd 0 \
- --armor --export-options export-backup \
- --export-secret-subkeys "${fpr}" |
- gpg --encrypt ${recipients backupRecipients} \
- --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
- fi
+ fpr:
+ { passPath
+ , backupRecipients ? [ ]
+ , uid
+ , ...
+ }:
+ lib.optionalString (backupRecipients != [ ])
+ ''
+ info " generateBackupKey backupRecipients=[${unwords (map (s: "\\\"${s}\\\"") backupRecipients)}]"
+ mkdir -p "${gnupg.gnupgHome}/backup/${uid}/"
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc"
+ then
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.pubkey.asc" \
+ --export-options export-backup \
+ --export "${fpr}"
+ fi
+ '' + (if backupRecipients == [ "" ] then
+ ''
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc" &&
+ ${gpg-with-home}/bin/gpg-with-home --list-secret-keys "${fpr}" | grep -q "sec "
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc" \
+ --gen-revoke "${fpr}"
+ fi
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec"
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec" \
+ --export-options export-backup \
+ --export-secret-key "${fpr}"
+ fi
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec"
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec" \
+ --export-options export-backup \
+ --export-secret-subkeys "${fpr}"
+ fi
+ '' else ''
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --gen-revoke "${fpr}" |
+ gpg --encrypt ${recipients backupRecipients} \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.revoke.asc.gpg"
+ fi
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --export-options export-backup \
+ --export-secret-key "${fpr}" |
+ gpg --encrypt ${recipients backupRecipients} \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.privkey.sec.gpg"
+ fi
+ if ! test -s "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
+ then
+ ${if passPath != "" then "${pkgs.pass}/bin/pass '${passPath}'" else "cat /dev/null"} |
+ ${gpg-with-home}/bin/gpg-with-home \
+ --batch --pinentry-mode loopback --passphrase-fd 0 \
+ --armor --export-options export-backup \
+ --export-secret-subkeys "${fpr}" |
+ gpg --encrypt ${recipients backupRecipients} \
+ --armor --yes --output "${gnupg.gnupgHome}/backup/${uid}/${fpr}.subkeys.sec.gpg"
+ fi
'');
recipients = rs: unwords (map (r: ''--recipient "${refKey r}"'') rs);
refKey = key: if builtins.typeOf key == "string" then key else "=${key.uid}";
- signer = s: if s == null
- then ""
- else ''--sign --default-key "${refKey s}"'';
lettersKeyUsage = usage:
(if builtins.elem "encrypt" usage then "e" else "") +
- (if builtins.elem "sign" usage then "s" else "") +
- (if builtins.elem "cert" usage then "c" else "") +
- (if builtins.elem "auth" usage then "a" else "");
-
- passOfFingerprint = key:
- # Return shell code
- # which fills a map from the fingerprints of the given key
- # to its password file.
- ''
- # shell.gnupg.pass.passOfFingerprint
- for fpr in $(${gpg-fingerprint}/bin/gpg-fingerprint -- "=${key.uid}")
- do eval "pass_$fpr=\"${key.passPath}\""
- done
- '';
- forgetPass =
- # Return shell code
- # which installs an exit and keyboard interruption (^C) trap
- # removing any pass from gpg-agent
- # whose keygrip is registered in $keygrips.
- ''
- # forgetPass
- keygrips=
- forgetPass () {
- for keygrip in $keygrips
- do
- echo >&2 "gpg: forget: keygrip=$keygrip"
- GNUPGHOME=${gnupg.gnupgHome} \
- ${pkgs.gnupg}/bin/gpg-connect-agent </dev/null >&2 "CLEAR_PASSPHRASE $keygrip" ||
- true
- done
- keygrips=
- }
- trap 'forgetPass' EXIT INT
- '';
- presetPass = keys: uid:
- # Return shell code
- # which preset the pass of given uid into gpg-agent,
- # using keys to find where the pass is stored.
- ''
- ${unlines (map passOfFingerprint keys)}
- # presetPass
- GNUPGHOME=${gnupg.gnupgHome} \
- ${pkgs.gnupg}/bin/gpgconf --launch gpg-agent
- ${head1}
- fpr="$(${gpg-fingerprint}/bin/fingerprint -- "${uid}" | head1)"
- eval pass="\''${pass_$fpr}"
- if test -n "$pass"
- then
- for keygrip in $(${gnupg.gpg-keygrip}/bin/gpg-keygrip -- "$fpr")
- do
- keygrips="$keygrips $keygrip"
- echo >&2 "gpg: preset: keygrip=$keygrip pass=$pass"
- ${pkgs.pass}/bin/pass "$pass" |
- GNUPGHOME=${gnupg.gnupgHome} \
- ${pkgs.gnupg}/libexec/gpg-preset-passphrase --preset ''${XTRACE:+--verbose} $keygrip
- done
- fi
- '';
+ (if builtins.elem "sign" usage then "s" else "") +
+ (if builtins.elem "cert" usage then "c" else "") +
+ (if builtins.elem "auth" usage then "a" else "");
# Initialize the keyring according to gnupg.keys.
gpg-init = pkgs.writeShellScriptBin "gpg-init" (''
set -eu
set -o pipefail
${info}
- ${pkgs.coreutils}/bin/install -dm0700 -D ${gnupg.gnupgHome}
- ${pkgs.coreutils}/bin/ln -snf ${gnupg.gpgConf} ${gnupg.gnupgHome}/gpg.conf
- ${pkgs.coreutils}/bin/ln -snf ${gnupg.gpgAgentConf} ${gnupg.gnupgHome}/gpg-agent.conf
- ${pkgs.coreutils}/bin/ln -snf ${gnupg.dirmngrConf} ${gnupg.gnupgHome}/dirmngr.conf
- '' +
- generateKeys gnupg.keys
+ '' +
+ generateKeys gnupg.keys
);
# A wrapper around gpg to set GNUPGHOME.
gpg-with-home = pkgs.writeScriptBin "gpg-with-home" ''
GNUPGHOME=${gnupg.gnupgHome} \
exec ${pkgs.gnupg}/bin/gpg "$@"
- '';
+ '';
# A wrapper around gpg to get fingerprints.
gpg-fingerprint = pkgs.writeScriptBin "gpg-fingerprint" ''
set -eu
${gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode --with-fingerprint --with-subkey-fingerprint \
+ --with-colons --with-fingerprint --with-subkey-fingerprint \
--list-public-keys "$@" |
while IFS=: read -r t x x x key x x x x uid x
do case $t in
esac done
;;
esac done
- '';
+ '';
# A wrapper around gpg to get keygrips.
gpg-keygrip = pkgs.writeScriptBin "gpg-keygrip" ''
set -eu
${gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode --with-keygrip \
+ --with-colons --with-keygrip \
--list-public-keys "$@" |
- while IFS=: read -r t x x x key x x x x uid x
- do case $t in
- (pub|sub|sec|ssb)
- while IFS=: read -r t x x x x x x x x grp x
- do case $t in (grp) printf '%s\n' "$grp"; break;;
- esac done
- ;;
- esac done
- '';
+ while IFS=: read -r t x x x key x x x x uid x do case $t in (pub|sub|sec|ssb) while IFS=: read -r t x x x x x x x x grp x do case $t in (grp) printf '%s\n' "$grp"; break;; esac done ;; esac done
+ '';
# A wrapper around gpg to get uids.
gpg-uid = pkgs.writeScriptBin "gpg-uid" ''
set -eu
${gpg-with-home}/bin/gpg-with-home \
- --with-colons --fixed-list-mode \
+ --with-colons \
--list-public-keys "$@" |
while IFS=: read -r t st x x x x x id x uid x
do case $t in
'';
in
{
-options.gnupg = {
- enable = lib.mkEnableOption "GnuPG shell utilities";
- gnupgHome = lib.mkOption {
- type = types.path;
- default = "sec/gnupg";
- description = ''
+ options.gnupg = {
+ enable = lib.mkEnableOption "GnuPG shell utilities";
+ gnupgHome = lib.mkOption {
+ type = types.str;
+ default = "sec/gnupg";
+ description = ''
'';
- };
- keys = lib.mkOption {
- default = {};
- example =
- { "John Doe. <contact@example.coop>" = {
- algo = "rsa4096";
- expire = "1y";
- usage = ["cert" "sign"];
- passPath = "example.coop/gpg/contact";
- subKeys = [
- { algo = "rsa4096"; expire = "1y"; usage = ["sign"];}
- { algo = "rsa4096"; expire = "1y"; usage = ["encrypt"];}
- { algo = "rsa4096"; expire = "1y"; usage = ["auth"];}
+ };
+ keys = lib.mkOption {
+ default = { };
+ example =
+ {
+ "John Doe. <contact@example.coop>" = {
+ algo = "rsa4096";
+ expire = "1y";
+ usage = [ "cert" "sign" ];
+ passPath = "example.coop/gpg/contact";
+ subKeys = [
+ { algo = "rsa4096"; expire = "1y"; usage = [ "sign" ]; }
+ { algo = "rsa4096"; expire = "1y"; usage = [ "encrypt" ]; }
+ { algo = "rsa4096"; expire = "1y"; usage = [ "auth" ]; }
];
- backupRecipients = ["@john@doe.pro"];
+ backupRecipients = [ "@john@doe.pro" ];
+ };
};
- };
- type = types.attrsOf (types.submodule ({uid, ...}: {
- #config.uid = lib.mkDefault uid;
- options = {
- uid = lib.mkOption {
- type = types.str;
- example = "John Doe <john.doe@example.coop>";
- default = uid;
- description = ''
- User ID.
- '';
- };
- algo = lib.mkOption {
- type = types.enum [ "rsa4096" ];
- default = "future-default";
- example = "rsa4096";
- description = ''
- Cryptographic algorithm.
- '';
- };
- expire = lib.mkOption {
- type = types.str;
- default = "1y";
- example = "1y";
- description = ''
- Expiration timeout.
- '';
- };
- usage = lib.mkOption {
- type = with types; listOf (enum [ "cert" "sign" "encrypt" "auth" "default" ]);
- default = ["default"];
- example = ["cert" "sign" "encrypt" "auth"];
- description = ''
- Cryptographic usage.
- '';
- };
- passPath = lib.mkOption {
- type = types.str;
- example = "gnupg/coop/example/contact@";
- description = ''
- Password path.
- '';
- };
- subKeys = lib.mkOption {
- type = types.listOf (types.submodule {
- options = {
- algo = lib.mkOption {
- type = types.enum [ "rsa4096" ];
- default = "default";
- example = "rsa4096";
- description = ''
- Cryptographic algorithm.
- '';
- };
- expire = lib.mkOption {
- type = types.str;
- default = "1y";
- example = "1y";
- description = ''
- Expiration timeout.
- '';
- };
- usage = lib.mkOption {
- type = with types; listOf (enum [ "sign" "encrypt" "auth" "default" ]);
- default = ["default"];
- example = ["sign" "encrypt" "auth"];
- description = ''
- Cryptographic usage.
- '';
+ type = types.attrsOf (types.submodule ({ name, ... }: {
+ options = {
+ uid = lib.mkOption {
+ type = types.str;
+ example = "John Doe <john.doe@example.coop>";
+ default = name;
+ description = ''
+ User ID.
+ '';
+ };
+ algo = lib.mkOption {
+ type = types.enum [ "rsa4096" ];
+ default = "future-default";
+ example = "rsa4096";
+ description = ''
+ Cryptographic algorithm.
+ '';
+ };
+ expire = lib.mkOption {
+ type = types.str;
+ default = "0";
+ example = "1y";
+ description = ''
+ Expiration timeout.
+ '';
+ };
+ usage = lib.mkOption {
+ type = with types; listOf (enum [ "cert" "sign" "encrypt" "auth" "default" ]);
+ default = [ "default" ];
+ example = [ "cert" "sign" "encrypt" "auth" ];
+ description = ''
+ Cryptographic usage.
+ '';
+ };
+ passPath = lib.mkOption {
+ type = types.str;
+ example = "gnupg/coop/example/contact@";
+ description = ''
+ Password path.
+ '';
+ };
+ subKeys = lib.mkOption {
+ type = types.listOf (types.submodule {
+ options = {
+ algo = lib.mkOption {
+ type = types.enum [ "rsa4096" ];
+ default = "default";
+ example = "rsa4096";
+ description = ''
+ Cryptographic algorithm.
+ '';
+ };
+ expire = lib.mkOption {
+ type = types.str;
+ default = "0";
+ example = "1y";
+ description = ''
+ Expiration timeout.
+ '';
+ };
+ usage = lib.mkOption {
+ type = with types; listOf (enum [ "sign" "encrypt" "auth" "default" ]);
+ default = [ "default" ];
+ example = [ "sign" "encrypt" "auth" ];
+ description = ''
+ Cryptographic usage.
+ '';
+ };
};
- };
- });
+ });
+ };
+ backupRecipients = lib.mkOption {
+ type = with types; listOf str;
+ default = [ ];
+ example = [ "@john@doe.pro" ];
+ description = ''
+ Backup keys used to encrypt the a backup copy of the secret keys.
+ '';
+ };
+ postRun = lib.mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell code to run after the key has been generated or tested to exist.
+ '';
+ };
};
- backupRecipients = lib.mkOption {
- type = with types; listOf str;
- default = [];
- example = ["@john@doe.pro"];
- description = ''
- Backup keys used to encrypt the a backup copy of the secret keys.
+ }));
+ };
+ dirmngrConf = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "dirmngr.conf" s;
+ default = ''
+ allow-ocsp
+ hkp-cacert ${gnupg.keyserverPEM}
+ keyserver hkps://keys.mayfirst.org
+ #use-tor
+ #log-file ${gnupg.gnupgHome}/dirmngr.log
+ #standard-resolver
+ '';
+ description = ''
+ GnuPG's dirmngr.conf content.
+ '';
+ };
+ keyserverPEM = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "keyserver.pem" s;
+ default = builtins.readFile gnupg/keyserver.pem;
+ description = ''
+ dirmngr's hkp-cacert content.
+ '';
+ };
+ gpgAgentConf = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "gpg-agent.conf" (s + "\n" + gnupg.gpgAgentExtraConf);
+ default =
+ let
+ pinentry = pkgs.writeShellScript "pinentry" ''
+ #!${pkgs.runtimeShell}
+ # choose pinentry depending on PINENTRY_USER_DATA
+ # this *only works* with gpg2
+ # see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=802020
+ case "''${PINENTRY_USER_DATA:-curses}" in
+ curses) exec ${pkgs.pinentry.curses}/bin/pinentry-curses "$@";;
+ #emacs) exec ''${pkgs.pinentry.emacs}/bin/pinentry-emacs "$@";;
+ #gnome3) exec ''${pkgs.pinentry.gnome3}/bin/pinentry-gnome3 "$@";;
+ gtk-2) exec ''${pkgs.pinentry.gtk2}/bin/pinentry-gtk-2 "$@";;
+ none) exit 1;; # do not ask for passphrase
+ #qt) exec ''${pkgs.pinentry.qt}/bin/pinentry-qt "$@";;
+ tty) exec ${pkgs.pinentry.tty}/bin/pinentry-tty "$@";;
+ esac
'';
- };
- };
- }));
- };
- dirmngrConf = lib.mkOption {
- type = types.lines;
- apply = s: pkgs.writeText "dirmngr.conf" s;
- default = ''
- allow-ocsp
- hkp-cacert ${gnupg.keyserverPEM}
- keyserver hkps://keys.mayfirst.org
- use-tor
- #log-file ${gnupg.gnupgHome}/dirmngr.log
- #standard-resolver
- '';
- description = ''
- GnuPG's dirmngr.conf content.
- '';
+ in
+ ''
+ allow-loopback-pinentry
+ allow-preset-passphrase
+ default-cache-ttl 17200
+ default-cache-ttl-ssh 17200
+ enable-ssh-support
+ max-cache-ttl 17200
+ max-cache-ttl-ssh 17200
+ no-allow-external-cache
+ pinentry-program ${pinentry}
+ '';
+ description = ''
+ GnuPG's gpg-agent.conf content.
+ '';
+ };
+ gpgConf = lib.mkOption {
+ type = types.lines;
+ apply = s: pkgs.writeText "gpg.conf" (s + "\n" + gnupg.gpgExtraConf);
+ default = ''
+ auto-key-locate keyserver
+ cert-digest-algo SHA512
+ charset utf-8
+ default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 TWOFISH BZIP2 ZLIB ZIP Uncompressed
+ keyid-format 0xlong
+ keyserver-options no-honor-keyserver-url
+ no-auto-key-locate
+ no-default-keyring
+ no-emit-version
+ personal-cipher-preferences AES256 AES CAST5
+ personal-digest-preferences SHA512
+ quiet
+ s2k-cipher-algo AES256
+ s2k-count 65536
+ s2k-digest-algo SHA512
+ s2k-mode 3
+ tofu-default-policy unknown
+ trust-model tofu+pgp
+ use-agent
+ utf8-strings
+ '';
+ description = ''
+ GnuPG's gpg.conf content.
+ '';
+ };
+ gpgExtraConf = lib.mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ GnuPG's gpg.conf extra content.
+ '';
+ };
+ gpgAgentExtraConf = lib.mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ GnuPG's gpg-agent.conf extra content.
+ '';
+ };
};
- keyserverPEM = lib.mkOption {
- type = types.lines;
- apply = s: pkgs.writeText "keyserver.pem" s;
- default = builtins.readFile gnupg/keyserver.pem;
- description = ''
- dirmngr's hkp-cacert content.
+ config = lib.mkIf gnupg.enable {
+ nix-shell.buildInputs = [
+ gpg-with-home
+ gpg-fingerprint
+ gpg-keygrip
+ gpg-uid
+ gpg-init
+ ];
+ nix-shell.shellHook = ''
+ # gnupg
+ ${pkgs.coreutils}/bin/install -dm0700 -D ${gnupg.gnupgHome}
+ ${pkgs.coreutils}/bin/ln -snf ${gnupg.gpgConf} ${gnupg.gnupgHome}/gpg.conf
+ ${pkgs.coreutils}/bin/ln -snf ${gnupg.gpgAgentConf} ${gnupg.gnupgHome}/gpg-agent.conf
+ ${pkgs.coreutils}/bin/ln -snf ${gnupg.dirmngrConf} ${gnupg.gnupgHome}/dirmngr.conf
+ export GNUPGHOME=${gnupg.gnupgHome}
+ install -dm700 "$GNUPGHOME"
+ export GPG_TTY=$(${pkgs.coreutils}/bin/tty)
+ ${pkgs.gnupg}/bin/gpgconf --launch gpg-agent
+ export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
'';
};
- gpgAgentConf = lib.mkOption {
- type = types.lines;
- apply = s: pkgs.writeText "gpg-agent.conf" s;
- default = ''
- allow-preset-passphrase
- default-cache-ttl 17200
- default-cache-ttl-ssh 17200
- enable-ssh-support
- max-cache-ttl 17200
- max-cache-ttl-ssh 17200
- pinentry-program ${pkgs.pinentry}/bin/pinentry
- '';
- description = ''
- GnuPG's gpg-agent.conf content.
- '';
- };
- gpgConf = lib.mkOption {
- type = types.lines;
- apply = s: pkgs.writeText "gpg.conf" s;
- default = ''
- auto-key-locate keyserver
- cert-digest-algo SHA512
- charset utf-8
- default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 TWOFISH BZIP2 ZLIB ZIP Uncompressed
- fixed-list-mode
- keyid-format 0xlong
- keyserver-options no-honor-keyserver-url
- no-auto-key-locate
- no-default-keyring
- no-emit-version
- personal-cipher-preferences AES256 AES CAST5
- personal-digest-preferences SHA512
- quiet
- s2k-cipher-algo AES256
- s2k-count 65536
- s2k-digest-algo SHA512
- s2k-mode 3
- tofu-default-policy unknown
- trust-model tofu+pgp
- use-agent
- utf8-strings
- '';
- description = ''
- GnuPG's gpg.conf content.
- '';
- };
-};
-config = lib.mkIf gnupg.enable {
- nix-shell.buildInputs = [
- gpg-with-home
- gpg-fingerprint
- gpg-keygrip
- gpg-uid
- gpg-init
- ];
- nix-shell.shellHook = ''
- # gnupg
- export GNUPGHOME=${gnupg.gnupgHome}
- install -dm700 "$GNUPGHOME"
- export GPG_TTY=$(${pkgs.coreutils}/bin/tty)
- ${pkgs.gnupg}/bin/gpgconf --launch gpg-agent
- export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
- '';
-};
}