<?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-10" 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="2024" month="March" day="01"/>

    <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>

<t>This document refers to a special verification-only subset of the <spanx style="verb">sop</spanx> command-line interface as <spanx style="verb">sopv</spanx> (see <xref target="sopv"/> for more details).</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="sopv"><name><spanx style="verb">sopv</spanx> Subset</name>

<t>While the primary goal of this document is to provide a full <spanx style="verb">sop</spanx> interface, as a special case, an implementer may choose to produce a version of the command-line interface that only supports OpenPGP signature verification.
As a shorthand, this document refers to such an interface as <spanx style="verb">sopv</spanx>, or "the <spanx style="verb">sopv</spanx> subset".
This can be useful for constrained environments where the only thing needed is signature verification, for example, system installation or update media.</t>

<t>A full implementation of <spanx style="verb">sop</spanx> by definition provides <spanx style="verb">sopv</spanx>, of course.</t>

<t>Only the following subcommands and their associated options <bcp14>MUST</bcp14> be implemented for <spanx style="verb">sopv</spanx>:</t>

<t><list style="symbols">
  <t><spanx style="verb">version</spanx> (<xref target="version"/>)</t>
  <t><spanx style="verb">verify</spanx> (<xref target="verify"/>)</t>
  <t><spanx style="verb">inline-verify</spanx> (<xref target="inline-verify"/>)</t>
</list></t>

<section anchor="sopv-versioning"><name><spanx style="verb">sopv</spanx> Versioning</name>

<t>The abstract <spanx style="verb">sopv</spanx> interface is itself versioned using <xref target="SEMVER"/>.
The definition of the relevant subcommands and options specified in this document is known as <spanx style="verb">sopv</spanx> version 1.0.</t>

<t>If backward-incompatible changes are made to the <spanx style="verb">sopv</spanx> subset, the major version number will be increased.
If the <spanx style="verb">sopv</spanx> subset is extended without backward-incompatible changes, the minor version number will be increased.</t>

<t>Elements of the CLI relevant to <spanx style="verb">sopv</spanx> are annotated in this document with the <spanx style="verb">sopv</spanx> version in which they were introduced.</t>

</section>
</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|--sopv]
]]></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"/>.</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>If <spanx style="verb">--sopv</spanx> is supplied, the implementation should produce a single line with the implemented <xref target="SEMVER"/> version of the <spanx style="verb">sopv</spanx> interface subset (see <xref target="sopv"/>) that this implementation provides complete coverage for.
If the implementation does not provide complete coverage for any <spanx style="verb">sopv</spanx> interface, it should emit nothing on standard out and return <spanx style="verb">UNSUPPORTED_OPTION</spanx>.</t>

<t><spanx style="verb">--backend</spanx>, <spanx style="verb">--extended</spanx>, <spanx style="verb">--sop-spec</spanx>, and <spanx style="verb">--sopv</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.
$ sop version --sopv
1.0
$
]]></artwork></figure>

<t>The <spanx style="verb">version</spanx> subcommand and all of its options are part of the <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>) starting at <spanx style="verb">sopv</spanx> version 1.0.</t>

</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>

<t>The <spanx style="verb">verify</spanx> subcommand and all of its options are part of the <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>) starting at <spanx style="verb">sopv</spanx> version 1.0.</t>

</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>

<t>The <spanx style="verb">inline-verify</spanx> subcommand and all of its options are part of the <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>) starting at <spanx style="verb">sopv</spanx> version 1.0.</t>

</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 two of those prefixes (<spanx style="verb">@ENV:</spanx> and <spanx style="verb">@FD:</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>

<t>The <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>) <bcp14>MUST</bcp14> be capable of supporting the <spanx style="verb">@ENV</spanx> special designator for all relevant inputs starting at <spanx style="verb">sopv</spanx> version 1.0.</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>

<t>On platforms which support file descriptors, the <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>) <bcp14>MUST</bcp14> be capable of supporting the <spanx style="verb">@FD</spanx> special designator for all relevant inputs and outputs starting at <spanx style="verb">sopv</spanx> version 1.0.</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>

<t>If any <spanx style="verb">CERTS</spanx> input contains secret key material, <spanx style="verb">sop</spanx> <bcp14>MUST</bcp14> fail with <spanx style="verb">BAD_DATA</spanx>.
This strictness is intended to keep the consumer of the <spanx style="verb">sop</spanx> interface clear about what material they are dealing with in what locations.
This should reduce the consumer's risk of accidentally exposing secret key materal where they meant to expose a <spanx style="verb">CERTS</spanx> object.</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>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, secret key where <spanx style="verb">CERTS</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 the hardware device (see <xref target="hardware-backed-secrets"/>)</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="hardware-backed-secrets"/>)</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>There is no formally adopted OpenPGP standard for identifying that a given secret key is backed by hardware based on the OpenPGP wire format.
<xref target="I-D.dkg-openpgp-hardware-secrets"/> proposes one simple and straightforward approach for how the wire format could cover this use case.
This simple mechanism is deliberately 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.</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'/>
    <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='I-D.dkg-openpgp-hardware-secrets'>
   <front>
      <title>OpenPGP Hardware-Backed Secret Keys</title>
      <author fullname='Daniel Kahn Gillmor' initials='D. K.' surname='Gillmor'>
         <organization>American Civil Liberties Union</organization>
      </author>
      <date day='28' month='December' year='2023'/>
      <abstract>
	 <t>   This document defines a standard wire format for indicating that the
   secret component of an OpenPGP asymmetric key is stored on a hardware
   device.

	 </t>
      </abstract>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-dkg-openpgp-hardware-secrets-00'/>
   
</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);



/* 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 anchor="libsopv-c-api-subset"><name><spanx style="verb">libsopv</spanx> C API Subset</name>

<t>A minimalist library subset that only does OpenPGP signature verification might be called <spanx style="verb">libsopv</spanx>.
This library is useful wherever the use case is just OpenPGP signature verification.</t>

<t>Such a library <bcp14>MUST</bcp14> implement the following functions from the C API:</t>

<t><list style="symbols">
  <t><spanx style="verb">sop_ctx_new</spanx></t>
  <t><spanx style="verb">sop_ctx_free</spanx></t>
  <t><spanx style="verb">sop_set_log_function</spanx></t>
  <t><spanx style="verb">sop_set_log_level</spanx></t>
  <t><spanx style="verb">sop_version</spanx></t>
  <t><spanx style="verb">sop_version_backend</spanx></t>
  <t><spanx style="verb">sop_version_extended</spanx></t>
  <t><spanx style="verb">sop_buf_size</spanx></t>
  <t><spanx style="verb">sop_buf_data</spanx></t>
  <t><spanx style="verb">sop_buf_free</spanx></t>
  <t><spanx style="verb">sop_certs_from_bytes</spanx></t>
  <t><spanx style="verb">sop_certs_free</spanx></t>
  <t><spanx style="verb">sop_sigs_from_bytes</spanx></t>
  <t><spanx style="verb">sop_sigs_free</spanx></t>
  <t><spanx style="verb">sop_verifications_count</spanx></t>
  <t><spanx style="verb">sop_verifications_get_time</spanx></t>
  <t><spanx style="verb">sop_verifications_get_mode</spanx></t>
  <t><spanx style="verb">sop_verifications_to_text</spanx></t>
  <t><spanx style="verb">sop_verifications_free</spanx></t>
  <t><spanx style="verb">sop_inlinesigned_from_bytes</spanx></t>
  <t><spanx style="verb">sop_op_verify_new</spanx></t>
  <t><spanx style="verb">sop_op_verify_not_before</spanx></t>
  <t><spanx style="verb">sop_op_verify_not_after</spanx></t>
  <t><spanx style="verb">sop_op_verify_add_signers</spanx></t>
  <t><spanx style="verb">sop_op_verify_detached_execute</spanx></t>
  <t><spanx style="verb">sop_op_verify_inline_execute</spanx></t>
  <t><spanx style="verb">sop_op_verify_free</spanx></t>
</list></t>

<t>This minimal library interface should be sufficient to implement the <spanx style="verb">sopv</spanx> subset (see <xref target="sopv"/>).</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>Guillem Jover</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-09-and-10"><name>Substantive Changes between -09 and -10:</name>

<t><list style="symbols">
  <t>drop <spanx style="verb">@HARDWARE:</spanx> special designator in favor of the simple <xref target="I-D.dkg-openpgp-hardware-secrets"/> or other magic</t>
  <t>drop hardware-specific C API function</t>
  <t>define SemVer-versioned <spanx style="verb">sopv</spanx> subset of CLI</t>
  <t><spanx style="verb">sop version</spanx>: add <spanx style="verb">--sopv</spanx> option</t>
  <t>define libsopv subset of C API</t>
  <t>explicitly require <spanx style="verb">BAD_DATA</spanx> failure when <spanx style="verb">KEYS</spanx> are passed as <spanx style="verb">CERTS</spanx></t>
</list></t>

</section>
<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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

-->

</rfc>

