<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.14 (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-11" 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="October" day="21"/>

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

    <abstract>


<?line 113?>

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


<?line 118?>

<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>Inputs to <spanx style="verb">sop</spanx> are immutable inputs.
Any named files that it receives as input should only need read access, and it must not write to or modify any of its inputs.
The only places a <spanx style="verb">sop</spanx> implementation should write to are standard output and (in some special cases) a location specified by an <spanx style="verb">--*-out=</spanx> argument.</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>

<?line -18?>

</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="10.2" sectionFormat="of" target="RFC9580"/>).</t>

<t>It uses the term "certificate" to refer to OpenPGP Transferable Public Key (see <xref section="10.1" sectionFormat="of" target="RFC9580"/>).</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.31" sectionFormat="of" target="RFC9580"/>), 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="universal-options"><name>Universal Options</name>

<t>Every invocation of <spanx style="verb">sop</spanx> or <spanx style="verb">sopv</spanx> <bcp14>MAY</bcp14> use the options described in this section, even though they are not specified in the synopsis for any specific subcommand.</t>

<section anchor="debug-emit-more-verbose-output"><name>--debug: emit more verbose output</name>

<t>When the <spanx style="verb">--debug</spanx> option is present, <spanx style="verb">sop</spanx> <bcp14>MAY</bcp14> emit implementation-specific debugging information to standard error.</t>

<t>A locale-aware, internationalized <spanx style="verb">sop</spanx> implementation will localize this debugging information.</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="RFC9580"/>) 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: <spanx style="verb">PROFILELIST</spanx> (<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.1.2" sectionFormat="of" target="RFC9580"/> 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 anchor="update-key"><name>update-key: Keep a Secret Key Up-To-Date</name>

<figure><artwork><![CDATA[
sop update-key [--no-armor]
    [--signing-only]
    [--no-added-capabilities]
    [--with-key-password=PASSWORD...]
    [--merge-certs=CERTS...]
]]></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 input OpenPGP Transferable Secret Keys that arrive on standard input will be updated by the implementation, and their updated forms will be produced on standard output.
This update will "fix" everything that the implementation knows how to fix to bring each Transferable Secret Key up to reasonable modern practice.
Each Transferable Secret Key output must be capable of signing, and (unless <spanx style="verb">--signing-only</spanx> is provided) capable of decryption.
The primary key of each Transferable Secret Key will not be changed in any way that affects its fingerprint.</t>

<t>One important aspect of <spanx style="verb">sop update-key</spanx> is how it handles advertisement of support for various OpenPGP capabilities (algorithms, mechanisms, etc).
All capabilities that the implementation knows it does not support, or knows to be weak and/or deprecated <bcp14>MUST</bcp14> be removed from the output Transferable Secret Keys.
This includes unknown/deprecated flags in the Features subpacket, and any unknown/deprecated algorithm IDs in algorithm preferences subpackets.
For example, an implementation compliant with <xref target="RFC9580"/> will never emit a Transferable Secret Key with a Preferred Hash Preferences subpacket that explicitly indicates support for <spanx style="verb">MD5</spanx>, <spanx style="verb">RIPEMD160</spanx>, or <spanx style="verb">SHA1</spanx>.</t>

<t>If <spanx style="verb">--no-added-capabilities</spanx> is not present, then any capability that the implementation supports and encourages that was not advertised in the input Transferable Secret Key <bcp14>MAY</bcp14> be added to the advertisements in the output Transferable Secret Key.
If <spanx style="verb">--no-added-capabilities</spanx> is present, then new capabilities <bcp14>MUST NOT</bcp14> be added to the advertised sets during the update.</t>

<t>Beyond cleanup of the advertised capabilities, <spanx style="verb">--signing-only</spanx>, and <spanx style="verb">--no-added-capabilities</spanx>, the choice of exactly what updates to do are up to the implementation.
It is expected that an implementer will document and describe the specific considerations and updates they make for this operation.
It is acceptable to propagate any non-critical unknown subpackets from old self-signatures to the new, replacement self-signatures.</t>

<t>Possible updates might include:</t>

<t><list style="symbols">
  <t>Refresh or replace any subkey approaching expiry.</t>
  <t>Refresh any self-signature (including cross-sigs) that is approaching expiry.</t>
  <t>Refresh any self-signature (including cross-sigs) that is made using weak or risky algorithms.</t>
  <t>Correct any mistaken 2-octet hash prefix found in a signature (see <xref section="5.2.3" sectionFormat="of" target="RFC9580"/>).</t>
  <t>Ensure proof of "aliveness": if no self-signatures are more recent than some cutoff in the recent past, re-issue the same self-signatures.</t>
</list></t>

<t>If there is nothing to be updated because all the incoming Transferable Secret Keys are already in good shape, then the same set of Transferable Secret Keys will be emitted to standard output and <spanx style="verb">sop update-key</spanx> succeeds.</t>

<t>If any Transferable Secret Key cannot be fixed (for example, because its primary key uses a weak algorithm, or because the whole certificate is hard-revoked), <spanx style="verb">sop update-key</spanx> fails with <spanx style="verb">PRIMARY_KEY_BAD</spanx>, emits an explanation on stderr, and nothing on stdout.</t>

<t>If any secret key that needs to make a signature to update the key cannot be unlocked with any of the supplied <spanx style="verb">PASSWORD</spanx> objects, <spanx style="verb">sop update-key</spanx> fails with <spanx style="verb">KEY_IS_PROTECTED</spanx>, emits an explanation on stderr, and nothing on stdout.</t>

<t>If <spanx style="verb">--merge-certs</spanx> is supplied, and any of the <spanx style="verb">CERTS</spanx> objects correspond to the Transferable Secret Keys being updated, then any additional elements found in the corresponding <spanx style="verb">CERTS</spanx> are merged into the Transferable Secret Key before it is emitted.
This can be used, for example, to absorb a third-party certification into the Transferable Secret Key.</t>

<t>Example (keeping certificates fresh):</t>

<figure><artwork><![CDATA[
$ sop update-key < alice.key > alice-updated.key
$ mv alice-updated.key alice.key
$ sop extract-cert < alice.key > alice.pgp
$
]]></artwork></figure>

<t>Example (advertising the intersection of features supported by two Stateless OpenPGP implementations, rendered here as <spanx style="verb">sop1</spanx> and <spanx style="verb">sop2</spanx>):</t>

<figure><artwork><![CDATA[
$ sop1 update-key < alice.key | sop2 update-key | \
  sop1 --no-added-capabilities update-key > alice-updated.key
$ mv alice-updated.key alice.key
$ sop1 extract-cert < alice.key > alice.pgp
$
]]></artwork></figure>

</section>
<section anchor="merge-certs"><name>merge-certs: Merge OpenPGP Certificates</name>

<figure><artwork><![CDATA[
sop merge-certs [--no-armor]
    [--] CERTS [CERTS...]
]]></artwork></figure>

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

<t>The OpenPGP certificates on standard input will be produced on standard output, merged with the corresponding elements of any of the <spanx style="verb">CERTS</spanx> objects named on the command line.</t>

<t>This can be used, for example, to absorb a third-party certification into a certificate, or to update a certificate's feature advertisements without losing local annotations.</t>

<t>The certificates produced on standard output are only the certificates received on standard input.
If any certificate found via named command line parameters does not share a primary key with any standard input certificate, the certificate from the command line is ignored.</t>

<t>If any of the OpenPGP certificates on standard input share the same primary key, they are also merged and de-deduplicated on standard output.
If multiple OpenPGP certificates named on the command line share a primary key with one of the certificates on standard input, their certificate updates are cumulatively merged for output.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop merge-certs alice-certified-by-bob.pgp < alice.pgp > alice-updated.pgp
$ mv alice-updated.pgp alice.pgp
$
]]></artwork></figure>

</section>
</section>
<section anchor="user-identity-subcommands"><name>User Identity Subcommands</name>

<t>The subcommands in this section handle OpenPGP user identities.
OpenPGP certificates contain cryptographic certifications which bind text-based "User IDs" to primary key material, which is in turn cryptographically bound to additional key material.</t>

<t>These subcommands are related to the network of cryptographic identity assertions that has traditionally been called the "Web of Trust".
Note also the similarity in structure between these subcommands and <spanx style="verb">sop sign</spanx> (<xref target="sign"/>) and <spanx style="verb">sop verify</spanx> (<xref target="verify"/>)</t>

<section anchor="certify-userid"><name>certify-userid: Certify OpenPGP Certificate User IDs</name>

<figure><artwork><![CDATA[
sop certify-userid [--no-armor]
    --userid=USERID
    [--userid=USERID...]
    [--with-key-password=PASSWORD...]
    [--no-require-self-sig]
    [--] KEYS [KEYS...]
]]></artwork></figure>

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

<t>With each Transferable Secret Key in all <spanx style="verb">KEYS</spanx> objects, add a third-party certification to <spanx style="verb">CERTS</spanx> found on standard input, and emit the updated OpenPGP certificates (including the new certification(s)) on standard output.</t>

<t>If the caller does not specify at least one <spanx style="verb">--userid=USERID</spanx> option, <spanx style="verb">sop certify-userid</spanx> fails with <spanx style="verb">MISSING_ARG</spanx>.</t>

<t>If the certification-capable key of any Transferable Secret Key in <spanx style="verb">KEYS</spanx> is locked and cannot be unlocked by any of the supplied <spanx style="verb">PASSWORD</spanx>s, fail with <spanx style="verb">KEY_IS_PROTECTED</spanx>.</t>

<t>If any incoming <spanx style="verb">CERTS</spanx> object does not already have all of the specified User IDs as valid, self-signed User IDs, then <spanx style="verb">sop certify-userid</spanx> fails with <spanx style="verb">CERT_USERID_MISSING</spanx>, unless <spanx style="verb">--no-require-self-sig</spanx> is supplied.</t>

<t>If <spanx style="verb">--no-require-self-sig</spanx> is supplied, then each incoming OpenPGP certificate will have each specified User ID added to it (if it did not have it already), and certified directly, regardless of self-signatures.
This may be useful for associating a certificate with a specific identity even in cases where the certificate does not itself advertise the identity.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ sop certify-userid --userid="Alice Lovelace <alice@openpgp.example>" \
  bob.key < alice.pgp > alice-signed-by-bob.pgp
$
]]></artwork></figure>

<t>Example (adding a User ID to your own certificate):</t>

<figure><artwork><![CDATA[
$ sop certify-userid --userid="Alice Lovelace <lovelace@business.example>" \
  alice.key < alice.pgp > alice-updated.pgp
$ sop update-key --merge-certs alice-updated.pgp < alice.key > alice-updated.key
$ mv alice-updated.key alice.key
$ rm alice-updated.pgp
$ sop extract-cert < alice.key > alice.pgp
$
]]></artwork></figure>

</section>
<section anchor="validate-userid"><name>validate-userid: Validate a User ID in an OpenPGP Certificate</name>

<figure><artwork><![CDATA[
sop validate-userid
    [--addr-spec-only]
    [--validate-at=DATE]
    [--] USERID CERTS [CERTS...]
]]></artwork></figure>

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

<t>Given a set of authority OpenPGP certificates on the command line, succeed if and only if all OpenPGP certificates on standard input are correctly bound by at least one valid signature from one authority to the <spanx style="verb">USERID</spanx> in question.</t>

<t>If <spanx style="verb">--addr-spec-only</spanx> is present, then the <spanx style="verb">USERID</spanx> is treated as an e-mail address, and matched only against the e-mail address part of each correctly bound User ID.
The rest of each correctly bound User ID is ignored.
If any correctly bound User ID is not a conventional OpenPGP User ID, it will not match with <spanx style="verb">--addr-spec-only</spanx> at all.
Note that <xref target="RFC9580"/> (and <xref target="RFC4880"/> and <xref target="RFC2440"/> before them) mislabeled an OpenPGP User ID as a <spanx style="verb">name-addr</spanx>, but that is likely to be wrong.</t>

<t>If <spanx style="verb">--validate-at</spanx> is present, then evaluate the validity of the User ID at the specified time.
If <spanx style="verb">--validate-at</spanx> is not present (or if it is present with the literal value <spanx style="verb">now</spanx>), the User ID validity is evaluated at the current time.</t>

<t>If any OpenPGP certificate in <spanx style="verb">CERTS</spanx> does not have a correctly bound User ID that matches <spanx style="verb">USERID</spanx>, <spanx style="verb">sop validate-userid</spanx> fails with <spanx style="verb">CERT_USERID_NO_MATCH</spanx>.</t>

<t>Example:</t>

<figure><artwork><![CDATA[
$ if sop validate-userid "Alice Lovelace <alice@openpgp.example>" \
  bob.pgp < alice.pgp; then echo Good; fi
Good
$ if sop validate-userid --addr-spec-only "alice@openpgp.example" \
  bob.pgp < alice.pgp; then echo Good; fi
Good
$
]]></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>.
In this case, <spanx style="verb">sop verify</spanx> <bcp14>MAY</bcp14> emit some human-readable explanation to standard error about why no valid signatures were found, see <xref target="explaining-non-verification"/>.</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 {"signers": ["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 separate 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="RFC9580"/>) 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>If no valid signatures were found, but <spanx style="verb">--verifications-out</spanx> was supplied, <spanx style="verb">sop decrypt</spanx> <bcp14>MAY</bcp14> emit some human-readable explanation to standard error about why no valid signatures were found, see <xref target="explaining-non-verification"/>.</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.2" sectionFormat="of" target="RFC9580"/>).
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.
See <xref target="verify"/> for their syntax and defaults.</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.
In this case, <spanx style="verb">sop inline-verify</spanx> <bcp14>MAY</bcp14> emit some human-readable explanation to standard error about why no valid signatures were found, see <xref target="explaining-non-verification"/>.</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", see <xref section="5.2.1.1" sectionFormat="of" target="RFC9580"/>).
<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.2" sectionFormat="of" target="RFC9580"/>).
<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="RFC9580"/> 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="RFC9580"/>), 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 material 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="RFC9580"/>).
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="RFC9580"/>).</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="RFC9580"/>) and SKESKs (<xref section="5.3" sectionFormat="of" target="RFC9580"/>),
followed by one SEIPD (<xref section="5.13" sectionFormat="of" target="RFC9580"/>).</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="RFC9580"/></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="RFC9580"/></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="RFC9580"/>) 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 four three structured fields delimited by a single space,
followed by a single-line JSON object or arbitrary text to the end of the line.</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>A JSON object or free-form message describing the verification (see <xref target="verifications-json"/>)</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 {"signers": ["dkg.asc"]}
]]></artwork></figure>

<section anchor="verifications-json"><name>VERIFICATIONS extension JSON</name>

<t>The final field of each <spanx style="verb">VERIFICATIONS</spanx> line is either JSON data or arbitrary text.</t>

<t>If the final field begins and ends with curly brackets (<u>{</u> and <u>}</u>, it is JSON data.
Otherwise, the final field is arbitrary text (whose content and structure are up to the discretion of the implementation).</t>

<t>JSON data allows for sophisticated future extensions, and is the preferred form of this field.
Arbitrary text is deprecated.
The rest of this subsection describes the JSON data.</t>

<t>The JSON data is a single JSON object, coerced into a one-line representation (there are no literal LINE FEED (U+000A) characters in it, though there may be appropriately escaped LINE FEED characters within the JSON text).</t>

<t>The JSON object <bcp14>MAY</bcp14> contain the following keys:</t>

<t><list style="symbols">
  <t><spanx style="verb">signers</spanx>: a list the supplied <spanx style="verb">CERTS</spanx> objects that could have issued the signature, identified by the name given on the command line.
If this key is present, as long as any OpenPGP certificate in a given <spanx style="verb">CERTS</spanx> object could have issued the signature, that <spanx style="verb">CERTS</spanx> object <bcp14>MUST</bcp14> be listed here.
If multiple <spanx style="verb">CERTS</spanx> objects contain certificates that could have issued the signature, each <spanx style="verb">CERTS</spanx> <bcp14>MUST</bcp14> be listed here.</t>
  <t><spanx style="verb">comment</spanx>: Free-form UTF-8-encoded text describing the verification.
An internationalized, locale-aware <spanx style="verb">sop</spanx> implementation should localize this field.</t>
  <t><spanx style="verb">ext</spanx>: A "extensions" JSON object containing arbitrary, implementation-specific data.</t>
</list></t>

<t>To avoid collisions with future definitions, the top-level JSON object <bcp14>MUST NOT</bcp14> contain any other keys.
For forward compatibility, when consuming a JSON object produced by a SOP implementation, unknown keys <bcp14>MUST</bcp14> be ignored.</t>

</section>
</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>1</c>
      <c><spanx style="verb">UNSPECIFIED_FAILURE</spanx></c>
      <c>An otherwise unspecified failure occurred</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>
      <c>103</c>
      <c><spanx style="verb">PRIMARY_KEY_BAD</spanx></c>
      <c>The primary key of a <spanx style="verb">KEYS</spanx> object is too weak or revoked</c>
      <c>107</c>
      <c><spanx style="verb">CERT_USERID_NO_MATCH</spanx></c>
      <c>The <spanx style="verb">CERTS</spanx> object has no matching User ID</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 <spanx style="verb">UNSPECIFIED_FAILURE</spanx> or 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>
      <c>rsop</c>
      <c>https://codeberg.org/heiko/rsop</c>
      <c><spanx style="verb">rsop</spanx></c>
      <c>Implemented in Rust using the <spanx style="verb">rpgpie</spanx> crate</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="RFC9580"/> 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="RFC9580"/> 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="RFC9580"/> 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 password <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 anchor="explaining-non-verification"><name>Explaining Non-Verification on Standard Error</name>

<t>When verifying OpenPGP signatures, sometimes no valid signatures are found.
This will cause the verifying subcommand to produce an empty <spanx style="verb">VERIFICATIONS</spanx> output, and for some subcommands (<spanx style="verb">sop verify</spanx> and <spanx style="verb">sop inline-verify</spanx> in particular) will also cause the subcommand to fail with <spanx style="verb">NO_SIGNATURE</spanx>.</t>

<t>When this happens, some consumers will want to know more details about the verification failure, since some verification failures may be indications that something is wrong with the verifier's setup, such as outdated OpenPGP implementations (which can be upgraded), expired signing certificates (which can be refreshed), and so on.</t>

<t>To address this, when no valid signatures are found at all, <spanx style="verb">sop</spanx> <bcp14>MAY</bcp14> emit a human-readable explanation to standard error.</t>

<t>Some example explanations for complete signature validation failure include:</t>

<t><list style="symbols">
  <t>Version 7 signature found, but FooPGP 2.0.3 only supports versions 4 and 6.</t>
  <t>Version 3 signature found, but BarPGP 0.9.7 rejects all version 3 signatures.</t>
  <t>Signature from pubkey algorithm 94 found, but BazPGP 1.1 does not support this pubkey algorithm.</t>
  <t>Signature using hash algorithm 22 found, but QuxPGP 19.0.5 does not support this hash algorithm.</t>
  <t>Two signatures found, both made by unknown OpenPGP certificates.</t>
  <t>Signature does not match hash prefix.</t>
  <t>No OpenPGP signatures found.</t>
</list></t>

<t>In some cases (such as when two OpenPGP signatures are discovered, and they both fail to validate for different reasons), a <spanx style="verb">sop</spanx> implementation may choose to emit a more complex warning.</t>

<t>Unless <spanx style="verb">--debug</spanx> is present, <spanx style="verb">sop</spanx> <bcp14>SHOULD NOT</bcp14> emit any such warning (even if true for one of the OpenPGP signatures found) if another signature was found in the same <spanx style="verb">SIGNATURES</spanx> object or <spanx style="verb">INLINESIGNED</spanx> message that does verify correctly.
This keeps the upgrade path smooth for the whole ecosystem.
As the ecosystem evolves, signatures using new versions and algorithms, or signatures simply using new signing keys, are typically introduced as a second signature distributed alongside the first.
A warning about a signature with a new or unknown algorithm (or key) when an accompanying signature still verifies from a known key with a known algorithm will discourage signers from adopting new algorithms or keys.
And introducing a warning about a signature using a deprecated algorithm (or key), when an accompanying signature still verifies using a more modern algorithm or key will discourage a verifier from upgrading their OpenPGP implementation or dropping old, deprecated keys.</t>

<t>Implementers should avoid emitting dangerous explanations.
For example, an explanation like "Signature from 0xDEADBEEF found, but not in list of acceptable signers" might encourage a user to go hunting for any certificate with short key ID 0xDEADBEEF and start using it to verify signatures.
This would be a very dangerous explanation, in particular because short key IDs are trivially forgeable.
But it would also be nearly as dangerous to use a full fingerprint (instead of a short Key ID) in such a message because then all an attacker has to do is to get their signature to appear in the place where the verifier is looking for a signature, and then the warning will encourage the verifier go look up the attacker's certificate by fingerprint.</t>

<t>An internationalized, locale-aware <spanx style="verb">sop</spanx> implementation should localize these warning messages.</t>

</section>
</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="RFC9580"/>)).
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' anchor="sec-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="RFC9580">
  <front>
    <title>OpenPGP</title>
    <author fullname="P. Wouters" initials="P." role="editor" surname="Wouters"/>
    <author fullname="D. Huigens" initials="D." surname="Huigens"/>
    <author fullname="J. Winter" initials="J." surname="Winter"/>
    <author fullname="Y. Niibe" initials="Y." surname="Niibe"/>
    <date month="July" year="2024"/>
    <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.</t>
      <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>This document obsoletes RFCs 4880 ("OpenPGP Message Format"), 5581 ("The Camellia Cipher in OpenPGP"), and 6637 ("Elliptic Curve Cryptography (ECC) in OpenPGP").</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9580"/>
  <seriesInfo name="DOI" value="10.17487/RFC9580"/>
</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' anchor="sec-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="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="RFC2440">
  <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="R. Thayer" initials="R." surname="Thayer"/>
    <date month="November" year="1998"/>
    <abstract>
      <t>This document is maintained in order to publish all necessary information needed to develop interoperable applications based on the OpenPGP format. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="2440"/>
  <seriesInfo name="DOI" value="10.17487/RFC2440"/>
</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="19" month="April" year="2024"/>
      <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-02"/>
   
</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>


<?line 1701?>

<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 ambiguity 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="simple-cli-test"><name>Simple CLI Test</name>

<t>The following POSIX-compliant shell script can be pointed to a SOP implementation.
It will report which subcommands have basic coverage.</t>

<t>It does not consider all possible combinations of all options.</t>

<figure><sourcecode type="text/x-sh" name="simple-sop-test"><![CDATA[
#!/bin/sh

# simple, positive self-test for Stateless OpenPGP implementations

SOP=$1

if [ -z "$SOP" ]; then
    cat >&2 <<EOF
Usage: $0 SOP

SOP should refer (either by \$PATH or by absolute path) to an
implementation of the Stateless OpenPGP command-line interface.
See https://datatracker.ietf.org/doc/draft-dkg-openpgp-stateless-cli/
EOF
    exit 1
fi

if ! COMMAND_OUTPUT=$(command -v "$SOP"); then
    printf >&2 "No such command: %s\n" "$SOP"
    exit 1
fi

shift

sop() {
    printf >&2 "🔒 [%s %s]\n" "$SOP" "$*"
    if ! $SOP "$@"; then
        printf >&2 "💣 Failed: %s\n" "$*"
        ERRORS="$*
$ERRORS"
    fi
}

compare() {
    if diff -u "$1" "$2"; then
        printf >&2 " 👍 %s and %s match!\n" "$1" "$2"
    else
        printf >&2 " 💣 %s and %s do not match!\n" "$1" "$2"
        ERRORS="Mismatch ($*)
$ERRORS"
    fi
}

show_errs() {
    if [ -z "$1" ]; then
        printf "No errors!\n"
    else
        cat <<EOF
$1
EOF
        E=$(echo "$1" | grep -v '^$')
        printf "%d Errors:\n" $(echo "$E" | wc -l)
        echo "$E" | cut -f1 -d\  | sort | uniq -c
    fi
}

ERRORS=""
WORKDIR=$(mktemp -d)
printf >&2 "Working in: %s\n" "$WORKDIR"
cd "$WORKDIR"

sop version
sop version --extended
sop version --backend
sop version --sop-spec
sop version --sopv

sop list-profiles generate-key
sop list-profiles encrypt

sop generate-key "Example User <user@example.net>" > test.key
sop extract-cert < test.key > test.cert

cat > test.txt <<EOF
This is a test message.

We all ♥ OpenPGP!
EOF

sop sign test.key < test.txt > test.sig
sop verify test.sig test.cert < test.txt

for as in binary text; do
    sop sign --as=$as test.key < test.txt > test.$as.sig
    sop verify test.$as.sig test.cert < test.txt
done

sop inline-sign test.key < test.txt > test.signed
sop inline-verify test.cert < test.signed > test.verified.txt
compare test.txt test.verified.txt

for as in binary text clearsigned; do
    sop inline-sign --as=$as test.key < test.txt > test.$as.signed
    sop inline-verify test.cert < test.signed > test.$as.verified.txt
    compare test.txt test.$as.verified.txt
done

sop encrypt test.cert < test.txt > test.msg
sop decrypt test.key < test.msg > test.decrypted.txt
compare test.txt test.decrypted.txt

# TODO (still untested):

# armor
# dearmor
# revoke-key
# change-key-password
# merge-certs
# update-key
# certify-userid
# validate-userid

show_errs "$ERRORS" >&2
if [ -d "$WORKDIR" ]; then
    rm -rf "$WORKDIR"
fi
]]></sourcecode></figure>

</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-10-and-11"><name>Substantive Changes between -10 and -11:</name>

<t><list style="symbols">
  <t><spanx style="verb">update-key</spanx>: new key management subcommand</t>
  <t><spanx style="verb">merge-certs</spanx>: new certificate management subcommand</t>
  <t><spanx style="verb">certify-userid</spanx>: new User ID certification subcommand</t>
  <t><spanx style="verb">validate-userid</spanx>: new User ID verification subcommand</t>
  <t>Replace references to RFC 4880 with RFC 9580</t>
  <t>Set aside error 1 as <spanx style="verb">UNSPECIFIED_FAILURE</spanx></t>
  <t>Encourage JSON output in tail of <spanx style="verb">VERIFICATIONS</spanx> lines</t>
  <t>Add universal (ignorable) <spanx style="verb">--debug</spanx> option</t>
  <t>Add simple (and incomplete) shell-script test in appendix</t>
</list></t>

</section>
<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:
H4sIAAAAAAAAA+y9+Xbj1pU++j+fAq3qtSylBWqoWW07piSqrLg0/ETJiePr
VQRJUESKBBgAlIqR3c9yn+U+2d3jGQCQUtlOJ+uum9WdlEDgzGfP+9thGLbK
pJzGB0GvjMp4GhdFcDGP08t3l8FRNptF6Sh4n6RxcJqWcT6OhnFrlA3TaAZf
jPJoXIajj7dhBl/Mb+dhoW2Ew2kS7u21hvD3bZYvD4IkHWetVjLPD4IyXxTl
/u7u2939VpTHEf5Ytu6z/ONtni3mB4E01/oYL+Hp6IA7T+MyPMYuW8ViMEuK
IsnS6+UcBnLavT5ptaDzdPQhmmYpPFrGRWueHAQ/ltlwOyiyvMzjcQH/Ws7w
Hz+1WtGinGT5QSsIWwH8J0mLg+C4HXzXDt4l0+ksy+kxz/Q4SpN4GnwXTVLv
1yy/PQg6szhPhlEaHCV3yRRWaxDnZRIXwU0KI6T3Cug9Lg+Cvf2XwWGeRSNY
7Tb9MkxKWJzz+D74Aea/HZz/wI+zEXS7t7u7+0L+XqQlLuNNr0MPosEgj++g
86P3N/QgnkXJFPbk4+0342RcTmBuBTxL27Bsrbs4XcQw1UAWeEO2eAMelbSE
G3+G7pP0NniHb+Bzbm9D9uKbJC7HbZgv/hTlwwn8NCnLeXGws4Nv4qPkLm7r
azv4YGeQZ/dFvCNt7OC3eTzPnG9v4fBFg/Ywm+3A0HcaDxJ9N4UHRel8Ca+3
5eskW/khHrt8FpUwNpi/TDuk8wSf5NEgmcIOhNfQdthbJCWtEixKlN/ihmln
2HfRLuK/L7IkCqEjmiO/ytdHL0216QCbDqhpen0E4zsI9nf398K93XD/ZSs4
mkSwVdD9fVLCIqa3OITqAHC2tX3dSTMY2E6STuGG4qhCaGo2XkxxZDKuU/ox
4PucFskozuNR8C2/h3up1yD49RdB57T3ItzdD/fhyB6f9i7fd344PX8X9k7f
nXeub666vaZ5RaNZkrYnWVHOM6ACbTg08wRWD8/UTpwmt/iPcFHEefFB/6Sp
Q2+vw/PsLp7BdduBe/LqzfP2pJxN7dQ3LtLgOCnm02iJJ7uX3KZRucjjYmPl
vC/bcD8XaTGc3Ce3zrwvoxLu+Efvx+5J5/R905ziMQ5yFDsj6Y7pNh0CtaNb
1ts5Oz3rBkhd9eB0cWpBNx3my3kJhCNYFPhm99M4mZZ5RI/gqKRpPF0zAdi4
y2w0igdpEn30Nm6WAInyf3O+O2oHx7Aycep8czTJk6LEz/Snyx+uv704D3sX
l03zni/nCd2LeZ79LR6WO0U2d04ifBXAZQzmSxh46s9gLZnViZlHVze961WD
cO+oJQ8wkjAvnMF0gitgQkEym0/jWZyWvL7ZOCgncQMrvMwzYCTZtGnUf4KG
FkXw5wRvvhnvn9rOE+ITPR5ZK+h1z77vXjUPfnYX50pbdN3wupfJMPgeLgGM
Ek/Ffnu3vevevOfh7qtw703T+K6zGYwfqFCWhn9GNmoHed2u/QLLGv6p832n
aXiwnpMFE2tY3gjoDqwRre3forvIGfHK9aMD8Cd4ud10gvWuLaZBbziJFgPv
Yuqjm/PTo4vjbnh+cXXWeX/618716cV5M9lepAlyUlpQZDx5WeyU+d5Lj3Lf
8EvBOTKKafIPPgon8FfhUey9t0jdhCE7Y9dxfxenwZ8ncGOmvMIycqCj/lM6
DNop0mQYVrKYAXe67J4jd+qdda6ujzpXx9R8dU739/ft23Qxv6VZjcv5TjGP
h8WO8rZiFuVlOIzyURjN51OQTHA+4fP2i/Z8NG7ZeZ8s0iH+FMFqQwvJWF7V
W6B757QSwP+d9i6CHvYRHEEf+BYSJ6Rpy6KMZyBjyTkNoMuWy/F2w93nfEa9
5QvdRewAB4TjCmIEkth35zeXwEG6R1dduPDXN4feilhRIL5zlqTIFvkw3qEH
KoHMIhhbvgOi685x9xrodu+/6fdwH5bl+X/uvdzb23CWBvoFwlvGKc6jCMqM
ycL+d0E0BXEWrsHMmxncvtdyMlbOjC9Y8F02nDjn4HZvF84A8IowDEGoA0Ex
Gpat1jWcmABGu0DaFIziMfDwIoiC2zhFYTMwYg5IhiSkh8TlExXS6Z6NYjjO
sDEgV0zMbs7go+g2hm36mGb3aRAVQR9ucL/dOi2DKJkV9GkUAFtO4DpsB/fx
dApiVb4YIu8cBZ3LU+gUyBQ2ra1mAyT4QREPF7A6y3aL5jNLRqNp3Go9Q6ko
z0YLOm+t1nEyHoMYAjPT7306XAST6C4GCTRdBiPzbg70M8npLRj9/SQZTlB4
haM5nS6DAbJWWDKYUpIG5X2GAmwaiAIC4vhBAOrEzhBlczrp1D6sBK0wMuL6
HK5h0+eLfJ4VMV8Kd1MSOhfA6u5ApoIF2zB7suHsQzmJSngJljJPYJTAv2FF
CjpOlf4ClM2km/QWZohjiooCeiu4GXgzj0ucRnXoK2Z1DwwzGMTS6wjUoBn0
AH3nwX2EEzwtsilf3upgxjlwjTULVkyyxXQETz7CqSuDOCoSaNVZkKQqB6MI
jT3h8Vo3/RVHYhtP6iguhjnoVyPc44cHbDIsULT+5Zf2/+algRWMg8GS5gHi
5TCeZFMQrD//JsGoO+mKKesag5BPJATWuQjiT7BeZTSYxtwZLrn5jE9o4RLz
dhDAaP6Gsk4ax6PKmYV/3ebRjI/XMCNdScgdNGQWBkcp3TUPcRrjfU3huxzX
EX7AlSmIIfBBxrEPYrjWCayJMzE4nRFc8GEJ6wELCjeejr+cUhhX6m8WkH7a
3oJbTeeLEs8x/i8NnEcZwfYks5ksFL1VtGGll7SQowBEar1UCRKWYQz6YYEn
jN7VAWYpXFlcNngFdPZoOIRzoPMJZrSoMId7OL8xdg5Tm2VAsGgeeJZx1to7
EhNqkA4Mnst1K2raxKmQZQOZbbYocXg4gE24AXSfabuBhw+jIi62oNlpJsxa
DoKubNAPwz+E0MRXfbOMsHYXA9iTRTFdbtOmoarFhIMmXmZy6/HHJHdoUBFs
4jj48TwGnv+FS4dgKDi8SXa/3RosSmr7NoNxKiG1144paRHPoxypTEZvw9aU
UfGRCRF+TH/hmuJ3wCRXXlKYEwhc07hKr0fw37gcuPTNBGC7hR3l2eJ2gqOY
Ev2oj1e2KJoWGZ1faJ7OGUwij6dka4BtRlae3E5KuFP3uHfTZJBH+bLG6mAf
LY+bRuntQibx7Flw5bC84L38xnwJuQAax4pg4wzUoY1t/t/g/IL+fdX9Pzen
V91j/Hfv28779+YfLXmj9+3Fzftj+y/75dHF2Vn3/Jg/hqeB96i1cdb5YYNv
wcbFJQrfnfcbxHS99caDW9IC0crN4djEyNBaHhE/PLr8f/7vvRdAzP/j6uRo
f2/v7S+/yB9v9l6/gD/uJ3HKvdHt4T9hn5YtEEzjKMdWQAKA8z9PStgTYhSw
RUKmYSH/8COuzE8HwZeD4XzvxdfyACfsPdQ18x7SmtWf1D7mRWx41NCNWU3v
eWWl/fF2fvD+1nV3Hn75RzrMIGD/8esWnZ7rOAfek02z22WVOcItZyEEdmYW
bMBh2uDjC+cQeMxwuij4FMNDvV/XeZQWY2TocNZ7TAe+IzpQxDHsGTwisrO3
297HW4N7+Pblm91fftlCEl3r1CEWTuerOrxcDEALwQ4b+tvD/rzuNnquNBZs
1FTSDaAX0HwQ3WXJCGmJI11VRSoSHJiCE3mElQSteY7mNBwasnkiktgMHkWd
gEsOqVGXesJCzIp4Cnxnu4W/zUHWwwbwucPJCqLD8cjp3qU/wkOBdw9Rvxgx
5UT2Q4NGwzG+SiyW6XsKgsqUDGIZq24wDWQDMuY8vhP+AWISMA2SxDeuQMCD
pcaZXpkXNoJNuwsv2/vt5+3nlZ1QOR1bgmHGCbH1jSIblxvILjcmQBo3eG4F
rAx8LD/m1COQRxDcN3DXUbJZwIgLXI0NJj/yHNY0QYEKn4EQMs3SW+gF1gqb
7sCGsDShTRLfcudJazbixeRli+TlLSJjPEr3k5q0SYeX+FhkODLqSCqHhUS8
isVAZolbwTu8QhYVveyur8cd/wBySIctg0GN4jJKpsUWc4obOjvwDpFDx+gc
PDxzxGS4h2MUBVZInCIZOsKJYY0o8cgu4sKSkIid1OT8zbh9294OfnyCrf0n
HHxvAecjSrUhbpVGi/1t04TjTxEOdBu7DoYgd4FMQOaTzT/Anv2BB7uFYyJZ
n3cwje+r+ilLfOkwA50up1uJL6F6liDXFtluHOs90s9oV1mYhL1rktvgU3gL
9oRoboxsSiRYVB6rPH9IYm2Kuh2dBBwFyt54D/NtoZHuMgSjHMYHahasVaPY
SJIQDJIes8wpTBNOXH4X6z1E4zLK/HP405k4t1xpczjJMiLZGa07Sseoy6Ie
j3IRyaJ8+tREWQR3Bdo94XiekNulJTdbfzarF9EJnqKvDAnzUkeOQ4Z7A5oy
yE7hNAYmhDcEREM5c9DcXVSU9HAaf8ITR9d+EaV4a+7QF4X7hAuSpJ4hy1eM
+ALDvZ3CFjNfQuoyR3p2R/ucgnQBI4tpPPMkHrJ6nmVTptMRXvspCpSZvVF4
VoY0uKSYkAKAgusB3NmipG+HkyhJkXKkX+CNgnWIBpkIyDrCgiUc1tvuo5R/
dZakqjzP6Yah1xE25B2MX6SxMWh3MNjtimzGtwTNJiWaRmjQyAcDtOvgwUTZ
NRVupJRGydY9bi971WQccHzgHIF4t400/R4X5mOSjugL922j+xbKw1B8Bq1q
LncLiHZq/5YtgnFm90iSnCsBA47voumCbjpy6yyFIRdlbYBwhhM8rbNoRBq7
FbUb5HA44cMp3lc+aKDXpCTNk2qc3C7ECwOvzbOCeD/r+siI0RJS1Ewhs6xs
MIXAOGK4/Lk5RkQDuCtn8GZZ8YMsrZIRJcdCSETLI1a3TccfTxUcUOb1qcxI
F6SyNYMY3zJbz63xoUGXO+lUaPSwj+A04YRZq1qao+u16pvsaKoz1Ilw2KMF
67ewnrMBLC4ujFxYuNZsK/JuLDBuJmKzaDmIxZwxTj7hi/G0iO9xgFt0BIlg
Dxa3RivxGlJzhxxAWFVgeyhhtZ4FXeY0BRGuIlbOwxoFChdxnme4ivHwI10s
1G1vceOiYDyFS5TjyuK7TOfMdIlpJshiUXdFYxMqtkCxJ/F02rY6XVX2ZFOF
pzORhChsth+BVBy3gRAA/zNTcnimcKBxtkjFavbH0/C4zbEbgzy2sRs80XB3
j4xp//M//9NCcUIZaoiD2+hgb8F7WC40YgRfUu/fSBNt6fLrjeDrwIyLWok/
kWE7xJkFX9ofzYsY7tHQ32E2CA6jwQANEF8OskFjV/B8VUfyk7xkOimS2zQI
w6j4qoQPnOF8yfIfmUZK+OVr/+92VHA3JNot6z/a2VSb4o5jdu9C3ziEEG/p
V7Z3GSN8Oitu2/FsCv0Pkzmcaxym6XwUcyM6uS8rL+FXU+Bd9De0QnvZ6pEU
iX5oIMDhDKSnwhUnTaAEEjhiSHTSWW/hQ09mZDj0dFFEOO2xRPvwjMRTa3mJ
xei99I0+K63n4wWI6TWZMyoccRoNXNskKSoZjFHvWoqcIu2hcAIf3YkPSnjW
CiGbhTyWzOfkHrTCgkYLeGI8qBM0pAm8i8tRZaxWDShcsdaX6IlEbagGAIvI
asGG8DsrZcOi0Aa5ZDlO75I8S9kkdC80WSyLbDplfZH0pcY5VERqttKir7IE
TituPmDE8xGZ/ONREpH9l3ao7i/nPUPOivb2xFcjzHzHSJtAdUMBl0eKJAkZ
O5H5xUA2iI8bcyrQhzPYeOR/2ZwZAJltBg4jRFtulks/B61WGPRl5/uonMq/
QRGVX+DS6g/wT3ku8TPOz94TfAuFXNks64Vnoq1OO/3ds2uC/BdPx3oaYbQc
1AFqM8UAIKW9JgnLrJ0cWODbIOCgo6WyNroU1rhbs7zBvz3fHgxKr8Nee7dN
OuAgGn5Es2SI2hCI1yVZMkA2BdW5IOmcJCaRuL1zyvrJLPobLLy2my4wDMc4
nKBR1J+Rp56O6y3gCGN0r+I5VUll7YikzyR9Up+t7lRsprKaR+9P7YqKbeWO
lZAoBZGJDlltHUmncgavHcOL4n1EGf0+JurJ/k2RIm7SBF+O0BRE2wVDIi0i
SdWEYO+OOb/BWecH0rToQss+Vzg/3mq2uGyjYoKPyFxNQ8H5kA3DPxvoiUmz
eZGIRyp1pDV7vFiTC8NRDILTAYmezBlg4APygJLCR4Igt9qXl/syWNzWOUUK
wRnhueGMqCWfcISmf2qADGcuA0L6qT4P4j1EgdCxMY3DCE4J2iMoJjTiCIbk
HzDZFYoxHA/6Et6RDW7qk/atZy9bq8XNkdEyctbJ5U+gtGLoI18TXKN5Nl/A
AxoO0ESmrUUwTT7Cct0mZZ/ucL+4S/t8D43LBRnQNKn2RQyKB0LiNu6umSDZ
ZMakmtFR7d+c924uLy+urrvHH3o3h2hK7pwf9+kSrnA3mVbZR0y900CU0ogT
85Z0SjuytX2zdRpniMY3l4KJO5y5tHHcwPXLkcOjz6ri6tJ3O72j09MwyvFE
jly746uKqdmopMySosW0BFn5E+qUhlWgkxdb6m+1Rcx3x0gWzwhPd5pxj3rA
rTVTTdkzV+oYJCkKPLVpIWuNo9Gq5WCFt3E1PG8k6sriZpJPxJzqrw3MUQbC
nke1H/IUomlIj/l1uAO4ZHjSyDlL2niWoz18ivEBLDOCKg9KHAjVGCqsQqMa
BVhWRIXnDs59tiAaMytcT76ZEdKn+NOcvb3sG7LucKY/Z9Csfw3JgOSsGYUw
18khNU7uN2soajzxzJKpt2dK0g9MzNKpQ4Uenqn80OIobhb86b0fwxAZFrCw
n8NQeRn8E4PhkLjxP+9+QpGkp2ea3NQHAUhluFPuLxd02g8cFmOGIZZmhygg
QS2aXkWGf3N9Er4JQc/IkLmSCgAkG69omlnvOfNTbQI2gZRosTbIeUObSiQM
hOIPPLO1v6rbIs2JFSJAKWeK9iwik+5vbr/MwduPBBeQ7bHK9cX6RuY6FIyC
mOyzCajTI0tE2N5bkE0GpE42JNIlYo8LsOgBysBEn12hDClm32xxX5wPRBd5
6ZqHavUPpyvSOdBx7X8ils76HhproGpQjsvGWhmz6cekNAPVE/j4SFFhYt4O
lDGZy/jovjaMhsXTcZIXJc+DJHD4jaUfb+AyeXMCxBKtAg+bSli2LYwPhPTv
CXq5MonYGVmaYKant+rJG0EzNMdQd4A6Q2o25KAn/J7zCnx90Zi4NEKEIw6L
iubUfywBZvdV3wjAlXFKi6rekihEXeoiuUouSvNFUysUlsCW8JJdNOYgwlp+
YustzwQDG9VL8OXi6//5cmfxtTefg6D/P0+a0HV9HEbMi0ajRGJK2bJChxnJ
FUdGgEQ7SeZKn3kRYMd5jBI2xOfRaocOxUCKhhNxD8bdr7id7rkwUr6rVFpa
ULUk1LQ8UWk8L92WmnVxg1a42HTbOJgSDVxjlHObj4sR09Ri0vg1ifbVAbrH
gvYITcRiEnalrYC9onDv0lXSnEMRtz2qs+1dUnY8md0hZXJRLtDfEJrYAlVw
UFuTA8hc9j9dPktP5PcePN5t77f36q8FZmD02/tkIN8grcTI5/3Gb3T8q3u5
WqSprNVZln6Mlz1QxkDyetF+ubYn+/yIPG7w0540CT/95Qh2D6ggDeMFqOT8
EUpbJpfC2jgpjaLRUNc4Kd0G+vEJN5reo/+6bjiuVf3gm5PjA2ORg2NMFiY0
E+L41CW4Ylh39MMeJS7ACyzaWXuNI+HQ/0+nGkKnujCepDlGnmdNRoXKDYR5
5kTlo7LZCoLyHwgMZQh3iqzsB8GxKNtBx/gRL+VHkAa9lx2Z0HseWMXrM2W/
/uXVxcnp++770941WaGkSWyebFDNcmBE/eOSmCGIMdMKXCb2beQp/Ja3y6fU
FNsO2fHH+pP82hSC643RqrTCZFEpdxRRe5pEgSEtS5qwShaFZCIdKnxCJOvT
X0Ey/G1w/QicxsGTOTAWFofDfoH8CZcFyAFzKfokHw9fvHmzy5+YyP+CXTeg
cgb4qx5mOE3fif/myPHfnNmY6V+t1tj4caTqZDXjuMwErQ1lzAFFFc9RIUfc
XYiD4J2Nj7AhXHC23beco+15Y360GvFPnMIA/4GHyEHxhRBDmDAm8avLTq/3
54urY+812ZqvZBu935COwF2lKBnvh5+CH2963avT43a7DcpUsPpGBU1X6rvu
Dz26S7hCdImcBRApQE+5ytYUWYlCwT/iXGJ6YQ9u0EhzelyIq04Xxo3pCiTg
j4z3kUaGwZ2ZoS/A057GJveGAhg8h3JKNC4ZoiHpgKZ86toA9E3ygbO3y43o
8XyHGjuLg4ODJcvBBpuqtwyuFXR1XXu7bn1AOytGxZl8ymDTNolP+yL/RMbz
QJ8CMWLzd9+60PpW/pLBxN4ppkHdUKKZ2hzds9LHtQLdtOSoPF8KfGwe6kfT
wGF3GvKbOxPx3TFVdSYizx+fiZj60W4Sj9R+ObXqjnFWOVsIk5rG41Il5lFS
4GmryKNVzdnS4X7D7XTNtf6C2UPNd4AN6/odXuCSbTeb0wykrdGWnbKxGurb
7dY5xj6wAVPpAYnq5BRjixJmUEWUgc5n1ZjVgUGgwGhao++GFEwwYgeNb5La
apOtiiIxaCaLZEQBQTDNeqiF2+pkAXQ0xPh+yRUApibrgIfM/1lZHCirv8fK
LlJzprwtMxxR7TVug+ohc3msckZ8jxwANQGgYq3hU0PjQCNugw3XYbbXZItA
u/7QGoGq99DO3OVRQioimrZaY8hXOYzmGk8nDW3T0OXikZuZBdLCdYWO4vk0
W7reT3bfchNqVLGhHuQSiTFvI8qXbQl/XJpZMG/pexImjuIOCDOsKxnT+rxc
Hi/se7bv7l8uu0e4aNfdv1w7hv2KLJ3HfxNr1bLas1kbr2MN8pBQGUMx5tk0
GS63AxZ40X2QjCjY9pFxHnaOPxx3rjurJCiP23/xtFiPL7xYD25rgtkyYbrn
RnpwQiT+57D77vScAAkur06/71x3AyDQweH7i6Pv6HcrUD0T9593yQ6CG3ZN
Ryi6gOR2qbf54VnD644w0/DrSpkmje+fINJk01HzWyullbpE8kS5hdKH2Cei
5IPoLhpmJab40UD9SIxIHB06WIiLEzUtL7dQzPVM5K1LQJmQJZ+GAgmZ6dcX
zpzwzUzC0pB6miaQt06nIPOPmz9Guj9Aj+KWx1DqS9/XuAlDJ42Bs0xmGtpL
Ya41XmVXNCcCi0oVZwdg6GuK60CXVhbEWyS0tC/wYpKzWzYnlVRyPKQrdsNE
1aoYagZDbt0ENV8QPpPbJKVAzQlcqRGFxQHb1HcLGhLZ7iMrYoJagcfGUjtn
c+doJiFKI5PBUzAkJzhzJHnMB8NSSrNmjUvv+RV8JVXELofLwNn+cNpDBnNN
VLNOjZ6RHRHJuV0VDhU040NlxqFcTVe74RJ/0z3//gCe4AMgTtpaG1fm68D+
IaPI41l254/j8U5rNKHSqdelOwLplFr9fTtdtRLwtGlQeTwGbj9xRiXUGBMg
PooieaSc3eaDeHrvwzP7tkOD7cNfoU7+Vqp61L265tdQxK7pgza/w9ei0EaO
12vVTabYyrY4S92sJM6DMr5pcaWjDL8o1KaM94S97Ow0bR7ECobtrKayWt5C
+nfIP48o7tHZRlfrO0CcA9Yhve2T6FTPRuB+52ypF3LpbWqD/au+U0/dKIcB
VhyUGBrdpP6i7ictzUE/fIQ92hBZHiOZx/KYRWpQKEDPBDIfc3g7nMqY09i1
BxuG1ObQEV+5VtsAopwZCu/QV7LgWGUVI2lqateKQ/Ck2NoVgpn+VBXMbg7f
nx6tkcs4OpApwXdxPPePys08vM7CYyYD9lXnzNiHK8nASpMQvj0C/SIkFQIj
6pO4+BwK4rw5i3MgpnTIvqKNZBLza89ts9jGURyPSmdiaKBEH9c3w58bnZFW
bqViZ8Mn9UWmLEaZVydtPdZG9C0J/KQPNsbJpw1OgGGfkVGhK6oNeygxCgT4
NHkes2CQG8Fk1ZVbzDnxE1Pt6DcMS85tkHy71V33uZADSsTHRIgGlZJS5Rds
P6rprBSvRv600Zb7teqg6v9WRzweV/h57ZRE/uMBEa8mmoJX/T4SHZjTMSk6
FBYLkxWhB07G5ywP0N0xUjGi8AaNFHQuDQ0dVzspDaRINLpD2lewrRnXgI0A
xHU0NseQSefqBJvWtL0Nci+OOinw33E53OIESu/99YcgKa2ZX4ZAAc/ixKao
n3vEaoFx77BGn8esRWh4L8ldeHTVfikbverqqKUgHU4X6FpdpBT/uuM0PZ5G
t4WGQ57EYrcEOZUFYkFbSZdN35rlQfsvp5vrgzkFfKNhxGkMxnPixgm4IevC
2Sk/LNIY04cHKyMI9MId5mFzEMPqk0bO/EsaAoP6FRP5szIi3rL4EwI5JSX5
EUaSluyekv7Z8Uu0dlydXnbPjvde7XKoer/3bWevb3zujfTXmJ5MAGiJYaK4
oua15cqTY6LvSUdDjSongyy9fx+Jz0gPuAlrZcq4an0wKAGtvaORjQjzLok5
D+uPV/vReftzxmRO774o2MDq0aAXAYYzUjulknlY88N4maFjZwr6KJBLERec
L92utms0zvjim0fP1knOCSPS9gkIL6EswMLzGOjOjhiIZGFCN6oG51MJ6tbg
Ps5C96JY6GRbeAgYlvoSWcPUOJihwFRK0he+aEYyIdX7YywoQmhM1CR2HYOT
T8ixmfPoltMEl3CM0hB6LBEzSm+6c2+Z4IAuFWCIYOg4OGTWsLXbiGCKBjGG
QfLfg/26VPeMjpkzwIQ2UYrCFetXeLWkLdbSSW1HuLU8iwgIFNczQbOl/YbV
ebdTRILBtil/L4fe8adiy1gUf+/2KC+A3R9ExnEWSfFx6ThIsYOjLCcLP3Yw
S0DU+AhXYz/M4HhQwNdEY5SM2B05+SoViAcCF6hiPIRBFy37JNPATwgdAEIt
iNYI+nCA8nWa1TaSglEyChUdMmJSJDg6w0WZjcdKEuRnECBL3PEwKYqFZ3Gr
7jubfFVfEGkp8yS2mOKGydzG1AvYAL622l6H+QlTdD6QI+s2y9CeEs1joTRV
A+DKhlT60whPN77ewRSqSRnFAi5TPHJMSauIrTUhwZ6ij8aLlNOpo8DjClMS
XM/igB4f4jn6BU7xfpJNa14xhGRQBVct3+7QXbv35dXpWefqhw9oeTrsHAPV
k9CJlHhilBpww6IEwpNvC5KEEyc1yhZlo0GNroWB1iLa5B5ktPKxQK0eyc8y
tlnHmYS1PzLTmm3tN0217ylIlTg7FZjUlSJ6sIbfD/H+I0aK4XYrTyfnHss1
cQQHJ5gw1oQeQy2Ib5k+yBkrI6ArjsMmH+vavqHrMcVUMffi21FLwxtV4j7R
FDkosnyAOemTBFX0KAfpxp5QjqJd37fV5oPNj6BCE711AWOIQG95qr6jNjfZ
e2QJrdkumN3Vf7IfPmZEcNp2bUhm2CqFqNBCDioNXIFzMbZytuuPvM8aEGJr
cBo5OhFRrCWqKqlse31DqPb73trsrVqcn/HXfffXn4P/S2wA9N0K2cj94rcv
8N5nrTCaWJybdxCc4R8WmN89Jg/PnDcdE4vzdKWN5aeA7kzw43rbR4M57nOs
do1wSKstHGtMFNt6sU3cgU8CDJnIxutoE4MAZkpE2FGBwcAK6/O73P3InbDC
EizUd+n89kWhN6Wqn2hu5DSjO0ZpbJqxmCgMUewv7JrlI9KYaf6t95VgII7q
+9JWpufbxJEM3yWRrKW7iDYkp3AsARMSZjzub9he5SB4y1YNiDE2Aa9L1P45
Dqzm43/i6eMBGonKGadgsbAwhkgffARZgQmBbCwYH3mFUQ1GYzyRjWNZeRpX
L1qWNgULNUxrW4yB7gqqYoJtgzK2MIiFMjE3krfR4OxSFiZ+0jxQ0MEytCgG
FgyhSkCtSbpGQPH1BoIoAXgUyAr3bW0sZTWGUmKXdfUZw41bIsScxm1R74IP
meTd80IClgZJyqlW4QATkIMNDRbcYBXU7p66jTWTMOHBYsy91w9DGtMlQ0pi
BSG3kXarIXuxIQ0ujUtyO6C3yZtMoqsZFQXOy2ChYUIOcCvtFccSxwg4M53G
HHy08ed4wCrHokDkAvLNm/AryYsVSBcb4DaAkcSsuFSHreoHxQ8iD8F/aHKi
FzDope9zlAhtyjLkSJgD4Y/LJn5p4jgxWsT7zA0U8X5o5p6h/PoVB/K4XNX7
oepxeLpvAvoU/JxQ1c0K80Z3Q/Aj/vc/g3VT0uBaW7cgb4rbw2gocFzXckdM
wJcOmY80kC2Nb3eMYaNm8umYK8RE43e3WWxtNRJmjdKiU507rIoMUUsMTZnG
iCmF1LZf2VYbrd6vnxhfJzs77fVOz9996Fy9c2LDvDGG6nwQD8M6TdtzEmqI
DloI63rlYPmIVokZbesDM4SXGluFL0o5Af1ipuAk4unUdGqgCMzFiyTKbdta
UZyfRf97dFVxHB94Lz7ICoOyaz09DbfHU2Bdc/baF2VADJCny9Dkbib5lebP
UUbVmVvbLxzrTQ7wGSUjya65Iy1UlnFr243mxwQ5inZFjOY8voVDTLNEH0/V
DkXiK+Z4+ggyiqXCcSX+qBk4UK2vhiewkzplXGkHacb92GISMM6JEV+drJNy
uUKMqFBZc8GeDDKlWhwKHK7W5wocfLocsaRBiZVQI90m2KBltgAZ6N4Lwdj6
dYOfyr++GaDNFLatYQJWF3yazFQxBXhWmgZp6nc0FeSztYP6XB2X6ABOQzn3
9/LA2Q5ynjay8odnle/dPH3/F5dvwobnlCFXDy0wX0XlV8ed626F3zK5+T11
5hR4iwI2RmrG5RIieAdX6S5VTWFbLbUcVSJQ2fjvVWjEdQWI1AE22hvZc1Dh
ghydbK2b7C9BWH4zZIVeUDYJ2/f3BZZ+0LSEfnUHGlxofgsoi8bsiWVDZkil
srAVg8dPKemxTDy6RYhNlh38l036IJHo6nTlyLHTX7PU173p6Z2qJq9+lRgl
KhZ3SBhJntfNkbco+c2EEHCePfO7+qpx6KwbFuv6kQnk+OHhj/AEs9TgiX2w
/+IFPhDjJ6zSbAt9NNNoEE9JmqgOi0Ni+6ip0jD6mszPLiGET2CscPTt5xlB
xPFWOzeqYZ8NhifleOOreIREdDB9lxVJAuN52yvad1zQGHEscbS2Y2s5miZY
R2CK3S7gtKXZfX9r2+vYDAhtwzLSkQ5nuMgJRpQHo5v/SBiak017xygRzWeF
kTLpSBfmIoioWaFsq6Wi84sPZ53ro2+bov1hWRraejq+o8t6K7r+f8vWDidZ
8C7LRv8djBN6G/9Y3331jJNDr97/b+1egGYw6YvqVv0GU4Kmjh1oFhgFHdkc
lm0/Eon1VoFQhEHgjyaU9jguI6JhtlAh4iqiGmz5GiFXugopRbGhweCWSnuc
nR513r+zfOszVE7ijcVXD4we9DPaM3756cmKJuWVILvDlK5VaqatBWlUfJoo
6ZtdiT1AfmJZjFqFFcCXyLFk9vlaDStFJhSd8Qqioq8JnlwfhmfXV/ohEKB9
J6sKmaFMRwhKJSnn4WFRjt/YhBs2WaxNCOKepG+NBYUNxrzTJK2DTjJyHebF
7X7a3Q02N8yZIAFBEZ40mmJjq91yJ/OZHezVOwBtMkspTIJwPNyOejXXvIL+
C6OpQtS3BTPOptVhkClXwLS5l1z04/ney1e0sky1RYWBjcNYDQ5LGSW3yJpt
EBYGCBG8rpaWcpJzdVZtHkLfvSwVNc/ZS/aZcsJlpTMDfu+xpD7fuz7B9XIw
g4n2q6DmM0Sc8Lw+j8ZNY9VJHGWYR1eGWOJY4yH4bYp+OK3q1/4QVB8nKGUT
6ESp8VKVyZluNQ/w4ub68ub6Q/cvp71rDIR+dOloKnxlmizrUq6CR0Qx0tXz
hUGqwebrcIBVBjDUaTs4unp/wmbwmJw7xbYUmEq4PtcE+DfhS21xxRcX89Ae
T40a4XNl4VWMPYNHXbNjzGKKmkMzpQ9ivWbZ/FtfVdXJo635nIZqUdgdkSm9
JZrKSG0azwEGFHudyxXXGAlyWtQOK7muCHjSElR7OSTmhrKP8kVqrCcmjoXi
YkzWoUGhNUg9vuFPSWrllODyxUWpIQNmRg7M5zJ0EW79VrkAVtMlpbA6YyOM
Z/NyqUhmmi0t+CTO7bAGOF1nL5tLInUd/lIZTWNgftPGlPmSE+ucxKmVCcNu
opnGiZgxLUBXmBLcImPqpyLtc9UpJlOLwjiEPlIqQ67za3O+snUYuTEl0nml
Z5GbUwExruc0b629Bg1mxP/lVHDfGWFywccUcAcbg9uOEdGRuoopMLCSCe5k
OQI9YZB9DKs0uXeaDP7ogUG64kSXs4OWbU7mWj66oked8/OL6w8oQfU1w8S5
BxheavCt0iVbYlx2P+A4UkGDxxWuDNTifjb6xZsseGtg1IWvC4i68xehmHMT
TjZK0wuVnBQjO9aSUViqJgxHtNs3y9HiMvKQHPFtkqXLkHVhNvros2gMN7DJ
DmTF2KfZgp4kG38PStsJECkE2+pZL5e6GklE7ruD7dvQXhlr38R182Vztp8O
Evt9gTBTrU3UUdHBmWOSghekrBG4sIYk+rZrPbsiNR6WQQyqFCNljUUl7lAc
bmGlFKtrh1y20o61oYFgM2nH7W2u53QPchFpyCD0btnRyKSrg1HVXJDNuTVW
8D93WDHa0moDgptSHZDroCTV1SAYXXzXJ0uca0fzzQMUGWyyRCoeFtJ7oprl
TYgNDewehgzCsZWAEBLOlckcn8dJDbrVmF6c4+KUgqRzkaSciUJtVg6q605L
My8Kr8K2dX3WO8egjepwqDFyFa5p6fzig7mXfYLRKTmUp4grXxm0QpJvKmTf
jZKswVDLkt1Plo3DJChwGScL7NQaVdIJkcW4N5rYB+tSponKCzVNSvpfVZvA
IdKbOn8TuXQf05iavzX2Y4IDM2lkKXMhxNHgyqZ4uiqAiEq6tyrwfUhcK2Td
q47h/EYfUoH1vd1w/+313puD568OXrz8a9A9fPPy8PDlSef5887rl929l923
L150Xz0/2QeB/uXu0YuTF6+7z990n/4iZpgdELt62CDnUI7B4j9umKFt/PSL
TIRsSP/5R/pLYL5ArAui8B9BJ/xrhcn9/KR5N7T8vIqGR2f0XwGGJyasg6Ar
VUoisZKhq0V+dPN+5a0ms1E1X7M5yfvREAhbJMXYnj7frvUY9BjjMFJDaEHr
dYEiXZxDh1Ugst+ByR+dXn4LraB+SK4hU7dF2ftqexVZJuOyFB4p79r4R8P+
SNanNAupwgS3FhEY3Mjp92L8PkahW3LE1LCdWSQqCRt0h20NZ2wDiEt3mMw4
uHf4tT+AafZ3P73a77PJgq06fbJS8btaSMx8suBPXr/sC6f3jkrfqD3FcjYD
YT4ZGtMrgoxIJIQxuPggIMiIzRMLosHF6ArUKKRPc/D6AmFUmNQo3zw5WFp8
ACcrwFvsqolSOPtmqaGmWkl4xYgdDqNl2Z1AeFM3mXEP/bn46glnGTUO5p+j
pmi6xBpVe/V4VurZBnDt317VXkej7ICGBtjERZlpXLQnq+YOKN2j2jlVJbBn
jCROzamm9DQ8Z6QysEhsbpuL+O31CpfIqvyDjP2XlXssykvDRtFclq6pwMGX
EXxstH0DFwq86tkYsgmURcMyFcyLLFici81lBTtu254prpmo1Aa/5alLxiSc
L13AIG8HNxunytGNUeNwVrXU1LMZNsVqKmN2pbPWlWeMlJXaloqi9ZV2XKbG
7/7PMNWcjivn1eApFS76j4mWZRe675ARo5/rl8kIDpJqId5jOBJ+lmeDBRWs
FTxymZ4R9UkRKLZblcImujYfkK59e3PWOf9w1e0cdw4JHK82fpC7iiYrtbJX
0Sjt3KhDuqUwDSl13/C5OOsXJtnGAi2yEuHrMa6ZylEjLPQMaxLmLRubsZqv
p4HPGWnQZAOi8ICKTyrYrJdSozPTR5cWMffGHq1s8Eh/K1xUa/vdIznEUw0T
9Qg85verO/7Mpj8GBujPwwVzxK3xutaYilUohKZP1GJ/y+JXWvt9jIgO0DTy
BHfakqvCPkkOJXWEYYvOKs5zRYwlAcopm+4n/FAdWPRvrLSoYHwymyTITXQf
w4NI6h0b8sLVjTTQxqf1NcsGe2wq3MzTytwaWM2HpG728OxDIj84q1lJ1iGa
WrhMSvHRbKpdZJmZk1u7ekwu+men98PZWff66vToQ+f9u4tfMUY5wnaEJsZZ
QC0ld3ebk9LxH1hdtf46I3eQtGHzKCiYgs0vDHa39kpSVIxIpt3zo6sfLl2U
zn87wNVrK2VGBpndAB64lgGpjFzDFxmT0EZ9iGMZTwHar/QgYCqLVAK2actw
9ZKC8UmivMCQLvSd2Ekx1gJWqfDwTe4p4MbEv2hIsWFw1qGYsh9/Go9u3bLX
XtqlKYAIynFC14iNIE2FbBh+pSF1RnCEXGAbJLSl+xVxxEGeRaNAPZGEUiIM
IqYIaAlyi6SiohmVWoNdaZ/pw1YzzkoUgCT9sYrL43xukmXnBtBFz5I5dwaI
v37EVBnCUtXoTBdjgBnwF8Uq0BCJ7bYI5MqxfMNI8+XYFgLNQgVeTetfNkfW
ImdrNM99jqnWqUETMTOcZl55dq8WaiUVk44dB6xJB4zbyRYraPkwG7C+QPr1
PXn7CG7KlLUyuDQEQjXi4EtOuZxEjPzI+RNYZo2wQhpgUm3N+QpqxVsOjKF6
y0lcjsMpjLwI432OSQ3VMRnu7ZEsXBcmmYhpZRfGyaLQGA5QIabkmmbWGoD7
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
vP1ZrI4CG6xGYPuZaiUm5ZVkdHV9eNB8HMwEJ5DjmzACyl074NS3CVJn8pxn
yFOGMcNLwiHFQ0tiSR0Wmc/f2ekRHAY4ezMkO7d67thMFJJ4T44VF083rmCk
wQhAtGfrHClwoGpUEgPVnSUxtBprR1o9fSJCumKQQktw2nbOTs+6mlGmYRMI
bo9kgAf8Vd9xK2gtiD5rUUDadjQDV0zAPJmoWMW6X8rBfb738hVnRmqFP+uo
im1UzTQB2ak/v52HxSR6ubcvUUWJRKsVSbkQYrdpFDtHjGQ5w8E7p4UstgIF
tx7EtbAek6FFjn0TfoaiN4jxs8GUV96snqwmL6JNeO/zxrsu11oAUctGLQhy
7CwRfJSGxccArVwT9AJNkMV4GVGhTbROao4WIXCI7MPusmhdbUhcWwN2qwCZ
23TAB8sydiNh7NBZWS8sPgHdLrSEiG/Y+jswTMur4kN0y0PjFDyZ+nX6D3ay
SKjy55V05CXzMGdg3fwwv1UX05UNUSgjtjmniSvS7EpEFEKWpw9AWslF8nci
mqn8dEGuUfaFkyiJhxbPMc7a12f1t5Da/FPv4lxtG2iRNu5qBcmlA2ex3SWa
NbTRijfXR4x1RCGQVfTF7UC0Xw5RRPsKF0FzgxVtkCI0fAJPEZ0uSUu3NVPp
VTLMIilNt1X/xK1kJ2jnZEZxbL+bUveZl8T5YJs1FhFBMT4uoWBQXGTWP+QA
C23SKcwEir0yeYW2wJ8PLL4F/SlYE9RoZRvGsMcUfm2k6Up3HvCNiyRtMMj+
ViD8zpYfv4riHgGWoCcRzp9EsDa7SA2Pq8fGMhy2Jw9QZVf5RV09KMaoiyQS
q3b94NgA2rZvJCJhX4IJJOgMA37lwGvDBp+TYgIwyYKsq0vn2mvClBtyVxhH
VWTuTi79UTfavmJZAt2BEW9baUujCDS+tk+B0Su/p+/QTlG9CdUg9qaQ6+Do
7W731fHzV/u7u529w7f7+529l7tvu69fv9p7s/f21cv9t53uy5OTN8HRi8Oj
/ePjw+dvjo66b1+9ePOye9h9e7R/sr/76u3e3uu3u8/fdF8evQqcMxg8bNBl
yIuNg+DHjdHHW4yW3/jpF3YU+jQPDnGckohEh7ZCAvnctSSoCANzabtIKaYS
GRXQLiJCifEWUpMkrdWIkYvgaNuVCC8yjZrAwuEiRxkgV8PRl4uvHyhwAV+D
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
ExTjqMoVC6Ojq6pvXVnxupwZJ/DNGzxTkq/sSDiWoeI9GxRz2d3jqnl6cLT3
u5xBioe4HCjOge4ggSvmqCQBxCKXagKoN6B48glE4/iUes/hxAtdSq+AjEXA
WO9M9dWo5BrSW4K672AVCttghISrWIYQxXXjUD74RaZYUcV549Y7m5TjJv1F
fSMft5WE7ALWwdEpp1uC3lQ6T5CAOnj64PbdRoPUjT9k+Y9Z8zY9aWY/3GcI
Tj4z0uzOPv+n97PPPts9eNx4jgDwrez2HXQkp7eBFq6uNb2YOr7M/nj76faz
r5hs7zJl1mrJFtGoD9KtVrserGyjAawHQ3TgTWrG+JAbw8H8lHEd+tOTTQbC
yz1leGEF5Cej4WYDzUJDB69pW7rbOB1yd7yTKZCQAhY9uL1mCP/5hfZTy3UT
Xwidck8195WwTBNsZe8Wf5w0NVG5rOJ8eDpna+CaePSkef39r//xl+wP7xaU
xw8xE/pnvWnRSO9keEaPvmi6ClUz+st/ZY/5tixWSDPBf3wXefSAnjVuy9/y
jur4ttGQuNNBqCIVC9i8LF9QLneR1furCs/+/td//zcqlQ887xaCmf6O1EFT
S7+MxPerLgOqfsxA8SSW5eMb9O2wEIj2tdvrrbq20QR+BTNM4Vuny+Fuuhhc
tTDKHD1doPxq7bFuZM3QArM5xvWiqTQ4OZ9K7n/OzkjsYE699y+332tVSnlX
WTiKLbQypNxFylcnWT6KSfwrEt1Zfno3y/t/zOgnE8f/OVtMhn/K8hPXduuk
ZuP7g8NvdvYOqXLjF3DRpKSthh+C76ezF3Jkj/NHEzUbJ33/C7PZApP931me
mxJReqw6R+lpoRHN1ccXUgZ0wjwErPnY4prX6oUvKZM45KZyU3IMWvYZjiZf
6AlmYzKYf97MPmfOxg3LWJ2Zcmgt2WfhnX2Gx7RmIDnlwfy1TYYYIcdyWiE1
ADcqPsX/95//bXLvHZ42XB6bvUIpn8VMNX96b30EW6k9i7VxaRqNUwHOBAaw
EDlhf7lPa6qh9kApj4lLb+NMtbxges2FW0JfAX1XXwmEWkvbvL18dRMnOm1S
e3IlezWSajrzbeBSVYzFzKuf1PeO8Knr3Y3vKV/7G3TYRGJBaszjVzQH6ZP6
sqypbVbl09jnuhRqh8ZKGhcyp4yPr9woem+f6icrOzn9hrSXZwc7B6TxMSI+
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

-->

</rfc>

