Below follows the "PROPOSED INTERFACE" written by catsup and the "CURRENTLY IMPLEMENTED" interface written by joe. Catsup's notion neglected the cross-merging capabilities of the currently implented --keypairs, --keyrings, and --wallets documented in the my "Merging" section. These are special because information flow is either or both ways (creation in the case of non existance). On IRC, we came up with a sensible way to incorporate this functionality, described as follows: Instead of a primitive (--keypairs, --keyrings, or --wallets) followed by a bunch of arguments, we would repeat a command. For exmaple: current ui: kiki sync --keypairs "tor=/var/lib/samizdat/torkey{openssl --create-key}" ssh-client=/home/joe/.ssh/id_rsa kiki --create="openssl --create-key" \ --keypairs tor=/var/lib/samizdat/torkey \ --no-create ssh-client=/home/joe/.ssh/id_rsa kiki --sync-key='tor:/var/lib/samizdat/torkey:openssl --create-key' proposed ui: kiki --sync-key --usage=tor --create="openssl --create-key" /var/lib/samizdat/torkey --sync-key --usage=ssh-client /home/joe/.ssh/id_rsa PROPOSAL2: kiki sync-secret tor=/var/lib/samizdat/torkey{open-ssl --create-key} \ ssh-client=/home/joe/.ssh/id_rsa With catsup's interface, it is intuitive to imagine that commands happen in order. My current interface tries to take a bunch of information on the command line and then synthesize it all with cross-merging and attempting to order things sensibly. My new notion to reconcile the two ideas is to expose a UI where the user expects things to happen in order, but to slurp all contiguous --sync-* commands into single operations. PROPOSED INTERFACE: kiki - a bridge between keys Kiki turns your OpenGPG key into a single sign-on (SSO) identity for all cryptographically-authenticated services. It also enables you to accept such identities for your own services. Fuck Google, fuck Facebook, and fuck Verisign. [TODO: enlarge list] Synopsis: kiki [command] [options] [[command] [options]]... [TODO: show the most useful commands as examples.] Description: Kiki creates a cryptographic chain of trust, _from_ a foundation of the OpenPGP web of trust, _to_ all other key types. The following key types are currently supported: * ssh (host and client) * ipsec * DNSKEY (DNSSEC) * x509 (TLS/SSL, client and server authentication; HTTP/SMTP) * Tor hidden service (.onion) * I2P hidden service (.b32.i2p) * GNUNet hidden service (.gnu, .zkey) * Bitcoin address (and other cryptocoins) * OpenPGP subkeys (merge subkeys from multiple keyrings into one) Kiki allows such keys to be taken from an existing system and imported into an OpenPGP key so that they can be shared easily. In the other direction, Kiki will determine the OpenPGP UID(s) cryptographically chained to any public key in any format, so that services with cryptographic authentication can be easily modified to accept OpenPGP identities by calling Kiki. Kiki can also export public keys into convenient formats, ready for use by services that do not call Kiki. In addition to supporting the traditional OpenPGP web of trust, Kiki recognizes the possibility of _self-authenticating_ OpenPGP signatures. These are signatures which assert ownership of UIDs which are provably owned by the signer. For example, an OpenPGP key which claims the UID is self-authenticating if the private key corresponding to 'hiotuxliwisbp6mi' has signed the UID. Such OpenPGP keys do not need to be validated by an external signature. They can be validated using their own internal data, and trusted immediately. Tutorial: To get started with Kiki, yada yada, [TODO] Commands: If no command is given, the default command is 'show-working-key'. For options common to multiple commands, see _Options_. import-key [options] [file] PROPOSAL2: import-public [options] [SPEC=file] -- [file] (recommended) PROPOSAL2: import-secret [options] [SPEC=file] -- [file] (allowed) PROPOSAL2: (Same options, and behavior as described, below) PROPOSAL2: (SPEC acts as a filter, only matching keys are touched by the import, import-public ensures secret keyring is not touched) options: --autosign --sign-key --authentic-only Import an OpenPGP key into the default keyring, optionally signing it with the default key. If no file is specified, the key is read from stdin. PROPOSAL2: If no SPEC=file is specified, the key is read from stdin. With --authentic-only, import the key only if it is self-authenticating or can be authenticated by already-trusted keys. With --autosign, import the key either way, but only sign it if it is self-authenticating (as if 'autosign' were run). [21:10] i guess i didn't say anything about --sign-key [21:11] it should say, 'With --sign-key, signs the imported key(s) unconditionally.' For a detailed description of the requirements for self-authenticated keys, see section _Self-authentication_. import-subkey [options] [public key filename | private key filename] [...] PROPOSAL2: import-secret [options] [SPEC=file] -- [file] options: [--usage=] [--set-notation ] [--no-usage] [key format] Import keys from an external file, or from stdin, into the keyring, as subkeys of the working key. The keys will be signed by the master key, and cross-certification will be performed (i.e., the keys will be used to sign the master key). PROPOSAL2: Same. Without a private key, cross-certification is impossible, and a confirmation will be required, which can be overridden with --yes. PROPOSAL2: Same. The --usage option can be used to specify the 'usage@' notation, which is used by Kiki and Samizdat to determine what functions the key should have outside of PGP. If neither --usage nor --no-usage is specified, the usage will be inferred from the filename and/or key format. PROPOSAL2: Infer usage from the SPEC as in 't:tor' PROPOSAL2: In the case of files without specs, and subkeys without any tags, import them without tags, and put ??? in the ui where the usage tag would usually appear. When the input is a file, the internal timestamp of the subkey will be set to match its mtime. The subkey timestamp is not altered if the subkey already exists. PROPOSAL2: Same. export-subkey [options] [output path] PROPOSAL2: export-secret [[options] SPEC=file{CMD}] -- [file] options: [--public[=file]] [--private[=file]] [--usage=string] [key format] PROPOSAL2: options: [--format format] [--with-public=file] Export the explicitly specified subkey, or the newest subkey indicated by the usage option, in the explicitly specified format, or the format indicated by the usage option. If no output file specification is supplied, stdout is used, but this may require --public or --private, depending on the key format. (Not all key formats allow public and private keys to be appended in a single file in a reasonable way.) PROPOSAL2: If the format only allows one key, it is the secret key. If a file is specified with --with-public it will be updated with the public key. (Even if the secret key file already has that information.) --with-public only applies to the very next SPEC=file. Alternatively, export-public --format blah SPEC=file could be run as a separate command. If a uid or master key is specified, then the usage option is mandatory; it is required to select which subkey to export. Only one of --public or --private can be specified unless both have arguments. PROPOSAL2: export-secret may export master keys and all their subkeys, such as when the file is in pgp format. If --public or --private is specified without arguments, then the public or private key is written to the specified output path. If neither is specified, then the output path is where the private key will be written. In that case, the public key will be also written, to a path determined by that of the private key, by a mechanism specified by the key format. PROPOSAL2: If they want the public key written to a separate path, they must say so with --with-public. When --public or --private have arguments, these are the locations where the public and private keys are written. A path of '-' can be specified for output to stdout. PROPOSAL2: Allow a - to appear in one and only one file slot and use stdout for that file. When the output is a file, the mtime on the file will be set to match OpenPGP's internal subkey timestamp. PROPOSAL2: Same. For more information about key formats, see _Key formats_. [TODO: generic 'authorize' command?] PROPOSAL2: Definitely favor a generic authorize. || In fact, lets figure out the semantics of the || generic form, so our UI is at least aware of || our future direction. || In keeping with the idea, that export and sync || commands modify files outside of GNUPGHOME, while || import comands only affect GNUPGHOME, lets create || a new set of commands: || At first the following will only work when SPEC is || referring to an ssh_client key. || authorize [--delete] [--masters] SPEC || - add a SPEC_auth key under the working key || corresponding to the specified key. Or if --delete || is indicated, then remove any such key. In the case || of --masters, the SPEC_auth key should correspond || to a corresponding master key instead, creating a || 'ghost' master if necessary. || - IF SPEC matched a uid to a master, use the email || address of the indicated master to tag || the new SPEC_auth key with appropriate meta data. || - if configured with an authorized key file and || format, then update the file, otherwise it is || a keyring only operation. Note that this means || the authorize command can behave as either a sync || or an import commmand, depending on kiki config. || Unlike explicit sync commands, it should probably || fallback to import when there are permission problems. || If falling back, issue a warning, rather than an error. || - If --masters, then remove all SPEC_auth keys which are || subkeys of masters replacing them with SPEC_auth keys || which are the masters instead. (If SPEC specifies a subkey || of an existing master, then the SPEC_auth created will be || for its master.) Non existent masters will be created as || 'ghost' masters which have entries but lack keys || * As a matter of Roadmap, --masters may not be implemented until || later, and then we may choose to make it the default. and add || --subkeys for the old behavior. || - use the present moment as the timestamp of the || SPEC_auth key || - Note, this command is only useful for authorizing keys || which are already found in your keyring. || Example: kiki authorize jim@samwise/ssh_client || - Assuming jim@oxio4inifatsetlx.onion is the working || key and jim@samwise appears as a substring of a uid || of one of the master keys, the above command authorizes || jim@samwise to ssh in to oxio4inifatsetlx.onion as user || jim. || import-auth [--format FORMAT] [--delete SPEC2] [--masters] SPEC=file || - Assume file in format specified. || - Import all keys from specified file as subkeys || of working (in public keyring), but not as SPEC || but rather as SPEC_auth. To each SPEC_auth key || tag it with additional meta from the file, such || as the user@host. || - If the --delete option is used, delete any || SPEC_AUTH keys which are singled out by SPEC2. If || SPEC2 indicates a master key, delete all SPEC_auth || keys under the working key which are also subkeys || of the master specified by SPEC2. The file is not || touched as this is an import command. || - In the --masters case, do not add any subkeys as SPEC_auth, || instead search for corresponding masters and add them as || SPEC_auth. Create ghost master entries for subkeys || which do not have them. Add a ghost SPEC_auth sub key || referring to the ghost master. || - If the key already exists as a SPEC subkey under || a master key in the ring, and the uid does not || match the address specified, then add a new uid || to that master with the given address(user@host), || if it does match, then update the meta tag with || the full uid. (Treating user@host like an email) || - use the mtime of the specified file for the keys. || export-auth [--format FORMAT] SPEC=file || - Export all SPEC_auth keys under the working key || to indicated file in the given || file format.(skip keys if they are already there.) || - Whenever a SPEC_auth key matches a master key, || don't write it to the file, but rather write entries || for all the SPEC subkeys under the indicated master. || - set mtime on file to match newest key || || sync-auth [--format FORMAT] [--delete SPEC2] [--masters] SPEC=file || sync-auth [--format FORMAT] [--delete SPEC2] [--masters] SPEC || - If set in a config file, then the file can be inferred from || SPEC alone. || - Add any keys missing from the file but present in || the public gpg keyring to the file and add any keys || missing from the keyring but present in the file to || the keyring. || - If a key in the file, is a subkey of a master that already || already has a SPEC_auth in the keyring, do not add it to the || keyring, but add any other SPEC subkeys under that master to || the indicated file. || - In the --masters case, do not add any subkeys as SPEC_auth, || instead search for corresponding masters and add them as || SPEC_auth. Create ghost master entries for subkeys || which do not have them. Add a ghost SPEC_auth sub key || referring to the ghost master. || - Also with --masters, remove any SPEC_auth subkeys of the || working key and replace them with SPEC_auth keys which are || also masters in the key ring. || - If the --delete option is used, delete any || SPEC_AUTH keys which are singled out by SPEC2. If || SPEC2 indicates a master key, delete all SPEC_auth || keys under the working key which are also subkeys || of the master specified by SPEC2. Naturally, their || entries in the file should also be removed. || - set mtime on the file to match newest key. || - all keys added to the keyring will have timestamp set || to match the mtime of file prior to sync. || || I think it is most convenient if we allow auth keys not to be || back signed, as users may not want to spread their secret keys || to every computer that they have auth access. || PROBLEM: What about user accounts? It is not presently clear || how kiki is supposed to treat users of the same unix || system which are not root. Presumeably, each user would || have it's own master entry in root's public gpg keyring. || Since root has access to their home folders etc, it may || be nice to facilate root using the above commands and || simply use the master portion of the spec to indicate || which user is being referred to, and then the _auth keys || would be added to that user, but then somewhere || kiki must remember which masters are local to the box. || (Actualy, kiki may have this information already as || for example username@hiotuxliwisbp6mi.onion may match || unix users on the same box.) If we did this, || then there is the added complication of also updating || the gnupghome of the specified user. || It strikes me as somewhat error-prone to operate that || way. Perhaps it is better for root to su to the || given user before updating the _auth subkeys etc. || if the root database should have all the public key || masters of all the users on the system, it can run an || import-public command to grab users keyrings. || (Of course, root can take private keys too, but that seems || messy to me. I think it is best practice if keyrings || only have private keys of a single unix user.) || In fact, a user may theoretically opt to take their own || private keyring with them on some portable media. || || Another possibility, is to give write access to root's || public keyring, and make it users responsibility to keep || root abreast rather than the other way around. || OR nobody writes to anyone elses GNUHOME and instead, we || simply mail announcements with the public key info. END PROPOSAL2 ssh-authorize [options] options: --user=user Authorize ssh access for the specified user by appending the appropriate key to $HOME/.ssh/authorized_keys unless it already exists there. Without --user, access to the current user account is granted. Otherwise, root is required, and access to the specified user account is granted. A comment will be written indicating the UID prepended with '[samizdat]'. ssh-unauthorize [uid] options: --user=user --authorized_keys= Without a uid argument, revoked keys, expired keys, and expired subkeys, will have their corresponding ssh keys removed from $HOME/.ssh/authorized_keys, or the specified file. Additionally, auth lines tagged [samizdat] for keys that are missing from the keyring will be removed. With a uid argument, all subkeys of the specified UID will be removed. Without --user, access to the current user account is removed. Otherwise, root is required, and access to the specified user account is removed. autosign [key] [...] PROPOSAL2: behaves exactly the same... Use SPEC to indicate the key This command will operate on all keys if none are specified. The working key is used to sign the specified keys if they can be self-authenticated. This tells GnuPG to trust such keys, which it would not otherwise do. For a detailed description of the requirements for self-authenticated keys, see section _Self-authentication_. show-working-key PROPOSAL2: show --working PROPOSAL2: same as show SPEC where SPEC indicates the master key that is the working key Show all available information about the default working key. Equivalent to 'show --all' with no uid argument. show [options] [uid or keyprint] PROPOSAL2: show [options] SPEC options: [--all | key format] PROPOSAL2: options: --all | --list | --working | --color | --native-fingerprint | --base64 PROPOSAL2: --native-fingerprint will replace gpg fingerprints with possibly more appropriate fingerprints given the usage of the keys in question. --base64 should not be used in conjunction with --native-fingerprint it will show all fingerprints in base64 --all means all masters and all their subkeys with trust relations --list (if a subkey is indicated, it shows all it's siblings and their master key, otherwise it is a nop) --color, make untrusted keys red, keys directly trusted (nesting 0) are green, and all the inbetweens are white. With '--all' or without a key format option, display a listing showing all keys and UIDs associated with a given UID, indicating trust-chain relationships between them. With a key format option, output a machine-useable version of the key type specified. If a UID or master keyprint is specified, then the 'usage@' annotation will be used to decide which subkey to display. If a subkey fingerprint is specified, then that key will be output in the specified format. If multiple keys are available with a matching 'usage@' annotation, the most recent key is chosen. PROPOSAL2: This belongs under one of the export commands using a --format option, show is reserved only for displaying to the user. SPEC=- can be used if they want to export to the stdout. Untrusted or unrequested data may be output via stderr. Only trusted and requested data is output via stdout. For more information about key formats, see _Key formats_. list PROPOSAL2: list can be a synonym for show --list, key format is not used here as that functionality is covered by export-public and export-secret. If nothing is indicated, i would have list default to show --all List all subkeys of the specified master key, or of the master key of the specified subkey, tagged with the usage specified by the key format. For more information about key formats, see _Key formats_. PROPOSAL2: The rest of this proposal can be added to PROPOSAL2 as it is described here. verify [options] [file or network resource] options: [key format | --challenge] --uid --short-uid --keyprint --datetime Output the verified identity of the signer of the data. If no file is specified, then the data is read from stdin. A key format can be specified to indicate the format of the data. Otherwise, an attempt is made to infer the key format from the data itself, in which case it must not contain extraneous information. For network resources, it can always be inferred. Supported network resources are: ssh://server[:port] https://[SNI domain@]server[:port] tls://[SNI domain@]server[:port] dnskey://[domain][@dns server:port] For DNSKEY network resources, all DNSKEY responses must validate; but ZSK's might be validated indirectly, through RRSIG records made with validated ZSK's. Identities are output on stdout, with one identity per line. Stderr may contain additional information. Special characters in UIDs (such as newline) are escaped. By default, or with --uid, show the full UID. With --short-uid, show only the email part of the UID, without brackets. With --keyprint, show the keyprint of the master key. With both --keyprint and one of --uid or --short-uid, show the keyprint, followed by a space, followed by the UID in the specified form. With '--challenge', a cryptographic challenge response is verified. In this case, the stdout output is not necessarily an OpenPGP UID or keyprint, but is specific to the challenge type. Kiki will exit with failure if verification fails. For more information about key formats, see _Key formats_. challenge [options] options: --language=[lang] --short --no-instructions --shell --validity-period=[interval] challenge types: --bitcoin --tor --i2p --pgp Output to stdout a human-readable challenge which can be completed only with the appropriate private key. Creating the challenge may require generating a PGP signature, in which case the working key will be used. The response to the challenge can be verified with the 'verify --challenge' command. With --validity-period, the challenge will expire after the specified interval. The interval is specified in DNS zone file format. The current system time is used to calculate an absolute expiration time in the future. Unless --no-instructions is specified, the challenge will contain detailed instructions intended for unsophisticated recipients. If --short is specified, the instructions will be less detailed. If --shell is specified, the "instructions" take the form of a Bourne shell script. response [file] A challenge generated from 'challenge' is read from the specified file, or via stdin, and an identity-proving response is generated automatically and output to stdout. help Key formats: [TODO: determine, and document, the precise relationship between key formats and usage notations.] --pem --ssh --wallet --dnskey --ipsec --pgp --wallet Bitcoin wallet input format. These cryptocoins are also supported: [...] --ssh OpenSSH key format. For public keys, this is the format used in authorized_keys. The "comment" section, which is output via stderr, contains a UID with special characters (such as newline) escaped. Options: These options are common to multiple commands. Options specific to commands are documented with the commands. --homedir --passphrase-fd --keyring --no-default-keyring --primary-keyring --default-key --trustdb-name --verbose --quiet --no-tty --yes --no Environment: HOME GNUPGHOME GPG_AGENT_INFO PINENTRY_USER_DATA Files: $HOME/.gnupg $GNUPGHOME/{pub,sec}ring.gpg /etc/ssh/ssh_host*_key /etc/ipsec.d/private/*.pem etc. Self-authentication: [Explain the criteria of self-authentication in precise terms.] Author: Kiki by Joe Crayne. This manual by Andrew Cady. Copyright: (C) 2014 Joe Crayne. All Rights Reserved. When released, Kiki will be released under a free software license. This version is a pre-release. Reporting Bugs: Bugs? Impossible. "From key to shining key..." CURRENTLY IMPLEMENTED: kiki [OPTIONS] kiki merges a set of keyring files into a combined database and then uses the database to update the files so that they have the most complete information. The files pubring.gpg and subring.gpg in the directory specified by the --homedir option are implicitly included in the keyring set. kiki can also import or export secret subkeys by using the --keypairs option. Subkeys that are imported with kiki are given an annotation "usage@" which indicates what the key is for. This tag can be used as a SPEC to select a particular key. Master keys may be specified by using fingerprints or by specifying a substring of an associated UID. Flags: --homedir DIR Where to find the the files secring.gpg and pubring.gpg. The default location is taken from the environment variable GNUPGHOME. --passphrase-fd N Read passphrase from the given file descriptor. --import Add master keys to pubring.gpg. Without this option, only UID and subkey data is updated. --import-if-authentic Add signed master keys to pubring.gpg. Like --import except that only keys with signatures from the working key (--show-wk) are imported. --autosign Sign all cross-certified tor-style UIDs. A tor-style UID is of the form: Anonymous It is considered cross certified if there exists a cross-certified 'tor' subkey corresponding to the address HOSTNAME.onion. Merging: --keyrings FILE FILE... Provide keyring files other than the implicit secring.gpg and pubring.gpg in the --homedir. This option is implicit unless --keypairs or --wallets is used. --wallets FILE FILE... Provide wallet files with secret crypto-coin keys in Wallet Import Format. The keys will be treated as subkeys of your current working key (the one shown by --show-wk). --keypairs KEYSPEC KEYSPEC... Each KEYSPEC specifies that a key should match the content and timestamp of an external PKCS #1 private RSA key file. KEYSPEC ::= SPEC=FILE{CMD} If neither SPEC or FILE match any keys, then the CMD will be executed in order to create the FILE. 2B9F3D5A99EF9E0BB50252C3C07428D3FCD7BFB7/tor joe/tor joe/9166F90FA7E4311088FA84BC9E6AFE3F58C673C2 joe/fp:C673C2 Output: --show-wk Show fingerprints for the working key (which will be used to make signatures) and all its subkeys and UID. --show-key SPEC Show fingerprints for the specified key and all its subkeys and UID. --show-all Show fingerprints and UIDs and usage tags for all known keys. --show-whose-key Shows the fingerprint and UIDs of the key that owns the one that is input on stdin in ssh-rsa format. --show-pem SPEC Outputs the PKCS #8 public key corresponding to SPEC. --show-ssh SPEC Outputs the ssh-rsa blob for the specified public key. --show-wip SPEC Outputs the secret crypto-coin key in Wallet Input Format. --help Shows this help screen.