<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version  (Ruby 3.1.2) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-dkg-openpgp-stateless-cli-09" category="info" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title>Stateless OpenPGP Command Line Interface</title>

    <author initials="D. K." surname="Gillmor" fullname="Daniel Kahn Gillmor">
      <organization abbrev="ACLU">American Civil Liberties Union</organization>
      <address>
        <postal>
          <street>125 Broad St.</street>
          <city>New York, NY</city>
          <code>10004</code>
          <country>USA</country>
        </postal>
        <email>dkg@fifthhorseman.net</email>
      </address>
    </author>

    <date year="2023" month="December" day="27"/>

    <area>int</area>
    <workgroup>openpgp</workgroup>
    <keyword>Internet-Draft</keyword>

    <abstract>


<t>This document defines a generic stateless command-line interface for dealing with OpenPGP messages, known as <spanx style="verb">sop</spanx>.
It aims for a minimal, well-structured API covering OpenPGP object security.</t>



    </abstract>

    <note title="About This Document" removeInRFC="true">
      <t>
        The latest revision of this draft can be found at <eref target="https://dkg.gitlab.io/openpgp-stateless-cli/"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-dkg-openpgp-stateless-cli/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        OpenPGP Working Group mailing list (<eref target="mailto:openpgp@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/openpgp/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/openpgp/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://gitlab.com/dkg/openpgp-stateless-cli/"/>.</t>
    </note>


  </front>

  <middle>


<section anchor="introduction"><name>Introduction</name>

<t>Different OpenPGP implementations have many different requirements, which typically break down in two main categories: key/certificate management and object security.</t>

<t>The purpose of this document is to provide a "stateless" interface that primarily handles the object security side of things, and assumes that secret key management and certificate management will be handled some other way.</t>

<t>Isolating object security from key/certificate management should make it easier to provide interoperability testing for the object security side of OpenPGP implementations, as described in <xref target="test-suite"/>.</t>

<t>This document defines a generic stateless command-line interface for dealing with OpenPGP messages, known here by the placeholder <spanx style="verb">sop</spanx>.
It aims for a minimal, well-structured API.</t>

<t>An OpenPGP implementation should not name its executable <spanx style="verb">sop</spanx> to implement this specification.  It just needs to provide a program that conforms to this interface.</t>

<t>A <spanx style="verb">sop</spanx> implementation should leave no trace on the system, and its behavior should not be affected by anything other than command-line arguments and input.</t>

<t>Obviously, the user will need to manage their secret keys (and their peers' certificates) somehow,
but the goal of this interface is to separate out that task from the task of interacting with OpenPGP messages.</t>

<t>While this document identifies a command-line interface,
the rough outlines of this interface should also be amenable to relatively straightforward library implementations in different languages.</t>

<section anchor="requirements-language"><name>Requirements Language</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

</section>
<section anchor="terminology"><name>Terminology</name>

<t>This document uses the term "key" to refer exclusively to OpenPGP Transferable Secret Keys (see <xref section="11.2" sectionFormat="of" target="RFC4880"/>).</t>

<t>It uses the term "certificate" to refer to OpenPGP Transferable Public Key (see <xref section="11.1" sectionFormat="of" target="RFC4880"/>).</t>

<t>"Stateless" in "Stateless OpenPGP" means avoiding secret key and certificate state.
The user is responsible for managing all OpenPGP certificates and secret keys themselves,
and passing them to <spanx style="verb">sop</spanx> as needed.
The user should also not be concerned that any state could affect the underlying operations.</t>

<t>OpenPGP revocations can have "Reason for Revocation" (<xref section="5.2.3.23" sectionFormat="of" target="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.</t>

</section>
<section anchor="test-suite"><name>Using sop in a Test Suite</name>

<t>If an OpenPGP implementation provides a <spanx style="verb">sop</spanx> interface, it can be used to test interoperability (e.g., <xref target="OpenPGP-Interoperability-Test-Suite"></xref>).</t>

<t>Such an interop test suite can, for example, use custom code (<em>not</em> <spanx style="verb">sop</spanx>) to generate a new OpenPGP object that incorporates new primitives, and feed that object to a stable of <spanx style="verb">sop</spanx> implementations, to determine whether those implementations can consume the new form.</t>

<t>Or, the test suite can drive each <spanx style="verb">sop</spanx> implementation with a simple input, and observe which cryptographic primitives each implementation chooses to use as it produces output.</t>

</section>
<section anchor="semantics-vs-wire-format"><name>Semantics vs. Wire Format</name>

<t>The semantics of <spanx style="verb">sop</spanx> are deliberately simple and very high-level compared to the vast complexity and nuance available within the OpenPGP specification.
This reflects the perspective of nearly every piece of tooling that relies on OpenPGP to accomplish its task: most toolchains don't care about the specifics, they just want the high-level object security properties.</t>

<t>Given this framing, this document generally tries to avoid overconstraining the details of the wire format objects emitted, or what kinds of wire format structures should be acceptable or unacceptable.
This allows a test suite to evaluate and contrast the wire format choices made by different implementations in as close to their native configuration as possible.
It also makes it easier to promote interoperability by ensuring that the native wire formats emitted by one implementation can be consumed by another, without relying on their choices of wire format being constrained by this draft.</t>

<t>Where this draft does identify specific wire format requirements, that might be due to an ambiguity in the existing specifications (which maybe needs fixing elsewhere), or to a bug in this specification that could be improved.</t>

</section>
</section>
<section anchor="examples"><name>Examples</name>

<t>These examples show no error checking, but give a flavor of how <spanx style="verb">sop</spanx> might be used in practice from a shell.</t>

<t>The key and certificate files described in them (e.g., <spanx style="verb">alice.sec</spanx>) could be for example those found in <xref target="I-D.draft-bre-openpgp-samples-01"/>.</t>

<figure><artwork><![CDATA[
sop generate-key "Alice Lovelace <alice@openpgp.example>" > alice.sec
sop extract-cert < alice.sec > alice.pgp

sop generate-key "Bob Babbage <bob@openpgp.example>" > bob.sec
sop extract-cert < bob.sec > bob.pgp

sop sign --as=text alice.sec < statement.txt > statement.txt.asc
sop verify statement.txt.asc alice.pgp < statement.txt

sop encrypt --sign-with=alice.sec bob.pgp < msg.eml > ciphertext.asc
sop decrypt bob.sec < ciphertext.asc > cleartext.eml
]]></artwork></figure>

<t>See <xref target="failure-modes"/> for more information about errors and error handling.</t>

</section>
<section anchor="subcommands"><name>Subcommands</name>

<t><spanx style="verb">sop</spanx> uses a subcommand interface, similar to those popularized by systems like <spanx style="verb">git</spanx> and <spanx style="verb">svn</spanx>.</t>

<t>If the user supplies a subcommand that <spanx style="verb">sop</spanx> does not implement, it fails with <spanx style="verb">UNSUPPORTED_SUBCOMMAND</spanx>.
If a <spanx style="verb">sop</spanx> implementation does not handle a supplied option for a given subcommand, it fails with <spanx style="verb">UNSUPPORTED_OPTION</spanx>.</t>

<t>All subcommands that produce OpenPGP material on standard output produce ASCII-armored (<xref section="6" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>) objects by default (except for <spanx style="verb">sop dearmor</spanx>).
These subcommands have a <spanx style="verb">--no-armor</spanx> option, which causes them to produce binary OpenPGP material instead.</t>

<t>All subcommands that accept OpenPGP material on input should be able to accept either ASCII-armored or binary inputs (see <xref target="optional-input-armoring"/>) and behave accordingly.</t>

<t>See <xref target="indirect-types"/> for details about how various forms of OpenPGP material are expected to be structured.</t>

<section anchor="meta-subcommands"><name>Meta Subcommands</name>

<t>The subcommands grouped in this section are related to the <spanx style="verb">sop</spanx> implementation itself.</t>

<section anchor="version"><name>version: Version Information</name>

<figure><artwork><![CDATA[
sop version [--backend|--extended|--sop-spec]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: ignored</t>
  <t>Standard Output: version information</t>
</list></t>

<t>This subcommand emits version information as UTF-8-encoded text.</t>

<t>With no arguments, the version string emitted should contain the name of the <spanx style="verb">sop</spanx> implementation, followed by a single space, followed by the version number.
A <spanx style="verb">sop</spanx> implementation should use a version number that respects an established standard that is easily comparable and parsable, like <xref target="SEMVER"></xref>.</t>

<t>If <spanx style="verb">--backend</spanx> is supplied, the implementation should produce a comparable line of implementation and version information about the primary underlying OpenPGP toolkit.</t>

<t>If <spanx style="verb">--extended</spanx> is supplied, the implementation may emit multiple lines of version information.
The first line <bcp14>MUST</bcp14> match the information produced by a simple invocation, but the rest of the text has no defined structure.</t>

<t>If <spanx style="verb">--sop-spec</spanx> is supplied, the implementation should emit a single line of text indicating the latest version of this draft that it targets, for example, <spanx style="verb">draft-dkg-openpgp-stateless-cli-06</spanx>.
If the implementation targets a specific draft but the implementer knows the implementation is incomplete, it should prefix the draft title with a <u>~</u>, for example: <spanx style="verb">~draft-dkg-openpgp-stateless-cli-06</spanx>.
The implementation <bcp14>MAY</bcp14> emit additional text about its relationship to the targeted draft on the lines following the versioned title.</t>

<t><spanx style="verb">--backend</spanx>, <spanx style="verb">--extended</spanx>, and <spanx style="verb">--sop-spec</spanx> are mutually-exclusive options.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop version
ExampleSop 0.2.1
$ sop version --backend
LibExamplePGP 3.4.2
$ sop version --extended
ExampleSop 0.2.1
Running on MonkeyScript 4.5
LibExamplePGP 3.4.2
LibExampleCrypto 3.1.1
LibXCompression 4.0.2
See https://pgp.example/sop/ for more information
$ sop version --sop-spec
~draft-dkg-openpgp-stateless-cli-06

This implementation does not handle @FD: special designators for output.
$
]]></artwork></figure>

</section>
<section anchor="list-profiles"><name>list-profiles: Describe Available Profiles</name>

<figure><artwork><![CDATA[
sop list-profiles SUBCOMMAND
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: ignored</t>
  <t>Standard Output: PROFILELIST (<xref target="profilelist"/>)</t>
</list></t>

<t>This subcommand emits a list of profiles supported by the identified subcommand.
The first profile listed is the default profile, as described in <xref target="profilelist"/>.</t>

<t>If the indicated <spanx style="verb">SUBCOMMAND</spanx> does not accept a <spanx style="verb">--profile</spanx> option, it returns <spanx style="verb">UNSUPPORTED_PROFILE</spanx>.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop list-profiles generate-key
default: use the implementer's recommendations
rfc4880: use algorithms from RFC 4880
$
]]></artwork></figure>

</section>
</section>
<section anchor="key-and-certificate-management-subcommands"><name>Key and Certificate Management Subcommands</name>

<t>The subcommands grouped in this section are primarily intended to manipulate keys and certificates.</t>

<section anchor="generate-key"><name>generate-key: Generate a Secret Key</name>

<figure><artwork><![CDATA[
sop generate-key [--no-armor]
    [--with-key-password=PASSWORD]
    [--profile=PROFILE]
    [--signing-only]
    [--] [USERID...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: ignored</t>
  <t>Standard Output: <spanx style="verb">KEYS</spanx> (<xref target="keys"/>)</t>
</list></t>

<t>Generate a single default OpenPGP key with zero or more User IDs.</t>

<t>The generated secret key <bcp14>SHOULD</bcp14> be usable for as much of the <spanx style="verb">sop</spanx> functionality as possible.
In particular:</t>

<t><list style="symbols">
  <t>It should be possible to extract an OpenPGP certificate from the key in <spanx style="verb">KEYS</spanx> with <spanx style="verb">sop extract-cert</spanx>.</t>
  <t>The key in <spanx style="verb">KEYS</spanx> should be able to create signatures (with <spanx style="verb">sop sign</spanx>) that are verifiable by using <spanx style="verb">sop verify</spanx> with the extracted certificate.</t>
  <t>Unless the <spanx style="verb">--signing-only</spanx> parameter is supplied, the key in <spanx style="verb">KEYS</spanx> should be able to decrypt messages (with <spanx style="verb">sop decrypt</spanx>) that are encrypted by using <spanx style="verb">sop encrypt</spanx> with the extracted certificate.</t>
</list></t>

<t>The detailed internal structure of the certificate is left to the discretion of the <spanx style="verb">sop</spanx> implementation.</t>

<t>If the <spanx style="verb">--with-key-password</spanx> option is supplied, the generated key will be password-protected (locked) with the supplied password.
Note that <spanx style="verb">PASSWORD</spanx> is an indirect data type from which the actual password is acquired (<xref target="indirect-types"/>).
See also the guidance on ensuring that the password is human-readable in <xref target="generating-human-readable"/>.</t>

<t>If no <spanx style="verb">--with-key-password</spanx> option is supplied, the generated key will be unencrypted.</t>

<t>If the <spanx style="verb">--profile</spanx> argument is supplied and the indicated <spanx style="verb">PROFILE</spanx> is not supported by the implementation, <spanx style="verb">sop</spanx> will fail with <spanx style="verb">UNSUPPORTED_PROFILE</spanx>.</t>

<t>The presence of the <spanx style="verb">--signing-only</spanx> option is intended to create a key that is only capable of signing, not decrypting.
This is useful for deployments where only signing and verification are necessary.</t>

<t>If any of the <spanx style="verb">USERID</spanx> options are not valid <spanx style="verb">UTF-8</spanx>, <spanx style="verb">sop generate-key</spanx> fails with <spanx style="verb">EXPECTED_TEXT</spanx>.</t>

<t>If the implementation rejects any <spanx style="verb">USERID</spanx> option that is valid <spanx style="verb">UTF-8</spanx> (e.g., due to internal policy, see <xref target="userid"/>), <spanx style="verb">sop generate-key</spanx> fails with <spanx style="verb">BAD_DATA</spanx>.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop generate-key 'Alice Lovelace <alice@openpgp.example>' > alice.sec
$ head -n1 < alice.sec
-----BEGIN PGP PRIVATE KEY BLOCK-----
$
]]></artwork></figure>

</section>
<section anchor="change-key-password"><name>change-key-password: Update a Key's Password</name>

<figure><artwork><![CDATA[
sop change-key-password [--no-armor]
    [--new-key-password=PASSWORD]
    [--old-key-password=PASSWORD...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">KEYS</spanx> (<xref target="keys"/>)</t>
  <t>Standard Output: <spanx style="verb">KEYS</spanx> (<xref target="keys"/>)</t>
</list></t>

<t>The output will be the same set of OpenPGP Transferable Secret Keys as the input, but with all secret key material locked according to the password indicated by the <spanx style="verb">--new-key-password</spanx> option (or, with no password at all, if <spanx style="verb">--new-key-password</spanx> is absent).
Note that <spanx style="verb">--old-key-password</spanx> can be supplied multiple times, and each supplied password will be tried as a means to unlock any locked key material encountered.
It will normalize a Transferable Secret Key to use a single password even if it originally had distinct passwords locking each of the subkeys.</t>

<t>If any secret key packet is locked but cannot be unlocked with any of the supplied <spanx style="verb">--old-key-password</spanx> arguments, this subcommand should fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
# adding a password to an unlocked key:
$ sop change-key-password --new-key-password=@ENV:keypass < unlocked.key > locked.key
# removing a password:
$ sop change-key-password --old-key-password=@ENV:keypass < locked.key > unlocked.key
# changing a password:
$ sop change-key-password --old-key-password=@ENV:keypass --new-key-password=@ENV:newpass < locked.key > refreshed.key
$
]]></artwork></figure>

</section>
<section anchor="revoke-key"><name>revoke-key: Create a Revocation Certificate</name>

<figure><artwork><![CDATA[
sop revoke-key [--no-armor]
    [--with-key-password=PASSWORD...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">KEYS</spanx> (<xref target="keys"/>)</t>
  <t>Standard Output: <spanx style="verb">CERTS</spanx> (<xref target="certs"/>)</t>
</list></t>

<t>Generate a revocation certificate for each Transferable Secret Key found.
See <xref section="10" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/> for a discussion of common forms of revocation certificate.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop revoke-key < alice.key > alice-revoked.pgp
$
]]></artwork></figure>

</section>
<section anchor="extract-cert"><name>extract-cert: Extract a Certificate from a Secret Key</name>

<figure><artwork><![CDATA[
sop extract-cert [--no-armor]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">KEYS</spanx> (<xref target="keys"/>)</t>
  <t>Standard Output: <spanx style="verb">CERTS</spanx> (<xref target="certs"/>)</t>
</list></t>

<t>The output should contain one OpenPGP certificate in <spanx style="verb">CERTS</spanx> per OpenPGP Transferable Secret Key found in <spanx style="verb">KEYS</spanx>.
There is no guarantee what order the <spanx style="verb">CERTS</spanx> will be in.</t>

<t><spanx style="verb">sop extract-cert</spanx> <bcp14>SHOULD</bcp14> work even if any of the keys in <spanx style="verb">KEYS</spanx> is password-protected.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop extract-cert < alice.sec > alice.pgp
$ head -n1 < alice.pgp
-----BEGIN PGP PUBLIC KEY BLOCK-----
$
]]></artwork></figure>

</section>
</section>
<section anchor="messaging-subcommands"><name>Messaging Subcommands</name>

<t>The subcommands in this section handle OpenPGP messages: encrypting, decrypting, signing, and verifying.</t>

<section anchor="sign"><name>sign: Create Detached Signatures</name>

<figure><artwork><![CDATA[
sop sign [--no-armor] [--micalg-out=MICALG]
     [--with-key-password=PASSWORD...]
     [--as={binary|text}] [--] KEYS [KEYS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
  <t>Standard Output: <spanx style="verb">SIGNATURES</spanx> (<xref target="signature"/>)</t>
</list></t>

<t>Exactly one signature will be made by each key in the supplied <spanx style="verb">KEYS</spanx> arguments.</t>

<t><spanx style="verb">--as</spanx> defaults to <spanx style="verb">binary</spanx>.
If <spanx style="verb">--as=text</spanx> and the input <spanx style="verb">DATA</spanx> is not valid <spanx style="verb">UTF-8</spanx> (<xref target="utf8"/>), <spanx style="verb">sop sign</spanx> fails with <spanx style="verb">EXPECTED_TEXT</spanx>.</t>

<t><spanx style="verb">--as=binary</spanx> <bcp14>SHOULD</bcp14> result in OpenPGP signatures of type 0x00 ("Signature of a binary document").
<spanx style="verb">--as=text</spanx> <bcp14>SHOULD</bcp14> result in OpenPGP signatures of type 0x01 ("Signature of a canonical text document").
See <xref section="5.2.1" sectionFormat="of" target="RFC4880"/> for more details.</t>

<t>When generating PGP/MIME messages (<xref target="RFC3156"/>), it is useful to know what digest algorithm was used for the generated signature.
When <spanx style="verb">--micalg-out</spanx> is supplied, <spanx style="verb">sop sign</spanx> emits the digest algorithm used to the specified <spanx style="verb">MICALG</spanx> file in a way that can be used to populate the <spanx style="verb">micalg</spanx> parameter for the Content-Type (see <xref target="micalg"/>).
If the specified <spanx style="verb">MICALG</spanx> file already exists in the filesystem, <spanx style="verb">sop sign</spanx> will fail with <spanx style="verb">OUTPUT_EXISTS</spanx>.
When <spanx style="verb">--micalg-out</spanx> is supplied, the <spanx style="verb">DATA</spanx> on standard input should already be in canonical text form (7-bit clean, CRLF line endings, no trailing whitespace), as specified in <xref section="3" sectionFormat="of" target="RFC3156"/>.
If the incoming <spanx style="verb">DATA</spanx> does not already meet these requirements, <spanx style="verb">sop sign</spanx> will fail with <spanx style="verb">EXPECTED_TEXT</spanx>, regardless of any argument supplied for <spanx style="verb">--as</spanx>.</t>

<t>When signing with multiple keys, <spanx style="verb">sop sign</spanx> <bcp14>SHOULD</bcp14> use the same digest algorithm for every signature generated in a single run, unless there is some internal constraint on the <spanx style="verb">KEYS</spanx> objects.
If <spanx style="verb">--micalg-out</spanx> is requested, and multiple incompatibly-constrained <spanx style="verb">KEYS</spanx> objects are supplied, <spanx style="verb">sop sign</spanx> <bcp14>MUST</bcp14> emit the empty string to the designated <spanx style="verb">MICALG</spanx>.</t>

<t>If the signing key material in any key in the <spanx style="verb">KEYS</spanx> objects is password-protected, <spanx style="verb">sop sign</spanx> <bcp14>SHOULD</bcp14> try all supplied <spanx style="verb">--with-key-password</spanx> options to unlock the key material until it finds one that enables the use of the key for signing.
If none of the <spanx style="verb">PASSWORD</spanx> options unlock the key (or if no such option is supplied), <spanx style="verb">sop sign</spanx> will fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.
Note that <spanx style="verb">PASSWORD</spanx> is an indirect data type from which the actual password is acquired (<xref target="indirect-types"/>).
Note also the guidance for retrying variants of a non-human-readable password in <xref target="consuming-passwords"/>.</t>

<t>If any key in the <spanx style="verb">KEYS</spanx> objects is not capable of producing a signature, <spanx style="verb">sop sign</spanx> will fail with <spanx style="verb">KEY_CANNOT_SIGN</spanx>.</t>

<t><spanx style="verb">sop sign</spanx> <bcp14>MUST NOT</bcp14> produce any extra signatures beyond those from <spanx style="verb">KEYS</spanx> objects supplied on the command line.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop sign --as=text alice.sec < message.txt > message.txt.asc
$ head -n1 < message.txt.asc
-----BEGIN PGP SIGNATURE-----
$
]]></artwork></figure>

</section>
<section anchor="verify"><name>verify: Verify Detached Signatures</name>

<figure><artwork><![CDATA[
sop verify [--not-before=DATE] [--not-after=DATE]
    [--] SIGNATURES CERTS [CERTS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
  <t>Standard Output: <spanx style="verb">VERIFICATIONS</spanx> (<xref target="verifications"/>)</t>
</list></t>

<t><spanx style="verb">--not-before</spanx> and <spanx style="verb">--not-after</spanx> indicate that signatures with dates outside certain range <bcp14>MUST NOT</bcp14> be considered valid.</t>

<t><spanx style="verb">--not-before</spanx> defaults to the beginning of time.
Accepts the special value <spanx style="verb">-</spanx> to indicate the beginning of time (i.e., no lower boundary).</t>

<t><spanx style="verb">--not-after</spanx> defaults to the current system time (<spanx style="verb">now</spanx>).
Accepts the special value <spanx style="verb">-</spanx> to indicate the end of time (i.e., no upper boundary).</t>

<t><spanx style="verb">sop verify</spanx> only returns <spanx style="verb">OK</spanx> if at least one certificate included in any <spanx style="verb">CERTS</spanx> object made a valid signature in the time window specified over the <spanx style="verb">DATA</spanx> supplied.</t>

<t>For details about the valid signatures, the user <bcp14>MUST</bcp14> inspect the <spanx style="verb">VERIFICATIONS</spanx> output.</t>

<t>If no <spanx style="verb">CERTS</spanx> are supplied, <spanx style="verb">sop verify</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>If no valid signatures are found, <spanx style="verb">sop verify</spanx> fails with <spanx style="verb">NO_SIGNATURE</spanx>.</t>

<t>See <xref target="signature-verification"/> for more details about signature verification.</t>

<t>Example:</t>

<t>(In this example, we see signature verification succeed first, and then fail on a modified version of the message.)</t>

<figure><artwork><![CDATA[
$ sop verify message.txt.asc alice.pgp < message.txt
2019-10-29T18:36:45Z EB85BB5FA33A75E15E944E63F231550C4F47E38E EB85BB5FA33A75E15E944E63F231550C4F47E38E mode:text signed by alice.pgp
$ echo $?
0
$ tr a-z A-Z < message.txt | sop verify message.txt.asc alice.pgp
$ echo $?
3
$
]]></artwork></figure>

</section>
<section anchor="encrypt"><name>encrypt: Encrypt a Message</name>

<figure><artwork><![CDATA[
sop encrypt [--as={binary|text}]
    [--no-armor]
    [--with-password=PASSWORD...]
    [--sign-with=KEYS...]
    [--with-key-password=PASSWORD...]
    [--profile=PROFILE]
    [--session-key-out=SESSIONKEY]
    [--] [CERTS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
  <t>Standard Output: <spanx style="verb">CIPHERTEXT</spanx> (<xref target="ciphertext"/>)</t>
</list></t>

<t><spanx style="verb">--as</spanx> defaults to <spanx style="verb">binary</spanx>.
The setting of <spanx style="verb">--as</spanx> corresponds to the one octet format field found in the Literal Data packet at the core of the output <spanx style="verb">CIPHERTEXT</spanx>.
If <spanx style="verb">--as</spanx> is set to <spanx style="verb">binary</spanx>, the octet is <spanx style="verb">b</spanx> (<spanx style="verb">0x62</spanx>).
If it is <spanx style="verb">text</spanx>, the format octet is <spanx style="verb">u</spanx> (<spanx style="verb">0x75</spanx>).</t>

<t><spanx style="verb">--with-password</spanx> enables symmetric encryption (and can be used multiple times if multiple passwords are desired).</t>

<t><spanx style="verb">--sign-with</spanx> creates exactly one signature by for each secret key found in the supplied <spanx style="verb">KEYS</spanx> object (this can also be used multiple times if signatures from keys found in separaate files are desired).
If any key in any supplied <spanx style="verb">KEYS</spanx> object is not capable of producing a signature, <spanx style="verb">sop sign</spanx> will fail with <spanx style="verb">KEY_CANNOT_SIGN</spanx>.
If any signing key material in any supplied <spanx style="verb">KEYS</spanx> object is password-protected, <spanx style="verb">sop encrypt</spanx> <bcp14>SHOULD</bcp14> try all supplied <spanx style="verb">--with-key-password</spanx> options to unlock the key material until it finds one that enables the use of the key for signing.
If none of the <spanx style="verb">--with-key-password=PASSWORD</spanx> options can unlock any locked signing key material (or if no such option is supplied), <spanx style="verb">sop encrypt</spanx> will fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.
All signatures made must be placed inside the encryption produced by <spanx style="verb">sop encrypt</spanx>.</t>

<t>Note that both <spanx style="verb">--with-password</spanx> and <spanx style="verb">--with-key-password</spanx> supply <spanx style="verb">PASSWORD</spanx> arguments, but they do so in different contexts which are not interchangeable.
A <spanx style="verb">PASSWORD</spanx> supplied for symmetric encryption (<spanx style="verb">--with-password</spanx>) <bcp14>MUST NOT</bcp14> be used to try to unlock a signing key (<spanx style="verb">--with-key-password</spanx>) and a <spanx style="verb">PASSWORD</spanx> supplied to unlock a signing key <bcp14>MUST NOT</bcp14> be used to symmetrically encrypt the message.
Regardless of context, each <spanx style="verb">PASSWORD</spanx> argument is presented as an indirect data type from which the actual password is acquired (<xref target="indirect-types"/>).
If <spanx style="verb">sop encrypt</spanx> encounters a password which is not a valid <spanx style="verb">UTF-8</spanx> string (<xref target="utf8"/>), or is otherwise not robust in its representation to humans,
it fails with <spanx style="verb">PASSWORD_NOT_HUMAN_READABLE</spanx>.
If <spanx style="verb">sop encrypt</spanx> sees trailing whitespace at the end of a password,
it will trim the trailing whitespace before using the password.
See <xref target="human-readable-passwords"/> for more discussion about passwords.</t>

<t>If <spanx style="verb">--as</spanx> is set to <spanx style="verb">binary</spanx>, then <spanx style="verb">--sign-with</spanx> will sign as a binary document (OpenPGP signature type <spanx style="verb">0x00</spanx>).</t>

<t>If <spanx style="verb">--as</spanx> is set to <spanx style="verb">text</spanx>, then <spanx style="verb">--sign-with</spanx> will sign as a canonical text document (OpenPGP signature type <spanx style="verb">0x01</spanx>).
In this case, if the input <spanx style="verb">DATA</spanx> is not valid <spanx style="verb">UTF-8</spanx>  (<xref target="utf8"/>), <spanx style="verb">sop encrypt</spanx> fails with <spanx style="verb">EXPECTED_TEXT</spanx>.</t>

<t>If <spanx style="verb">--sign-with</spanx> is supplied for input <spanx style="verb">DATA</spanx> that is not valid <spanx style="verb">UTF-8</spanx>, <spanx style="verb">sop encrypt</spanx> <bcp14>MAY</bcp14> sign as a binary document (OpenPGP signature type <spanx style="verb">0x00</spanx>).</t>

<t><spanx style="verb">sop encrypt</spanx> <bcp14>MUST NOT</bcp14> produce any extra signatures beyond those from <spanx style="verb">KEYS</spanx> objects identified by <spanx style="verb">--sign-with</spanx>.</t>

<t>The resulting <spanx style="verb">CIPHERTEXT</spanx> should be decryptable by the secret keys corresponding to every certificate included in all <spanx style="verb">CERTS</spanx>, as well as each password given with <spanx style="verb">--with-password</spanx>.</t>

<t>If no <spanx style="verb">CERTS</spanx> or <spanx style="verb">--with-password</spanx> options are present, <spanx style="verb">sop encrypt</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>If at least one of the identified certificates requires encryption to an unsupported asymmetric algorithm, <spanx style="verb">sop encrypt</spanx> fails with <spanx style="verb">UNSUPPORTED_ASYMMETRIC_ALGO</spanx>.</t>

<t>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), <spanx style="verb">sop encrypt</spanx> fails with <spanx style="verb">CERT_CANNOT_ENCRYPT</spanx>.</t>

<t>If the <spanx style="verb">--profile</spanx> argument is supplied and the indicated <spanx style="verb">PROFILE</spanx> is not supported by the implementation, <spanx style="verb">sop</spanx> will fail with <spanx style="verb">UNSUPPORTED_PROFILE</spanx>.
The use of a profile for this subcommand allows an implementation faced with parametric or algorithmic choices to make a decision coarsely guided by the operator.
For example, when encrypting with a password, there is no knowledge about the capabilities of the recipient, and an implementation may prefer cryptographically modern algorithms, or it may prefer more broad compatibility.
In the event that a known recipient (i.e., one of the <spanx style="verb">CERTS</spanx>) explicitly indicates a lack of support for one of the features preferred by the indicated profile, the implementation <bcp14>SHOULD</bcp14> conform to the recipient's advertised capabilities where possible.</t>

<t>If <spanx style="verb">--session-key-out</spanx> argument is supplied, the session key generated for this encrypted will be written to the indicated location.
This can be useful, for example, when Alice encrypts a message to Bob, but also wants to retain the ability to read it without having any of her own secret key material available (see <xref section="9.1" sectionFormat="of" target="I-D.ietf-lamps-e2e-mail-guidance-11"/>).</t>

<t>If <spanx style="verb">sop encrypt</spanx> fails for any reason, it emits no <spanx style="verb">CIPHERTEXT</spanx>.</t>

<t>Example:</t>

<t>(In this example, <spanx style="verb">bob.bin</spanx> is a file containing Bob's binary-formatted OpenPGP certificate.
Alice is encrypting a message to both herself and Bob.)</t>

<figure><artwork><![CDATA[
$ sop encrypt --as=text --sign-with=alice.key alice.asc bob.bin < message.eml > encrypted.asc
$ head -n1 encrypted.asc
-----BEGIN PGP MESSAGE-----
$
]]></artwork></figure>

</section>
<section anchor="decrypt"><name>decrypt: Decrypt a Message</name>

<figure><artwork><![CDATA[
sop decrypt [--session-key-out=SESSIONKEY]
    [--with-session-key=SESSIONKEY...]
    [--with-password=PASSWORD...]
    [--with-key-password=PASSWORD...]
    [--verifications-out=VERIFICATIONS
     [--verify-with=CERTS...]
     [--verify-not-before=DATE]
     [--verify-not-after=DATE] ]
    [--] [KEYS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">CIPHERTEXT</spanx> (<xref target="ciphertext"/>)</t>
  <t>Standard Output: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
</list></t>

<t>The caller can ask <spanx style="verb">sop</spanx> for the session key discovered during decryption by supplying the <spanx style="verb">--session-key-out</spanx> option.
If the specified file already exists in the filesystem, <spanx style="verb">sop decrypt</spanx> will fail with <spanx style="verb">OUTPUT_EXISTS</spanx>.
When decryption is successful, <spanx style="verb">sop decrypt</spanx> writes the discovered session key to the specified file.</t>

<t><spanx style="verb">--with-session-key</spanx> enables decryption of the <spanx style="verb">CIPHERTEXT</spanx> using the session key directly against the <spanx style="verb">SEIPD</spanx> packet.
This option can be used multiple times if several possible session keys should be tried.
<spanx style="verb">SESSIONKEY</spanx> is an indirect data type from which the actual <spanx style="verb">sessionkey</spanx> value is acquired (<xref target="indirect-types"/>).</t>

<t><spanx style="verb">--with-password</spanx> enables decryption based on any <spanx style="verb">SKESK</spanx> (<xref section="5.3" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>) packets in the <spanx style="verb">CIPHERTEXT</spanx>.
This option can be used multiple times if the user wants to try more than one password.</t>

<t><spanx style="verb">--with-key-password</spanx> lets the user use password-protected (locked) secret key material.
If the decryption-capable secret key material in any key in the <spanx style="verb">KEYS</spanx> objects is password-protected, <spanx style="verb">sop decrypt</spanx> <bcp14>SHOULD</bcp14> try all supplied <spanx style="verb">--with-key-password</spanx> options to unlock the key material until it finds one that enables the use of the key for decryption.
If none of the <spanx style="verb">--with-key-password</spanx> options unlock the key (or if no such option is supplied), and the message cannot be decrypted with any other <spanx style="verb">KEYS</spanx>, <spanx style="verb">--with-session-key</spanx>, or <spanx style="verb">--with-password</spanx> options, <spanx style="verb">sop decrypt</spanx> will fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.</t>

<t>Note that the two kinds of <spanx style="verb">PASSWORD</spanx> options are for different domains: <spanx style="verb">--with-password</spanx> is for unlocking an <spanx style="verb">SKESK</spanx>, and <spanx style="verb">--with-key-password</spanx> is for unlocking secret key material in <spanx style="verb">KEYS</spanx>.
<spanx style="verb">sop decrypt</spanx> <bcp14>SHOULD NOT</bcp14> apply the <spanx style="verb">--with-key-password</spanx> argument to any <spanx style="verb">SKESK</spanx>, or the <spanx style="verb">--with-password</spanx> argument to any <spanx style="verb">KEYS</spanx>.</t>

<t>Each <spanx style="verb">PASSWORD</spanx> argument is an indirect data type from which the actual password is acquired (<xref target="indirect-types"/>).
If <spanx style="verb">sop decrypt</spanx> tries and fails to use a password supplied by a <spanx style="verb">PASSWORD</spanx>,
and it observes that there is trailing <spanx style="verb">UTF-8</spanx> whitespace at the end of the password,
it will retry with the trailing whitespace stripped.
See <xref target="consuming-passwords"/> for more discussion about consuming password-protected key material.</t>

<t><spanx style="verb">--verifications-out</spanx> produces signature verification status to the designated file.
If the designated file already exists in the filesystem, <spanx style="verb">sop decrypt</spanx> will fail with <spanx style="verb">OUTPUT_EXISTS</spanx>.</t>

<t>The return code of <spanx style="verb">sop decrypt</spanx> is not affected by the results of signature verification.
The caller <bcp14>MUST</bcp14> check the returned <spanx style="verb">VERIFICATIONS</spanx> to confirm signature status.
An empty <spanx style="verb">VERIFICATIONS</spanx> output indicates that no valid signatures were found.</t>

<t><spanx style="verb">--verify-with</spanx> identifies a set of certificates whose signatures would be acceptable for signatures over this message.</t>

<t>If the caller is interested in signature verification, both <spanx style="verb">--verifications-out</spanx> and at least one <spanx style="verb">--verify-with</spanx> must be supplied.
If only one of these options is supplied, <spanx style="verb">sop decrypt</spanx> fails with <spanx style="verb">INCOMPLETE_VERIFICATION</spanx>.</t>

<t><spanx style="verb">--verify-not-before</spanx> and <spanx style="verb">--verify-not-after</spanx> provide a date range for acceptable signatures,
by analogy with the options for <spanx style="verb">sop verify</spanx> (see <xref target="verify"/>).
They should only be supplied when doing signature verification.</t>

<t>See <xref target="signature-verification"/> for more details about signature verification.</t>

<t>If no <spanx style="verb">KEYS</spanx> or <spanx style="verb">--with-password</spanx> or <spanx style="verb">--with-session-key</spanx> options are present, <spanx style="verb">sop decrypt</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>If unable to decrypt, <spanx style="verb">sop decrypt</spanx> fails with <spanx style="verb">CANNOT_DECRYPT</spanx>.</t>

<t><spanx style="verb">sop decrypt</spanx> only emits cleartext to Standard Output that was successfully decrypted.</t>

<t>Example:</t>

<t>(In this example, Alice stashes and re-uses the session key of an encrypted message.)</t>

<figure><artwork><![CDATA[
$ 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
$
]]></artwork></figure>

<section anchor="historic-options-for-sop-decrypt"><name>Historic Options for sop decrypt</name>

<t>The <spanx style="verb">sop decrypt</spanx> option <spanx style="verb">--verifications-out</spanx> used to be named <spanx style="verb">--verify-out</spanx>.
An implementation <bcp14>SHOULD</bcp14> accept either form of this option, and <bcp14>SHOULD</bcp14> produce a deprecation warning to standard error if the old form is used.</t>

</section>
</section>
<section anchor="inline-detach"><name>inline-detach: Split Signatures from an Inline-Signed Message</name>

<figure><artwork><![CDATA[
sop inline-detach [--no-armor] --signatures-out=SIGNATURES
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">INLINESIGNED</spanx></t>
  <t>Standard Output: <spanx style="verb">DATA</spanx> (the message without any signatures)</t>
</list></t>

<t>In some contexts, the user may expect an inline-signed message of some form or another (<spanx style="verb">INLINESIGNED</spanx>, see <xref target="inlinesigned"/>) rather than a message and its detached signature.
<spanx style="verb">sop inline-detach</spanx> takes such an inline-signed message on standard input, and splits it into:</t>

<t><list style="symbols">
  <t>the potentially signed material on standard output, and</t>
  <t>a detached signature block to the destination identified by <spanx style="verb">--signatures-out</spanx></t>
</list></t>

<t>Note that no cryptographic verification of the signatures is done by this subcommand.
Once the inline-signed message is separated, verification of the detached signature can be done with <spanx style="verb">sop verify</spanx>.</t>

<t>If no <spanx style="verb">--signatures-out</spanx> is supplied, <spanx style="verb">sop inline-detach</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>Note that there may be more than one Signature packet in an inline-signed message.
All signatures found in the inline-signed message will be emitted to the <spanx style="verb">--signatures-out</spanx> destination.</t>

<t>If the inline-signed message uses the Cleartext Signature Framework, it may be dash-escaped (see <xref section="7.1" sectionFormat="of" target="RFC4880"/>).
The output of <spanx style="verb">sop detach-inband-signature-and-message</spanx> will have any dash-escaping removed.</t>

<t>If the input is not an <spanx style="verb">INLINESIGNED</spanx> message, <spanx style="verb">sop inline-detach</spanx> fails with <spanx style="verb">BAD_DATA</spanx>.
If the input contains more than one object that could be interpreted as an <spanx style="verb">INLINESIGNED</spanx> message, <spanx style="verb">sop inline-detach</spanx> also fails with <spanx style="verb">BAD_DATA</spanx>.
A <spanx style="verb">sop</spanx> implementation <bcp14>MAY</bcp14> accept (and discard) leading and trailing data when the incoming <spanx style="verb">INLINESIGNED</spanx> message uses the Cleartext Signature Framework.</t>

<t>If the file designated by <spanx style="verb">--signatures-out</spanx> already exists in the filesystem, <spanx style="verb">sop detach-inband-signature-and-message</spanx> will fail with <spanx style="verb">OUTPUT_EXISTS</spanx>.</t>

<t>Note that <spanx style="verb">--no-armor</spanx> here governs the data written to the <spanx style="verb">--signatures-out</spanx> destination.
Standard output is always the raw message, not an OpenPGP packet.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop inline-detach --signatures-out=Release.pgp < InRelease >Release
$ sop verify Release.pgp archive-keyring.pgp < Release
$
]]></artwork></figure>

</section>
<section anchor="inline-verify"><name>inline-verify: Verify an Inline-Signed Message</name>

<figure><artwork><![CDATA[
sop inline-verify [--not-before=DATE] [--not-after=DATE]
    [--verifications-out=VERIFICATIONS]
    [--] CERTS [CERTS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">INLINESIGNED</spanx> (<xref target="inlinesigned"/>)</t>
  <t>Standard Output: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
</list></t>

<t>This command is similar to <spanx style="verb">sop verify</spanx> (<xref target="verify"/>) except that it takes an <spanx style="verb">INLINESIGNED</spanx> message (see <xref target="inlinesigned"/>) and produces the message body (without signatures) on standard output.
It is also similar to <spanx style="verb">sop inline-detach</spanx> (<xref target="inline-detach"/>) except that it actually performs signature verification.</t>

<t><spanx style="verb">--not-before</spanx> and <spanx style="verb">--not-after</spanx> indicate that signatures with dates outside certain range <bcp14>MUST NOT</bcp14> be considered valid.</t>

<t><spanx style="verb">--not-before</spanx> defaults to the beginning of time.
Accepts the special value <spanx style="verb">-</spanx> to indicate the beginning of time (i.e., no lower boundary).</t>

<t><spanx style="verb">--not-after</spanx> defaults to the current system time (<spanx style="verb">now</spanx>).
Accepts the special value <spanx style="verb">-</spanx> to indicate the end of time (i.e., no upper boundary).</t>

<t><spanx style="verb">sop inline-verify</spanx> only returns <spanx style="verb">OK</spanx> if <spanx style="verb">INLINESIGNED</spanx> contains at least one valid signature made during the time window specified by a certificate included in any <spanx style="verb">CERTS</spanx> object.</t>

<t>For details about the valid signatures, the user <bcp14>MUST</bcp14> inspect the <spanx style="verb">VERIFICATIONS</spanx> output.</t>

<t>If no <spanx style="verb">CERTS</spanx> are supplied, <spanx style="verb">sop inline-verify</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>If no valid signatures are found, <spanx style="verb">sop inline-verify</spanx> fails with <spanx style="verb">NO_SIGNATURE</spanx> and emits nothing on standard output.</t>

<t>See <xref target="signature-verification"/> for more details about signature verification.</t>

<t>Example:</t>

<t>(In this example, we see signature verification succeed first, and then fail on a modified version of the message.)</t>

<figure><artwork><![CDATA[
$ sop inline-verify -- alice.pgp < message.txt
Hello, world!
$ echo $?
0
$ sed s/Hello/Goodbye/ < message.txt | sop inline-verify -- alice.pgp
$ echo $?
3
$
]]></artwork></figure>

</section>
<section anchor="inline-sign"><name>inline-sign: Create an Inline-Signed Message</name>

<figure><artwork><![CDATA[
sop inline-sign [--no-armor]
     [--with-key-password=PASSWORD...]
     [--as={binary|text|clearsigned}]
     [--] KEYS [KEYS...]
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: <spanx style="verb">DATA</spanx> (<xref target="data"/>)</t>
  <t>Standard Output: <spanx style="verb">INLINESIGNED</spanx> (<xref target="inlinesigned"/>)</t>
</list></t>

<t>Exactly one signature will be made by each key in the supplied <spanx style="verb">KEYS</spanx> arguments.</t>

<t>The generated output stream will be an inline-signed message, by default producing an OpenPGP "Signed Message" packet stream.</t>

<t><spanx style="verb">--as</spanx> defaults to <spanx style="verb">binary</spanx>.
If <spanx style="verb">--as=</spanx> is set to either <spanx style="verb">text</spanx> or <spanx style="verb">clearsigned</spanx>, and the input <spanx style="verb">DATA</spanx> is not valid <spanx style="verb">UTF-8</spanx> (<xref target="utf8"/>), <spanx style="verb">sop inline-sign</spanx> fails with <spanx style="verb">EXPECTED_TEXT</spanx>.</t>

<t><spanx style="verb">--as=binary</spanx> <bcp14>SHOULD</bcp14> result in OpenPGP signatures of type 0x00 ("Signature of a binary document").
<spanx style="verb">--as=text</spanx> <bcp14>SHOULD</bcp14> result in an OpenPGP signature of type 0x01 ("Signature of a canonical text document").
See <xref section="5.2.1" sectionFormat="of" target="RFC4880"/> for more details.
<spanx style="verb">--as=clearsigned</spanx> <bcp14>SHOULD</bcp14> behave the same way as <spanx style="verb">--as=text</spanx> except that it produces an output stream using the Cleartext Signature Framework (see <xref section="7" sectionFormat="of" target="RFC4880"/> and <xref target="csf-risks"/>).</t>

<t>If both <spanx style="verb">--no-armor</spanx> and <spanx style="verb">--as=clearsigned</spanx>  are supplied, <spanx style="verb">sop inline-sign</spanx> fails with <spanx style="verb">INCOMPATIBLE_OPTIONS</spanx>.</t>

<t>If the signing key material in any key in the <spanx style="verb">KEYS</spanx> objects is password-protected, <spanx style="verb">sop inline-sign</spanx> <bcp14>SHOULD</bcp14> try all supplied <spanx style="verb">--with-key-password</spanx> options to unlock the key material until it finds one that enables the use of the key for signing.
If none of the <spanx style="verb">PASSWORD</spanx> options unlock the key (or if no such option is supplied), <spanx style="verb">sop inline-sign</spanx> will fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.
Note that <spanx style="verb">PASSWORD</spanx> is an indirect data type from which the actual password is acquired (<xref target="indirect-types"/>).
Note also the guidance for retrying variants of a non-human-readable password in <xref target="consuming-passwords"/>.</t>

<t>If any key in the <spanx style="verb">KEYS</spanx> objects is not capable of producing a signature, <spanx style="verb">sop inline-sign</spanx> will fail with <spanx style="verb">KEY_CANNOT_SIGN</spanx>.</t>

<t><spanx style="verb">sop inline-sign</spanx> <bcp14>MUST NOT</bcp14> produce any extra signatures beyond those from <spanx style="verb">KEYS</spanx> objects supplied on the command line.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop inline-sign --as=clearsigned alice.sec < message.txt > message-signed.txt
$ head -n5 < message-signed.txt
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

This is the message.
-----BEGIN PGP SIGNATURE-----
$
]]></artwork></figure>

</section>
</section>
<section anchor="transport-subcommands"><name>Transport Subcommands</name>

<t>The commands in this section handle manipulating OpenPGP objects for transport: armoring and dearmoring for 7-bit cleanness and compactness, respectively.</t>

<section anchor="armor-convert-binary-to-ascii"><name>armor: Convert Binary to ASCII</name>

<figure><artwork><![CDATA[
sop armor
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: OpenPGP material (<spanx style="verb">SIGNATURES</spanx>, <spanx style="verb">KEYS</spanx>, <spanx style="verb">CERTS</spanx>, <spanx style="verb">CIPHERTEXT</spanx>, or <spanx style="verb">INLINESIGNED</spanx>)</t>
  <t>Standard Output: the same material with ASCII-armoring added, if not already present</t>
</list></t>

<t><spanx style="verb">sop armor</spanx> inspects the input and chooses the label appropriately, based on the OpenPGP packets encountered.
If the type of the first OpenPGP packet is:</t>

<t><list style="symbols">
  <t><spanx style="verb">0x05</spanx> (Secret-Key), the packet stream should be parsed as a <spanx style="verb">KEYS</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP PRIVATE KEY BLOCK</spanx>).</t>
  <t><spanx style="verb">0x06</spanx> (Public-Key), the packet stream should be parsed as a <spanx style="verb">CERTS</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP PUBLIC KEY BLOCK</spanx>).</t>
  <t><spanx style="verb">0x01</spanx> (Public-key Encrypted Session Key) or <spanx style="verb">0x03</spanx> (Symmetric-key Encrypted Session Key), the packet stream should be parsed as a <spanx style="verb">CIPHERTEXT</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP MESSAGE</spanx>).</t>
  <t><spanx style="verb">0x04</spanx> (One-Pass Signature), the packet stream should be parsed as an <spanx style="verb">INLINESIGNED</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP MESSAGE</spanx>).</t>
  <t><spanx style="verb">0x02</spanx> (Signature), the packet stream may be either a <spanx style="verb">SIGNATURES</spanx> input or an <spanx style="verb">INLINESIGNED</spanx> input.
If the packet stream contains only Signature packets, it should be parsed as a<spanx style="verb">SIGNATURES</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP SIGNATURE</spanx>).
If it contains any packet other than a Signature packet, it should be parsed as an <spanx style="verb">INLINESIGNED</spanx> input (with Armor Header <spanx style="verb">BEGIN PGP MESSAGE</spanx>).</t>
</list></t>

<t>If the input packet stream does not match any expected sequence of packet types, <spanx style="verb">sop armor</spanx> fails with <spanx style="verb">BAD_DATA</spanx>.</t>

<t>Since <spanx style="verb">sop armor</spanx> accepts ASCII-armored input as well as binary input, this operation is idempotent on well-structured data.
A caller can use this subcommand blindly to ensure that any well-formed OpenPGP packet stream is 7-bit clean.</t>

<t>FIXME: what to do if the input is a CSF <spanx style="verb">INLINESIGNED</spanx> message?
Three choices:</t>

<t><list style="symbols">
  <t>Leave it untouched -- this violates the claim about blindly ensuring 7-bit clean, since UTF-8-encoded message text is not necessarily 7-bit clean.</t>
  <t>Convert to ASCII-armored <spanx style="verb">INLINESIGNED</spanx> -- this requires synthesis of OPS packet (from signatures block) and Literal Data packet (from the message body).</t>
  <t>Raise a specific error.</t>
</list></t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop armor < bob.bin > bob.pgp
$ head -n1 bob.pgp
-----BEGIN PGP PUBLIC KEY BLOCK-----
$
]]></artwork></figure>

<section anchor="historic-options-for-sop-armor"><name>Historic Options for sop armor</name>

<t><spanx style="verb">sop armor</spanx> used to be specified as having a <spanx style="verb">--label</spanx> option, with an argument that took one of the following values: <spanx style="verb">auto</spanx>, <spanx style="verb">sig</spanx>, <spanx style="verb">key</spanx>, <spanx style="verb">cert</spanx>, or <spanx style="verb">message</spanx>, which allowed the user to specify the label used in the header and tail of the armoring.</t>

<t>The default value for <spanx style="verb">--label</spanx> was <spanx style="verb">auto</spanx>, which matches the currently specified behavior.
This option is now deprecated, as it offers no useful functionality.</t>

</section>
</section>
<section anchor="dearmor-convert-ascii-to-binary"><name>dearmor: Convert ASCII to Binary</name>

<figure><artwork><![CDATA[
sop dearmor
]]></artwork></figure>

<t><list style="symbols">
  <t>Standard Input: OpenPGP material (<spanx style="verb">SIGNATURES</spanx>, <spanx style="verb">KEYS</spanx>, <spanx style="verb">CERTS</spanx>, <spanx style="verb">CIPHERTEXT</spanx>, or <spanx style="verb">INLINESIGNED</spanx>)</t>
  <t>Standard Output: the same material with any ASCII-armoring removed</t>
</list></t>

<t>If the input packet stream does not match any of the expected sequence of packet types, <spanx style="verb">sop dearmor</spanx> fails with <spanx style="verb">BAD_DATA</spanx>.  See also <xref target="optional-input-armoring"/>.</t>

<t>Since <spanx style="verb">sop dearmor</spanx> accepts binary-formatted input as well as ASCII-armored input, this operation is idempotent on well-structured data.
A caller can use this subcommand blindly ensure that any well-formed OpenPGP packet stream is in its standard binary representation.</t>

<t>FIXME: what to do if the input is a CSF <spanx style="verb">INLINESIGNED</spanx>?
Three choices:</t>

<t><list style="symbols">
  <t>Leave it untouched -- output data is not really in binary format.</t>
  <t>Convert to binary-format <spanx style="verb">INLINESIGNED</spanx> -- this requires synthesis of OPS packet (from CSF <spanx style="verb">Hash</spanx> header) and Literal Data packet (from the message body).</t>
  <t>Raise a specific error.</t>
</list></t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop dearmor < message.txt.asc > message.txt.sig
$
]]></artwork></figure>

</section>
</section>
</section>
<section anchor="input-string-types"><name>Input String Types</name>

<t>Some material is passed to <spanx style="verb">sop</spanx> directly as a string on the command line.</t>

<section anchor="date"><name>DATE</name>

<t>An ISO-8601 formatted timestamp with time zone, or the special value <spanx style="verb">now</spanx> to indicate the current system time.</t>

<t>Examples:</t>

<t><list style="symbols">
  <t><spanx style="verb">now</spanx></t>
  <t><spanx style="verb">2019-10-29T12:11:04+00:00</spanx></t>
  <t><spanx style="verb">2019-10-24T23:48:29Z</spanx></t>
  <t><spanx style="verb">20191029T121104Z</spanx></t>
</list></t>

<t>In some cases where used to specify lower and upper boundaries, a <spanx style="verb">DATE</spanx> value can be set to <spanx style="verb">-</spanx> to indicate "no time limit".</t>

<t>A flexible implementation of <spanx style="verb">sop</spanx> <bcp14>MAY</bcp14> accept date inputs in other unambiguous forms.</t>

<t>Note that whenever <spanx style="verb">sop</spanx> emits a timestamp (e.g., in <xref target="verifications"/>) it <bcp14>MUST</bcp14> produce only a UTC-based ISO-8601 compliant representation with a resolution of one second, using the literal <spanx style="verb">Z</spanx> suffix to indicate timezone.</t>

</section>
<section anchor="userid"><name>USERID</name>

<t>This is an arbitrary <spanx style="verb">UTF-8</spanx> string (<xref target="utf8"/>).
By convention, most User IDs are of the form <spanx style="verb">Display Name &lt;email.address@example.com&gt;</spanx>, but they do not need to be.</t>

<t>By internal policy, an implementation <bcp14>MAY</bcp14> reject a <spanx style="verb">USERID</spanx> if there are certain <spanx style="verb">UTF-8</spanx> strings it declines to work with as a User ID.
For example, an implementation may reject the empty string, or a string with characters in it that it considers problematic.
Of course, refusing to create a particular User ID does not prevent an implementation from encountering such a User ID in its input.</t>

</section>
<section anchor="subcommand"><name>SUBCOMMAND</name>

<t>This is an <spanx style="verb">ASCII</spanx> string that matches the name of one of the subcommands listed in <xref target="subcommands"/>.</t>

</section>
<section anchor="profile"><name>PROFILE</name>

<t>Some <spanx style="verb">sop</spanx> subcommands can accept a <spanx style="verb">--profile</spanx> option, which takes as an argument the name of a profile.</t>

<t>A profile name is a UTF-8 string that has no whitespace in it.</t>

<t>Which profiles are available depends on the <spanx style="verb">sop</spanx> implementation.</t>

<t>Similar to OpenPGP Notation names, profile names are divided into two namespaces: the IETF namespace and the user namespace.
A profile name in the user namespace ends with the <spanx style="verb">@</spanx> character (0x40) followed by a DNS domain name.
A profile name in the IETF namespace does not have an <spanx style="verb">@</spanx> character.</t>

<t>A profile name in the user space is owned and controlled by the owner of the domain in the suffix.
A <spanx style="verb">sop</spanx> implementation that implements a user profile but does not own the domain in question <bcp14>SHOULD</bcp14> hew as closely as possible to the semantics described by the owner of the domain.</t>

<t>A profile name in the IETF namespace that begins with the string <spanx style="verb">rfc</spanx> should have semantics that hew as closely as possible to the referenced RFC.
Similarly, a profile name in the IETF namespace that begins with the string <spanx style="verb">draft-</spanx> should have semantics that hew as closely as possible to the referenced Internet Draft.</t>

<t>The reserved profile name <spanx style="verb">default</spanx> in the IETF namespace simply refers to the implementation's default choices.
It is not mandatory to name the default profile <spanx style="verb">default</spanx>.
The first profile listed in the <spanx style="verb">list-profiles</spanx> output is considered the default configuration, as specified in <xref target="profilelist"/>.</t>

<t>Note that this profile mechanism is intended to provide a limited way for an implementation to select among a small set of options that the implementer has vetted and is satisfied with.
It is not intended to provide an arbitrary channel for complex configuration, and a <spanx style="verb">sop</spanx> implementation <bcp14>MUST NOT</bcp14> use it in that way.</t>

</section>
</section>
<section anchor="indirect-types"><name>Input/Output Indirect Types</name>

<t>Some material is passed to <spanx style="verb">sop</spanx> indirectly, typically by referring to a filename containing the data in question.
This type of data may also be passed to <spanx style="verb">sop</spanx> on Standard Input, or delivered by <spanx style="verb">sop</spanx> to Standard Output.</t>

<t>If any input data is specified explicitly to be read from a file that does not exist, <spanx style="verb">sop</spanx> will fail with <spanx style="verb">MISSING_INPUT</spanx>.</t>

<t>If any input data does not meet the requirements described below, <spanx style="verb">sop</spanx> will fail with <spanx style="verb">BAD_DATA</spanx>.</t>

<section anchor="special-designators"><name>Special Designators for Indirect Types</name>

<t>An indirect argument or parameter that starts with <u>@</u> is not treated as a filename, but is reserved for special handling, based on the prefix that follows the <spanx style="verb">@</spanx>.
We describe three of those prefixes (<spanx style="verb">@ENV:</spanx>, <spanx style="verb">@FD:</spanx>, and <spanx style="verb">@HARDWARE:</spanx>) here.
A <spanx style="verb">sop</spanx> implementation that receives such a special designator but does not know how to handle a given prefix in that context <bcp14>MUST</bcp14> fail with <spanx style="verb">UNSUPPORTED_SPECIAL_PREFIX</spanx>.</t>

<t>See <xref target="special-designators-guidance"/> for more details about safe handling of these special designators.</t>

<section anchor="env-special-designator-for-environment-variable"><name>@ENV: Special Designator for Environment Variable</name>

<t>If the filename for any indirect material used as input has the special form <spanx style="verb">@ENV:xxx</spanx>,
then contents of environment variable <spanx style="verb">$xxx</spanx> is used instead of looking in the filesystem.
<spanx style="verb">@ENV</spanx> is for input only: if the prefix <spanx style="verb">@ENV:</spanx> is used for any output argument, <spanx style="verb">sop</spanx> fails with <spanx style="verb">UNSUPPORTED_SPECIAL_PREFIX</spanx>.</t>

</section>
<section anchor="fd-special-designator-for-file-descriptor"><name>@FD: Special Designator for File Descriptor</name>

<t>If the filename for any indirect material used as either input or output has the special form <spanx style="verb">@FD:nnn</spanx> where <spanx style="verb">nnn</spanx> is a decimal integer,
then the associated data is read from file descriptor <spanx style="verb">nnn</spanx>.</t>

</section>
<section anchor="special-designator-hardware"><name>@HARDWARE: Special Designator for Hardware-backed Secret Keys</name>

<t>Some OpenPGP implementations can talk to hardware-backed mechanisms secret key cryptography.
If the filename for any input <spanx style="verb">KEYS</spanx> material (see <xref target="keys"/>) has the special form <spanx style="verb">@HARDWARE:xxx</spanx>, then the <spanx style="verb">sop</spanx> implementation should use a corresponding hardware token.</t>

<t>In this situation, <spanx style="verb">xxx</spanx> is interpreted as an indirect <spanx style="verb">CERTS</spanx> object (see <xref target="certs"/>), and each OpenPGP certificate in the <spanx style="verb">CERTS</spanx> object is attempted to be used as a secret key, but with the <spanx style="verb">sop</spanx> implementation looking for corresponding secret key material usable from any available hardware device.</t>

<t>When such a hardware-backed secret key is in use, a <spanx style="verb">PASSWORD</spanx> argument to <spanx style="verb">--with-key-password</spanx> can be sent to the hardware token, if the hardware token requires a password or PIN or similar authentication mechanism.</t>

<t>Cryptographic hardware devices that might be relevant can include hardware security modules (HSMs), Trusted Platform Modules (TPMs), and OpenPGP smartcards (<xref target="OPENPGP-SMARTCARD"/>).
Not every <spanx style="verb">sop</spanx> implementation will be able to handle all kinds of cryptographic secret key hardware.
If a <spanx style="verb">sop</spanx> implementation does not know how to access any cryptographic secret key hardware and it receives this designator, it should fail with <spanx style="verb">UNSUPPORTED_SPECIAL_PREFIX</spanx>.
If the implementation knows how to handle at least some cryptographic secret key hardware, but none appears to be available for a relevant secret key referenced by any certificate in <spanx style="verb">xxx</spanx>, it should fail with <spanx style="verb">NO_HARDWARE_KEY_FOUND</spanx>.
If it identifies a relevant hardware-backed secret key but the key is locked and no <spanx style="verb">--with-key-password</spanx> argument can unlock it, it should fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.
If it fails to use the hardware-backed secret key (e.g., because the hardware module declines access, or because of a timeout), it should fail with <spanx style="verb">HARDWARE_KEY_FAILURE</spanx>.</t>

<t>A <spanx style="verb">sop</spanx> implementation that is capable of accessing hardware-backed secret keys in this way <bcp14>MAY</bcp14> wait briefly for the relevant hardware to become available and be used, or for a user to physically interact with a hardware module (e.g., by pressing a button), but it <bcp14>MUST NOT</bcp14> hang indefinitely.</t>

<t>See <xref target="hardware-backed-secrets"/> for more information about hardware-backed keys.</t>

</section>
</section>
<section anchor="certs"><name>CERTS</name>

<t>One or more OpenPGP certificates (<xref section="10.1" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>), aka "Transferable Public Key".
May be armored (see <xref target="optional-input-armoring"/>).</t>

<t>Although some existing workflows may prefer to use one <spanx style="verb">CERTS</spanx> object with multiple certificates in it (a "keyring"), supplying exactly one certificate per <spanx style="verb">CERTS</spanx> input will make error reporting clearer and easier.</t>

</section>
<section anchor="keys"><name>KEYS</name>

<t>One or more OpenPGP Transferable Secret Keys (<xref section="10.2" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>).
May be armored (see <xref target="optional-input-armoring"/>).</t>

<t>Secret key material is often locked with a password to ensure that it cannot be simply copied and reused.
If any secret key material is locked with a password and no <spanx style="verb">--with-key-password</spanx> option is supplied, <spanx style="verb">sop</spanx> may fail with error <spanx style="verb">KEY_IS_PROTECTED</spanx>.
However, when a cleartext secret key (that is, one not locked with a password) is available, <spanx style="verb">sop</spanx> should always be able to use it, whether a <spanx style="verb">--with-key-password</spanx> option is supplied or not.</t>

<t>Although some existing workflows may prefer to use one <spanx style="verb">KEYS</spanx> object with multiple keys in it (a "secret keyring"), supplying exactly one key per <spanx style="verb">KEYS</spanx> input will make error reporting clearer and easier.</t>

</section>
<section anchor="ciphertext"><name>CIPHERTEXT</name>

<t><spanx style="verb">sop</spanx> accepts only a restricted subset of the arbitrarily-nested grammar allowed by the OpenPGP Messages definition (<xref section="10.3" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>).</t>

<t>In particular, it accepts and generates only:</t>

<t>An OpenPGP message, consisting of a sequence of PKESKs (<xref section="5.1" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>) and SKESKs (<xref section="5.3" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>),
followed by one SEIPD (<xref section="5.13" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>).</t>

<t>The SEIPD can decrypt into one of two things:</t>

<t><list style="symbols">
  <t>"Maybe Signed Data" (see below), or</t>
  <t>Compressed data packet that contains "Maybe Signed Data"</t>
</list></t>

<t>"Maybe Signed Data" is a sequence of:</t>

<t><list style="symbols">
  <t>N (zero or more) one-pass signature packets, followed by</t>
  <t>zero or more signature packets, followed by</t>
  <t>one Literal data packet, followed by</t>
  <t>N signature packets (corresponding to the outer one-pass signatures packets)</t>
</list></t>

<t>FIXME: does any tool do compression inside signing?  Do we need to handle that?</t>

<t>May be armored (see <xref target="optional-input-armoring"/>).</t>

</section>
<section anchor="inlinesigned"><name>INLINESIGNED</name>

<t>An inline-signed message may take any one of three different forms:</t>

<t><list style="symbols">
  <t>A binary sequence of OpenPGP packets that matches a subset of the "Signed Message" element in the grammar in <xref section="10.3" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/></t>
  <t>The same sequence of packets, but ASCII-armored (see <xref target="optional-input-armoring"/>)</t>
  <t>A message using the Cleartext Signature Framework described in <xref section="7" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/></t>
</list></t>

<t>The subset of the packet grammar expected in the first two forms consists of either:</t>

<t><list style="symbols">
  <t>a series of Signature packets followed by a Literal Data packet</t>
  <t>a series of One-Pass Signature (OPS) packets, followed by one Literal Data packet, followed by an equal number of Signature packets corresponding to the OPS packets</t>
</list></t>

<t>When the message is in the third form (Cleartext Signature Framework), it has the following properties:</t>

<t><list style="symbols">
  <t>The stream <bcp14>SHOULD</bcp14> consist solely of <spanx style="verb">UTF-8</spanx> text</t>
  <t>Every Signature packet found in the stream <bcp14>SHOULD</bcp14> have Signature Type 0x01 (canonical text document).</t>
  <t>It <bcp14>SHOULD NOT</bcp14> contain leading text (before the <spanx style="verb">-----BEGIN PGP SIGNED MESSAGE-----</spanx> cleartext header) or trailing text (after the <spanx style="verb">-----END PGP SIGNATURE-----</spanx> armor tail).</t>
</list></t>

<t>While some OpenPGP implementations <bcp14>MAY</bcp14> produce more complicated inline signed messages, a <spanx style="verb">sop</spanx> implementation <bcp14>SHOULD</bcp14> limit itself to producing these straightforward forms.</t>

</section>
<section anchor="signature"><name>SIGNATURES</name>

<t>One or more OpenPGP Signature packets.  May be armored (see <xref target="optional-input-armoring"/>).</t>

</section>
<section anchor="sessionkey"><name>SESSIONKEY</name>

<t>This documentation uses the GnuPG defacto <spanx style="verb">ASCII</spanx> representation:</t>

<t><spanx style="verb">ALGONUM:HEXKEY</spanx></t>

<t>where <spanx style="verb">ALGONUM</spanx> is the decimal value associated with the OpenPGP Symmetric Key Algorithms (<xref section="9.3" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>) and <spanx style="verb">HEXKEY</spanx> is the hexadecimal
representation of the binary key.</t>

<t>Example AES-256 session key:</t>

<figure><artwork><![CDATA[
9:FCA4BEAF687F48059CACC14FB019125CD57392BAB7037C707835925CBF9F7BCD
]]></artwork></figure>

<t>A <spanx style="verb">sop</spanx> implementation <bcp14>SHOULD</bcp14> produce session key data in this format.
When consuming such a session key, <spanx style="verb">sop</spanx> <bcp14>SHOULD</bcp14> be willing to accept either upper or lower case hexadecimal digits, and to gracefully ignore any trailing whitespace.</t>

</section>
<section anchor="micalg"><name>MICALG</name>

<t>This output-only type indicates the cryptographic digest used when making a signature.
It is useful specifically when generating signed PGP/MIME objects, which want a <spanx style="verb">micalg=</spanx> parameter for the <spanx style="verb">multipart/signed</spanx> content type as described in <xref section="5" sectionFormat="of" target="RFC3156"/>.</t>

<t>It will typically be a string like <spanx style="verb">pgp-sha512</spanx>, but in some situations (multiple signatures using different digests) it will be the empty string.
If the user of <spanx style="verb">sop</spanx> is assembling a PGP/MIME signed object, and the <spanx style="verb">MICALG</spanx> output is the empty string,
the user should omit the <spanx style="verb">micalg=</spanx> parameter entirely.</t>

</section>
<section anchor="password"><name>PASSWORD</name>

<t>This input-only is expected to be a <spanx style="verb">UTF-8</spanx> string (<xref target="utf8"/>), but for <spanx style="verb">sop decrypt</spanx>, any bytestring that the user supplies will be accepted.
Note the details in <spanx style="verb">sop encrypt</spanx> and <spanx style="verb">sop decrypt</spanx> about trailing whitespace!</t>

<t>See also <xref target="human-readable-passwords"/> for more discussion.</t>

</section>
<section anchor="verifications"><name>VERIFICATIONS</name>

<t>This output-only type consists of one line per successful signature verification.
Each line has three structured fields delimited by a single space,
followed by arbitrary text to the end of the line that forms a message describing the verification.</t>

<t><list style="symbols">
  <t>ISO-8601 UTC datestamp of the signature, to one second precision, using the <spanx style="verb">Z</spanx> suffix</t>
  <t>Fingerprint of the signing key (may be a subkey)</t>
  <t>Fingerprint of primary key of signing certificate (if signed by primary key, same as the previous field)</t>
  <t>(optional) a string describing the mode of the signature, either <spanx style="verb">mode:text</spanx> or <spanx style="verb">mode:binary</spanx></t>
  <t>message describing the verification (free form)</t>
</list></t>

<t>Note that while <xref target="date"/> permits a <spanx style="verb">sop</spanx> implementation to accept other unambiguous date representations,
its date output here <bcp14>MUST</bcp14> be a strict ISO-8601 UTC date timestamp.
In particular:</t>

<t><list style="symbols">
  <t>the date and time fields <bcp14>MUST</bcp14> be separated by <spanx style="verb">T</spanx>, not by whitespace, since whitespace is used as a delimiter</t>
  <t>the time <bcp14>MUST</bcp14> be emitted in UTC, with the explicit suffix <spanx style="verb">Z</spanx></t>
  <t>the time <bcp14>MUST</bcp14> be emitted with one-second precision</t>
</list></t>

<t>Example:</t>

<figure><artwork><![CDATA[
2019-10-24T23:48:29Z C90E6D36200A1B922A1509E77618196529AE5FF8 C4BC2DDB38CCE96485EBE9C2F20691179038E5C6 mode:binary certificate from dkg.asc
]]></artwork></figure>

</section>
<section anchor="data"><name>DATA</name>

<t>Cleartext, arbitrary data.  This is either a bytestream or <spanx style="verb">UTF-8</spanx> text.</t>

<t>It <bcp14>MUST</bcp14> only be <spanx style="verb">UTF-8</spanx> text in the case of input supplied to <spanx style="verb">sop sign --as=text</spanx> or <spanx style="verb">sop encrypt --as=text</spanx>.
If <spanx style="verb">sop</spanx> receives <spanx style="verb">DATA</spanx> containing non-<spanx style="verb">UTF-8</spanx> octets in this case, it will fail (see <xref target="utf8"/>) with <spanx style="verb">EXPECTED_TEXT</spanx>.</t>

</section>
<section anchor="profilelist"><name>PROFILELIST</name>

<t>This output-only type consists of simple UTF-8 textual output, with one line per profile.
Each line consists of the profile name optionally followed by a colon (0x31), a space (0x20), and a brief human-readable description of the intended semantics of the profile.
Each line may be at most 1000 bytes, and no more than 4 profiles may be listed.</t>

<t>These limits are intended to force <spanx style="verb">sop</spanx> implementers to make hard decisions and to keep things simple.</t>

<t>The first profile <bcp14>MAY</bcp14> be explicitly named <spanx style="verb">default</spanx>.
If it is not named <spanx style="verb">default</spanx>, then <spanx style="verb">default</spanx> is an alias for the first profile listed.
No profile after the first listed may be named <spanx style="verb">default</spanx>.</t>

<t>See <xref target="profile"/> for more discussion about the namespace and intended semantics of each profile.</t>

</section>
</section>
<section anchor="failure-modes"><name>Failure Modes</name>

<t><spanx style="verb">sop</spanx> return codes have both mnemonics and numeric values.</t>

<t>When <spanx style="verb">sop</spanx> succeeds, it will return 0 (<spanx style="verb">OK</spanx>) and emit nothing to Standard Error.
When <spanx style="verb">sop</spanx> fails, it fails with a non-zero return code, and emits one or more warning messages on Standard Error.
Known return codes include:</t>

<texttable title="Error return codes">
      <ttcol align='right'>Value</ttcol>
      <ttcol align='left'>Mnemonic</ttcol>
      <ttcol align='left'>Meaning</ttcol>
      <c>0</c>
      <c><spanx style="verb">OK</spanx></c>
      <c>Success</c>
      <c>3</c>
      <c><spanx style="verb">NO_SIGNATURE</spanx></c>
      <c>No acceptable signatures found (<spanx style="verb">sop verify</spanx>)</c>
      <c>13</c>
      <c><spanx style="verb">UNSUPPORTED_ASYMMETRIC_ALGO</spanx></c>
      <c>Asymmetric algorithm unsupported (<spanx style="verb">sop encrypt</spanx>)</c>
      <c>17</c>
      <c><spanx style="verb">CERT_CANNOT_ENCRYPT</spanx></c>
      <c>Certificate not encryption-capable (e.g., expired, revoked, unacceptable usage flags) (<spanx style="verb">sop encrypt</spanx>)</c>
      <c>19</c>
      <c><spanx style="verb">MISSING_ARG</spanx></c>
      <c>Missing required argument</c>
      <c>23</c>
      <c><spanx style="verb">INCOMPLETE_VERIFICATION</spanx></c>
      <c>Incomplete verification instructions (<spanx style="verb">sop decrypt</spanx>)</c>
      <c>29</c>
      <c><spanx style="verb">CANNOT_DECRYPT</spanx></c>
      <c>Unable to decrypt (<spanx style="verb">sop decrypt</spanx>)</c>
      <c>31</c>
      <c><spanx style="verb">PASSWORD_NOT_HUMAN_READABLE</spanx></c>
      <c>Non-<spanx style="verb">UTF-8</spanx> or otherwise unreliable password (<spanx style="verb">sop encrypt</spanx>, <spanx style="verb">sop generate-key</spanx>)</c>
      <c>37</c>
      <c><spanx style="verb">UNSUPPORTED_OPTION</spanx></c>
      <c>Unsupported option</c>
      <c>41</c>
      <c><spanx style="verb">BAD_DATA</spanx></c>
      <c>Invalid data type (no secret key where <spanx style="verb">KEYS</spanx> expected, etc)</c>
      <c>53</c>
      <c><spanx style="verb">EXPECTED_TEXT</spanx></c>
      <c>Non-text input where text expected</c>
      <c>59</c>
      <c><spanx style="verb">OUTPUT_EXISTS</spanx></c>
      <c>Output file already exists</c>
      <c>61</c>
      <c><spanx style="verb">MISSING_INPUT</spanx></c>
      <c>Input file does not exist</c>
      <c>67</c>
      <c><spanx style="verb">KEY_IS_PROTECTED</spanx></c>
      <c>A <spanx style="verb">KEYS</spanx> input is password-protected (locked), and <spanx style="verb">sop</spanx> cannot unlock it with any of the <spanx style="verb">--with-key-password</spanx> (or <spanx style="verb">--old-key-password</spanx>) options</c>
      <c>69</c>
      <c><spanx style="verb">UNSUPPORTED_SUBCOMMAND</spanx></c>
      <c>Unsupported subcommand</c>
      <c>71</c>
      <c><spanx style="verb">UNSUPPORTED_SPECIAL_PREFIX</spanx></c>
      <c>An indirect parameter is a special designator (it starts with <spanx style="verb">@</spanx>) but <spanx style="verb">sop</spanx> does not know how to handle the prefix</c>
      <c>73</c>
      <c><spanx style="verb">AMBIGUOUS_INPUT</spanx></c>
      <c>A indirect input parameter is a special designator (it starts with <spanx style="verb">@</spanx>), and a filename matching the designator is actually present</c>
      <c>79</c>
      <c><spanx style="verb">KEY_CANNOT_SIGN</spanx></c>
      <c>Key not signature-capable (e.g., expired, revoked, unacceptable usage flags) (<spanx style="verb">sop sign</spanx> and <spanx style="verb">sop encrypt</spanx> with <spanx style="verb">--sign-with</spanx>)</c>
      <c>83</c>
      <c><spanx style="verb">INCOMPATIBLE_OPTIONS</spanx></c>
      <c>Options were supplied that are incompatible with each other</c>
      <c>89</c>
      <c><spanx style="verb">UNSUPPORTED_PROFILE</spanx></c>
      <c>The requested profile is unsupported (<spanx style="verb">sop generate-key</spanx>, <spanx style="verb">sop encrypt</spanx>), or the indicated subcommand does not accept profiles (<spanx style="verb">sop list-profiles</spanx>)</c>
      <c>97</c>
      <c><spanx style="verb">NO_HARDWARE_KEY_FOUND</spanx></c>
      <c>The <spanx style="verb">sop</spanx> implementation  supports some form of hardware-backed secret keys, but could not identify one from a keys object designated by the <spanx style="verb">@HARDWARE:</spanx> prefix (see <xref target="special-designator-hardware"/>)</c>
      <c>101</c>
      <c><spanx style="verb">HARDWARE_KEY_FAILURE</spanx></c>
      <c>The <spanx style="verb">sop</spanx> implementation tried to use a hardware-backed secret key, but the cryptographic hardware refused the operation for some reason other than a bad PIN or password (see <xref target="special-designator-hardware"/>)</c>
</texttable>

<t>If a <spanx style="verb">sop</spanx> implementation fails in some way not contemplated by this document, it <bcp14>MAY</bcp14> return any non-zero error code, not only those listed above.</t>

</section>
<section anchor="known-implementations"><name>Known Implementations</name>

<t>The following implementations are known at the time of this draft:</t>

<texttable title="Known implementations">
      <ttcol align='left'>Project name</ttcol>
      <ttcol align='left'>URL</ttcol>
      <ttcol align='left'>cli name</ttcol>
      <ttcol align='left'>notes</ttcol>
      <c>Sequoia SOP</c>
      <c>https://gitlab.com/sequoia-pgp/sequoia-sop</c>
      <c><spanx style="verb">sqop</spanx></c>
      <c>Implemented in Rust using the <spanx style="verb">sequoia-openpgp</spanx> crate</c>
      <c>gosop</c>
      <c>https://github.com/ProtonMail/gosop</c>
      <c><spanx style="verb">gosop</spanx></c>
      <c>Implemented in golang (Go) using GOpenPGP</c>
      <c>PGPainless SOP</c>
      <c>https://codeberg.org/PGPainless/pgpainless/src/branch/master/pgpainless-sop</c>
      <c><spanx style="verb">pgpainless-cli</spanx></c>
      <c>Implemented in Java using PGPainless</c>
      <c>sopgpy</c>
      <c>https://gitlab.com/sequoia-pgp/openpgp-interoperability-test-suite/-/blob/main/glue/sopgpy</c>
      <c><spanx style="verb">sopgpy</spanx></c>
      <c>Implemented in Python using PGPy</c>
      <c>sop-openpgp.js</c>
      <c>https://github.com/openpgpjs/sop-openpgpjs</c>
      <c><spanx style="verb">sop-openpgp</spanx></c>
      <c>Implemented in JavaScript using OpenPGP.js</c>
      <c>gpgme-sop</c>
      <c>https://gitlab.com/sequoia-pgp/gpgme-sop</c>
      <c><spanx style="verb">gpgme-sop</spanx></c>
      <c>A Rust wrapper around the gpgme C library</c>
      <c>RNP-sop</c>
      <c>https://gitlab.com/sequoia-pgp/rnp-sop</c>
      <c><spanx style="verb">rnp-sop</spanx></c>
      <c>A Rust wrapper around the librnp C library</c>
      <c>dkg-sop</c>
      <c>https://git.savannah.nongnu.org/cgit/dkgpg.git/tree/tools/dkg-sop.cc</c>
      <c><spanx style="verb">dkg-sop</spanx></c>
      <c>Implemented in C++ using the LibTMCG library</c>
</texttable>

</section>
<section anchor="alternate-interfaces"><name>Alternate Interfaces</name>

<t>This draft primarily defines a command line interface, but future versions may try to outline a comparable idiomatic interface for C or some other widely-used programming language.</t>

<t>Comparable idiomatic interfaces are already active in the wild for different programming languages, in particular:</t>

<t><list style="symbols">
  <t>Rust: <xref target="RUST-SOP"/></t>
  <t>Java: <xref target="SOP-JAVA"/></t>
  <t>Python: <xref target="PYTHON-SOP"/></t>
</list></t>

<t>These programmatic interfaces are typically coupled with a wrapper that can automatically generate a command-line tool compatible with this draft.</t>

<t>An implementation that uses one of these languages should target the corresponding idiomatic interface for ease of development and interoperability.</t>

</section>
<section anchor="guidance-for-implementers"><name>Guidance for Implementers</name>

<t><spanx style="verb">sop</spanx> uses a few assumptions that implementers might want to consider.</t>

<section anchor="one-openpgp-message-at-a-time"><name>One OpenPGP Message at a Time</name>

<t><spanx style="verb">sop</spanx> 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 deal with multiple OpenPGP objects.</t>

<t>FIXME: discuss what this means for streaming.
The stdio interface doesn't necessarily imply streamed output.</t>

</section>
<section anchor="simplified-subset-of-openpgp-message"><name>Simplified Subset of OpenPGP Message</name>

<t>While the formal grammar for OpenPGP Message is arbitrarily nestable, <spanx style="verb">sop</spanx> constrains itself to what it sees as a single "layer" (see <xref target="ciphertext"/>).</t>

<t>This is a deliberate choice, because it is what most consumers expect.
Also, if an arbitrarily-nested structure is parsed with a recursive algorithm, this risks a denial of service vulnerability.
<spanx style="verb">sop</spanx> intends to be implementable with a parser that defensively declines to do recursive descent into an OpenPGP Message.</t>

<t>Note that an implementation of <spanx style="verb">sop decrypt</spanx> <bcp14>MAY</bcp14> choose to handle 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 documentation to improve future versions of this spec.</t>

</section>
<section anchor="validate-signatures-only-from-known-signers"><name>Validate Signatures Only from Known Signers</name>

<t>There are generally only a few signers who are relevant for a given OpenPGP message.
When verifying signatures, <spanx style="verb">sop</spanx> expects that the caller can identify those relevant signers ahead of time.</t>

</section>
<section anchor="optional-input-armoring"><name>OpenPGP Inputs can be either Binary or ASCII-armored</name>

<t>OpenPGP material on input can be in either ASCII-armored or binary form.
This is a deliberate choice because there are typical scenarios where the program can't predict which form will appear.
Expecting the caller of <spanx style="verb">sop</spanx> to detect the form and adjust accordingly seems both redundant and error-prone.</t>

<t>The simple way to detect possible ASCII-armoring is to see whether the high bit of the first octet is set:
<xref section="4.2" sectionFormat="of" target="RFC4880"/> indicates that bit 7 is always one in the first octet of an OpenPGP packet.
In standard ASCII-armor, the first character is <u>-</u>, so the high bit should be cleared.</t>

<t>When considering an input as ASCII-armored OpenPGP material, <spanx style="verb">sop</spanx> <bcp14>MAY</bcp14> reject an input based on any of the following variations (see <xref section="6.2" sectionFormat="of" target="RFC4880"/> for precise definitions):</t>

<t><list style="symbols">
  <t>An unknown Armor Header Line</t>
  <t>Any text before the Armor Header Line</t>
  <t>Malformed lines in the Armor Headers section</t>
  <t>Any non-whitespace data after the Armor Tail</t>
  <t>Any Radix-64 encoded line with more than 76 characters</t>
  <t>Invalid characters in the Radix-64-encoded data</t>
  <t>An invalid Armor Checksum</t>
  <t>A mismatch between the Armor Header Line and the Armor Tail</t>
  <t>More than one ASCII-armored object in the input</t>
</list></t>

<t>For robustness, <spanx style="verb">sop</spanx> <bcp14>SHOULD</bcp14> be willing to ignore whitespace after the Armor Tail.</t>

<t>For any plural data type (i.e.,<spanx style="verb">SIGNATURES</spanx>, <spanx style="verb">CERTS</spanx>, or <spanx style="verb">KEYS</spanx>), the unarmored form is trivially concatenatable with another object of the same type (e.g., with Unix's <spanx style="verb">cat</spanx> utility).
But the armored forms are not concatenatable without first dearmoring.
To avoid inconsistent behavior, a <spanx style="verb">sop</spanx> implementation <bcp14>SHOULD</bcp14> reject anything that appears to be a concatenated series of ASCII-armored objects.</t>

<t>When considering OpenPGP material as input, regardless of whether it is ASCII-armored or binary, <spanx style="verb">sop</spanx> <bcp14>SHOULD</bcp14> reject any material that doesn't produce a valid stream of OpenPGP packets.
For example, <spanx style="verb">sop</spanx> <bcp14>SHOULD</bcp14> raise an error if an OpenPGP packet header is malformed, or if there is trailing garbage after the end of a packet.</t>

<t>For a given type of OpenPGP input material (i.e.,  <spanx style="verb">SIGNATURES</spanx>, <spanx style="verb">CERTS</spanx>, <spanx style="verb">KEYS</spanx>, <spanx style="verb">INLINESIGNED</spanx>, or <spanx style="verb">CIPHERTEXT</spanx>), <spanx style="verb">sop</spanx> <bcp14>SHOULD</bcp14> also reject any input that does not conform to the expected packet stream.
See <xref target="indirect-types"/> for the expected packet stream for different types.</t>

</section>
<section anchor="csf-risks"><name>Complexities of the Cleartext Signature Framework</name>

<t><spanx style="verb">sop</spanx> prefers a detached signature as the baseline form of OpenPGP signature, but provides affordances for dealing with inline-signed messages (see <spanx style="verb">INLINESIGNED</spanx>, <xref target="inlinesigned"/>) as well.</t>

<t>The most complex form of inline-signed messages is the Cleartext Signature Framework (CSF).
Handling the CSF structure requires parsing to delimit the multiple parts of the document, including at least:</t>

<t><list style="symbols">
  <t>any preamble before the message</t>
  <t>the inline message header (delimiter line, OpenPGP headers)</t>
  <t>the message itself</t>
  <t>the divider between the message and the signature (including any OpenPGP headers there)</t>
  <t>the signature</t>
  <t>the divider that terminates the signature</t>
  <t>any suffix after the signature</t>
</list></t>

<t>Note also that the preamble or the suffix might be arbitrary text, and might themselves contain OpenPGP messages (whether signatures or otherwise).</t>

<t>If the parser that does this split differs in any way from the parser that does the verification, or parts of the message are confused,
it would be possible to produce a verification status and an actual signed message that don't correspond to one another.</t>

<t>Blurred boundary problems like this can produce ugly attacks similar to those found in <xref target="EFAIL"></xref>.</t>

<t>A user of <spanx style="verb">sop</spanx> that receives an inline-signed message (whether the message uses the CSF or not) can detach the signature from the message with <spanx style="verb">sop inline-detach</spanx> (see <xref target="inline-detach"/>).</t>

<t>Alternately, the user can send the message through <spanx style="verb">sop inline-verify</spanx> to confirm required signatures, and then (if signatures are valid) supply its output to the consumer of the signed message.</t>

</section>
<section anchor="cert-validity-performance"><name>Reliance on Supplied Certs and Keys</name>

<t>A truly stateless implementation may find that it spends more time validating the internal consistency of certificates and keys than it does on the actual object security operations.</t>

<t>For performance reasons, an implementation may choose to ignore validation on certificate and key material supplied to it.  The security implications of doing so depend on how the certs and keys are managed outside of <spanx style="verb">sop</spanx>.</t>

</section>
<section anchor="utf8"><name>Text is always UTF-8</name>

<t>Various places in this specification require UTF-8 <xref target="RFC3629"/> when encoding text. <spanx style="verb">sop</spanx> implementations <bcp14>SHOULD NOT</bcp14> consider textual data in any other character encoding.</t>

<t>OpenPGP Implementations <bcp14>MUST</bcp14> already handle UTF-8, because various parts of <xref target="RFC4880"/> require it, including:</t>

<t><list style="symbols">
  <t>User ID</t>
  <t>Notation name</t>
  <t>Reason for revocation</t>
  <t>ASCII-armor Comment: header</t>
</list></t>

<t>Dealing with messages in other charsets leads to weird security failures like <xref target="Charset-Switching"/>, especially when the charset indication is not covered by any sort of cryptographic integrity check.
Restricting textual data to <spanx style="verb">UTF-8</spanx> universally across the OpenPGP ecosystem eliminates any such risk without losing functionality, since <spanx style="verb">UTF-8</spanx> can encode all known characters.</t>

</section>
<section anchor="human-readable-passwords"><name>Passwords are Human-Readable</name>

<t>Passwords are generally expected to be human-readable, as they are typically recorded and transmitted as human-visible, human-transferable strings.
However, they are used in the OpenPGP protocol as bytestrings, so it is important to ensure that there is a reliable bidirectional mapping between strings and bytes.
The maximally robust behavior here is for <spanx style="verb">sop encrypt</spanx> and <spanx style="verb">sop generate-key</spanx> (that is, commands that use a password to encrypt) to constrain the choice of passwords to strings that have such a mapping,
and for <spanx style="verb">sop decrypt</spanx> and <spanx style="verb">sop sign</spanx> (and <spanx style="verb">sop inline-sign</spanx>, as well as<spanx style="verb">sop encrypt</spanx> when decrypting a signing key; that is, commands that use a password to decrypt) to try multiple plausible versions of any password supplied by <spanx style="verb">PASSWORD</spanx>.</t>

<section anchor="generating-human-readable"><name>Generating Material with Human-Readable Passwords</name>

<t>When generating material based on a password, <spanx style="verb">sop encrypt</spanx> and <spanx style="verb">sop generate-key</spanx> enforce that the password is actually meaningfully human-transferable.
In particular, an implementation generating material based on a new paasword <bcp14>SHOULD</bcp14> apply the following considerations to the supplied password:</t>

<t><list style="symbols">
  <t>require <spanx style="verb">UTF-8</spanx></t>
  <t>trim trailing whitespace</t>
</list></t>

<t>Some <spanx style="verb">sop encrypt</spanx> and <spanx style="verb">sop generate-key</spanx> implementations may make even more strict requirements on input to ensure that they are transferable between humans in a robust way.</t>

<t>For example, a more strict <spanx style="verb">sop encrypt</spanx> or <spanx style="verb">sop generate-key</spanx> <bcp14>MAY</bcp14> also:</t>

<t><list style="symbols">
  <t>forbid leading whitespace</t>
  <t>forbid non-printing characters other than <spanx style="verb">SPACE (U+0020)</spanx>, such as <spanx style="verb">ZERO WIDTH NON-JOINER (U+200C)</spanx> or <spanx style="verb">TAB (U+0009)</spanx></t>
  <t>require the password to be in Unicode Normal Form C (<xref target="UNICODE-NORMALIZATION"/>)</t>
</list></t>

<t>Violations of these more-strict policies <bcp14>SHOULD</bcp14> result in an error of <spanx style="verb">PASSWORD_NOT_HUMAN_READABLE</spanx>.</t>

<t>A <spanx style="verb">sop encrypt</spanx> or <spanx style="verb">sop generate-key</spanx> implementation typically <bcp14>SHOULD NOT</bcp14> attempt enforce a minimum "password strength",
but in the event that some implementation does, it <bcp14>MUST NOT</bcp14> represent a weak password with <spanx style="verb">PASSWORD_NOT_HUMAN_READABLE</spanx>.</t>

</section>
<section anchor="consuming-passwords"><name>Consuming Password-protected Material</name>

<t>When <spanx style="verb">sop decrypt</spanx> receives a <spanx style="verb">PASSWORD</spanx> input, either from a <spanx style="verb">--with-key-password</spanx> or <spanx style="verb">--with-password</spanx> option, it sees its content as a bytestring.
<spanx style="verb">sop sign</spanx> also sees the content of any <spanx style="verb">PASSWORD</spanx> input supplied to its <spanx style="verb">--with-key-password</spanx>  option as a bytestring.
If the bytestring fails to work as a password, but ends in <spanx style="verb">UTF-8</spanx> whitespace, it will try again with the trailing whitespace removed.
This handles a common pattern of using a file with a final newline, for example.
The pattern here is one of robustness in the face of typical errors in human-transferred textual data.</t>

<t>A more robust <spanx style="verb">sop decrypt</spanx> or <spanx style="verb">sop sign</spanx> implementation that finds neither of the above two attempts work for a given <spanx style="verb">PASSWORD</spanx> <bcp14>MAY</bcp14> try additional variations if they produce a different bytestring, such as:</t>

<t><list style="symbols">
  <t>trimming any leading whitespace, if discovered</t>
  <t>trimming any internal non-printable characters other than <spanx style="verb">SPACE (U+0020)</spanx></t>
  <t>converting the supplied <spanx style="verb">PASSWORD</spanx> into Unicode Normal Form C (<xref target="UNICODE-NORMALIZATION"/>)</t>
</list></t>

<t>A <spanx style="verb">sop decrypt</spanx> or <spanx style="verb">sop sign</spanx> implementation that stages multiple decryption attempts like this <bcp14>SHOULD</bcp14> consider the computational resources consumed by each attempt, to avoid presenting an attack surface for resource exhaustion in the face of a non-standard <spanx style="verb">PASSWORD</spanx> input.</t>

</section>
</section>
<section anchor="special-designators-guidance"><name>Be Careful with Special Designators</name>

<t>As documented in <xref target="special-designators"/>, special designators for indirect inputs like <spanx style="verb">@ENV:</spanx> and <spanx style="verb">@FD:</spanx> (and indirect outputs using <spanx style="verb">@FD:</spanx>) warrant some special/cautious handling.</t>

<t>For one thing, it's conceivable that the filesystem could contain a file with these literal names.
If <spanx style="verb">sop</spanx> receives an indirect output parameter that starts with an <u>@</u> it <bcp14>MUST NOT</bcp14> write to the filesystem for that parameter.
A <spanx style="verb">sop</spanx> implementation that receives such a parameter as input <bcp14>MAY</bcp14> test for the presence of such a file in the filesystem and fail with <spanx style="verb">AMBIGUOUS_INPUT</spanx> to warn the user of the ambiguity and possible confusion.</t>

<t>These special designators are likely to be used to pass sensitive data (like secret key material or passwords) so that it doesn't need to touch the filesystem.
Given this sensitivity, <spanx style="verb">sop</spanx> should be careful with such an input, and minimize its leakage to other processes.
In particular, <spanx style="verb">sop</spanx> <bcp14>SHOULD NOT</bcp14> leak any environment variable identified by <spanx style="verb">@ENV:</spanx> or file descriptor identified by <spanx style="verb">@FD:</spanx> to any subprocess unless the subprocess specifically needs access to that data.</t>

</section>
<section anchor="hardware-backed-secrets"><name>Nuances for Hardware-backed Secret Key Material</name>

<t>There are a number of limitations and nuances to be aware of for hardware-backed secret key support in this interface.
Some <spanx style="verb">sop</spanx> implementations will simply not support hardware-backed secret key material.
Other implementations might support only a single kind of hardware-backing (e.g., an OpenPGP Smartcard <xref target="OPENPGP-SMARTCARD"/> but not a TPM, or vice versa).</t>

<t>The specification of the <spanx style="verb">@HARDWARE:</spanx> special designator (see <xref target="special-designator-hardware"/>) is agnostic about the specific kind of cryptographic hardware, but it does imply a sort of rough shape of what the interface to the hardware would permit.
In particular, it will work best with hardware that has the following properties:</t>

<t><list style="symbols">
  <t>The hardware does specific asymmetric secret key operations, using secret keys that it does not release.</t>
  <t>The user can ask the hardware to provide a list of corresponding public key material (or OpenPGP key fingerprints) for any of the secret keys held by the device.</t>
  <t>The hardware <bcp14>MAY</bcp14> require the provision of a PIN or password to enable secret key operation, but does not require a PIN or password for the list of public key material.</t>
</list></t>

<t>The <spanx style="verb">sop</spanx> interface does not currently provide for provisioning cryptographic hardware with secret key material, or for changing the PIN or password for the cryptographic hardware.
Users of cryptographic hardware need to do provisioning and PIN or password setting outside of <spanx style="verb">sop</spanx>.</t>

<t>If a user has two attached hardware tokens that both hold the same secret key, and they are both password-locked, and they use different passwords, <spanx style="verb">sop</spanx> offers no way for the user to clearly indicate which password belongs to which device.
Some cryptographic hardware is designed to lock the device if the wrong password is entered too many times, so users in this configuration are at risk of accidental lockout.
The easiest resolution for this is for the user to detach any duplicate devices before invoking <spanx style="verb">sop</spanx>.</t>

<t>Note that some OpenPGP implementations use the private codepoint ranges in the OpenPGP specification within an OpenPGP Transferable Secret Key (e.g., <xref target="GNUPG-SECRET-STUB"/>) to indicate that the secret key can be found on a smartcard.
A non-private, non-experimental specification of this approach might make the <spanx style="verb">@HARDWARE:</spanx> special designator obsolete.</t>

<t>While hardware-backed secret key operations can be significantly slower than modern computers, and physical affordances like button-presses or NFC tapping can themselves incur delay, it's bad form for an invocation of <spanx style="verb">sop</spanx> to hang forever.
This specification doesn't define a specific maximum allowable delay, but if an implementation calls into a hardware device either for public key listing or for secret key operations, it should not allow the cryptographic hardware to take an arbitrary amount of time to respond.</t>

</section>
</section>
<section anchor="guidance-for-consumers"><name>Guidance for Consumers</name>

<t>While <spanx style="verb">sop</spanx> is originally conceived of as an interface for interoperability testing, it's conceivable that an application that uses OpenPGP for object security would want to use it.</t>

<t>FIXME: more guidance for how to use such a tool safely and efficiently goes here.</t>

<t>FIXME: if an encrypted OpenPGP message arrives without metadata, it is difficult to know which signers to consider when decrypting.
How do we do this efficiently without invoking <spanx style="verb">sop decrypt</spanx> twice, once without <spanx style="verb">--verify-*</spanx> and again with the expected identity material?</t>

<section anchor="choosing-between-astext-and-asbinary"><name>Choosing Between --as=text and --as=binary</name>

<t>A program that invokes <spanx style="verb">sop</spanx> to generate an OpenPGP signature typically needs to decide whether it is making a text or binary signature.</t>

<t>By default, <spanx style="verb">sop</spanx> will make a binary signature.
The caller of <spanx style="verb">sop sign</spanx> should choose <spanx style="verb">--as=text</spanx> only when it knows that:</t>

<t><list style="symbols">
  <t>the data being signed is in fact textual, and encoded in <spanx style="verb">UTF-8</spanx>, and</t>
  <t>the signed data might be transmitted to the recipient (the verifier of the signature) over a channel that has the propensity to transform line-endings.</t>
</list></t>

<t>Examples of such channels include FTP (<xref target="RFC0959"/>) and SMTP (<xref target="RFC5321"/>).</t>

</section>
<section anchor="special-designators-and-unusual-filenames"><name>Special Designators and Unusual Filenames</name>

<t>In some cases, a user of <spanx style="verb">sop</spanx> might want to pass all the files in a given directory as positional parameters (e.g., a list of CERTS files to test a signature against).</t>

<t>If one of the files has a name that starts with <spanx style="verb">--</spanx>, it might be confused by <spanx style="verb">sop</spanx> for an option.
If one of the files has a name that starts with <spanx style="verb">@</spanx>, it might be confused by <spanx style="verb">sop</spanx> as a special designator (<xref target="special-designators"/>).</t>

<t>If the user wants to deliberately refer to such an ambiguously-named file in the filesystem, they should prefix the filename with  <spanx style="verb">./</spanx> or use an absolute path.</t>

<t>Any specific <spanx style="verb">@FD:</spanx> special designator <bcp14>SHOULD NOT</bcp14> be supplied more than once to an invocation of <spanx style="verb">sop</spanx>.
If a <spanx style="verb">sop</spanx> invocation sees multiple copies of a specific <spanx style="verb">@FD:n</spanx> input (e.g., <spanx style="verb">sop sign @FD:3 @FD:3</spanx>),
it <bcp14>MAY</bcp14> fail with <spanx style="verb">MISSING_INPUT</spanx> even if file descriptor 3 contains a valid <spanx style="verb">KEYS</spanx>, because the bytestream for the <spanx style="verb">KEYS</spanx> was consumed by the first argument.
Doubling up on the same <spanx style="verb">@FD:</spanx> for output (e.g., <spanx style="verb">sop decrypt --session-key-out=@FD:3 --verifications-out=@FD:3</spanx>) also results in an ambiguous data stream.</t>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<t>The OpenPGP object security model is typically used for confidentiality and authenticity purposes.</t>

<section anchor="signature-verification"><name>Signature Verification</name>

<t>In many contexts, an OpenPGP signature is verified to prove the origin and integrity of an underlying object.</t>

<t>When <spanx style="verb">sop</spanx> checks a signature over data (e.g., via <spanx style="verb">sop verify</spanx> or <spanx style="verb">sop decrypt --verify-with</spanx>), it <bcp14>MUST NOT</bcp14> consider it to be verified unless all of these conditions are met:</t>

<t><list style="symbols">
  <t>The signature must be made by a signing-capable public key that is present in one of the supplied certificates</t>
  <t>The certificate and signing subkey must have been created before or at the signature time</t>
  <t>The certificate and signing subkey must not have been expired at the signature time</t>
  <t>The certificate and signing subkey must not be revoked with a "hard" revocation</t>
  <t>If the certificate or signing subkey is revoked with a "soft" revocation, then the signature time must predate the revocation</t>
  <t>The signing subkey must be properly bound to the primary key, and cross-signed</t>
  <t>The signature (and any dependent signature, such as the cross-sig or subkey binding signatures) must be made with strong cryptographic algorithms (e.g., not <spanx style="verb">MD5</spanx> or a 1024-bit <spanx style="verb">RSA</spanx> key)</t>
  <t>The signature must be of type 0x00 ("Signature of a binary document") or 0x01 ("Signature of a canonical text document"); other signature types are inappropriate for data signatures</t>
</list></t>

<t>Implementers <bcp14>MAY</bcp14> also consider other factors in addition to the origin and authenticity, including application-specific information.</t>

<t>For example, consider the application domain of checking software updates.
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 2019-10-16, it may be authentic and have a more recent signature date.
But it is not an upgrade (12.4.8 &lt; 13.3.2), and therefore it should not be applied automatically.</t>

<t>In such cases, it is critical that the application confirms that the other information verified is <em>also</em> protected by the relevant OpenPGP signature.</t>

<t>Signature validity is a complex topic (see for example the discussion at <xref target="DISPLAYING-SIGNATURES"/>), and this documentation cannot list all possible details.</t>

</section>
<section anchor="compression"><name>Compression</name>

<t>The interface as currently specified does not allow for control of compression.
Compressing and encrypting data that may contain both attacker-supplied material and sensitive material could leak information about the sensitive material (see the CRIME attack).</t>

<t>Unless an application knows for sure that no attacker-supplied material is present in the input, it should not compress during encryption.</t>

</section>
</section>
<section anchor="privacy-considerations"><name>Privacy Considerations</name>

<t>Material produced by <spanx style="verb">sop encrypt</spanx> may be placed on an untrusted machine (e.g., sent through the public <spanx style="verb">SMTP</spanx> network).
That material may contain metadata that leaks associational information (e.g., recipient identifiers in PKESK packets (<xref section="5.1" sectionFormat="of" target="I-D.ietf-openpgp-crypto-refresh-10"/>)).
FIXME: document things like PURBs and <spanx style="verb">--hidden-recipient</spanx>)</t>

<section anchor="object-security-vs-transport-security"><name>Object Security vs. Transport Security</name>

<t>OpenPGP offers an object security model, but says little to nothing about how the secured objects get to the relevant parties.</t>

<t>When sending or receiving OpenPGP material, the implementer should consider what privacy leakage is implicit with the transport.</t>

</section>
</section>


  </middle>

  <back>


    <references title='Normative References'>





<reference anchor='RFC2119'>
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author fullname='S. Bradner' initials='S.' surname='Bradner'><organization/></author>
<date month='March' year='1997'/>
<abstract><t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t></abstract>
</front>
<seriesInfo name='BCP' value='14'/>
<seriesInfo name='RFC' value='2119'/>
<seriesInfo name='DOI' value='10.17487/RFC2119'/>
</reference>

<reference anchor='RFC8174'>
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname='B. Leiba' initials='B.' surname='Leiba'/>
    <date month='May' year='2017'/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name='BCP' value='14'/>
  <seriesInfo name='RFC' value='8174'/>
  <seriesInfo name='DOI' value='10.17487/RFC8174'/>
</reference>

<reference anchor='RFC4880'>
  <front>
    <title>OpenPGP Message Format</title>
    <author fullname='J. Callas' initials='J.' surname='Callas'/>
    <author fullname='L. Donnerhacke' initials='L.' surname='Donnerhacke'/>
    <author fullname='H. Finney' initials='H.' surname='Finney'/>
    <author fullname='D. Shaw' initials='D.' surname='Shaw'/>
    <author fullname='R. Thayer' initials='R.' surname='Thayer'/>
    <date month='November' year='2007'/>
    <abstract>
      <t>This document is maintained in order to publish all necessary information needed to develop interoperable applications based on the OpenPGP format. It is not a step-by-step cookbook for writing an application. It describes only the format and methods needed to read, check, generate, and write conforming packets crossing any network. It does not deal with storage and implementation questions. It does, however, discuss implementation issues necessary to avoid security flaws.</t>
      <t>OpenPGP software uses a combination of strong public-key and symmetric cryptography to provide security services for electronic communications and data storage. These services include confidentiality, key management, authentication, and digital signatures. This document specifies the message formats used in OpenPGP. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='4880'/>
  <seriesInfo name='DOI' value='10.17487/RFC4880'/>
</reference>


<reference anchor='I-D.ietf-openpgp-crypto-refresh-10'>
   <front>
      <title>OpenPGP</title>
      <author fullname='Paul Wouters' initials='P.' surname='Wouters'>
         <organization>Aiven</organization>
      </author>
      <author fullname='Daniel Huigens' initials='D.' surname='Huigens'>
         <organization>Proton AG</organization>
      </author>
      <author fullname='Justus Winter' initials='J.' surname='Winter'>
         <organization>Sequoia-PGP</organization>
      </author>
      <author fullname='Niibe Yutaka' initials='N.' surname='Yutaka'>
         <organization>FSIJ</organization>
      </author>
      <date day='21' month='June' year='2023'/>
      <abstract>
	 <t>   This document specifies the message formats used in OpenPGP.  OpenPGP
   provides encryption with public-key or symmetric cryptographic
   algorithms, digital signatures, compression and key management.

   This document is maintained in order to publish all necessary
   information needed to develop interoperable applications based on the
   OpenPGP format.  It is not a step-by-step cookbook for writing an
   application.  It describes only the format and methods needed to
   read, check, generate, and write conforming packets crossing any
   network.  It does not deal with storage and implementation questions.
   It does, however, discuss implementation issues necessary to avoid
   security flaws.

   This document obsoletes: RFC 4880 (OpenPGP), RFC 5581 (Camellia in
   OpenPGP) and RFC 6637 (Elliptic Curves in OpenPGP).

	 </t>
      </abstract>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-ietf-openpgp-crypto-refresh-10'/>
   
</reference>

<reference anchor='RFC3156'>
  <front>
    <title>MIME Security with OpenPGP</title>
    <author fullname='M. Elkins' initials='M.' surname='Elkins'/>
    <author fullname='D. Del Torto' initials='D.' surname='Del Torto'/>
    <author fullname='R. Levien' initials='R.' surname='Levien'/>
    <author fullname='T. Roessler' initials='T.' surname='Roessler'/>
    <date month='August' year='2001'/>
    <abstract>
      <t>This document describes how the OpenPGP Message Format can be used to provide privacy and authentication using the Multipurpose Internet Mail Extensions (MIME) security content types described in RFC 1847. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='3156'/>
  <seriesInfo name='DOI' value='10.17487/RFC3156'/>
</reference>

<reference anchor='RFC3629'>
  <front>
    <title>UTF-8, a transformation format of ISO 10646</title>
    <author fullname='F. Yergeau' initials='F.' surname='Yergeau'/>
    <date month='November' year='2003'/>
    <abstract>
      <t>ISO/IEC 10646-1 defines a large character set called the Universal Character Set (UCS) which encompasses most of the world's writing systems. The originally proposed encodings of the UCS, however, were not compatible with many current applications and protocols, and this has led to the development of UTF-8, the object of this memo. UTF-8 has the characteristic of preserving the full US-ASCII range, providing compatibility with file systems, parsers and other software that rely on US-ASCII values but are transparent to other values. This memo obsoletes and replaces RFC 2279.</t>
    </abstract>
  </front>
  <seriesInfo name='STD' value='63'/>
  <seriesInfo name='RFC' value='3629'/>
  <seriesInfo name='DOI' value='10.17487/RFC3629'/>
</reference>




    </references>

    <references title='Informative References'>

<reference anchor="OpenPGP-Interoperability-Test-Suite" target="https://tests.sequoia-pgp.org/">
  <front>
    <title>OpenPGP Interoperability Test Suite</title>
    <author >
      <organization></organization>
    </author>
    <date year="2021" month="October" day="25"/>
  </front>
</reference>
<reference anchor="Charset-Switching" target="https://dkg.fifthhorseman.net/notes/inline-pgp-harmful/">
  <front>
    <title>Inline PGP Considered Harmful</title>
    <author initials="D. K." surname="Gillmor" fullname="Daniel Kahn Gillmor">
      <organization></organization>
    </author>
    <date year="2014" month="February" day="24"/>
  </front>
</reference>
<reference anchor="DISPLAYING-SIGNATURES" target="https://admin.hostpoint.ch/pipermail/enigmail-users_enigmail.net/2017-November/004683.html">
  <front>
    <title>On Displaying Signatures</title>
    <author initials="P." surname="Brunschwig" fullname="Patrick Brunschwig">
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="EFAIL" target="https://efail.de">
  <front>
    <title>Efail: Breaking S/MIME and OpenPGP Email Encryption using Exfiltration Channels</title>
    <author initials="D." surname="Poddebniak" fullname="Damian Poddebniak">
      <organization></organization>
    </author>
    <author initials="C." surname="Dresen" fullname="Christian Dresen">
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="PYTHON-SOP" target="https://pypi.org/project/sop/">
  <front>
    <title>SOP for python</title>
    <author initials="D." surname="Gillmor" fullname="Daniel Kahn Gillmor">
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="RUST-SOP" target="https://sequoia-pgp.gitlab.io/sop-rs/">
  <front>
    <title>A Rust implementation of the Stateless OpenPGP Protocol</title>
    <author initials="J." surname="Winter" fullname="Justus Winter">
      <organization>Sequoia</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="SEMVER" target="https://semver.org/">
  <front>
    <title>Semantic Versioning 2.0.0</title>
    <author initials="T." surname="Preston-Werner" fullname="Tom Preston-Werner">
      <organization></organization>
    </author>
    <date year="2013" month="June" day="18"/>
  </front>
</reference>
<reference anchor="SOP-JAVA" target="https://github.com/pgpainless/sop-java">
  <front>
    <title>Stateless OpenPGP Protocol for Java.</title>
    <author initials="P." surname="Schaub" fullname="Paul Schaub">
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="UNICODE-NORMALIZATION" target="https://unicode.org/reports/tr15/">
  <front>
    <title>Unicode Normalization Forms</title>
    <author initials="K." surname="Whistler" fullname="Ken Whistler">
      <organization>Unicode Consortium</organization>
    </author>
    <date year="2019" month="February" day="04"/>
  </front>
</reference>
<reference anchor="OPENPGP-SMARTCARD" target="https://www.gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf">
  <front>
    <title>Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems, Version 3.4</title>
    <author initials="A." surname="Pietig" fullname="Achim Pietig">
      <organization></organization>
    </author>
    <date year="2020" month="March" day="18"/>
  </front>
</reference>
<reference anchor="GNUPG-SECRET-STUB" target="https://dev.gnupg.org/source/gnupg/browse/master/doc/DETAILS;gnupg-2.4.3$1511">
  <front>
    <title>GNU Extensions to the S2K algorithm</title>
    <author initials="W." surname="Koch" fullname="Werner Koch">
      <organization>g10 Code</organization>
    </author>
    <date year="2023" month="July" day="04"/>
  </front>
</reference>



<reference anchor='I-D.draft-bre-openpgp-samples-01'>
   <front>
      <title>OpenPGP Example Keys and Certificates</title>
      <author fullname='Bjarni Rúnar Einarsson' initials='B. R.' surname='Einarsson'>
         <organization>Mailpile ehf</organization>
      </author>
      <author fullname='&quot;juga&quot;' initials='' surname='&quot;juga&quot;'>
         <organization>Independent</organization>
      </author>
      <author fullname='Daniel Kahn Gillmor' initials='D. K.' surname='Gillmor'>
         <organization>American Civil Liberties Union</organization>
      </author>
      <date day='20' month='December' year='2019'/>
      <abstract>
	 <t>   The OpenPGP development community benefits from sharing samples of
   signed or encrypted data.  This document facilitates such
   collaboration by defining a small set of OpenPGP certificates and
   keys for use when generating such samples.

	 </t>
      </abstract>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-bre-openpgp-samples-01'/>
   
</reference>


<reference anchor='I-D.ietf-lamps-e2e-mail-guidance-11'>
   <front>
      <title>Guidance on End-to-End E-mail Security</title>
      <author fullname='Daniel Kahn Gillmor' initials='D. K.' surname='Gillmor'>
         <organization>American Civil Liberties Union</organization>
      </author>
      <author fullname='Bernie Hoeneisen' initials='B.' surname='Hoeneisen'>
         <organization>pEp Foundation</organization>
      </author>
      <author fullname='Alexey Melnikov' initials='A.' surname='Melnikov'>
         <organization>Isode Ltd</organization>
      </author>
      <date day='8' month='August' year='2023'/>
      <abstract>
	 <t>   End-to-end cryptographic protections for e-mail messages can provide
   useful security.  However, the standards for providing cryptographic
   protection are extremely flexible.  That flexibility can trap users
   and cause surprising failures.  This document offers guidance for
   mail user agent implementers to help mitigate those risks, and to
   make end-to-end e-mail simple and secure for the end user.  It
   provides a useful set of vocabulary as well as suggestions to avoid
   common failures.  It also identifies a number of currently unsolved
   usability and interoperability problems.

	 </t>
      </abstract>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-ietf-lamps-e2e-mail-guidance-11'/>
   
</reference>

<reference anchor='RFC0959'>
  <front>
    <title>File Transfer Protocol</title>
    <author fullname='J. Postel' initials='J.' surname='Postel'/>
    <author fullname='J. Reynolds' initials='J.' surname='Reynolds'/>
    <date month='October' year='1985'/>
    <abstract>
      <t>This memo is the official specification of the File Transfer Protocol (FTP) for the DARPA Internet community. The primary intent is to clarify and correct the documentation of the FTP specification, not to change the protocol. The following new optional commands are included in this edition of the specification: Change to Parent Directory (CDUP), Structure Mount (SMNT), Store Unique (STOU), Remove Directory (RMD), Make Directory (MKD), Print Directory (PWD), and System (SYST). Note that this specification is compatible with the previous edition.</t>
    </abstract>
  </front>
  <seriesInfo name='STD' value='9'/>
  <seriesInfo name='RFC' value='959'/>
  <seriesInfo name='DOI' value='10.17487/RFC0959'/>
</reference>

<reference anchor='RFC5321'>
  <front>
    <title>Simple Mail Transfer Protocol</title>
    <author fullname='J. Klensin' initials='J.' surname='Klensin'/>
    <date month='October' year='2008'/>
    <abstract>
      <t>This document is a specification of the basic protocol for Internet electronic mail transport. It consolidates, updates, and clarifies several previous documents, making all or parts of most of them obsolete. It covers the SMTP extension mechanisms and best practices for the contemporary Internet, but does not provide details about particular extensions. Although SMTP was designed as a mail transport and delivery protocol, this specification also contains information that is important to its use as a "mail submission" protocol for "split-UA" (User Agent) mail reading systems and mobile environments. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='5321'/>
  <seriesInfo name='DOI' value='10.17487/RFC5321'/>
</reference>




    </references>


<section anchor="c-library-api-tentative"><name>C Library API (Tentative)</name>

<t>As specified in this draft, SOP is a command-line tool.</t>

<t>However, it can also be useful to have a comparable API exposed as a C library.
This library can be implemented as a shared object (e.g., <spanx style="verb">.so</spanx>, <spanx style="verb">.dll</spanx>, or <spanx style="verb">.dylib</spanx> depending on the platform) or as a statically linked object.
This interface can be reused in many different places, as most modern programming languages offer "bindings" to C libraries.</t>

<t>A proposed interface to a C library follows here as a C header file.</t>

<t>The primary goal of this shared object interface is to make it easy to implement the command-line interface described in this document.
That said, it is also intended to be relatively ergonomic to use in plausible OpenPGP workflows where the caller has access to all of the explicit state.</t>

<t>If there is a plausible OpenPGP workflow that is not supported by this library API, please propose improvements and explain the specific workflow.</t>

<figure><sourcecode type="text/x-chdr" name="sop.h"><![CDATA[
#ifndef __SOP_H__
#define __SOP_H__

#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>

/* C API for Stateless OpenPGP */

/* Depends on C99 */


/* statically-defined, non-opaque definitions */

typedef enum {
  SOP_OK = 0,
  SOP_INTERNAL_ERROR = 1, /* Not part of sop CLI */
  SOP_INVALID_ARG = 2, /* Not part of sop CLI */
  SOP_NO_SIGNATURE = 3,
  SOP_OPERATION_ALREADY_EXECUTED = 4, /* Not part of sop CLI */
  SOP_UNSUPPORTED_ASYMMETRIC_ALGO = 13,
  SOP_CERT_CANNOT_ENCRYPT = 17,
  SOP_MISSING_ARG = 19,
  SOP_INCOMPLETE_VERIFICATION = 23,
  SOP_CANNOT_DECRYPT = 29,
  SOP_PASSWORD_NOT_HUMAN_READABLE = 31,
  SOP_UNSUPPORTED_OPTION = 37,
  SOP_BAD_DATA = 41,
  SOP_EXPECTED_TEXT = 53,
  SOP_OUTPUT_EXISTS = 59,
  SOP_MISSING_INPUT = 61,
  SOP_KEY_IS_PROTECTED = 67,
  SOP_UNSUPPORTED_SUBCOMMAND = 69,
  SOP_UNSUPPORTED_SPECIAL_PREFIX = 71,
  SOP_AMBIGUOUS_INPUT = 73,
  SOP_KEY_CANNOT_SIGN = 79,
  SOP_INCOMPATIBLE_OPTIONS = 83,
  SOP_UNSUPPORTED_PROFILE = 89,
  SOP_NO_HARDWARE_KEY_FOUND = 97,
  SOP_HARDWARE_KEY_FAILURE = 101,

  /* ensures a stable size for the enum -- do not use! */
  SOP_MAX_ERR = INT_MAX,
} sop_err;
  

typedef enum {
  SOP_SIGN_AS_BINARY = 0,
  SOP_SIGN_AS_TEXT = 1,

  /* ensures a stable size for the enum -- do not use! */
  SOP_SIGN_AS_MAX = INT_MAX,
} sop_sign_as;

typedef enum {
  SOP_INLINE_SIGN_AS_BINARY = 0,
  SOP_INLINE_SIGN_AS_TEXT = 1,
  SOP_INLINE_SIGN_AS_CLEARSIGNED = 2,

  /* ensures a stable size for the enum -- do not use! */
  SOP_INLINE_SIGN_AS_MAX = INT_MAX,
} sop_inline_sign_as;

typedef enum {
  SOP_ENCRYPT_AS_BINARY = 0,
  SOP_ENCRYPT_AS_TEXT = 1,

  /* ensures a stable size for the enum -- do not use! */
  SOP_ENCRYPT_AS_MAX = INT_MAX,
} sop_encrypt_as;


/* FIXME: timestamps */
/* time_t is 32-bit on some architectures; we also want this to be
   able to represent a "none" value as well as a "now" value without
   removing some value from the range of time_t */
typedef time_t sop_time;
#define sop_time_none ((sop_time)0)
#define sop_time_now ((sop_time)-1)


/* Context object
 *
 * Each SOP object is bound back to a context object, and, when used
 * in combination with other SOP objects, all SOP objects should come
 * from the same context.
 *
 * A SOP context object need not be thread-safe; it should probably
 * not be used across multiple threads.  See "Zero global state" in
 * https://git.kernel.org/pub/scm/linux/kernel/git/kay/libabc.git/plain/README
 */

struct sop_ctx_st;
typedef struct sop_ctx_st sop_ctx;

sop_ctx*
sop_ctx_new ();
void
sop_ctx_free (sop_ctx *sop);

/* Logging: */

typedef enum {
  SOP_LOG_NEVER = 0,
  SOP_LOG_ERROR = 1,
  SOP_LOG_WARNING = 2,
  SOP_LOG_INFO = 3,
  SOP_LOG_DEBUG = 4,

  /* ensures a stable size for the enum -- do not use! */
  SOP_LOG_MAX = INT_MAX,
} sop_log_level;

static inline const char *
sop_log_level_name (sop_log_level log_level) {
#define rep(x) if (log_level == SOP_LOG_ ## x) return #x
  rep(ERROR);
  rep(WARNING);
  rep(INFO);
  rep(DEBUG);
#undef rep
  return "Unknown";
}

/* Handle warnings and other feedback.
 * 
 * A SOP implementation that is capable of producing log messages will
 * invoke the requested function with the log level of the message,
 * and a NULL-terminated UTF-8 human-readable string with no trailing
 * whitespace.
 *
 * the "passthrough" pointer is supplied by the library user via
 * sop_set_log_level.
 */
typedef void (*sop_log_func) (sop_log_level log_level, void *passthrough, const char *);
sop_err
sop_set_log_function (sop_ctx *sop, sop_log_func func, void *passthrough);
/* Set the logging verbosity.
 *
 * Only log warnings up to max_level. (by default, max_level is
 * SOP_LOG_WARNING, meaning SOP_LOG_INFO and SOP_LOG_DEBUG will be
 * suppressed).
 */
sop_err
sop_set_log_level (sop_ctx *sop, sop_log_level max_level);



/* Information about the library: */

/* The name and version of the implementation of the C API (simple
 * NUL-terminated string, no newlines), or NULL if there is an error
 * producing the version. */
const char *
sop_version (sop_ctx *sop);
/* The name and version of the primary underlying OpenPGP toolkit (or
 * NULL if there is no backend, or if there was an error producing the
 * backend version) */
const char *
sop_version_backend (sop_ctx *sop);
/* Any arbitrary extended version information other than sop_ctx_version.
   Version info should be UTF-8 text, separated by newlines (a
   NUL-terminated string, no trailing newline).  Can return NULL if
   there is nothing more to report beyond sop_version. */
const char *
sop_version_extended (sop_ctx *sop);

/* note: there is nothing comparable to sop version --sop-spec because
 * that should be visible based on the exported symbols in the shared
 * object */



/* PROFILE objects: */

/* These describe a profile (e.g. for generate-key or encrypt).  This
 * use used when the implementation might legitimately want to offer
 * the user some minimal amount of control over what is done.  The
 * profile-listing functions return blocks of four profiles.  A
 * sop_profile value of NULL represents no profile at all.  In a list
 * of sop_profile objects, once a NULL profile appears, no non-NULL
 * profiles may follow.
 
 */
struct sop_profile_st;
typedef struct sop_profile_st sop_profile;
/* the NUL-terminated string returned by sop_profile_name MUST be a
   UTF-8 encoded string, and MUST NOT include any whitespace or colon
   (`:`) characters.  It MUST NOT vary depending on locale. */
const char *
sop_profile_name (const sop_profile *profile);
/* The NUL-terminated string returned by sop_profile_description
   cannot contain any newlines, and it MAY vary depending on
   locale(7) if the implementation is internationalized. */
const char *
sop_profile_description (const sop_profile *profile);


#define SOP_MAX_PROFILE_COUNT 4

typedef struct {
  sop_profile *profile[SOP_MAX_PROFILE_COUNT];
} sop_profiles;

static inline int
sop_profiles_count(const sop_profiles profiles) {
  for (int i = 0; i < SOP_MAX_PROFILE_COUNT; i++)
    if (profiles.profile[i] == NULL)
      return i;
  return SOP_MAX_PROFILE_COUNT;
}

/* Return a list of profiles supported by the library for generating
 * keys.
 */
sop_err
sop_list_profiles_generate_key (sop_ctx *sop, sop_profiles *out);


/* CLEARTEXT (and other raw data): */

/* This is a standard buffer for bytestrings produced by sop.  Users
   never create this kind of object, but it is sometimes returned from
   the library. */
struct sop_buf_st;
typedef struct sop_buf_st sop_buf;

void
sop_buf_free (sop_buf *buf);
size_t
sop_buf_size (const sop_buf *buf);
const uint8_t *
sop_buf_data (const sop_buf *buf);


/* KEYS objects: */
struct sop_keys_st;
typedef struct sop_keys_st sop_keys;

sop_err
sop_keys_from_bytes (sop_ctx *sop,
                     const uint8_t* data, size_t len,
                     sop_keys **out);
sop_err
sop_keys_to_bytes (const sop_keys *keys,
                   bool armor, sop_buf **out);
void
sop_keys_free (sop_keys *keys);



/* Generate a new, minimal OpenPGP Transferable secret key.  `profile`
   can be NULL to mean the default profile. */
sop_err
sop_generate_key_with_profile (sop_ctx *sop,
                               sop_profile *profile,
                               bool sign_only,
                               sop_keys **out);

static inline sop_err
sop_generate_key (sop_ctx *sop, sop_keys **out) {
  return sop_generate_key_with_profile (sop, NULL, false, out);
}

/* For each key in the sop_keys object, add the given user ID, and
   return a new sop_keys object containing the updated keys.  If the
   supplied user ID is not valid UTF-8 text, this call will fail and
   return SOP_EXPECTED_TEXT.

   If the implementation rejects the user ID string by policy for any
   other reason, this call will fail and return SOP_BAD_DATA.
 */
sop_err
sop_keys_add_uid (const sop_keys *keys, const char *uid, sop_keys **out);

/* returns true if any of the secret key material is currently locked
   with a password */
sop_err
sop_keys_locked (const sop_keys *keys, bool *out);

/* return a new sop_keys object with any secret key material encrypted
   with `password` unlocked, Returns SOP_OK if all keys have now been
   unlocked.

   If any locked key material could not be unlocked, return
   SOP_KEY_IS_PROTECTED, while also unlocking what key material can be
   unlocked.

   This allows the user to try an arbitrary bytestream as a password.
   Most users will just invoke the inlined sop_keys_unlock, below.

   An implementation MUST NOT reject proposed passwords by policy
   during unlock, but rather should try them as requested.
*/
sop_err
sop_keys_unlock_raw (const sop_keys *keys,
                     const uint8_t *raw_password, size_t len,
                     sop_keys **out);


static inline sop_err
sop_keys_unlock (const sop_keys *keys, const char *password, sop_keys **out) {
  return sop_keys_unlock_raw (keys,
                              (const uint8_t *)password,
                              strlen (password),
                              out);
}


/* return a new sop_keys object where all secret key material is
   locked with `password` where possible.

   During locking, a safety-oriented implementation MAY reject the
   supplied password by policy for any number of reasons.  This helps
   libsop ensure that the proposed password can be successfully
   re-supplied during some future unlock attempt.

   If the implementation requires passwords to be UTF-8 text and the
   supplied password is not valid UTF-8, the implementation will fail,
   returning SOP_EXPECTED_TEXT.  If an implementation rejects a
   supplied password for some other reason (for example, if it
   contains an NUL, unprintable, or otherwise forbidden character),
   this call will fail and return SOP_BAD_DATA.

   If any key material is already locked, it does nothing and returns
   SOP_KEY_IS_PROTECTED.

   Upon a successful locking, the user probably wants to use
   sop_keys_free to free the original keys object.
*/
sop_err
sop_keys_lock_raw (const sop_keys *keys,
                   const uint8_t *password, size_t len,
                   sop_keys **out);

static inline sop_err
sop_keys_lock (const sop_keys *keys, const char *password, sop_keys **out) {
  return sop_keys_lock_raw (keys,
                            (const uint8_t *)password,
                            strlen (password),
                            out);
}





/* CERTS objects: */
struct sop_certs_st;
typedef struct sop_certs_st sop_certs;

sop_err
sop_certs_from_bytes (sop_ctx *sop,
                      const uint8_t* data, size_t len,
                      sop_certs **out);
sop_err
sop_certs_to_bytes (const sop_certs *certs,
                    bool armor, sop_buf **out);
void
sop_certs_free (sop_certs *certs);

/* Return the OpenPGP certificates ("Transferable Public Keys") that
   correspond to the OpenPGP Transferable Secret Keys. */
sop_err
sop_keys_extract_certs (const sop_keys *keys, sop_certs **out);


/* Return an OpenPGP revocation certificate for each Transferable
   Secret Key found in the input. */
sop_err
sop_keys_revoke_keys (const sop_keys *keys, sop_certs **out);


/* Create a keys object backed by available cryptographic hardware for
   secret keys that corresponds to the public keys from the given
   certs object.  If the implementation does not support any hardware
   backed secret keys, this function should fail with
   SOP_UNSUPPORTED_SPECIAL_PREFIX.

   If the implementation supports hardware-backed secret keys, but it
   cannot find available hardware-backed keys that correspond to the
   public keys in the certs object, it should fail with
   SOP_NO_HARDWARE_KEY_FOUND.
 */
sop_err
sop_keys_from_hardware (const sop_certs *certs, sop_keys **out);



/* SIGNATURES objects: */
struct sop_sigs_st;
typedef struct sop_sigs_st sop_sigs;

sop_err
sop_sigs_from_bytes (sop_ctx *sop,
                     const uint8_t* data, size_t len,
                     sop_sigs **out);
sop_err
sop_sigs_to_bytes (const sop_sigs *sigs,
                   bool armor, sop_buf **out);
void
sop_sigs_free (sop_sigs *sigs);



/* VERIFICATIONS (output only, describes valid, verified signatures): */
struct sop_verifications_st;
typedef struct sop_verifications_st sop_verifications;

void
sop_verifications_free (sop_verifications *verifs);
sop_err
sop_verifications_count (const sop_verifications *verifs, int *out);
/* textual representations of verifications, in the form described by
   VERIFICATIONS in the CLI */
sop_err
sop_verifications_to_text (const sop_verifications *verifs,
                           sop_buf **out);
/* returns SOP_INTERNAL_ERROR if count is out of bounds. */
sop_err
sop_verifications_get_time (const sop_verifications *verifs,
                            int count, sop_time *out);
/* returns SOP_INTERNAL_ERROR if count is out of bounds.  If the
   signature is neither type 0x00 nor 0x01, this should probably not
   be considered a valid, verified signature. */
sop_err
sop_verifications_get_mode (const sop_verifications *verifs,
                            int count, sop_sign_as *out);

/* FIXME: (do we want to get more detailed info programmatically?
   each verification should also have an issuing key fingerprint, a
   primary key fingerprint, and a trailing text string) */






/* create detached signatures: */
struct sop_op_sign_st;
typedef struct sop_op_sign_st sop_op_sign;

sop_err
sop_op_sign_new (sop_ctx *sop, sop_op_sign** out);
void
sop_op_sign_free (sop_op_sign *sign);

sop_err
sop_op_sign_use_keys (sop_op_sign *sign, const sop_keys *keys);

sop_err
sop_op_sign_detached_execute (sop_op_sign *sign,
                              sop_sign_as sign_as,
                              const uint8_t *msg,
                              size_t sz,
                              sop_buf **micalg_out,
                              sop_sigs **out);


/* verify detached signatures: */
struct sop_op_verify_st;
typedef struct sop_op_verify_st sop_op_verify;

sop_err
sop_op_verify_new (sop_ctx *sop, sop_op_verify** out);
void
sop_op_verify_free (sop_op_verify *verify);

sop_err
sop_op_verify_not_before (sop_op_verify *verify, sop_time when);
sop_err
sop_op_verify_not_after (sop_op_verify *verify, sop_time when);
sop_err
sop_op_verify_add_signers (sop_op_verify *verify,
                           const sop_certs *signers);

/* if no verifications are possible with the set of signers, this
   returns SOP_NO_SIGNATURE, and *out is set to NULL */
sop_err
sop_op_verify_detached_execute (sop_op_verify *verify,
                                const sop_sigs *sigs,
                                const uint8_t *msg,
                                size_t sz,
                                sop_verifications **out);



/* INLINESIGNED object: */
struct sop_inlinesigned_st;
typedef struct sop_inlinesigned_st sop_inlinesigned;

sop_err
sop_inlinesigned_from_bytes (sop_ctx *sop,
                             const uint8_t* data, size_t len,
                             sop_inlinesigned **out);
/* if the inlinesigned object uses the Cleartext Signing framework,
 * the armor parameter is ignored.
 */
sop_err
sop_inlinesigned_to_bytes (const sop_inlinesigned *inlinesigned,
                           bool armor, sop_buf **out);
void
sop_inlinesigned_free (sop_inlinesigned *inlinesigned);


/* sop inline-sign */
sop_err
sop_op_sign_inline_execute (sop_op_sign *sign,
                            sop_inline_sign_as sign_as,
                            const uint8_t *msg,
                            size_t sz,
                            sop_inlinesigned **out);

/* sop inline-verify */
sop_err
sop_op_verify_inline_execute (sop_op_verify *verify,
                              const sop_inlinesigned *msg,
                              sop_verifications **verifications_out,
                              sop_buf **msg_out);

/* sop inline-detach */
sop_err
sop_inlinesigned_detach (const sop_inlinesigned *msg,
                         sop_sigs **sigs_out,
                         sop_buf **msg_out);

#endif // __SOP_H__
]]></sourcecode></figure>

<t>This proposed interface currently deals only with signing.
Encryption and decryption will be added in a future revision.</t>

<section anchor="design-choices-for-library-api"><name>Design Choices for Library API</name>

<t>The library is deliberately minimal, with data types and functionality corresponding to the SOP CLI.
The interface itself should expose no dependencies beyond libc.</t>

<t>All datatypes are opaque structs.
Library implementations <bcp14>MUST NOT</bcp14> expose library users to the memory layout of the underlying objects.</t>

<t>The library deals with data that is all in RAM, and produces data in RAM.
For simplicity, it does not currently expose a streaming interface.</t>

<t>It should be fairly straightforward to implement the SOP CLI on top of such a library.</t>

</section>
<section anchor="library-use-patterns"><name>Library Use Patterns</name>

<t>There are two main kinds of data structures: operations (e.g., <spanx style="verb">sop_op_sign</spanx> and <spanx style="verb">sop_op_verify</spanx>) and datatypes (e.g., <spanx style="verb">sop_keys</spanx> and <spanx style="verb">sop_certs</spanx>).</t>

<t>Operation objects are one-shot objects.
They are used in the following pattern:</t>

<t><list style="symbols">
  <t>create an operations object (<spanx style="verb">sop_op_*_new</spanx>)</t>
  <t>adjust it to behave in certain ways (e.g., <spanx style="verb">sop_op_sign_use_keys</spanx>, <spanx style="verb">sop_op_verify_not_before</spanx>)</t>
  <t>execute it (with some specific <spanx style="verb">sop_op_*_execute</spanx> function)</t>
  <t>dispose of it (<spanx style="verb">sop_op_*_free</spanx>)</t>
</list></t>

<t>The library user <bcp14>MUST NOT</bcp14> execute the same operation object more than once.
When a single operation object is executed more than once, it should fail with <spanx style="verb">SOP_OPERATION_ALREADY_EXECUTED</spanx>.
FIXME: if a use case arises with a reasonable need to re-execute an already adjusted object, we could extend the API to allow the user to clone an object.</t>

<t>Datatype objects are reusable objects.
For example, it is fine for a library user to pass the same <spanx style="verb">sop_certs</spanx> to multiple <spanx style="verb">sop_op_*</spanx> operation objects, as long as the <spanx style="verb">sop_certs</spanx> object is not freed before the execution of all the operation objects it has been passed to.</t>

<t>Datatype objects are also immutable.
Any function which modifies a datatype object always creates a new copy of the object, with the specific change applied.
This immutability avoids any ambguity about what should happen when a datatype object is adjusted after it was passed to an operation object but before it was executed.</t>

</section>
</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>This work was inspired by Justus Winter's <xref target="OpenPGP-Interoperability-Test-Suite"/>.</t>

<t>The following people contributed helpful feedback and considerations to this draft, but are not responsible for its problems:</t>

<t><list style="symbols">
  <t>Allan Nordhøy</t>
  <t>Antoine Beaupré</t>
  <t>Edwin Taylor</t>
  <t>Heiko Schaefer</t>
  <t>Jameson Rollins</t>
  <t>Justus Winter</t>
  <t>Paul Schaub</t>
  <t>Vincent Breitmoser</t>
</list></t>

</section>
<section anchor="future-work"><name>Future Work</name>

<t><list style="symbols">
  <t>certificate transformation into popular publication forms:
  <list style="symbols">
      <t>WKD</t>
      <t>DANE OPENPGPKEY</t>
      <t>Autocrypt</t>
    </list></t>
  <t><spanx style="verb">sop encrypt</spanx> -- specify compression? (see <xref target="compression"/>)</t>
  <t><spanx style="verb">sop encrypt</spanx> -- specify padding policy/mechanism?</t>
  <t><spanx style="verb">sop decrypt</spanx> -- how can it more safely handle zip bombs?</t>
  <t><spanx style="verb">sop decrypt</spanx> -- what should it do when encountering weakly-encrypted (or unencrypted) input?</t>
  <t><spanx style="verb">sop encrypt</spanx> -- minimize metadata (e.g., <spanx style="verb">--throw-keyids</spanx>)?</t>
  <t>specify an error if a <spanx style="verb">DATE</spanx> arrives as input without a time zone?</t>
  <t>add considerations about what it means for armored <spanx style="verb">CERTS</spanx> to contain multiple certificates -- multiple armorings?  one big blob?</t>
  <t>do we need an interface or option (for performance?) with the semantics that <spanx style="verb">sop</spanx> doesn't validate certificates internally, it just accepts whatever's given as legit data? (see <xref target="cert-validity-performance"/>)</t>
  <t>do we need to be able to convert a message with a text-based signature to a CSF <spanx style="verb">INLINESIGNED</spanx> message? I'd rather not, given the additional complications.</t>
  <t>add encryption and decryption to C Library API</t>
</list></t>

</section>
<section anchor="document-history"><name>Document History</name>

<section anchor="substantive-changes-between-08-and-09"><name>Substantive Changes between -08 and -09:</name>

<t><list style="symbols">
  <t>enable the use of hardware-backed secret key material via the <spanx style="verb">@HARDWARE:</spanx> special designator</t>
  <t>C API: clarify design goals and usage patterns</t>
  <t>C API: major overhaul and normalization:
  <list style="symbols">
      <t>allow passthrough "cookie" for logging</t>
      <t>allow NULL return from <spanx style="verb">sop_version_*</spanx></t>
      <t>explicitly offer <spanx style="verb">SOP_LOG_NEVER</spanx></t>
      <t>use <spanx style="verb">*_from_bytes</spanx> and <spanx style="verb">*_to_bytes</spanx> instead of <spanx style="verb">*_import</spanx> and <spanx style="verb">*_export</spanx></t>
      <t>datatype objects are now immutable</t>
      <t>operation objects are one-shot</t>
      <t>always return <spanx style="verb">sop_err</spanx>, even at a slight cost to C caller ergonomics</t>
    </list></t>
</list></t>

</section>
<section anchor="substantive-changes-between-07-and-08"><name>Substantive Changes between -07 and -08:</name>

<t><list style="symbols">
  <t><spanx style="verb">revoke-key</spanx>, <spanx style="verb">change-key-password</spanx>: add <spanx style="verb">--no-armor</spanx> option</t>
  <t><spanx style="verb">generate-key</spanx>: should fail on non-UTF-8 <spanx style="verb">USERID</spanx></t>
  <t><spanx style="verb">generate-key</spanx>: acknowledge that implementations <bcp14>MAY</bcp14> reject <spanx style="verb">USERID</spanx>s that seem bad</t>
  <t><spanx style="verb">armor</spanx>: drop <spanx style="verb">--label</spanx> option</t>
  <t><spanx style="verb">encrypt</spanx>: add <spanx style="verb">--session-key-out</spanx> option</t>
  <t>ASCII-armored objects should not be concatenated</t>
  <t>signature verification should only work for sigtypes 0x00 (binary) and 0x01 (canonical text)</t>
  <t><spanx style="verb">sign</spanx>: Constrain input when <spanx style="verb">--micalg-out</spanx> is present for alignment with <xref target="RFC3156"/></t>
  <t>propose simple C API for signing and verification</t>
</list></t>

</section>
<section anchor="substantive-changes-between-06-and-07"><name>Substantive Changes between -06 and -07:</name>

<t><list style="symbols">
  <t><spanx style="verb">generate-key</spanx>: add <spanx style="verb">--signing-only</spanx> option</t>
  <t>new key management subcommand: <spanx style="verb">change-key-password</spanx></t>
  <t>new key management subcommand: <spanx style="verb">revoke-key</spanx></t>
</list></t>

</section>
<section anchor="substantive-changes-between-05-and-06"><name>Substantive Changes between -05 and -06:</name>

<t><list style="symbols">
  <t><spanx style="verb">version</spanx>: add <spanx style="verb">--sop-spec</spanx> argument</t>
  <t><spanx style="verb">encrypt</spanx>: add <spanx style="verb">--profile</spanx> argument</t>
</list></t>

</section>
<section anchor="substantive-changes-between-04-and-05"><name>Substantive Changes between -04 and -05:</name>

<t><list style="symbols">
  <t><spanx style="verb">decrypt</spanx>: change <spanx style="verb">--verify-out</spanx> to <spanx style="verb">--verifications-out</spanx></t>
  <t><spanx style="verb">encrypt</spanx>: add missing <spanx style="verb">--with-key-password</spanx></t>
  <t>add the concept of "profiles", use with <spanx style="verb">generate-key</spanx></t>
  <t>include table of known implementations</t>
  <t><spanx style="verb">VERIFICATIONS</spanx> can now indicate the type of the signature (<spanx style="verb">mode:text</spanx> or <spanx style="verb">mode:binary</spanx>)</t>
</list></t>

</section>
<section anchor="substantive-changes-between-03-and-04"><name>Substantive Changes between -03 and -04:</name>

<t><list style="symbols">
  <t>Reinforce that PASSWORD and SESSIONKEY are indirect data types</t>
  <t><spanx style="verb">encrypt</spanx>: remove <spanx style="verb">--as=mime</spanx> option</t>
  <t>Handle password-locked secret key material: add <spanx style="verb">--with-key-password</spanx> options to <spanx style="verb">generate-key</spanx>, <spanx style="verb">sign</spanx>, and <spanx style="verb">decrypt</spanx>.</t>
  <t>Introduce <spanx style="verb">INLINESIGNED</spanx> message type (<xref target="inlinesigned"/>)</t>
  <t>Rename <spanx style="verb">detach-inband-signature-and-message</spanx> to <spanx style="verb">inline-detach</spanx>, clarify its possible inputs</t>
  <t>Add <spanx style="verb">inline-verify</spanx></t>
  <t>Add <spanx style="verb">inline-sign</spanx></t>
</list></t>

</section>
<section anchor="substantive-changes-between-02-and-03"><name>Substantive Changes between -02 and -03:</name>

<t><list style="symbols">
  <t>Added <spanx style="verb">--micalg-out</spanx> parameter to <spanx style="verb">sign</spanx></t>
  <t>Change from <spanx style="verb">KEY</spanx> to <spanx style="verb">KEYS</spanx> (permit multiple secret keys in each blob)</t>
  <t>New error code: <spanx style="verb">KEY_CANNOT_SIGN</spanx></t>
  <t><spanx style="verb">version</spanx> now has <spanx style="verb">--backend</spanx> and <spanx style="verb">--extended</spanx> options</t>
</list></t>

</section>
<section anchor="substantive-changes-between-01-and-02"><name>Substantive Changes between -01 and -02:</name>

<t><list style="symbols">
  <t>Added mnemonics for return codes</t>
  <t><spanx style="verb">decrypt</spanx> should fail when asked to output to a pre-existing file</t>
  <t>Removed superfluous <spanx style="verb">--armor</spanx> option</t>
  <t>Much more specific about what <spanx style="verb">armor --label=auto</spanx> should do</t>
  <t><spanx style="verb">armor</spanx> and <spanx style="verb">dearmor</spanx> are now fully idempotent, but work only well-formed OpenPGP streams</t>
  <t>Dropped <spanx style="verb">armor --allow-nested</spanx></t>
  <t>Specified what <spanx style="verb">encrypt --as=</spanx> means</t>
  <t>New error code: <spanx style="verb">KEY_IS_PROTECTED</spanx></t>
  <t>Documented expectations around human-readable, human-transferable passwords</t>
  <t>New subcommand: <spanx style="verb">detach-inband-signature-and-message</spanx></t>
  <t>More specific guidance about special designators like <spanx style="verb">@FD:</spanx> and <spanx style="verb">@ENV:</spanx>, including new error codes <spanx style="verb">UNSUPPORTED_SPECIAL_PREFIX</spanx> and <spanx style="verb">AMBIGUOUS_INPUT</spanx></t>
</list></t>

</section>
<section anchor="substantive-changes-between-00-and-01"><name>Substantive Changes between -00 and -01:</name>

<t><list style="symbols">
  <t>Changed <spanx style="verb">generate</spanx> subcommand to <spanx style="verb">generate-key</spanx></t>
  <t>Changed <spanx style="verb">convert</spanx> subcommand to <spanx style="verb">extract-cert</spanx></t>
  <t>Added "Input String Types" section as distinct from indirect I/O</t>
  <t>Made implicit arguments potentially explicit (e.g., <spanx style="verb">sop armor --label=auto</spanx>)</t>
  <t>Added <spanx style="verb">--allow-nested</spanx> to <spanx style="verb">sop armor</spanx> to make it idempotent by default</t>
  <t>Added fingerprint of signing (sub)key to <spanx style="verb">VERIFICATIONS</spanx> output</t>
  <t>Dropped <spanx style="verb">--mode</spanx> and <spanx style="verb">--session-key</spanx> arguments for <spanx style="verb">sop encrypt</spanx> (no plausible use, not needed for interop)</t>
  <t>Added <spanx style="verb">--with-session-key</spanx> argument to <spanx style="verb">sop decrypt</spanx> to allow for session-key-based decryption</t>
  <t>Added examples to each subcommand</t>
  <t>More detailed error codes for <spanx style="verb">sop encrypt</spanx></t>
  <t>Move from <spanx style="verb">CERT</spanx> to <spanx style="verb">CERTS</spanx> (each <spanx style="verb">CERTS</spanx> argument might contain multiple certificates)</t>
</list></t>

</section>
</section>


  </back>

<!-- ##markdown-source:
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
AQA=

-->

</rfc>

