| < draft-dkg-openpgp-stateless-cli-00.txt | draft-dkg-openpgp-stateless-cli-01.txt > | |||
|---|---|---|---|---|
| openpgp D. Gillmor | openpgp D. Gillmor | |||
| Internet-Draft ACLU | Internet-Draft ACLU | |||
| Intended status: Informational October 28, 2019 | Intended status: Informational October 29, 2019 | |||
| Expires: April 30, 2020 | Expires: May 1, 2020 | |||
| Stateless OpenPGP Command Line Interface | Stateless OpenPGP Command Line Interface | |||
| draft-dkg-openpgp-stateless-cli-00 | draft-dkg-openpgp-stateless-cli-01 | |||
| Abstract | Abstract | |||
| This document defines a generic stateless command-line interface for | This document defines a generic stateless command-line interface for | |||
| dealing with OpenPGP messages, known as "sop". It aims for a | dealing with OpenPGP messages, known as "sop". It aims for a | |||
| minimal, well-structured API for dealing with OpenPGP object | minimal, well-structured API covering OpenPGP object security. | |||
| security. | ||||
| Status of This Memo | Status of This Memo | |||
| This Internet-Draft is submitted in full conformance with the | This Internet-Draft is submitted in full conformance with the | |||
| provisions of BCP 78 and BCP 79. | provisions of BCP 78 and BCP 79. | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on April 30, 2020. | This Internet-Draft will expire on May 1, 2020. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2019 IETF Trust and the persons identified as the | Copyright (c) 2019 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
| (https://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| publication of this document. Please review these documents | publication of this document. Please review these documents | |||
| skipping to change at page 2, line 12 ¶ | skipping to change at page 2, line 12 ¶ | |||
| the Trust Legal Provisions and are provided without warranty as | the Trust Legal Provisions and are provided without warranty as | |||
| described in the Simplified BSD License. | described in the Simplified BSD License. | |||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 1.1. Requirements Language . . . . . . . . . . . . . . . . . . 3 | 1.1. Requirements Language . . . . . . . . . . . . . . . . . . 3 | |||
| 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 | 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
| 2. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 4 | 2. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
| 3. Subcommands . . . . . . . . . . . . . . . . . . . . . . . . . 4 | 3. Subcommands . . . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
| 3.1. Version Information . . . . . . . . . . . . . . . . . . . 5 | 3.1. version: Version Information . . . . . . . . . . . . . . 5 | |||
| 3.2. Generate a Secret Key . . . . . . . . . . . . . . . . . . 5 | 3.2. generate-key: Generate a Secret Key . . . . . . . . . . . 5 | |||
| 3.3. Convert a Secret Key to a Certificate . . . . . . . . . . 5 | 3.3. extract-cert: Extract a Certificate from a Secret Key . . 5 | |||
| 3.4. Create a Detached Signature . . . . . . . . . . . . . . . 5 | 3.4. sign: Create a Detached Signature . . . . . . . . . . . . 6 | |||
| 3.5. Verify a Detached Signature . . . . . . . . . . . . . . . 5 | 3.5. verify: Verify a Detached Signature . . . . . . . . . . . 6 | |||
| 3.6. Encrypt a Message . . . . . . . . . . . . . . . . . . . . 6 | 3.6. encrypt: Encrypt a Message . . . . . . . . . . . . . . . 7 | |||
| 3.7. Decrypt a Message . . . . . . . . . . . . . . . . . . . . 7 | 3.7. decrypt: Decrypt a Message . . . . . . . . . . . . . . . 8 | |||
| 3.8. Adding ASCII Armor . . . . . . . . . . . . . . . . . . . 8 | 3.8. armor: Add ASCII Armor . . . . . . . . . . . . . . . . . 10 | |||
| 3.9. Removing ASCII Armor . . . . . . . . . . . . . . . . . . 9 | 3.9. dearmor: Remove ASCII Armor . . . . . . . . . . . . . . . 11 | |||
| 4. Input/Output Indirect Types . . . . . . . . . . . . . . . . . 9 | 4. Input String Types . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 4.1. CERT . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 4.1. DATE . . . . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 4.2. KEY . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 4.2. USERID . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
| 4.3. CIPHERTEXT . . . . . . . . . . . . . . . . . . . . . . . 9 | 5. Input/Output Indirect Types . . . . . . . . . . . . . . . . . 12 | |||
| 4.4. SIGNATURE . . . . . . . . . . . . . . . . . . . . . . . . 10 | 5.1. CERTS . . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
| 4.5. SESSIONKEY . . . . . . . . . . . . . . . . . . . . . . . 10 | 5.2. KEY . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
| 4.6. PASSWORD . . . . . . . . . . . . . . . . . . . . . . . . 11 | 5.3. CIPHERTEXT . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 4.7. VERIFICATIONS . . . . . . . . . . . . . . . . . . . . . . 11 | 5.4. SIGNATURE . . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 4.8. DATA . . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 5.5. SESSIONKEY . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
| 5. Failure modes . . . . . . . . . . . . . . . . . . . . . . . . 11 | 5.6. PASSWORD . . . . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 6. Guidance for Implementors . . . . . . . . . . . . . . . . . . 12 | 5.7. VERIFICATIONS . . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 6.1. One OpenPGP Message At a Time . . . . . . . . . . . . . . 12 | 5.8. DATA . . . . . . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 6.2. Simplified Subset of OpenPGP Message . . . . . . . . . . 12 | 6. Failure modes . . . . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 6.3. Validate Signatures Only From Known Signers . . . . . . . 13 | 7. Guidance for Implementors . . . . . . . . . . . . . . . . . . 15 | |||
| 6.4. Detached Signatures . . . . . . . . . . . . . . . . . . . 13 | 7.1. One OpenPGP Message At a Time . . . . . . . . . . . . . . 15 | |||
| 6.5. Reliance on Supplied Certs and Keys . . . . . . . . . . . 13 | 7.2. Simplified Subset of OpenPGP Message . . . . . . . . . . 16 | |||
| 7. Guidance for Consumers . . . . . . . . . . . . . . . . . . . 13 | 7.3. Validate Signatures Only From Known Signers . . . . . . . 16 | |||
| 8. Security Considerations . . . . . . . . . . . . . . . . . . . 14 | 7.4. Detached Signatures . . . . . . . . . . . . . . . . . . . 16 | |||
| 8.1. Signature Verification . . . . . . . . . . . . . . . . . 14 | 7.5. Reliance on Supplied Certs and Keys . . . . . . . . . . . 16 | |||
| 8.2. Compression . . . . . . . . . . . . . . . . . . . . . . . 15 | 8. Guidance for Consumers . . . . . . . . . . . . . . . . . . . 16 | |||
| 9. Privacy Considerations . . . . . . . . . . . . . . . . . . . 15 | 9. Security Considerations . . . . . . . . . . . . . . . . . . . 17 | |||
| 9.1. Object Security vs. Transport Security . . . . . . . . . 15 | 9.1. Signature Verification . . . . . . . . . . . . . . . . . 17 | |||
| 10. Document Considerations . . . . . . . . . . . . . . . . . . . 15 | 9.2. Compression . . . . . . . . . . . . . . . . . . . . . . . 18 | |||
| 10.1. Document History . . . . . . . . . . . . . . . . . . . . 16 | 10. Privacy Considerations . . . . . . . . . . . . . . . . . . . 18 | |||
| 10.2. Future Work . . . . . . . . . . . . . . . . . . . . . . 16 | 10.1. Object Security vs. Transport Security . . . . . . . . . 18 | |||
| 11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 16 | 11. Document Considerations . . . . . . . . . . . . . . . . . . . 18 | |||
| 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 16 | 11.1. Document History . . . . . . . . . . . . . . . . . . . . 19 | |||
| 12.1. Normative References . . . . . . . . . . . . . . . . . . 16 | 11.2. Future Work . . . . . . . . . . . . . . . . . . . . . . 19 | |||
| 12.2. Informative References . . . . . . . . . . . . . . . . . 17 | 12. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 20 | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 17 | 13. References . . . . . . . . . . . . . . . . . . . . . . . . . 20 | |||
| 13.1. Normative References . . . . . . . . . . . . . . . . . . 21 | ||||
| 13.2. Informative References . . . . . . . . . . . . . . . . . 21 | ||||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 21 | ||||
| 1. Introduction | 1. Introduction | |||
| Different OpenPGP implementations have many different requirements, | Different OpenPGP implementations have many different requirements, | |||
| which typically break down in two main categories: key/certificate | which typically break down in two main categories: key/certificate | |||
| management and object security. | management and object security. | |||
| The purpose of this document is to provide a "stateless" interface | The purpose of this document is to provide a "stateless" interface | |||
| that primarily handles the object security side of things, and | that primarily handles the object security side of things, and | |||
| assumes that secret key management and certificate management will be | assumes that secret key management and certificate management will be | |||
| skipping to change at page 3, line 25 ¶ | skipping to change at page 3, line 27 ¶ | |||
| This separation should make it easier to provide interoperability | This separation should make it easier to provide interoperability | |||
| testing for the object security work, and to allow implementations to | testing for the object security work, and to allow implementations to | |||
| consume and produce new cryptographic primitives as needed. | consume and produce new cryptographic primitives as needed. | |||
| This document defines a generic stateless command-line interface for | This document defines a generic stateless command-line interface for | |||
| dealing with OpenPGP messages, known here by the placeholder "sop". | dealing with OpenPGP messages, known here by the placeholder "sop". | |||
| It aims for a minimal, well-structured API. | It aims for a minimal, well-structured API. | |||
| An OpenPGP implementation should not name its executable "sop" to | An OpenPGP implementation should not name its executable "sop" to | |||
| implement this specification, of course. It just needs to provide an | implement this specification, of course. It just needs to provide a | |||
| binary that conforms to this interface. | binary that conforms to this interface. | |||
| A "sop" implementation should leave no trace on the system, and its | A "sop" implementation should leave no trace on the system, and its | |||
| behavior should not be affected by anything other than command-line | behavior should not be affected by anything other than command-line | |||
| arguments and input. | arguments and input. | |||
| Obviously, the user will need to manage their secret keys (and their | Obviously, the user will need to manage their secret keys (and their | |||
| peers' certificates) somehow, but the goal of this interface is to | peers' certificates) somehow, but the goal of this interface is to | |||
| separate out that task from the task of interacting with OpenPGP | separate out that task from the task of interacting with OpenPGP | |||
| messages. | messages. | |||
| skipping to change at page 4, line 19 ¶ | skipping to change at page 4, line 19 ¶ | |||
| It uses the term "certificate" to refer to OpenPGP Transferable | It uses the term "certificate" to refer to OpenPGP Transferable | |||
| Public Key (see section 11.1 of [RFC4880]). | Public Key (see section 11.1 of [RFC4880]). | |||
| "Stateless" in "Stateless OpenPGP" means avoiding secret key and | "Stateless" in "Stateless OpenPGP" means avoiding secret key and | |||
| certificate state. The user is responsible for managing all OpenPGP | certificate state. The user is responsible for managing all OpenPGP | |||
| certificates and secret keys themselves, and passing them to "sop" as | certificates and secret keys themselves, and passing them to "sop" as | |||
| needed. The user should also not be concerned that any state could | needed. The user should also not be concerned that any state could | |||
| affect the underlying operations. | affect the underlying operations. | |||
| OpenPGP revocations can have "Reason for Revocation" (section | ||||
| 5.2.3.23 of [RFC4880]), which can be either "soft" or "hard". The | ||||
| set of "soft" reasons is: "Key is superseded" and "Key is retired and | ||||
| no longer used". All other reasons (and revocations that do not | ||||
| state a reason) are "hard" revocations. | ||||
| 2. Examples | 2. Examples | |||
| These examples show no error checking, but give a flavor of how "sop" | These examples show no error checking, but give a flavor of how "sop" | |||
| might be used in practice from a shell. | might be used in practice from a shell. | |||
| The key and certificate files described in them (e.g. "alice.sec") | The key and certificate files described in them (e.g. "alice.sec") | |||
| could be for example those found in | could be for example those found in | |||
| [I-D.draft-bre-openpgp-samples-00]. | [I-D.draft-bre-openpgp-samples-00]. | |||
| sop generate "Alice Lovelace <alice@openpgp.example>" > alice.sec | sop generate-key "Alice Lovelace <alice@openpgp.example>" > alice.sec | |||
| sop convert < alice.sec > alice.pgp | sop extract-cert < alice.sec > alice.pgp | |||
| sop sign --as=text alice.sec < announcement.txt > announcement.txt.asc | sop sign --as=text alice.sec < announcement.txt > announcement.txt.asc | |||
| sop verify announcement.txt.asc alice.pgp < announcement.txt | sop verify announcement.txt.asc alice.pgp < announcement.txt | |||
| sop encrypt --sign-with=alice.sec --as=mime bob.pgp < msg.eml > encrypted.asc | sop encrypt --sign-with=alice.sec --as=mime bob.pgp < msg.eml > encrypted.asc | |||
| sop decrypt alice.sec < ciphertext.asc > cleartext.out | sop decrypt alice.sec < ciphertext.asc > cleartext.out | |||
| 3. Subcommands | 3. Subcommands | |||
| "sop" uses a subcommand interface, similar to those popularized by | "sop" uses a subcommand interface, similar to those popularized by | |||
| skipping to change at page 5, line 5 ¶ | skipping to change at page 5, line 10 ¶ | |||
| If the user supplies a subcommand that "sop" does not implement, it | If the user supplies a subcommand that "sop" does not implement, it | |||
| fails with a return code of 69. If a "sop" implementation does not | fails with a return code of 69. If a "sop" implementation does not | |||
| handle a supplied option for a given subcommand, it fails with a | handle a supplied option for a given subcommand, it fails with a | |||
| return code of 37. | return code of 37. | |||
| For all commands that have an "--armor|--no-armor" option, it | For all commands that have an "--armor|--no-armor" option, it | |||
| defaults to "--armor", meaning that any output OpenPGP material | defaults to "--armor", meaning that any output OpenPGP material | |||
| should be ASCII-armored (section 6 of [I-D.ietf-openpgp-rfc4880bis]) | should be ASCII-armored (section 6 of [I-D.ietf-openpgp-rfc4880bis]) | |||
| by default. | by default. | |||
| 3.1. Version Information | 3.1. version: Version Information | |||
| sop version | sop version | |||
| o Standard Input: ignored | o Standard Input: ignored | |||
| o Standard Output: version string | o Standard Output: version string | |||
| The version string emitted should contain the name of the "sop" | The version string emitted should contain the name of the "sop" | |||
| implementation, followed by a single space, followed by the version | implementation, followed by a single space, followed by the version | |||
| number. | number. | |||
| 3.2. Generate a Secret Key | Example: | |||
| sop generate [--armor|--no-armor] [--] [USERID...] | $ sop version | |||
| ExampleSop 0.2.1 | ||||
| $ | ||||
| 3.2. generate-key: Generate a Secret Key | ||||
| sop generate-key [--armor|--no-armor] [--] [USERID...] | ||||
| o Standard Input: ignored | o Standard Input: ignored | |||
| o Standard Output: "KEY" (Section 4.2) | o Standard Output: "KEY" (Section 5.2) | |||
| Generate a single default OpenPGP certificate with zero or more User | Generate a single default OpenPGP certificate with zero or more User | |||
| IDs. | IDs. | |||
| 3.3. Convert a Secret Key to a Certificate | Example: | |||
| sop convert [--armor|--no-armor] | $ sop generate-key 'Alice Lovelace <alice@openpgp.example>' > alice.sec | |||
| $ head -n1 < alice.sec | ||||
| -----BEGIN PGP PRIVATE KEY BLOCK----- | ||||
| $ | ||||
| o Standard Input: "KEY" (Section 4.2) | 3.3. extract-cert: Extract a Certificate from a Secret Key | |||
| o Standard Output: "CERT" (Section 4.1) | sop extract-cert [--armor|--no-armor] | |||
| 3.4. Create a Detached Signature | o Standard Input: "KEY" (Section 5.2) | |||
| o Standard Output: "CERTS" (Section 5.1) | ||||
| Note that the resultant "CERTS" object will only ever contain one | ||||
| OpenPGP certificate. | ||||
| Example: | ||||
| $ sop extract-cert < alice.sec > alice.pgp | ||||
| $ head -n1 < alice.pgp | ||||
| -----BEGIN PGP PUBLIC KEY BLOCK----- | ||||
| $ | ||||
| 3.4. sign: Create a Detached Signature | ||||
| sop sign [--armor|--no-armor] | sop sign [--armor|--no-armor] | |||
| [--as={binary|text}] [--] KEY [KEY...] | [--as={binary|text}] [--] KEY [KEY...] | |||
| o Standard Input: "DATA" (Section 4.8) | o Standard Input: "DATA" (Section 5.8) | |||
| o Standard Output: "SIGNATURE" (Section 4.4) | o Standard Output: "SIGNATURE" (Section 5.4) | |||
| "--as" defaults to "binary". If "--as=text" and the input "DATA" is | "--as" defaults to "binary". If "--as=text" and the input "DATA" is | |||
| not valid "UTF-8", "sop sign" fails with a return code of 53. | not valid "UTF-8", "sop sign" fails with a return code of 53. | |||
| 3.5. Verify a Detached Signature | Example: | |||
| $ sop sign --as=text alice.sec < message.txt > message.txt.asc | ||||
| $ head -n1 < message.txt.asc | ||||
| -----BEGIN PGP SIGNATURE----- | ||||
| $ | ||||
| 3.5. verify: Verify a Detached Signature | ||||
| sop verify [--not-before=DATE] [--not-after=DATE] | sop verify [--not-before=DATE] [--not-after=DATE] | |||
| [--] SIGNATURE CERT [CERT...] | [--] SIGNATURE CERTS [CERTS...] | |||
| o Standard Input: "DATA" (Section 4.8) | o Standard Input: "DATA" (Section 5.8) | |||
| o Standard Output: "VERIFICATIONS" (Section 4.7) | o Standard Output: "VERIFICATIONS" (Section 5.7) | |||
| "--not-before" and "--not-after" indicate that only signatures with | "--not-before" and "--not-after" indicate that signatures with dates | |||
| dates in a certain range should be considered as possibly valid. | outside certain range MUST NOT be considered valid. | |||
| "--not-before" defaults to the beginning of time. | "--not-before" defaults to the beginning of time. Accepts the | |||
| special value "-" to indicate the beginning of time (i.e. no lower | ||||
| boundary). | ||||
| "--not-after" defaults to "now". | "--not-after" defaults to the current system time ("now"). Accepts | |||
| the special value "-" to indicate the end of time (i.e. no upper | ||||
| boundary). | ||||
| "sop verify" only returns 0 if at least one of the supplied "CERT"s | "sop verify" only returns 0 if at least one certificate included in | |||
| made a valid signature in the range over the "DATA" supplied. | any "CERTS" object made a valid signature in the range over the | |||
| "DATA" supplied. | ||||
| For details about the valid signatures, the user MUST inspect the | For details about the valid signatures, the user MUST inspect the | |||
| "VERIFICATIONS" output. | "VERIFICATIONS" output. | |||
| If no "CERT" is supplied, "sop verify" fails with a return code of | If no "CERTS" are supplied, "sop verify" fails with a return code of | |||
| 19. | 19. | |||
| If at least one "CERT" is supplied, but no valid signatures are | If no valid signatures are found, "sop verify" fails with a return | |||
| found, "sop verify" fails with a return code of 3. | code of 3. | |||
| See Section 8.1 for more details about signature verification. | See Section 9.1 for more details about signature verification. | |||
| 3.6. Encrypt a Message | Example: | |||
| (In this example, we see signature verification succeed first, and | ||||
| then fail on a modified version of the message.) | ||||
| $ sop verify message.txt.asc alice.pgp < message.txt | ||||
| 2019-10-29T18:36:45Z EB85BB5FA33A75E15E944E63F231550C4F47E38E EB85BB5FA33A75E15E944E63F231550C4F47E38E signed by alice.pgp | ||||
| $ echo $? | ||||
| 0 | ||||
| $ tr a-z A-Z < message.txt | sop verify message.txt.asc alice.pgp | ||||
| $ echo $? | ||||
| 3 | ||||
| $ | ||||
| 3.6. encrypt: Encrypt a Message | ||||
| sop encrypt [--as={binary|text|mime}] | sop encrypt [--as={binary|text|mime}] | |||
| [--armor|--no-armor] | [--armor|--no-armor] | |||
| [--mode={any|communications|storage}] | ||||
| [--with-password=PASSWORD...] | [--with-password=PASSWORD...] | |||
| [--session-key=SESSIONKEY] | ||||
| [--sign-with=KEY...] | [--sign-with=KEY...] | |||
| [--] [CERT...] | [--] [CERTS...] | |||
| o Standard Input: "DATA" (Section 4.8) | o Standard Input: "DATA" (Section 5.8) | |||
| o Standard Output: "CIPHERTEXT" (Section 4.3) | o Standard Output: "CIPHERTEXT" (Section 5.3) | |||
| "--as" defaults to "binary". | "--as" defaults to "binary". | |||
| "--mode" defaults to "any", meaning any encryption-capable subkey may | ||||
| be used. | ||||
| "--with-password" enables symmetric encryption (and can be used | "--with-password" enables symmetric encryption (and can be used | |||
| multiple times if multiple passwords are desired). If "sop encrypt" | multiple times if multiple passwords are desired). If "sop encrypt" | |||
| encounters a "PASSWORD" which is not a valid "UTF-8" string, it fails | encounters a "PASSWORD" which is not a valid "UTF-8" string, it fails | |||
| with a return code of 31. If "sop encrypt" sees trailing whitespace | with a return code of 31. If "sop encrypt" sees trailing whitespace | |||
| at the end of a "PASSWORD", it will trim the trailing whitespace | at the end of a "PASSWORD", it will trim the trailing whitespace | |||
| before using the password. | before using the password. | |||
| "--session-key" permits the encryptor to select the symmetric | ||||
| encryption algorithm and specific session key. | ||||
| "--sign-with" enables signing by a secret key (and can be used | "--sign-with" enables signing by a secret key (and can be used | |||
| multiple times if multiple signatures are desired). | multiple times if multiple signatures are desired). | |||
| If "--as" is set to either "--text" or "--mime", then "--sign-with" | If "--as" is set to either "text" or "mime", then "--sign-with" will | |||
| will sign as a canonical text document. In this case, if the input | sign as a canonical text document. In this case, if the input "DATA" | |||
| "DATA" is not valid "UTF-8", "sop encrypt" fails with a return code | is not valid "UTF-8", "sop encrypt" fails with a return code of 53. | |||
| of 53. | ||||
| The resulting "CIPHERTEXT" should be decryptable by the secret keys | The resulting "CIPHERTEXT" should be decryptable by the secret keys | |||
| corresponding to each identified "CERT". | corresponding to every certificate included in all "CERTS", as well | |||
| as each password given with "--with-password". | ||||
| If no "CERT" or "--with-password" options are present, "sop encrypt" | If no "CERTS" or "--with-password" options are present, "sop encrypt" | |||
| fails with a return code of 19. | fails with a return code of 19. | |||
| 3.7. Decrypt a Message | If at least one of the identified certificates requires encryption to | |||
| an unsupported asymmetric algorithm, "sop encrypt" fails with a | ||||
| return code of 13. | ||||
| If at least one of the identified certificates is not encryption- | ||||
| capable (e.g., revoked, expired, no encryption-capable flags on | ||||
| primary key and valid subkeys), "sop encrypt" fails with a return | ||||
| code of 17. | ||||
| If "sop encrypt" fails for any reason, it emits no "CIPHERTEXT". | ||||
| Example: | ||||
| (In this example, "bob.bin" is a file containing Bob's binary- | ||||
| formatted OpenPGP certificate. Alice is encrypting a message to both | ||||
| herself and Bob.) | ||||
| $ sop encrypt --as=mime --sign-with=alice.key alice.asc bob.bin < message.eml > encrypted.asc | ||||
| $ head -n1 encrypted.asc | ||||
| -----BEGIN PGP MESSAGE----- | ||||
| $ | ||||
| 3.7. decrypt: Decrypt a Message | ||||
| sop decrypt [--session-key-out=SESSIONKEY] | sop decrypt [--session-key-out=SESSIONKEY] | |||
| [--with-session-key=SESSIONKEY...] | ||||
| [--with-password=PASSWORD...] | [--with-password=PASSWORD...] | |||
| [--verify-out=VERIFICATIONS | [--verify-out=VERIFICATIONS | |||
| [--verify-with=CERT...] | [--verify-with=CERTS...] | |||
| [--verify-not-before=DATE] | [--verify-not-before=DATE] | |||
| [--verify-not-after=DATE] ] | [--verify-not-after=DATE] ] | |||
| [--] [KEY...] | [--] [KEY...] | |||
| o Standard Input: "CIPHERTEXT" (Section 4.3) | o Standard Input: "CIPHERTEXT" (Section 5.3) | |||
| o Standard Output: "DATA" (Section 4.8) | o Standard Output: "DATA" (Section 5.8) | |||
| "--session-key-out" can be used to learn the session key on | "--session-key-out" can be used to learn the session key on | |||
| successful decryption. | successful decryption. | |||
| If "sop decrypt" fails for any reason and the identified "SESSIONKEY" | If "sop decrypt" fails for any reason and the identified "--session- | |||
| file already exists in the filesystem, the file will be unlinked. | key-out" file already exists in the filesystem, the file will be | |||
| unlinked. | ||||
| "--with-password" enables symmetric decryption (and can be used | "--with-session-key" enables decryption of the "CIPHERTEXT" using the | |||
| multiple times if the user wants to try more password are tried). | session key directly against the "SEIPD" packet. This option can be | |||
| used multiple times if several possible session keys should be tried. | ||||
| "--with-password" enables decryption based on any "SKESK" packets in | ||||
| the "CIPHERTEXT". This option can be used multiple times if the user | ||||
| wants to try more than one password. | ||||
| If "sop decrypt" tries and fails to use a supplied "PASSWORD", and it | If "sop decrypt" tries and fails to use a supplied "PASSWORD", and it | |||
| observes that there is trailing "UTF-8" whitespace at the end of the | observes that there is trailing "UTF-8" whitespace at the end of the | |||
| "PASSWORD", it will retry with the trailing whitespace stripped. | "PASSWORD", it will retry with the trailing whitespace stripped. | |||
| "--verify-out" produces signature verification status to the | "--verify-out" produces signature verification status to the | |||
| designated file. | designated file. | |||
| "sop decrypt" does not fail (that is, the return code is not | "sop decrypt" does not fail (that is, the return code is not | |||
| modified) based on the results of signature verification. The caller | modified) based on the results of signature verification. The caller | |||
| MUST check the returned "VERIFICATIONS" to confirm signature status. | MUST check the returned "VERIFICATIONS" to confirm signature status. | |||
| An empty "VERIFICATIONS" output indicates that no valid signatures | An empty "VERIFICATIONS" output indicates that no valid signatures | |||
| were found. If "sop decrypt" itself fails for any reason, and the | were found. If "sop decrypt" itself fails for any reason, and the | |||
| identified "VERIFICATIONS" file already exists in the filesystem, the | identified "VERIFICATIONS" file already exists in the filesystem, the | |||
| file will be unlinked. | file will be unlinked. | |||
| "--verify-with" identifies a certificate whose signatures would be | "--verify-with" identifies a set of certificates whose signatures | |||
| acceptable for signatures over this message. | would be acceptable for signatures over this message. | |||
| If the caller is interested in signature verification, both "-- | If the caller is interested in signature verification, both "-- | |||
| verify-out" and at least one "--verify-with" must be supplied. If | verify-out" and at least one "--verify-with" must be supplied. If | |||
| only one of these arguments is supplied, "sop decrypt" fails with a | only one of these arguments is supplied, "sop decrypt" fails with a | |||
| return code of 23. | return code of 23. | |||
| "--verify-not-before" and "--verify-not-after" provide a date range | "--verify-not-before" and "--verify-not-after" provide a date range | |||
| for acceptable signatures, by analogy with the options for "sop | for acceptable signatures, by analogy with the options for "sop | |||
| verify". They should only be supplied when doing signature | verify" (see Section 3.5). They should only be supplied when doing | |||
| verification. | signature verification. | |||
| See Section 8.1 for more details about signature verification. | See Section 9.1 for more details about signature verification. | |||
| If no "KEY" or "--with-password" options are present, "sop decrypt" | If no "KEY" or "--with-password" or "--with-session-key" options are | |||
| fails with a return code of 19. | present, "sop decrypt" fails with a return code of 19. | |||
| If unable to decrypt, "sop decrypt" fails with a return code of 29. | If unable to decrypt, "sop decrypt" fails with a return code of 29. | |||
| "sop decrypt" only returns cleartext to Standard Output that was | "sop decrypt" only returns cleartext to Standard Output that was | |||
| successfully decrypted. | successfully decrypted. | |||
| 3.8. Adding ASCII Armor | Example: | |||
| sop armor [--label={sig|key|cert|message}] | (In this example, Alice stashes and re-uses the session key of an | |||
| encrypted message.) | ||||
| $ sop decrypt --session-key-out=session.key alice.sec < ciphertext.asc > cleartext.out | ||||
| $ ls -l ciphertext.asc cleartext.out | ||||
| -rw-r--r-- 1 user user 321 Oct 28 01:34 ciphertext.asc | ||||
| -rw-r--r-- 1 user user 285 Oct 28 01:34 cleartext.out | ||||
| $ sop decrypt --with-session-key=session.key < ciphertext.asc > cleartext2.out | ||||
| $ diff cleartext.out cleartext2.out | ||||
| $ | ||||
| 3.8. armor: Add ASCII Armor | ||||
| sop armor [--label={auto|sig|key|cert|message}] | ||||
| [--allow-nested] | ||||
| o Standard Input: 8-bit, unarmored OpenPGP material ("SIGNATURE", | o Standard Input: 8-bit, unarmored OpenPGP material ("SIGNATURE", | |||
| "CERT", "KEY", or "CIPHERTEXT") | "CERTS", "KEY", or "CIPHERTEXT") | |||
| o Standard Output: the same material with ASCII-armoring added | o Standard Output: the same material with ASCII-armoring added | |||
| The user can choose to specify the label used in the header and tail | The user can choose to specify the label used in the header and tail | |||
| of the armoring. If the user does not specify, "sop" inspects the | of the armoring. The default is "auto", in which case, "sop" | |||
| input and chooses the label appropriately. If "sop" cannot select a | inspects the input and chooses the label appropriately. In this | |||
| label on the basis of the input, it treats it as literal data, and | case, if "sop" cannot select a label on the basis of the input, it | |||
| labels it as a "message". | treats it as literal data, and labels it as a "message". | |||
| 3.9. Removing ASCII Armor | If the incoming data is already armored, and the "--allow-nested" | |||
| flag is not specified, the data MUST be output with no modifications. | ||||
| Data is considered ASCII armored iff the first 14 bytes are exactly " | ||||
| -----BEGIN PGP". This operation is thus idempotent by default. | ||||
| Example: | ||||
| $ sop armor < bob.bin > bob.pgp | ||||
| $ head -n1 bob.pgp | ||||
| -----BEGIN PGP PUBLIC KEY BLOCK----- | ||||
| $ | ||||
| 3.9. dearmor: Remove ASCII Armor | ||||
| sop dearmor | sop dearmor | |||
| o Standard Input: ASCII-armored OpenPGP material ("CIPHERTEXT", | o Standard Input: ASCII-armored OpenPGP material ("CIPHERTEXT", | |||
| "SIGNATURE", "CERT", or "KEY") | "SIGNATURE", "CERTS", or "KEY") | |||
| o Standard Output: the same material with ASCII-armoring removed | o Standard Output: the same material with ASCII-armoring removed | |||
| 4. Input/Output Indirect Types | Example: | |||
| $ sop dearmor < message.txt.asc > message.txt.sig | ||||
| $ | ||||
| 4. Input String Types | ||||
| Some material is passed to "sop" directly as a string on the command | ||||
| line. | ||||
| 4.1. DATE | ||||
| An ISO-8601 formatted timestamp with time zone, or the special value | ||||
| "now" to indicate the current system time. | ||||
| Examples: | ||||
| now | ||||
| 2019-10-29T12:11:04+00:00 | ||||
| 2019-10-24T23:48:29Z | ||||
| 20191029T121104Z | ||||
| In some cases where used to specify lower and upper boundaries, a | ||||
| "DATE" value can be set to "-" to indicate "no time limit". | ||||
| A flexible implementation of "sop" MAY accept date inputs in other | ||||
| unambiguous forms. | ||||
| 4.2. USERID | ||||
| This is an arbitrary "UTF-8" string. By convention, most User IDs | ||||
| are of the form "Display Name <email.address@example.com>", but they | ||||
| do not need to be. | ||||
| 5. Input/Output Indirect Types | ||||
| Some material is passed to "sop" indirectly, typically by referring | Some material is passed to "sop" indirectly, typically by referring | |||
| to a filename containing the data in question. This type of data may | to a filename containing the data in question. This type of data may | |||
| also be passed to "sop" on Standard Input, or delivered by "sop" to | also be passed to "sop" on Standard Input, or delivered by "sop" to | |||
| Standard Output. | Standard Output. | |||
| If the filename for any indirect material used as input has the | If the filename for any indirect material used as input has the | |||
| special form "@ENV:xxx", then contents of environment variable "$xxx" | special form "@ENV:xxx", then contents of environment variable "$xxx" | |||
| is used instead of looking in the filesystem. | is used instead of looking in the filesystem. | |||
| If the filename for any indirect material used as either input or | If the filename for any indirect material used as either input or | |||
| output has the special form "@FD:nnn" where "nnn" is a decimal | output has the special form "@FD:nnn" where "nnn" is a decimal | |||
| integer, then the associated data is read from file descriptor "nnn". | integer, then the associated data is read from file descriptor "nnn". | |||
| If any input data does not meet the requirements described below, | If any input data does not meet the requirements described below, | |||
| "sop" will fail with a return code of 41. | "sop" will fail with a return code of 41. | |||
| 4.1. CERT | 5.1. CERTS | |||
| One OpenPGP certificate (section 11.1 of | One or more OpenPGP certificates (section 11.1 of | |||
| [I-D.ietf-openpgp-rfc4880bis]) aka "Transferable Public Key". May be | [I-D.ietf-openpgp-rfc4880bis]), aka "Transferable Public Key". May | |||
| armored. | be armored. | |||
| 4.2. KEY | Although some existing workflows may prefer to use one "CERTS" object | |||
| with multiple certificates in it (a "keyring"), supplying exactly one | ||||
| certificate per "CERTS" input will make error reporting clearer and | ||||
| easier. | ||||
| One OpenPGP Transferable Secret Key (section 11.2 of | 5.2. KEY | |||
| Exactly one OpenPGP Transferable Secret Key (section 11.2 of | ||||
| [I-D.ietf-openpgp-rfc4880bis]). May be armored. | [I-D.ietf-openpgp-rfc4880bis]). May be armored. | |||
| Secret key material should be in cleartext (that is, it should not be | Secret key material should be in cleartext (that is, it should not be | |||
| locked with a password). If the secret key maerial is locked with a | locked with a password). If the secret key maerial is locked with a | |||
| password, "sop" may fail to use the key. | password, "sop" may fail to use the key. | |||
| 4.3. CIPHERTEXT | 5.3. CIPHERTEXT | |||
| "sop" accepts only a restricted subset of the arbitrarily-nested | "sop" accepts only a restricted subset of the arbitrarily-nested | |||
| grammar allowed by the OpenPGP Messages definition (section 11.3 of | grammar allowed by the OpenPGP Messages definition (section 11.3 of | |||
| [I-D.ietf-openpgp-rfc4880bis]). | [I-D.ietf-openpgp-rfc4880bis]). | |||
| In particular, it accepts and generates only: | In particular, it accepts and generates only: | |||
| An OpenPGP message, consisting of a sequence of PKESKs (section 5.1 | An OpenPGP message, consisting of a sequence of PKESKs (section 5.1 | |||
| of [I-D.ietf-openpgp-rfc4880bis]) and SKESKs (section 5.3 of | of [I-D.ietf-openpgp-rfc4880bis]) and SKESKs (section 5.3 of | |||
| [I-D.ietf-openpgp-rfc4880bis]), followed by one SEIPD (section 5.14 | [I-D.ietf-openpgp-rfc4880bis]), followed by one SEIPD (section 5.14 | |||
| skipping to change at page 10, line 34 ¶ | skipping to change at page 13, line 40 ¶ | |||
| o one Literal data packet, followed by | o one Literal data packet, followed by | |||
| o N signature packets (corresponding to the outer one-pass | o N signature packets (corresponding to the outer one-pass | |||
| signatures packets) | signatures packets) | |||
| FIXME: does any tool do compression inside signing? Do we need to | FIXME: does any tool do compression inside signing? Do we need to | |||
| handle that? | handle that? | |||
| May be armored. | May be armored. | |||
| 4.4. SIGNATURE | 5.4. SIGNATURE | |||
| One or more OpenPGP Signature packets. May be armored. | One or more OpenPGP Signature packets. May be armored. | |||
| 4.5. SESSIONKEY | 5.5. SESSIONKEY | |||
| This documentation uses the GnuPG defacto "ASCII" representation: | This documentation uses the GnuPG defacto "ASCII" representation: | |||
| "ALGONUM:HEXKEY" | "ALGONUM:HEXKEY" | |||
| where "ALGONUM" is the decimal value associated with the OpenPGP | where "ALGONUM" is the decimal value associated with the OpenPGP | |||
| Symmetric Key Algorithms (section 9.3 of | Symmetric Key Algorithms (section 9.3 of | |||
| [I-D.ietf-openpgp-rfc4880bis]). | [I-D.ietf-openpgp-rfc4880bis]). | |||
| As input, "ALGONUM:" alone (with an empty "HEXKEY") means "user | Example AES-256 session key: | |||
| specifies the algorithm, but the implementation chooses an arbitrary | ||||
| key for the cipher." | ||||
| Example AES256 session key: | ||||
| 9:FCA4BEAF687F48059CACC14FB019125CD57392BAB7037C707835925CBF9F7BCD | 9:FCA4BEAF687F48059CACC14FB019125CD57392BAB7037C707835925CBF9F7BCD | |||
| 4.6. PASSWORD | 5.6. PASSWORD | |||
| This is expected to be a "UTF-8" string, but for "sop decrypt", any | This is expected to be a "UTF-8" string, but for "sop decrypt", any | |||
| bytestring that the user supplies will be accepted. Note the details | bytestring that the user supplies will be accepted. Note the details | |||
| in "sop encrypt" and "sop decrypt" about trailing whitespace! | in "sop encrypt" and "sop decrypt" about trailing whitespace! | |||
| 4.7. VERIFICATIONS | 5.7. VERIFICATIONS | |||
| One line per successful signature verification. Each line has two | One line per successful signature verification. Each line has three | |||
| structured fields delimited by a single space, followed by arbitary | structured fields delimited by a single space, followed by arbitrary | |||
| text to the end of the line. | text to the end of the line. | |||
| o ISO-8601 UTC datestamp | o ISO-8601 UTC datestamp | |||
| o Fingerprint of primary key of signing certificate | o Fingerprint of the signing key (may be a subkey) | |||
| o Fingerprint of primary key of signing certificate (if signed by | ||||
| primary key, same as the previous field) | ||||
| o arbitrary text | o arbitrary text | |||
| Example: | Example: | |||
| 2019-10-24T23:48:29Z C4BC2DDB38CCE96485EBE9C2F20691179038E5C6 signed by dkg! | 2019-10-24T23:48:29Z C90E6D36200A1B922A1509E77618196529AE5FF8 C4BC2DDB38CCE96485EBE9C2F20691179038E5C6 certificate from dkg.asc | |||
| 4.8. DATA | 5.8. DATA | |||
| Cleartext, arbitrary data. This is either a bytestream or "UTF-8" | Cleartext, arbitrary data. This is either a bytestream or "UTF-8" | |||
| text. | text. | |||
| It MUST only be "UTF-8" text in the case of input supplied to "sop | It MUST only be "UTF-8" text in the case of input supplied to "sop | |||
| sign --as=text" or "encrypt --as={mime|text}". If "sop" receives | sign --as=text" or "sop encrypt --as={mime|text}". If "sop" receives | |||
| "DATA" containing non-"UTF-8" octets it will fail with return code | "DATA" containing non-"UTF-8" octets in this case, it will fail with | |||
| 53. | return code 53. | |||
| 5. Failure modes | 6. Failure modes | |||
| When "sop" succeeds, it will return 0 and emit nothing to Standard | When "sop" succeeds, it will return 0 and emit nothing to Standard | |||
| Error. When "sop" fails, it fails with a non-zero return code, and | Error. When "sop" fails, it fails with a non-zero return code, and | |||
| emits one or more warning messages on Standard Error. Known return | emits one or more warning messages on Standard Error. Known return | |||
| codes include: | codes include: | |||
| +--------+----------------------------------------------------------+ | +--------+----------------------------------------------------------+ | |||
| | Return | Meaning | | | Return | Meaning | | |||
| +--------+----------------------------------------------------------+ | +--------+----------------------------------------------------------+ | |||
| | 0 | Success | | | 0 | Success | | |||
| | | | | | | | | |||
| | 3 | No acceptable signatures found ("sop verify") | | | 3 | No acceptable signatures found ("sop verify") | | |||
| | | | | | | | | |||
| | 13 | Asymmetric algorithm unsupported ("sop encrypt") | | ||||
| | | | | ||||
| | 17 | Certificate not encryption-capable (e.g., expired, | | ||||
| | | revoked, unacceptable usage flags) ("sop encrypt") | | ||||
| | | | | ||||
| | 19 | Missing required argument | | | 19 | Missing required argument | | |||
| | | | | | | | | |||
| | 23 | Incomplete verification instructions ("sop decrypt") | | | 23 | Incomplete verification instructions ("sop decrypt") | | |||
| | | | | | | | | |||
| | 29 | Unable to decrypt ("sop decrypt") | | | 29 | Unable to decrypt ("sop decrypt") | | |||
| | | | | | | | | |||
| | 31 | Non-"UTF-8" password ("sop encrypt") | | | 31 | Non-"UTF-8" password ("sop encrypt") | | |||
| | | | | | | | | |||
| | 37 | Unsupported option | | | 37 | Unsupported option | | |||
| | | | | | | | | |||
| skipping to change at page 12, line 33 ¶ | skipping to change at page 15, line 38 ¶ | |||
| | | etc) | | | | etc) | | |||
| | | | | | | | | |||
| | 53 | Non-text input where text expected | | | 53 | Non-text input where text expected | | |||
| | | | | | | | | |||
| | 69 | Unsupported subcommand | | | 69 | Unsupported subcommand | | |||
| +--------+----------------------------------------------------------+ | +--------+----------------------------------------------------------+ | |||
| A "sop" implementation MAY return other error codes than those listed | A "sop" implementation MAY return other error codes than those listed | |||
| above. | above. | |||
| 6. Guidance for Implementors | 7. Guidance for Implementors | |||
| "sop" uses a few assumptions that implementers might want to | "sop" uses a few assumptions that implementers might want to | |||
| consider. | consider. | |||
| 6.1. One OpenPGP Message At a Time | 7.1. One OpenPGP Message At a Time | |||
| "sop" is intended to be a simple tool that operates on one OpenPGP | "sop" is intended to be a simple tool that operates on one OpenPGP | |||
| object at a time. It should be composable, if you want to use it to | object at a time. It should be composable, if you want to use it to | |||
| deal with multiple OpenPGP objects | deal with multiple OpenPGP objects | |||
| FIXME: discuss what this means for streaming. The stdio interface | FIXME: discuss what this means for streaming. The stdio interface | |||
| doesn't necessarily imply streamed output. | doesn't necessarily imply streamed output. | |||
| 6.2. Simplified Subset of OpenPGP Message | 7.2. Simplified Subset of OpenPGP Message | |||
| While the formal grammar for OpenPGP Message is arbitrarily | While the formal grammar for OpenPGP Message is arbitrarily | |||
| nestable,"sop" constrains itself to what it sees as a single "layer" | nestable,"sop" constrains itself to what it sees as a single "layer" | |||
| (see Section 4.3). | (see Section 5.3). | |||
| This is a deliberate choice, because it is what most consumers | This is a deliberate choice, because it is what most consumers | |||
| expect, and runaway recursion is bad news. | expect, and runaway recursion is bad news. | |||
| Note that an implementation of "sop decrypt" MAY choose to handle | Note that an implementation of "sop decrypt" MAY choose to handle | |||
| more complex structures, but if it does, it should document the other | more complex structures, but if it does, it should document the other | |||
| structures it handles and why it chooses to do so. We can use such | structures it handles and why it chooses to do so. We can use such | |||
| documentation to improve future versions of this spec. | documentation to improve future versions of this spec. | |||
| 6.3. Validate Signatures Only From Known Signers | 7.3. Validate Signatures Only From Known Signers | |||
| There are generally only a few signers who are relevant for a given | There are generally only a few signers who are relevant for a given | |||
| OpenPGP message. When verifying signatures, "sop" expects that the | OpenPGP message. When verifying signatures, "sop" expects that the | |||
| caller can identify those relevant signers ahead of time. | caller can identify those relevant signers ahead of time. | |||
| 6.4. Detached Signatures | 7.4. Detached Signatures | |||
| "sop" deals with detached signatures as the baseline form of OpenPGP | "sop" deals with detached signatures as the baseline form of OpenPGP | |||
| signatures. | signatures. | |||
| The main problem this avoids is the trickiness of handling a | The main problem this avoids is the trickiness of handling a | |||
| signature that is mixed inline into the data that it is signing. | signature that is mixed inline into the data that it is signing. | |||
| 6.5. Reliance on Supplied Certs and Keys | 7.5. Reliance on Supplied Certs and Keys | |||
| A truly stateless implementation may find that it spends more time | A truly stateless implementation may find that it spends more time | |||
| validating the internal consistency of certificates and keys than it | validating the internal consistency of certificates and keys than it | |||
| does on the actual object security operations. | does on the actual object security operations. | |||
| For performance reasons, an implementation may choose to ignore | For performance reasons, an implementation may choose to ignore | |||
| validation on certificate and key material supplied to it. The | validation on certificate and key material supplied to it. The | |||
| security implications are of doing so depend on how the certs and | security implications are of doing so depend on how the certs and | |||
| keys are managed outside of "sop". | keys are managed outside of "sop". | |||
| 7. Guidance for Consumers | 8. Guidance for Consumers | |||
| While "sop" is originally conceived of as an interface for | While "sop" is originally conceived of as an interface for | |||
| interoperability testing, it's conceivable that an application that | interoperability testing, it's conceivable that an application that | |||
| uses OpenPGP for object security would want to use it. | uses OpenPGP for object security would want to use it. | |||
| FIXME: more guidance for how to use such a tool safely and | FIXME: more guidance for how to use such a tool safely and | |||
| efficiently goes here. | efficiently goes here. | |||
| FIXME: if an encrypted OpenPGP message arrives without metadata, it | FIXME: if an encrypted OpenPGP message arrives without metadata, it | |||
| is difficult to know which signers to consider when decrypting. How | is difficult to know which signers to consider when decrypting. How | |||
| do we do this efficiently without invoking "sop decrypt" twice, once | do we do this efficiently without invoking "sop decrypt" twice, once | |||
| without "--verify-*" and again with the expected identity material? | without "--verify-*" and again with the expected identity material? | |||
| 8. Security Considerations | 9. Security Considerations | |||
| The OpenPGP object security model is typically used for | The OpenPGP object security model is typically used for | |||
| confidentiality and authenticity purposes. | confidentiality and authenticity purposes. | |||
| 8.1. Signature Verification | 9.1. Signature Verification | |||
| In many contexts, an OpenPGP signature is verified, to prove the | In many contexts, an OpenPGP signature is verified, to prove the | |||
| origin and integrity of an underlying object. | origin and integrity of an underlying object. | |||
| When "sop" checks a signature (e.g. via "sop verify" or "sop decrypt | When "sop" checks a signature (e.g. via "sop verify" or "sop decrypt | |||
| --verify-with", it should only consider it to be verified only if at | --verify-with", it MUST NOT consider it to be verified unless all of | |||
| least all of these conditions are met: | these conditions are met: | |||
| o The signature must be made by a signing-capable public key that is | o The signature must be made by a signing-capable public key that is | |||
| present in one of the supplied "CERT"s | present in one of the supplied certificates | |||
| o The "CERT" and signing subkey must have been created before or at | o The certificate and signing subkey must have been created before | |||
| the signature time | or at the signature time | |||
| o The "CERT" and signing subkey must not have been expired at the | o The cetificate and signing subkey must not have been expired at | |||
| signature time | the signature time | |||
| o The "CERT" and signing subkey must not be revoked with a "hard" | o The certificate and signing subkey must not be revoked with a | |||
| revocation | "hard" revocation | |||
| o If the "CERT" or signing subkey is revoked with a "soft" | o If the certificate or signing subkey is revoked with a "soft" | |||
| revocation, then the signature time must predate the revocation | revocation, then the signature time must predate the revocation | |||
| o The signing subkey must be properly bound to the primary key, and | o The signing subkey must be properly bound to the primary key, and | |||
| cross-signed | cross-signed | |||
| o The signature (and any dependent signature, such as the cross-sig | o The signature (and any dependent signature, such as the cross-sig | |||
| or subkey binding signatures) must be made with strong | or subkey binding signatures) must be made with strong | |||
| cryptographic algorithms (e.g., not "MD5" or a 1024-bit "RSA" key) | cryptographic algorithms (e.g., not "MD5" or a 1024-bit "RSA" key) | |||
| Implementers should typically also consider other factors in addition | Implementers MAY also consider other factors in addition to the | |||
| to the origin and authenticity, including application-specific | origin and authenticity, including application-specific information. | |||
| information. | ||||
| For example, consider the application domain of checking software | For example, consider the application domain of checking software | |||
| updates. | updates. | |||
| If software package Foo version 13.3.2 was signed on 2019-10-04, and | If software package Foo version 13.3.2 was signed on 2019-10-04, and | |||
| the user receives a copy of Foo version 12.4.8 that was signed on | the user receives a copy of Foo version 12.4.8 that was signed on | |||
| 2019-10-16, it may be authentic and have a more recent signature | 2019-10-16, it may be authentic and have a more recent signature | |||
| date. But it is not an upgrade (12.4.8 < 13.3.2), and therefore it | date. But it is not an upgrade (12.4.8 < 13.3.2), and therefore it | |||
| should not be applied automatically. | should not be applied automatically. | |||
| In such cases, it is critical that the application confirms that the | In such cases, it is critical that the application confirms that the | |||
| other information verified is _also_ protected by the relevant | other information verified is _also_ protected by the relevant | |||
| OpenPGP signature. | OpenPGP signature. | |||
| Signature validity is a complex topic, and this documentation cannot | Signature validity is a complex topic, and this documentation cannot | |||
| list all possible details. | list all possible details. | |||
| 8.2. Compression | 9.2. Compression | |||
| The interface as currently specified does not allow for control of | The interface as currently specified does not allow for control of | |||
| compression. Compressing and encrypting data that may contain both | compression. Compressing and encrypting data that may contain both | |||
| attacker-supplied material and sensitive material could leak | attacker-supplied material and sensitive material could leak | |||
| information about the sensitive material (see the CRIME attack). | information about the sensitive material (see the CRIME attack). | |||
| Unless an application knows for sure that no attacker-supplied | Unless an application knows for sure that no attacker-supplied | |||
| material is present on the input, it should not compress during | material is present on the input, it should not compress during | |||
| encryption. | encryption. | |||
| 9. Privacy Considerations | 10. Privacy Considerations | |||
| Material produced by "sop encrypt" may be placed on untrusted machine | Material produced by "sop encrypt" may be placed on an untrusted | |||
| (e.g., sent through the public "SMTP" network). That material may | machine (e.g., sent through the public "SMTP" network). That | |||
| contain metadata that leaks associational information (e.g., | material may contain metadata that leaks associational information | |||
| recipient identifiers in PKESK packets). FIXME: document things like | (e.g., recipient identifiers in PKESK packets). FIXME: document | |||
| PURBs and "--hidden-recipient") | things like PURBs and "--hidden-recipient") | |||
| 9.1. Object Security vs. Transport Security | 10.1. Object Security vs. Transport Security | |||
| OpenPGP offers an object security model, but says little to nothing | OpenPGP offers an object security model, but says little to nothing | |||
| about how the secured objects get to the relevant parties. | about how the secured objects get to the relevant parties. | |||
| When sending or receiving OpenPGP material, the implementer should | When sending or receiving OpenPGP material, the implementer should | |||
| consider what privacy leakage is implicit with the transport. | consider what privacy leakage is implicit with the transport. | |||
| 10. Document Considerations | 11. Document Considerations | |||
| [ RFC Editor: please remove this section before publication ] | [ RFC Editor: please remove this section before publication ] | |||
| This document is currently edited as markdown. Minor editorial | This document is currently edited as markdown. Minor editorial | |||
| changes can be suggested via merge requests at | changes can be suggested via merge requests at | |||
| https://gitlab.com/dkg/openpgp-stateless-cli or by e-mail to the | https://gitlab.com/dkg/openpgp-stateless-cli or by e-mail to the | |||
| authors. Please direct all significant commentary to the public IETF | authors. Please direct all significant commentary to the public IETF | |||
| OpenPGP mailing list: openpgp@ietf.org | OpenPGP mailing list: openpgp@ietf.org | |||
| 10.1. Document History | 11.1. Document History | |||
| 10.2. Future Work | substantive changes between -00 and -01: | |||
| o "split" subcommand (split a clearsigned message into a message and | o Changed "generate" subcommand to "generate-key" | |||
| a detached signature) (see Section 6.4 | ||||
| o Changed "convert" subcommand to "extract-cert" | ||||
| o Added "Input String Types" section as distinct from indirect I/O | ||||
| o Made implicit arguments potentially explicit (e.g. "sop armor | ||||
| --label=auto") | ||||
| o Added "--allow-nested" to "sop armor" to make it idempotent by | ||||
| default | ||||
| o Added fingerprint of signing (sub)key to "VERIFICATIONS" output | ||||
| o Dropped "--mode" and "--session-key" arguments for "sop encrypt" | ||||
| (no plausible use, not needed for interop) | ||||
| o Added "--with-session-key" argument to "sop decrypt" to allow for | ||||
| session-key-based decryption | ||||
| o Added examples to each subcommand | ||||
| o More detailed error codes for "sop encrypt" | ||||
| o Move from "CERT" to "CERTS" (each "CERTS" argument might contain | ||||
| multiple certificates) | ||||
| 11.2. Future Work | ||||
| o "detach-inband-signature-and-message" subcommand (split a | ||||
| clearsigned message into a message and a detached signature) (see | ||||
| Section 7.4 | ||||
| o certificate transformation into popular publication forms: | o certificate transformation into popular publication forms: | |||
| * WKD | * WKD | |||
| * DANE OPENPGPKEY | * DANE OPENPGPKEY | |||
| * Autocrypt | * Autocrypt | |||
| o "sop encrypt" - specify compression? (see Section 8.2) | o "sop encrypt" - specify compression? (see Section 9.2) | |||
| o "sop encrypt" - specify padding policy/mechanism? | o "sop encrypt" - specify padding policy/mechanism? | |||
| o "sop decrypt" - how can it more safely handle zip bombs? | o "sop decrypt" - how can it more safely handle zip bombs? | |||
| o "sop decrypt" - what should it do when encountering weakly- | o "sop decrypt" - what should it do when encountering weakly- | |||
| encrypted (or unencrypted) input? | encrypted (or unencrypted) input? | |||
| o "sop encrypt" - minimize metadata (e.g. "--throw-keyids")? | o "sop encrypt" - minimize metadata (e.g. "--throw-keyids")? | |||
| o handling secret keys that are locked with passwords? | o handling secret keys that are locked with passwords? | |||
| o do we need an interface (for performance?) that says "don't | o specify an error if a "DATE" arrives as input without a time zone? | |||
| validate certificates internally, just accept whatever's given as | ||||
| legit data"? (see Section 6.5) | ||||
| 11. Acknowledgements | o specify an error if a "sop" invocation sees multiple copies of a | |||
| specific "@FD:n" input (e.g., "sop sign @FD:3 @FD:3") | ||||
| o add considerations about what it means for armored "CERTS" to | ||||
| contain multiple certificates - multiple armorings? one big blob? | ||||
| o do we need an interface or option (for performance?) with the | ||||
| semantics that "sop" doesn't validate certificates internally, it | ||||
| just accepts whatever's given as legit data? (see Section 7.5) | ||||
| 12. Acknowledgements | ||||
| This work was inspired by Justus Winter's | This work was inspired by Justus Winter's | |||
| [OpenPGP-Interoperability-Test-Suite], and discussions with Justus. | [OpenPGP-Interoperability-Test-Suite]. | |||
| Problems with this spec are not his fault. | ||||
| 12. References | The following people contributed helpful feedback and considerations | |||
| to this draft, but are not responsible for its problems: | ||||
| 12.1. Normative References | o Justus Winter | |||
| o Vincent Breitmoser | ||||
| o Edwin Taylor | ||||
| o Jameson Rollins | ||||
| o Allan Nordhoey | ||||
| 13. References | ||||
| 13.1. Normative References | ||||
| [I-D.ietf-openpgp-rfc4880bis] | [I-D.ietf-openpgp-rfc4880bis] | |||
| Koch, W., carlson, b., Tse, R., Atkins, D., and D. | Koch, W., carlson, b., Tse, R., Atkins, D., and D. | |||
| Gillmor, "OpenPGP Message Format", draft-ietf-openpgp- | Gillmor, "OpenPGP Message Format", draft-ietf-openpgp- | |||
| rfc4880bis-08 (work in progress), September 2019. | rfc4880bis-08 (work in progress), September 2019. | |||
| [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
| Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
| DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
| <https://www.rfc-editor.org/info/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
| [RFC4880] Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. | [RFC4880] Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. | |||
| Thayer, "OpenPGP Message Format", RFC 4880, | Thayer, "OpenPGP Message Format", RFC 4880, | |||
| DOI 10.17487/RFC4880, November 2007, | DOI 10.17487/RFC4880, November 2007, | |||
| <https://www.rfc-editor.org/info/rfc4880>. | <https://www.rfc-editor.org/info/rfc4880>. | |||
| [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
| 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
| May 2017, <https://www.rfc-editor.org/info/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
| 12.2. Informative References | 13.2. Informative References | |||
| [I-D.draft-bre-openpgp-samples-00] | [I-D.draft-bre-openpgp-samples-00] | |||
| Einarsson, B., juga, j., and D. Gillmor, "OpenPGP Example | Einarsson, B., juga, j., and D. Gillmor, "OpenPGP Example | |||
| Keys and Certificates", draft-bre-openpgp-samples-00 (work | Keys and Certificates", draft-bre-openpgp-samples-00 (work | |||
| in progress), October 2019. | in progress), October 2019. | |||
| [OpenPGP-Interoperability-Test-Suite] | [OpenPGP-Interoperability-Test-Suite] | |||
| "OpenPGP Interoperability Test Suite", October 2019, | "OpenPGP Interoperability Test Suite", October 2019, | |||
| <https://tests.sequoia-pgp.org/>. | <https://tests.sequoia-pgp.org/>. | |||
| End of changes. 109 change blocks. | ||||
| 187 lines changed or deleted | 381 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||