85.1.44. pepsi-keys

manage the end-to-end key store: identities, peer keys and anchors

Section du manuel:

1

85.1.44.1.1. Nom

pepsi-keys - générer, importer, publier et retirer du matériel de clé de bout en bout.

85.1.44.1.2. Synopsis

pepsi-keys [GLOBAL-OPTIONS] identity list [–address ADDRESS] [–json]

pepsi-keys [GLOBAL-OPTIONS] identity show IDENTITY-ID [–json]

pepsi-keys [GLOBAL-OPTIONS] identity generate ADDRESS –protocol PROTOCOL [–name NAME] [–days N] [–no-publish] [–csr] [–shared | –split]

pepsi-keys [GLOBAL-OPTIONS] identity import ADDRESS –protocol PROTOCOL –purpose PURPOSE –public FILE [–private FILE] [–algorithm NAME] [–primary] [–no-publish]

pepsi-keys [GLOBAL-OPTIONS] identity export IDENTITY-ID [–private] [–pem]

pepsi-keys [GLOBAL-OPTIONS] identity csr IDENTITY-ID

pepsi-keys [GLOBAL-OPTIONS] identity revoke IDENTITY-ID [–reason TEXT] [–upload]

pepsi-keys [GLOBAL-OPTIONS] identity forget-private IDENTITY-ID [-y]

pepsi-keys [GLOBAL-OPTIONS] identity set-primary IDENTITY-ID

pepsi-keys [GLOBAL-OPTIONS] identity publish [IDENTITY-ID] [–wkd] [–vks] [–retry [–dry-run]] [-y]

pepsi-keys [GLOBAL-OPTIONS] identity unpublish IDENTITY-ID

pepsi-keys [GLOBAL-OPTIONS] identity delete IDENTITY-ID [-y]

pepsi-keys [GLOBAL-OPTIONS] identity retire

pepsi-keys [GLOBAL-OPTIONS] peer list [–address ADDRESS] [–json]

pepsi-keys [GLOBAL-OPTIONS] peer show ADDRESS [–protocol PROTOCOL] [–json]

pepsi-keys [GLOBAL-OPTIONS] peer unclaimed [–address ADDRESS] [–all-sources] [–json]

pepsi-keys [GLOBAL-OPTIONS] peer import ADDRESS –protocol PROTOCOL –file FILE [–pin]

pepsi-keys [GLOBAL-OPTIONS] peer pin | unpin | remove PEER-KEY-ID

pepsi-keys [GLOBAL-OPTIONS] peer refresh [–address ADDRESS | –expire PEER-KEY-ID] [–expiring-within-days DAYS] [–limit N]

pepsi-keys [GLOBAL-OPTIONS] peer prune [–retain-days DAYS] [–dry-run]

pepsi-keys [GLOBAL-OPTIONS] ca list [–json]

pepsi-keys [GLOBAL-OPTIONS] ca add FILE [–label TEXT]

pepsi-keys [GLOBAL-OPTIONS] ca enable | disable | remove CA-ID

pepsi-keys [GLOBAL-OPTIONS] identity –otp CODE COMMAND …

pepsi-keys [GLOBAL-OPTIONS] otp status [ADDRESS] [–json]

pepsi-keys [GLOBAL-OPTIONS] otp enroll | remove ADDRESS [–otp CODE]

pepsi-keys [GLOBAL-OPTIONS] otp reset ADDRESS

pepsi-keys [GLOBAL-OPTIONS] wrap rotate [–dry-run]

pepsi-keys [GLOBAL-OPTIONS] dns ADDRESS

85.1.44.1.3. Description

pepsi-keys est l’outil de l’opérateur pour le magasin de clés de la cryptographie de bout en bout de Pepsi — les trois tables qui contiennent chaque clé dont le traitement OpenPGP et S/MIME a besoin :

pepsi.crypto_identity

Les paires de clés des adresses que nous servons, moitié privée comprise et enveloppée au repos (custody = local, une clé MTA). Utilisées pour signer le courrier sortant et déchiffrer le courrier entrant. Elle contient aussi les propres clés des utilisateurs, dont la moitié privée ne réside que dans leur client de messagerie (custody = client, une clé MUA ; voir Clés MTA et clés MUA).

pepsi.peer_key

Les clés publiques et certificats des correspondants distants, quelle qu’en soit la provenance, chacun accompagné de la source dont il vient, d’un verdict de validité et d’une échéance de cache. Sert à chiffrer le courrier sortant et à vérifier les signatures entrantes.

pepsi.ca_trust

Les certificats d’autorité qu’une chaîne S/MIME entrante doit atteindre pour que sa signature compte comme digne de confiance.

L’outil n’est pas une étape. Il gère directement des lignes, à la manière de pepsi-whitelist(1) et de pepsi-settings(1), se connectant à la même base de données que les autres composants par la section partagée [pepsi-postgres] et lisant les options CRYPTO_* de [pepsi] ainsi que la section [pepsi-crypto] décrite dans pepsi.conf(5).

C’est un binaire autonome plutôt qu’une partie de l’exécutable pepsi unifié pour deux raisons : c’est le seul programme de l’arbre qui génère du matériel de clé, et un site peut l’installer setuid (voir Privilèges).

85.1.44.1.3.1. Capacité, non forme

Le matériel d’une adresse est stocké à raison d’une ligne par capacité, jamais comme « l’identité ». Le purpose de chaque ligne vaut sign, encrypt ou both :

  • une identité OpenPGP est une unique ligne both — une clé transférable dont la clé primaire, capable de signer, porte une sous-clé de chiffrement : la séparation est donc intrinsèque et ne coûte rien ;

  • une identité S/MIME est normalement faite de deux lignes, un certificat avec digitalSignature et un avec keyEncipherment/keyAgreement ;

  • avec [pepsi] CRYPTO_SMIME_SHARED_KEY = yes, c’est à la place un seul certificat both portant les deux usages de clé (RSA seulement).

Cette option ne décide que de l’allure des identités nouvellement créées. Les deux formes sont prises en charge de façon permanente et peuvent coexister pour une même adresse — un ancien certificat partagé encore valide à côté d’une paire séparée fraîchement délivrée — de sorte que chaque consultation corresponde à une capacité (sign ou both ; encrypt ou both) plutôt que de compter des lignes. Les listages et identity show impriment le purpose exactement pour cette raison.

85.1.44.1.3.2. Le retrait est asymétrique

Pepsi remet du texte clair dans la boîte aux lettres : une clé privée de déchiffrement n’est donc nécessaire que pour le courrier encore en vol et pour le texte chiffré qu’un opérateur a archivé — jamais pour lire sa propre boîte. Une clé privée de signature, une fois retirée, ne peut plus rien faire de légitime : rien ne resigne jamais du vieux courrier. Donc, à l’expiration ou à la révocation :

  • la moitié privée d’une ligne sign est détruite, et seule la moitié publique est conservée pour que les anciennes signatures restent vérifiables ;

  • la moitié privée d’une ligne encrypt est conservée ;

  • une ligne both suit la règle du déchiffrement — la détruire ôterait la capacité de déchiffrer avec elle — ce qui est le prix du mode à certificat partagé : y révoquer une clé de signature compromise met aussi fin à la capacité de recevoir du nouveau courrier chiffré.

private_purged_at note quand du matériel a été abandonné, de sorte que « délibérément détruit » reste distinguable de « jamais détenu » ; identity list comme identity show le rapportent.

85.1.44.1.3.3. Clés MTA et clés MUA

Une adresse peut détenir des clés de deux sortes. Une clé MTA (custody = local) est une clé dont Pepsi détient la moitié privée : pepsi-stage-encrypt(1) signe avec elle, pepsi-stage-decrypt(1) ouvre le courrier avec elle, et elle est annoncée dans les en-têtes Autocrypt:. Elle est créée par identity generate, par une importation avec –private, ou automatiquement à la première soumission d’un utilisateur sous [stage-encrypt] ENABLE_PEP. Une clé MUA (custody = client) est la propre clé de l’utilisateur issue de son client de messagerie : publique seulement pour toujours, jamais principale. Pepsi chiffre vers elle et laisse passer sans l’ouvrir le courrier chiffré vers elle, mais ne peut jamais signer ni déchiffrer avec elle. Elle est créée par une importation sans –private, par la console web ou l’API, par la commande de courriel register, ou automatiquement à partir de l’en-tête Autocrypt: du courrier que l’utilisateur soumet lui-même.

La face publique d’une adresse – ce que sert le Web Key Directory, ce vers quoi est chiffré le courrier local destiné à l’utilisateur – est la plus récente clé MUA active lorsqu’il y en a une, sinon la clé MTA active principale. La clé MTA n’est pas retirée lorsqu’une clé MUA apparaît ; elle continue de déchiffrer le courrier des correspondants qui l’utilisent encore. identity show affiche la garde et si l’identité est la face publique.

85.1.44.1.3.4. Les téléversements vers le serveur de clés sont demandés par identité

Chaque identité enregistre si son téléversement vers le serveur de clés a été demandé (crypto_identity.vks_wanted). Les clés générées automatiquement et les clés MUA enregistrées automatiquement démarrent avec cet indicateur éteint : Autocrypt et le propre Web Key Directory du déploiement sont la façon dont on les trouve, et un téléversement ne peut pas être retiré. Les clés faites à la main (identity generate, identity import, et le generate web et par courriel) prennent [pepsi-keys] VKS_PUBLISH comme valeur par défaut, et –no-publish le garde éteint. Une demande explicite – identity publish –vks, Téléverser vers le serveur de clés de la console web, la commande de courriel publish – l’allume quoi que dise VKS_PUBLISH. identity publish –retry téléverse exactement les lignes où il est allumé, de sorte que « non téléversé » est un état enregistré, et identity show le rapporte.

85.1.44.1.3.5. Propriété

Une identité est indexée sur l”adresse mise en minuscules. Lorsque les règles de localité de pepsi-common ([pepsi-crypto] LOCAL_DOMAINS, RECIPIENT_DELIMITER et TARGETS, se rabattant sur [pepsi-ingress] ACCEPTED_DOMAINS et la plage d’uid d”/etc/login.defs) résolvent cette adresse vers un compte local, le login passwd est consigné dans crypto_identity.login ; sinon la colonne vaut NULL — une adresse de rôle, un domaine hébergé, un déploiement placé devant un Exchange.

Cette colonne est la règle d’accès. Un appelant non privilégié ne peut voir et modifier que les identités dont le login est le sien, résolu depuis l’entrée passwd de l’uid réel — non $USER, non un argument, non l’uid effectif. Une identité sans compte propriétaire n’appartient à personne en particulier et est donc réservée à l’opérateur : traiter « sans propriétaire » comme « à tout le monde » rendrait chaque adresse de rôle inscriptible par chaque utilisateur local.

root, ainsi que les comptes pepsi-crypto, pepsi et pepsi-owner, peuvent gérer toutes les identités. Les clés de pairs et les ancres de confiance n’ont pas d’espace de noms par utilisateur — ce sont la clé de quelqu’un d’autre, ou une politique valant pour tout le déploiement — de sorte que chaque sous-commande peer et ca, list compris, soit réservée à l’opérateur, tout comme wrap rotate et identity retire.

85.1.44.1.3.6. Privilèges

Atteindre une clé privée demande deux choses, et elles sont gardées séparément :

  • le rôle de base de données pepsi-crypto, le seul auquel la colonne crypto_identity.private_wrapped soit accordée (hormis le propriétaire du schéma pepsi-owner, qui la lit en vertu de la propriété mais ne peut pas lire la clé de chiffrement de clés). Tout rôle de service ordinaire — y compris le compte pepsi sous lequel s’exécute chaque worker d’étape ordinaire — détient un droit au niveau colonne qui l’omet, de sorte qu’une compromission ailleurs dans le pipeline livre la moitié publique de chaque identité et rien de plus (voir pepsi-setup(1)) ;

  • la clé de chiffrement de clés, qui ne vit que dans le système de fichiers, dans secrets.d/pepsi-crypto.secret.

La base de données seule ne livre donc que du texte chiffré, et la clé de chiffrement de clés seule ne livre rien du tout.

pepsi-keys n’endosse l’identité pepsi-crypto que pour la durée de chaque appel à la base de données. Exécuté en tant que root, il devient ce compte le temps de l’appel (root n’a pas de rôle de base de données à lui) puis revient ; exécuté en tant que pepsi-crypto ou pepsi-owner, il se connecte simplement sous sa propre identité ; lancé depuis une installation setuid, il élève ses identifiants effectifs vers le propriétaire du binaire. L’authentification par pair de PostgreSQL se fonde sur l”uid effectif, non sur le gid : un bit setgid accorderait donc le groupe qui garde le fragment de secret mais pas l’identité de base de données — un programme qui doit être ce rôle doit être ce compte.

Tel qu’il est livré, le binaire ne porte aucun bit setuid (mode 0755) : un binaire capable d’ouvrir chaque clé privée d’un déploiement est une prise bien plus grosse que l’unique table de pepsi-whitelist(1), la valeur par défaut est donc que seul l’opérateur l’exécute. Un site qui veut que les utilisateurs ordinaires gèrent leurs propres identités le rend setuid pepsi-crypto.

L’autorité en vigueur diffère entre les deux installations. La règle de propriété par identité ci-dessus ne s’applique que lorsque le binaire porte réellement le bit setuid : un appelant est traité comme privilégié lorsqu’il est root, lorsque son login est l’un des comptes privilégiés, ou lorsque le binaire n’est pas setuid du tout. Sur l’installation 0755 livrée, chaque appelant est donc privilégié du point de vue de ce programme, et seul PostgreSQL se dresse entre un utilisateur et les identités d’un autre — l’appelant s’authentifie sous sa propre identité et les droits de la base de données décident. C’est la conception voulue, mais cela signifie qu’accorder à quelqu’un le rôle de base de données pepsi-crypto lui remet chaque identité du déploiement, quoi qu’aurait dit par ailleurs la règle de propriété de ce programme. Lorsqu’il est setuid, les trois mêmes précautions que prend pepsi-whitelist(1) s’appliquent : les identifiants effectifs sont abaissés vers l’utilisateur appelant avant toute autre chose, les variables d’environnement qui orientent la découverte de la configuration (HOME, XDG_CONFIG_HOME), l’expansion de ${DATADIR} (PATH) et libpq (PG*) sont supprimées, et -c/–config est refusé aux appelants non privilégiés — la configuration nomme la base de données et la clé de chiffrement de clés.

85.1.44.1.4. Commandes

85.1.44.1.4.1. Commandes d’identité

identity list [–address ADDRESS] [–json]

Liste les identités sous forme de tableau : identifiant, adresse, protocole, finalité, statut, si la ligne est la principale pour sa capacité, si elle est publiée, l’état de sa moitié privée (yes/no/purged, ou client pour la propre clé MUA de l’utilisateur, dont Pepsi n’a jamais détenu la moitié privée) et son expiration. Un appelant non privilégié ne voit que les siennes. –address restreint le listage à une adresse ; –json émet les lignes en JSON à la place.

identity show IDENTITY-ID [–json]

Affiche une identité en entier, y compris son empreinte, son algorithme, sa garde (local pour une clé MTA, client pour la propre clé MUA de l’utilisateur), si elle est la face publique de l’adresse (la clé donnée aux correspondants), wrap_key_id, les horodatages, toute raison de révocation, le hachage de partie locale Web Key Directory sous lequel l’adresse est servie, et son état sur le serveur de clés : l’un de verified at TIME, uploaded at TIME , awaiting confirmation, upload requested ou not uploaded (not requested).

identity generate ADDRESS –protocol openpgp|smime [OPTIONS]

Crée du matériel de clé pour ADDRESS et le stocke, moitié privée enveloppée. Le nouveau matériel devient le principal pour sa capacité ; rien d’existant n’est réécrit ni remplacé, de sorte que le matériel précédent reste utilisable pour déchiffrer ce qui lui a déjà été envoyé.

OpenPGP produit un unique enregistrement both en employant [pepsi] CRYPTO_OPENPGP_ALGORITHM (ed25519, la valeur par défaut, ou rsa à CRYPTO_GENERATE_RSA_BITS, qui doit valoir 2048, 3072 ou 4096). S/MIME produit la paire signature/chiffrement en employant CRYPTO_SMIME_ALGORITHM (rsa, p256 ou p384), chacune avec un certificat auto-signé pour un usage immédiat.

–name NAME

Nom affiché pour l’identifiant utilisateur OpenPGP (Name <address>) ou le sujet du certificat. Sans lui, l’identifiant utilisateur est l’adresse nue.

–days N

Durée de vie du matériel généré. Vaut par défaut [pepsi-crypto] IDENTITY_VALIDITY_DAYS (730, soit deux ans).

–no-publish

Ne pas servir la moitié publique par le Web Key Directory ni la téléverser. Par défaut une nouvelle identité est publiée — on ne peut pas chiffrer vers une clé que personne ne peut récupérer — et son téléversement vers le serveur de clés est demandé lorsque [pepsi-keys] VKS_PUBLISH est activé.

La génération sur demande est toujours permise, même pour une adresse qui a déjà la propre clé MUA de l’utilisateur ou une clé révoquée ; seule la création automatique refuse une adresse ayant une identité quelconque.

–csr

Imprime en outre une demande de signature de certificat PKCS#10 portant sur chaque clé générée, de sorte qu’une véritable autorité puisse délivrer un certificat de remplacement pour la même clé sans en changer. S/MIME seulement ; OpenPGP n’a pas d’objet équivalent.

–shared

Force un seul certificat S/MIME portant les deux usages de clé, quoi que dise CRYPTO_SMIME_SHARED_KEY. Refusé avec un CRYPTO_SMIME_ALGORITHM à courbes elliptiques : une seule clé EC faisant à la fois ECDSA et ECDH est une réutilisation de clé entre algorithmes que plusieurs clients S/MIME rejettent.

–split

Force les certificats de signature et de chiffrement séparés. Mutuellement exclusif avec –shared ; sans l’un ni l’autre, la valeur par défaut configurée s’applique.

identity import ADDRESS –protocol P –purpose PURPOSE –public FILE [OPTIONS]

Stocke du matériel généré ailleurs. PURPOSE vaut sign, encrypt ou both et doit décrire ce que le matériel sait réellement faire — c’est là-dessus que porte chaque consultation ultérieure. La moitié publique est une clé transférable OpenPGP ou un certificat X.509 (DER ou PEM, détecté) ; - lit l’entrée standard. L’empreinte est dérivée du matériel lui-même : l’empreinte OpenPGP, ou le SHA-256 du DER du certificat.

–private FILE

La moitié privée — une clé secrète transférable OpenPGP, ou une clé PKCS#8 — qui est enveloppée avant d’être stockée, comme clé MTA (custody = local). Sans elle, seule la moitié publique est conservée. Pour OpenPGP, la ligne est alors enregistrée comme la propre clé MUA de l’utilisateur (custody = client), qui n’est jamais principale (–primary est ignoré pour elle) : Pepsi peut la publier et chiffrer vers elle, mais jamais signer ni déchiffrer avec elle. Elle préempte la création automatique de clé pour l’adresse et devient la face publique de l’adresse ; le courrier chiffré vers elle est transmis au client de messagerie sans être ouvert. Une importation S/MIME publique seulement conserve custody = local – typiquement un certificat émis par une AC sur une clé déjà présente dans le magasin (voir identity csr).

–algorithm NAME

Nom d’algorithme à noter. À titre indicatif ; vaut imported par défaut.

–primary

Fait de ceci le matériel employé pour les nouveaux messages de sa capacité.

–no-publish

Ne pas publier la moitié publique. Sinon, le téléversement vers le serveur de clés est demandé lorsque [pepsi-keys] VKS_PUBLISH est activé.

identity export IDENTITY-ID [–private] [–pem]

Écrit le matériel sur la sortie standard dans sa forme binaire propre — paquets OpenPGP ou DER X.509 — de sorte qu’il puisse être acheminé directement vers un autre outil.

–private

Exporte la moitié privée plutôt que la publique, en la désenveloppant d’abord. Échoue lorsque la ligne n’en détient aucune, en nommant lequel de « jamais détenue » et « purgée » s’applique.

–pem

Enveloppe le matériel X.509 dans un bloc PEM. Le matériel OpenPGP n’a pas de forme PEM et est refusé avec un renvoi vers gpg --enarmor.

identity csr IDENTITY-ID

Imprime une demande de signature de certificat PKCS#10 portant sur la clé privée existante d’une identité, avec l’usage de clé qu’implique son purpose. C’est le chemin qui compte une fois qu’une identité est en service : le certificat auto-signé permet de démarrer, et la même clé — déjà publiée, déjà employée pour recevoir du courrier chiffré — est ensuite présentée à une véritable autorité sans en changer. Identités S/MIME seulement, et seulement tant que la moitié privée est encore détenue.

identity revoke IDENTITY-ID [–reason TEXT] [–upload]

Retire une identité. La ligne devient revoked et cesse d’être principale ; la moitié publique est conservée pour que les signatures faites avant la révocation restent vérifiables. La moitié privée d’une ligne sign est détruite ici et maintenant ; une ligne encrypt ou both conserve la sienne, et la commande le dit. TEXT est noté avec la ligne.

–upload construit en outre un certificat de révocation — signé par la clé qu’il retire, avec TEXT comme motif — et le publie auprès du serveur de clés configuré. C’est le seul remède pour une clé déjà téléversée : on peut dire à un serveur de clés qu’une clé est révoquée, jamais lui dire de l’oublier.

Le téléversement a lieu avant la révocation locale, parce que révoquer une identité sign détruit la clé privée avec laquelle le certificat de révocation est signé. Si le téléversement échoue, rien n’est révoqué : le problème de serveur de clés peut donc être corrigé et la commande relancée. Révoquer sans –upload puis vouloir une révocation publiée n’est pas rattrapable.

identity forget-private IDENTITY-ID [-y, –yes]

Détruit définitivement la clé privée d’une identité, en laissant la moitié publique. C’est le seul moyen par lequel une clé de déchiffrement quitte le magasin, et il est irréversible : tout ce qui est encore en file d’attente dans pepsi.workqueue, tout ce qui se trouve dans une archive chiffrée et tout message remis à nouveau plus tard depuis une sauvegarde devient illisible. Le courrier déjà remis n’est pas affecté. La commande imprime exactement cela et demande confirmation ; –yes saute la question, et sans terminal ni –yes la réponse est non, de sorte qu’une exécution sans surveillance ne puisse détruire du matériel de clé parce que personne n’était là pour s’y opposer.

identity set-primary IDENTITY-ID

Fait de ceci le matériel employé pour les nouveaux messages de son triplet (adresse, protocole, finalité). Seule une identité active peut être rendue principale. La précédente principale du même triplet est rétrogradée.

identity publish IDENTITY-ID [–wkd] [–vks] [-y, –yes]

Sert la moitié publique de l’identité par le Web Key Directory. C’est le canal réversible — notre propre serveur, notre propre domaine — et c’est celui que nomme –wkd ; c’est aussi le canal par défaut, l’indicateur n’existe donc que pour rendre le canal explicite. Le matériel reste utilisable dans les deux cas.

–vks enregistre en outre la demande de téléversement (vks_wanted), téléverse la clé vers le serveur de clés configuré et lui demande d’envoyer le lien de confirmation à l’adresse. Comme la demande est enregistrée avant la tentative, un téléversement échoué est réessayé par identity publish –retry plutôt qu’oublié. C’est irréversible : on pourra plus tard dire au serveur de clés que la clé est révoquée, mais jamais lui dire de l’oublier, et l’adresse devient un enregistrement public permanent. La commande imprime exactement ce qui ne peut être repris et demande confirmation ; –yes saute la question, et sans terminal ni –yes la réponse est non. OpenPGP seulement — il n’existe pas de serveur de clés pour S/MIME, dont le canal de publication est l’enregistrement SMIMEA qu’imprime dns.

identity publish –retry [–dry-run]

Traite chaque identité OpenPGP publiée et active dont le téléversement a été demandé (vks_wanted) et qui n’est pas encore vérifiée sur le serveur de clés, plutôt qu’une seule. C’est la forme à exécuter depuis cron (toutes les heures suffit largement). Elle n’est pas conditionnée par [pepsi-keys] VKS_PUBLISH : cette option décide seulement si les clés faites à la main démarrent avec une demande, et la propre demande d’un utilisateur est honorée quoi qu’elle dise. Une clé créée automatiquement n’est jamais sur la liste à moins que son propriétaire ne l’ait demandé.

Elle existe parce que la publication est un protocole en deux temps : un téléversement rend un jeton, seul le jeton autorise le courrier de confirmation, et seul un lien suivi amène le serveur à servir la clé par adresse. Une clé téléversée mais jamais confirmée est stockée et pourtant introuvable. Chaque tour demande d’abord au serveur de clés si l’adresse est déjà servie — de sorte qu’une confirmation faite par pepsi-stage-vks-confirm(1), par un humain, ou lors d’une exécution antérieure dont l’écriture en base de données n’a pas abouti, mette fin à la boucle — et sinon téléverse et demande la vérification. Les identités sont espacées de VKS_RETRY_INTERVAL, au plus VKS_BATCH par exécution, et abandonnées après VKS_MAX_ATTEMPTS, le motif restant sur la ligne pour identity show. –dry-run liste ce qui serait publié et ne change rien. Réservé à l’opérateur.

identity unpublish IDENTITY-ID

Cesse de servir l’identité par le Web Key Directory, et oublie sa comptabilité de serveur de clés afin que la tâche de reprise la laisse tranquille et qu’une republication ultérieure reparte de zéro.

Cela ne retire rien d’un serveur de clés, car rien ne le peut. Lorsque l’identité avait été téléversée, la commande le dit et renvoie vers identity revoke –upload, qui est le seul moyen de dire au monde que la clé est morte.

identity delete IDENTITY-ID [-y, –yes]

Supprime la ligne purement et simplement, moitié publique comprise. Confirmé comme forget-private. Préférez revoke, qui garde la moitié publique afin que les anciennes signatures restent vérifiables ; une identité supprimée ne laisse absolument rien derrière elle.

identity retire

Exécute le balayage de retrait sur chaque identité : tout ce qui a dépassé son expires_at devient expired, le matériel privé de signature est détruit et horodaté, et le matériel de déchiffrement (y compris celui d’une ligne both partagée) est laissé intact. Prévu pour une minuterie périodique autant que pour la ligne de commande ; identity revoke applique la même règle en ligne pour une identité. Réservé à l’opérateur.

85.1.44.1.4.2. Commandes de pairs

peer list [–address ADDRESS] [–json]

Liste les clés de pairs en cache : identifiant, adresse, protocole, source, validité, si la consultation qui l’a produite était validée par DNSSEC, si elle est épinglée, et l’empreinte.

peer show ADDRESS [–protocol PROTOCOL] [–json]

Montre les clés qui seraient réellement employées pour ADDRESS, après application de la règle de correspondance : une correspondance exacte d’adresse l’emporte toujours, et une ligne *@domain n’est consultée qu’en l’absence de correspondance exacte (elle est signalée dans la sortie comme repli valant pour tout le domaine). PROTOCOL vaut openpgp par défaut.

peer unclaimed [–address ADDRESS] [–all-sources] [–json]

Liste les adresses que ce déploiement sert qui ne détiennent aucune identité chez nous, mais ont une clé de pair moissonnée ou reçue par gossip — les clés qu’un inconnu peut implanter en nous envoyant un message avec un From: falsifié. Les clés sont moissonnées sur l’en-tête From:, que l’expéditeur écrit, et l’authentification entrante est fail-open : sur un déploiement qui n’impose pas DMARC sur son propre domaine, une telle ligne peut donc désigner l’un de nos propres utilisateurs. Là où nous détenons une identité, la ligne est inerte (notre propre clé la préempte) ; là où nous n’en détenons pas, elle décide avec quoi le courrier destiné à cet utilisateur est chiffré. C’est délibéré — c’est aussi le seul moyen pour qu’un utilisateur qui utilise GnuPG dans son propre client voie sa vraie clé utilisée ici — de sorte qu’il s’agit d’une liste de travail, non d’une alarme : confirmez chaque clé avec son propriétaire, puis importez-la comme identité (identity import sans –private), après quoi elle est inerte, ou retirez-la (peer remove).

Servie signifie que le domaine figure dans [pepsi-ingress] ACCEPTED_DOMAINS ou [pepsi-crypto] LOCAL_DOMAINS ; aucun compte passwd n’est requis. Aucune identité signifie aucune identité active capable de chiffrer, la même règle qu’applique la préemption de l’étape de chiffrement, de sorte qu’une adresse dont la seule identité a expiré, a été révoquée ou ne peut que signer est listée ; la colonne IDS compte ses identités dans tout état. Moissonnée désigne la source inbound (l’en-tête Autocrypt: propre de l’expéditeur ou sa clé jointe) ou gossip (l”Autocrypt-Gossip: d’un tiers) ; –all-sources inclut aussi les clés découvertes, manuelles et d’API, soit l’ensemble que rapporte GET /api/v1/peers/unclaimed. Une ligne *@domain n’est jamais listée. Lecture seule et réservé à l’opérateur. Le code de sortie est 0 que quelque chose ait été trouvé ou non ; avec –json, un rapport vide est [], ce que doit tester une vérification périodique.

peer import ADDRESS –protocol P –file FILE [–pin]

Stocke la clé d’un correspondant à la main (- lit l’entrée standard). La ligne est notée avec la source manual, qui surclasse tout mécanisme de découverte, et c’est la seule source autorisée à porter une adresse *@domain — une contrainte de base de données, non une convention, de sorte qu’aucune réponse de découverte pour une adresse ne puisse jamais être généralisée à un domaine entier.

Une clé qui entre en conflit avec une clé déjà stockée ne la remplace que si elle surclasse tout ce qui s’y trouve ; une ligne épinglée n’est jamais délogée, et la commande dit lequel de stocké, rafraîchi, remplacé et conservé s’est produit. (L’unique exception au « seulement si elle surclasse » est la règle du plus récent l’emporte du palier Autocrypt, qui n’implique jamais de clé manual, dans un sens comme dans l’autre — voir pepsi-keydisc(1).)

–pin

Épingle la clé importée, de sorte que la découverte ne la remplace jamais.

peer pin PEER-KEY-ID, peer unpin PEER-KEY-ID

Pose ou retire l’épinglage sur une clé stockée.

peer refresh [–address ADDRESS] [–expire PEER-KEY-ID] [–expiring-within-days DAYS] [–limit N]

Revalide les clés de pairs en cache. Elle ne rafraîchit jamais que des clés qui existent déjà : elle ne découvre jamais de clé pour une adresse qui n’en a aucune. Pepsi consulte une adresse lorsqu’il a du courrier pour elle, ce qui explique que la découverte soit pilotée par le pipeline (pepsi-keydisc(1)) plutôt que par cette commande.

Trois formes, choisies par les indicateurs :

–address ADDRESS

Exécute tout l’éventail de découverte pour une adresse dans ce processus — chaque méthode de [pepsi-keydiscovery] SOURCES en même temps, avec la règle d’arrêt à délai de grâce sur le rang — et stocke ce qu’elle trouve avec la bonne source et le bon indicateur DNSSEC. Une ligne par méthode est imprimée : le protocole et l’empreinte (marquée (dnssec) pour une réponse DANE validée par le bit AD), no key, ou l’erreur. Cela règle aussi la demande de découverte de l’adresse, ce qui libère tout message garé sur elle. Une adresse exclue par ALLOW_DOMAINS/DENY_DOMAINS est refusée plutôt qu’interrogée.

–expire PEER-KEY-ID

Efface l’échéance de cache d’une ligne, de sorte que le prochain message pour cette adresse la récupère à nouveau. Aucune entrée-sortie réseau, et mutuellement exclusif avec –address.

(aucun des deux indicateurs)

Balayage : chaque clé arrivée à échéance — son refresh_after est dépassé, ou sa propre expiration tombe dans –expiring-within-days (7 par défaut) — passe par le même éventail, jusqu’à –limit clés (100 par défaut). Les clés épinglées et saisies à la main (manual/api) sont sautées, de même que les lignes *@domain : un opérateur les a mises là et aucune réponse de découverte ne surclasse cela, aller les chercher serait donc un coût pur. Le nombre de clés revalidées est imprimé. C’est le corps naturel d’une minuterie périodique.

peer prune [–retain-days DAYS] [–dry-run]

Supprime les clés de pairs expirées et les demandes de découverte périmées — deux tables, un seul travail. Une clé de pair expirée depuis plus de DAYS (7 par défaut) est retirée sauf si elle est épinglée. L’expiration est celle que la clé indique elle-même — l’auto-signature courante d’une clé primaire OpenPGP, le notAfter d’un X.509 — enregistrée chaque fois qu’une clé est apprise, que ce soit par découverte, par moisson ou par gossip (une clé importée à la main n’en enregistre aucune, et une clé qui n’en indique aucune n’est jamais élaguée) ; du côté de pepsi.key_request, une ligne réglée dont l’entrée négative a vieilli au-delà de la même fenêtre, comme une ligne en attente abandonnée depuis aussi longtemps au-delà de son échéance, n’ont plus rien à dire et partent aussi. –dry-run rapporte combien de clés portent une expiration et ne sont pas épinglées, et ne retire rien.

peer remove PEER-KEY-ID

Supprime une clé stockée. C’est aussi ainsi qu’un opérateur laisse passer la clé Autocrypt plus récente d’un correspondant que ACCEPT_ROTATION = expired a retenue (une ligne d’audit key.peer.rotate.held ; voir pepsi-stage-autocrypt-learn(1)) : l’ancienne ligne disparue, le prochain message portant la nouvelle clé la stocke comme une première clé.

85.1.44.1.4.3. Commandes d’ancres de confiance

ca list [–json]

Liste les ancres de confiance avec leur identifiant, si elles sont activées, leur étiquette et leur sujet.

ca add FILE [–label TEXT]

Ajoute un certificat d’autorité (DER ou PEM ; - lit l’entrée standard) comme ancre de confiance. Un certificat sans basicConstraints CA:TRUE est refusé : aucune chaîne ne pourrait jamais s’y terminer. Idempotent sur le SHA-256 du certificat — ajouter deux fois la même ancre ne fait que mettre à jour l’étiquette.

Une ancre est acceptée ici sur ses seules basicConstraints, mais la construction du chemin applique ses contraintes comme celles de toute autre AC (RFC 5937) : une ancre contrainte en noms ne se porte garante que des noms situés dans ses nameConstraints, une AC qui a déclaré pathlen:0 ne verra aucune sous-AC acceptée sous elle, et une requireExplicitPolicy ou une inhibitAnyPolicy qu’elle porte est respectée. Une chaîne qui en enfreint une échoue avec policy-rejected. Il en va de même d’une chaîne passant par une AC portant une extension critique que Pepsi ne sait pas du tout traiter (RFC 5280 §4.2) — une telle AC n’est jamais utilisée comme émetteur.

ca enable CA-ID, ca disable CA-ID

Remet une ancre au vérificateur, ou cesse de le faire tout en conservant la ligne pour mémoire.

ca remove CA-ID

Supprime une ancre.

Pepsi ne livre délibérément aucun jeu d’ancres par défaut. Une signature qui remonte jusqu’à une autorité que personne n’a choisie est rapportée comme non digne de confiance plutôt que mauvaise : un magasin vide se dégrade donc en « nous ne pouvons pas nous en porter garants » — et un opérateur qui ajoute une ancre prend une décision au lieu d’en hériter une.

85.1.44.1.4.4. Commandes de second facteur

Une adresse peut avoir un second facteur : un secret TOTP (RFC 6238, SHA-1, six chiffres, pas de 30 secondes) que son propriétaire conserve dans une application d’authentification. Dès qu’il existe, un appelant non privilégié (installation setuid) doit présenter un code en cours de validité pour chaque modification des identités de cette adresse – identity generate, import, revoke, forget-private, set-primary, publish, unpublish, delete – ainsi que pour identity export --private et identity csr, sous la forme de l’option –otp CODE du groupe identity (pepsi-keys identity --otp 123456 revoke 7). La propriété est vérifiée avant le code, de sorte qu’un utilisateur ne puisse pas accumuler des échecs contre l’enrôlement d’un autre. L’opérateur (root, pepsi-crypto, une installation non setuid) n’est jamais sollicité. Le même second facteur protège les commandes de clé par e-mail et la console web ; voir pepsi-stage-encrypt(1) et le chapitre du manuel consacré à la gestion des clés.

Un code n’est accepté qu’une fois (un rejeu dans ses propres 30 secondes est refusé), un pas de décalage d’horloge dans un sens ou dans l’autre est toléré, un code faux ou rejoué compte comme un échec et un code correct remet le compteur à zéro, et dix échecs consécutifs verrouillent le second facteur jusqu’à ce que l’opérateur le réinitialise.

otp status [ADDRESS] [–json]

Affiche l’enrôlement d’une adresse : quand elle a été enrôlée et utilisée pour la dernière fois, et les échecs consécutifs (ou LOCKED). L’opérateur peut omettre ADDRESS pour lister tous les enrôlements. N’affiche jamais de secret.

otp enroll ADDRESS [–otp CODE]

Crée un nouveau secret pour ADDRESS et l’imprime une seule fois, en base32 et sous forme d’URI otpauth:// (qrencode -t ansiutf8 en fait un code QR à scanner). Remplace un enrôlement existant, en repartant de zéro échec ; le propriétaire a besoin pour cela d’un code en cours de validité de l’ancien, l’opérateur non – c’est ainsi que l’opérateur remet un nouveau secret à un utilisateur verrouillé.

otp remove ADDRESS [–otp CODE]

Supprime le second facteur ; le propriétaire a besoin d’un code en cours de validité.

otp reset ADDRESS

Réservé à l’opérateur : supprime le second facteur quel que soit son état, ce qui déverrouille l’adresse. Son propriétaire s’enrôle de nouveau (par e-mail, ou avec otp enroll).

Le secret est stocké enveloppé sous la clé de chiffrement de clés, comme une clé privée, dans une table que seul le rôle pepsi-crypto peut lire ; wrap rotate le réenveloppe aussi.

85.1.44.1.4.5. Commandes de la clé de chiffrement de clés

wrap rotate [–dry-run]

Réenveloppe chaque clé privée stockée, et chaque secret de second facteur, sous le [pepsi-crypto] KEY_WRAP_KEY_ID courant. La rotation est incrémentale par construction, car chaque ligne note la clé qui l’a scellée : configurez le nouveau secret comme KEY_WRAP_SECRET et gardez l’ancien à côté sous KEY_WRAP_SECRET_<OLD-ID>, faites pointer KEY_WRAP_KEY_ID vers le nouvel identifiant, et lancez ceci. Entre le changement de configuration et le balayage, le déploiement continue de fonctionner — le nouveau matériel est scellé sous la nouvelle clé, l’ancien s’ouvre toujours sous celle qui a été retirée — et ce n’est qu’ensuite que le secret retiré peut être supprimé.

Les lignes dont la clé de chiffrement de clés n’a aucun secret configuré sont signalées et laissées intactes plutôt que de faire échouer l’exécution ; de même pour les lignes réenveloppées en parallèle (chaque mise à jour est gardée sur l’ancien identifiant de clé, de sorte qu’un enveloppement plus récent ne soit jamais écrasé).

–dry-run

Liste ce qui serait réenveloppé, et ne change rien.

85.1.44.1.4.6. Publication DNS

dns ADDRESS

Imprime, au format de fichier de zone, les enregistrements DNS qui publient chaque identité publiée et active d”ADDRESS : un enregistrement OPENPGPKEY (RFC 7929) pour le matériel OpenPGP et un enregistrement SMIMEA (RFC 8162, sous la forme TLSA 3 0 0 — certificat délivré par le domaine, certificat complet, correspondance exacte) pour S/MIME. Les deux sont publiés sous un nom de propriétaire haché, l’hexadécimal des 28 premiers octets du SHA-256 du local-part, afin que la zone n’énumère pas les adresses qu’elle sert.

Ne publiez ceux-ci que dans une zone signée par DNSSEC, ce que la sortie répète en commentaire : un enregistrement de clé non signé est une clé fournie par quiconque peut répondre pour la zone, ce qui n’améliore en rien le fait de n’avoir aucune clé.

Le hachage du nom de propriétaire DNS distingue la casse (RFC 7929 §3), contrairement au hachage Web Key Directory du même local-part, qui met en minuscules. Les deux sont calculés par des fonctions différentes, à dessein.

pepsi-setup(1) imprime les mêmes enregistrements pour chaque identité publiée dans le cadre de sa sortie DNS, plafonnés à un nombre lisible ; cette commande est la façon d’obtenir une adresse précise dans un grand déploiement.

85.1.44.1.5. Configuration du serveur de clés

La publication par le Web Key Directory n’a besoin d’aucune configuration : elle suit l’indicateur published de chaque identité et est servie par pepsi-httpd(1). La publication par serveur de clés, elle, en a besoin, parce qu’elle ne peut pas être défaite, et ses options vivent dans [pepsi-keys] :

VKS_PUBLISH (no par défaut)

Indique si les identités créées ou importées à la main démarrent avec leur téléversement vers le serveur de clés demandé, de sorte que identity publish –retry les téléverse et continue de réessayer jusqu’à ce que l’adresse soit vérifiée. Un téléversement peut être révoqué mais jamais retiré, la valeur par défaut reste donc une décision de l’opérateur. Elle ne conditionne pas la tâche de réessai, et ne s’applique jamais aux clés créées ou enregistrées automatiquement ; voir Les téléversements vers le serveur de clés sont demandés par identité. Lorsqu’elle est désactivée, identity publish –vks (ou la propre demande d’un utilisateur via la console web ou par courriel) reste disponible.

VKS_SERVER (par défaut : la première entrée de [pepsi-keydiscovery] VKS_SERVERS)

Où vont les téléversements ; https:// uniquement. Un serveur, non une liste : publier la même clé auprès de plusieurs multiplie un acte irréversible, et chacun doit ensuite être tenu à jour des révocations.

VKS_MAX_ATTEMPTS (5 par défaut), VKS_RETRY_INTERVAL (6 h par défaut), VKS_BATCH (50 par défaut)

Avec quelle insistance, à quelle fréquence et combien à la fois identity publish –retry essaie. Notez que les durées refusent les unités calendaires : 6 h s’analyse, 1 d non.

85.1.44.1.6. Options globales

Ces options globales précèdent la sous-commande (un indicateur placé à la fin est rejeté).

-c FILE, –config FILE

Lit la configuration depuis FILE au lieu de parcourir les emplacements par défaut. Refusé aux appelants non privilégiés lorsque ce programme est installé setuid : la configuration nomme la connexion à la base de données, chaque chemin développé par ${…}, et la clé de chiffrement de clés elle-même.

-L LOGLEVEL, –log LOGLEVEL

Règle la verbosité de journalisation. LOGLEVEL est l’un de error, warn, info, debug ou trace (par défaut : info).

-v, –verbose

Affiche les messages de journal de toutes les sources, y compris les bibliothèques tierces.

-h, –help

Affiche un résumé d’utilisation et quitte.

-V, –version

Affiche la version et quitte.

85.1.44.1.7. Code de sortie

0

Achèvement réussi. Une commande destructrice déclinée à son invite de confirmation sort également en 0, sans avoir rien changé.

1

Une erreur s’est produite : un fichier de configuration malformé, une combinaison d’options inadmissible, une adresse qui se résout vers le compte d’un autre utilisateur, du matériel de clé impossible à analyser, une clé de chiffrement de clés manquante ou qui n’ouvre pas une ligne, ou une connexion ou requête de base de données en échec. La raison est écrite dans le journal.

85.1.44.1.8. Fichiers

Lorsque –config n’est pas fourni, le premier fichier existant de la liste suivante est utilisé :

  • $XDG_CONFIG_HOME/pepsi.conf

  • $HOME/.config/pepsi.conf

  • /etc/pepsi/pepsi.conf

  • /etc/pepsi.conf

secrets.d/pepsi-crypto.secret

La clé de chiffrement de clés, à côté du fichier de configuration et tirée dans la section [pepsi-crypto] par une directive @inline-secret@. Elle est tenue hors de la configuration lisible par tous parce que c’est l’unique secret qui ouvre chaque clé privée stockée ; pepsi-setup(1) lui donne le mode 0640 et la remet au compte pepsi-crypto à chaque exécution. Sauvegardez-la séparément — voir le chapitre Gestion des clés du manuel pour ce que coûte sa perte.

Aucun autre fichier n’est lu ni écrit : tout le matériel de clé vit dans la base de données.

85.1.44.1.9. Exemples

Trouver les adresses servies dont le chiffrement est décidé par une clé fournie par quelqu’un d’autre, et faire d’une clé confirmée la clé propre de l’utilisateur (une clé de MUA : pas de –private)

pepsi-keys -c /etc/pepsi/pepsi.conf peer unclaimed
pepsi-keys -c /etc/pepsi/pepsi.conf peer show bob@example.org
gpg --export bob@example.org > bob.pgp    # the key bob confirmed to you
pepsi-keys -c /etc/pepsi/pepsi.conf identity import bob@example.org \
    --protocol openpgp --purpose both --public bob.pgp

Générer une identité OpenPGP et vérifier que GnuPG accepte la moitié publique

pepsi-keys -c /etc/pepsi/pepsi.conf identity generate alice@example.org \
    --protocol openpgp --name 'Alice Example'
pepsi-keys -c /etc/pepsi/pepsi.conf identity list --address alice@example.org
pepsi-keys -c /etc/pepsi/pepsi.conf identity export 1 | gpg --import

Générer la paire S/MIME, en imprimant une demande de certificat sur chaque clé pour une véritable autorité

pepsi-keys -c /etc/pepsi/pepsi.conf identity generate alice@example.org \
    --protocol smime --csr

Installer le certificat délivré par cette autorité, portant sur la clé déjà présente dans le magasin

pepsi-keys -c /etc/pepsi/pepsi.conf identity import alice@example.org \
    --protocol smime --purpose sign --public /tmp/alice-sign.pem --primary

Publier l’adresse dans le DNS (zone signée uniquement)

pepsi-keys -c /etc/pepsi/pepsi.conf dns alice@example.org >> example.org.zone

Retirer une clé de signature compromise, puis confirmer que la moitié privée a disparu

pepsi-keys -c /etc/pepsi/pepsi.conf identity revoke 1 --reason 'laptop stolen'
pepsi-keys -c /etc/pepsi/pepsi.conf identity show 1

Faire confiance à la main à la clé d’un correspondant et l’épingler contre une découverte ultérieure

pepsi-keys -c /etc/pepsi/pepsi.conf peer import bob@example.com \
    --protocol openpgp --file bob.pgp --pin

Consulter un correspondant avec chaque méthode activée et stocker le résultat

pepsi-keys -c /etc/pepsi/pepsi.conf peer refresh --address bob@example.com

Garder le cache honnête depuis une minuterie périodique : revalider ce qui est dû, puis jeter ce qui a vieilli

pepsi-keys -c /etc/pepsi/pepsi.conf peer refresh
pepsi-keys -c /etc/pepsi/pepsi.conf peer prune

Ajouter une ancre de confiance S/MIME et voir ce qui est approuvé

pepsi-keys -c /etc/pepsi/pepsi.conf ca add /etc/ssl/certs/our-ca.pem --label 'Our CA'
pepsi-keys -c /etc/pepsi/pepsi.conf ca list

Renouveler la clé de chiffrement de clés, en regardant d’abord

pepsi-keys -c /etc/pepsi/pepsi.conf wrap rotate --dry-run
pepsi-keys -c /etc/pepsi/pepsi.conf wrap rotate

Faire expirer tout ce qui a dépassé sa validité (depuis une minuterie périodique)

pepsi-keys -c /etc/pepsi/pepsi.conf identity retire

Publier une clé sur le serveur de clés, puis vérifier qu’elle est arrivée

pepsi-keys -c /etc/pepsi/pepsi.conf identity publish 1 --vks
pepsi-keys -c /etc/pepsi/pepsi.conf identity show 1

Mener à terme chaque vérification de serveur de clés en attente (depuis cron)

pepsi-keys -c /etc/pepsi/pepsi.conf identity publish --retry

Cesser de publier une clé, et dire au monde que celle qui a été téléversée est morte

pepsi-keys -c /etc/pepsi/pepsi.conf identity unpublish 1
pepsi-keys -c /etc/pepsi/pepsi.conf identity revoke 1 --upload \
    --reason 'address closed'

85.1.44.1.10. Voir aussi

pepsi-keydisc(1), pepsi-httpd(1), pepsi-stage-vks-confirm(1), pepsi-setup(1), pepsi-config(1), pepsi-whitelist(1), pepsi-settings(1), pepsi.conf(5), pepsi.state(7)

85.1.44.1.11. Bogues

Signalez les bogues au gestionnaire de tickets de Pepsi.