$Id: use-cases.txt,v 1.1.1.1 2008/09/10 09:32:57 agcrooks Exp $

Use cases document - BSD Privacy Guard
======================================

This is an attempt to sketch out some of the use cases for PGP encryption,
along with interface ideas and notes about problems with other programs.


1. OpenPGP message processing use cases
=======================================

----------------------------------------
Hybrid encryption
----------------------------------------

BPG must be able to encrypt and decrypt data with both symmetric and
asymmetric algorithms, using enveloping as defined in OpenPGP.

The public asymmetric key must be previously imported (key servers, or
direct import).

When a user wants to encrypt data:

1. Chooses a key via the key management library:

  * If the key is a signing key, the library searchs for the
    encryption key attached to it.

  * The library checks if the key has expired.

  * The key management library checks the trust of that key with the
    trust library (with searches in the trust database, which can be
    local or remote).

  * The library returns:
    a) An error state (ok / key not found / key expired / ambiguous ID
    ...).
    b) Trust level.
    c) The key if the error state was "ok".

2. Selects cryptographic algorithms to be used (asymmetric and
   symmetric). If this step is skipped, the default algorithms will be
   used.

3. Selects compression method (algorithm and compression level). If
   this step is skipped, the default method will be used.

4. Selects armoring flag (whether to perform radix-64 conversion or
   not). If this step is skipped, the output will be armored.

5. Calls data securizing library to perform the encryption, passing as
   arguments the key and the symmetric and asymmetric algorithms that
   must be used. The encrypted PGP data is returned.


----------------------------------------
Symmetric-only encryption
----------------------------------------

BPG will also support symmetric-only encryption. This is performed by
symmetrically encrypting the session key (instead of asymmetrically as
usual).

When a user wants to encrypt data with symmetric-only encryption:

1. Asks the key management library to get the key. This library asks
   the user for the password that generate the key.

2. Selects symmetric algorithm to be used. If this step is skipped,
   the default algorithm will be used.

3. Selects the compression method (algorithm and compression
   level). If this step is skipped, the default method will be used.

4. Selects armoring flag (whether to perform radix-64 conversion or
   not). If this step is skipped, the output will be armored.

5. Calls data securizing library to perform the encryption, passing as
   arguments the key and the symmetric algorithm to be used. The
   encrypted PGP data is returned.


----------------------------------------
Decryption
----------------------------------------

When a user wants to decrypt data:

1. Calls data securizing library to perform the decryption.

  * The library dearmors data if necessary.

  * If it's not a symmetric-only package, the library locates in the
    PGP info of the data the key ID, algorithms and compression method
    used in the encryption.

  * If it's not a symmetric-only package, the library asks the key
    management library for the key, who asks the user for the
    passphrase to unlock the private key.

  * If it's a symmetric-only package, the library asks the key
    management library to obtain the passphrase from the user.

  * The library performs the decryption of the data.

  * It returns:
    a) An error state (ok / key not found / key expired / unknown
    algorithms / malformed PGP message / PGP data not found / ...).
    b) Decrypted data if error state was "ok".


----------------------------------------
Digital signing
----------------------------------------

BPG must be able to make digital signatures of data with private
keys. The user selects the key to use (or use the default one), and
BPG asks for the passphrase to unlock it.

If the passphrase is correct, the data is signed as defined in
OpenPGP. If not, an error occurs.

When a user wants to sign data:

1. Chooses a key via the key management library:

  * The library checks if the key has expired.

  * The library returns:
    a) An error state (ok / key not found / key expired / ambiguous ID
    ...).
    b) The key if the error state was "ok".

2. Selects cryptographic algorithms to be used (asymmetric and
   hashing). If this step is skipped, the default algorithms will be
   used.

3. Selects armoring flag (whether to perform radix-64 conversion or
   not). If this step is skipped, the output will be armored.

4. Calls data securizing library to perform the signing, passing as
   arguments the key and the algorithms that must be used. The signed
   PGP data is returned (digital signature + plaintext).


----------------------------------------
Signature verification
----------------------------------------

For verifying a signature, BPG receives the signed data, and checks
the digital signature by calculating the hash function as defined in
OpenPGP.

When a user wants to verify data:

1. Calls data securizing library to perform the verification.

  * The library dearmors data if necessary.

  * The library locates in the PGP info of the data the key ID and
    algorithms used in the signature.

  * The key management library checks the trust of that key with the
    trust library (with searches in the trust database, which can be
    local or remote).

  * The library performs the verification:
    a) It takes the digital signature, decrypting it with the sender's
    public key.
    b) It calculates the hash of the plaintext.

  * It returns:
    a) An error state (ok / key not found / key expired / unknown
    algorithms / malformed PGP message / PGP data not found / ...).
    b) If the error state was "ok", returns the verification result:
    KU(digital signature) == H(plaintext)?


----------------------------------------
Compression
----------------------------------------

BPG will be able to compress data as defined in OpenPGP. The supported
algorithms will be ZIP and ZLIB.


----------------------------------------
Radix-64 armor/dearmor
----------------------------------------

BPG will handle radix-64 armor and dearmor of data, as defined in
OpenPGP.



2. Key management use cases
===========================

----------------------------------------
Keys from Arbitrary Sources
----------------------------------------

Rather than have this keyring thing from which all keys must come, it
would be nice to be able to specify arbitrary sources for keys, such as
a key export file. I currently have to set up an entire keyring, import
keys, set up a trustdb, etc. for my backup scripts, since they encrypt
the backups. I'd like to just have a bunch of keys in a directory, or a
keyring in an arbitrary file, and say "encrypt to all of these."


----------------------------------------
Delegated Trust Model
----------------------------------------

I'd like to have an external interface into the keyring that's usable
by scripts, and have the encryption and signature verification programs
call a program script of my chosing in order to determine how much I trust
a particular key.  That way I'm not stuck with the built-in trust model,
but can design my own.

There is the question of how we deal with the trust database. Maybe we
could use some sort of keyword/value system with a standardized set of
basic keywords ("trust=low/medium/high/ultimate", a la gnupg) but the
ability to add other things ("mycompany.com=it_dept/security_dept") for
specialized applications. The trust database owner would be able to add,
change and delete these as he wished.

Security considerations:

The trust database entries need to be signed by the trust database owner
to prevent attackers from changing trust. (Or maybe the whole trust
database should be.)

The trust database also probably wants something like signed hashes of
external programs it relies on, so it can detect when those are changed.


----------------------------------------
Management of Keys on Encrypted Files
----------------------------------------

An encrypted file, if I'm not totally out to lunch on this, consists of
a symmetrically encrypted data chunk and the key for that encryption,
encrypted once for each key that can decrypt the file, encrypted with
that key's private component. I ought to be able easily list all of the
keys on this list, and to add and delete keys from this list, without
doing a symmetric re-encryption of every file.

For example, when I decide to trust a new systems administrator, I ought
to be able to go to my directory full of encrypted backups and say, "Allow
this additional key to decrypt all of these," and have it quickly and
painlessly do that.


----------------------------------------
Key Agent
----------------------------------------

[Someone fill this in.]


----------------------------------------
Trusting Your Trust Database
----------------------------------------

One thing bugging me about a lot of the scenarios above is that a lot
of operations rely on my trust database. For example, listing the keys
that decrypt a file: I want to know not only that a 2048 bit RSA key
with self-signed identity 'Curt Sampson <cjs@cynic.net>' can decrypt
that file, but I want to know that it's the same key that I have in
my trust database marked as "very trusted", rather than any random key
with the parameters above. I use my trust database to do that.

But how do I know that an attacker has not substituted my trust
database? I wonder if I don't want to check the fingerprint of the trust
database signer every time. What ways are there of verifying the key
that signed a trust database against external information (a card in my
wallet, information on a USB key, someting fetched from several places
on the net, etc.) when I use it? What are the security implications
of these? What does an attacker have to do to compromise them? Can we
verify against multiple sources (say, stuff on my USB key, which never
leaves my physical presence, and against a download from my company's
SSL-signed page, and against signed information from The NetBSD
Foundation) to make an attacker's life harder?



3. Extensibility use cases
==========================

----------------------------------------
User-defined algorithms
----------------------------------------

Support for dynamic load of user-defined algorithms would be a very
interesting feature for encouraging researchers and cryptographers to
test their algorithms in our framework.

We may want to use the same system for our own internal algorithms,
and make the whole thing pluggable.

But it would also be interesting to have ways to plug in new algorithms
that are not written in C, e.g., in Perl for example. (See the note
above regarding trust calculations, as well.)

There are security and performance issues yet to be studied, but an
initial approach of its working would be something like this:

* The library receives a call for registering an algorithm with its
  location and interpreter ("register algorithm foo, written in
  Perl, located in /algorithms/foo_v1.pl").

* It receives a function call, with the input and the algorithm 'foo'
  in the parameters.

* It searches for the library, returning an error if not found.

* Selects interpreter, in this case the Perl intepreter.

* Executes algorithm.

* Returns output.



4. External systems use cases
=============================

----------------------------------------
Use of Library by External Programs
----------------------------------------

A program wants to be able to add PGP signing and encryption to
something it does. Take for example, archangel, an archiver similar to
tar. It wants to allow users to sign and encrypt archive entries. It
might look something like this:

    clear:	aatar cvf archive.aa file1 file2 dir1
    signed:	aatar cvf archive.aa -o signed file1 file2 dir1
    encrypted:	aatar cvf archive.aa -o encrypted file1 file2 dir1
    both:	aatar cvf archive.aa -o signed -o encrypted file1 file2 dir1

Presumably you want to use existing bpg keyrings, trust databases, etc. So:

    1. How do you chose the key with which to sign, when there is a
    choice?

	? Program gets information about the key to use, and provides
	that to the library. Program needs to deal with error conditions
	(key not found, etc.) Program may need to get a list of choices
	to offer the user.

	? bpg uses default values (from user's config file, perhaps)
	and fails if those don't work.

	? bpg takes over the terminal and asks the user, without the
	knowledge of the calling program

    2. How do provide the passphrase to decrypt the key, or otherwise
    let the library get access to the key?

	? bpg uses some default (e.g., gets it from a running key agent
	that has the key), and returns an error if that doesn't work

	? bpg takes over the terminal and asks the user, without the
	knowledge of the calling program

    3. When chosing an encryption key, how do you chose it, and how do
    you deal with the trust model, interacting with it if necessary?

	? Environment variable specifies which key file to use

	? Program specifies, as per #1 above.


----------------------------------------
Generic Archive Signer
----------------------------------------

Given a file that pax understands, and a key, bpg generates a list of
filenames, sizes and hashes (probably multiple ones--SHA1 and others),
signs this, and includes this and the public key of the signer in a file
that it appends to the archive. bpg can then later be used to verify the
signature and hashes and, in conjuction with your trust database, tell
you how much you trust this archive. This level of trust would range
anywhere from "has a valid signature, but Lord knows who signed it" to
"you signed this yourself, and it's not been modified since."

Or perhaps pax should be modified to do this.

Security notes:

    1. We need to make sure that this is defined well enough that it's
    as secure as a detached signature of the entire archive.

    2. It is an error if any files are included in the archive that
    are not included in the signed list of files and hashes. Otherwise
    someone might add something like /root/.profile to the archive.

    3. We need to verify all of the hashes before extraction, to ensure
    that we don't partly extract a known-corrupt archive. However,
    this makes streaming use of this (i.e., "cat foo.tar | tar xf -")
    impossible, unless we have a mode where we'd warn after extracting a
    known-bad archive that it is indeed bad. Do we want to allow this?

    4. For duplicate files, failure will be automatic if they differ,
    and if they're the same, it's no consequence.



----------------------------------------
Signing Packages
----------------------------------------

1. We include the signature in the package itself. This might be a
list of all of the files in the archive (excepting the signature  
file itself), their sizes and hashes (multiple ones), the signature
itself, and the public key used to sign the package, all as an 
ascii-armored file.

2. When pkg_add detects a signature, it verifies the signature and
the hashes of all of the files. It then does something undefined
(probably involving invoking bpg routines) to decide if the
signature is trusted, and if not, it issues appropriate warnings and
asks if it should continue, or abandons the install, or whatever.

3. Something is added either to BPG (a generic tar file signer?) or
to the package creation tools to create this signature. (See also
the "generic archive signer" use case.

(This is entirely orthogonal to pkg_add's "-s" option.)



5. Miscellaneous use cases
==========================

----------------------------------------
Encryption/Signing Beyond Files and E-mail
----------------------------------------

There are things beyond files and e-mail that I'd like to be able to
encrypt and sign. For example:

    * Since my web server asks for the full credit card number every
    time it wants to charge a card, it doesn't need access to the credit
    card numbers in the database. I'd like to be able to encrypt the
    data for the credit-card-number column before insert it, or looking
    it up to get the credit card ID.

    * I'd like to be able to sign my ssh authorized_keys file, to make
    it harder for attackers to replace it. (Where ssh gets a key to
    verify that signature is an interesting issue, but it could at least
    be changable only by the root user, so that an attacker who gets
    enough access to append to a file that I own cannot from that gain
    unlimited login rights.)

    * I'd like to be able to present a key to sudo rather than using
    a password. Ssh keys would seem, offhand, more suitable for this
    but given that there's no mechanism for that now, I could live with
    using my PGP key.

    * I currently keep a few files with lists of passwords and the
    like; ought not a nice modular PGP-based system be able to have
    extensions that would deal with things such as automatically filling
    in passwords in web pages?

    * I'd like to be able to sign CVS or other revision control commits.
    This might work something like:
	1. Make a bunch of changes to my checkout.
	2. cvs update, and verify that the checkout without my changes
	   has a valid signature of the previous committer.
	3. Examine my diffs and, if I'm happy with them, commit both
	   them and a new signature from me verifying that the commit
	   is correct.

----------------------------------------
SSH Encryption/Signing/Key Management
----------------------------------------

A wild idea: why do have two completely different and incompatable
programs (right now, ssh and gpg) for doing asymetric cryptographic
operations, with separate key storage and all of that? Couldn't all this
be managed by one modular system?

What would be some scenarios for this?

    * Put my SSH private keys in my private keyring with all the rest
    of my keys, so I need only one keyring and one passphrase. (I might
    carry this around on a USB key.) Have a bpg utility that can add a
    key or keys (with a default time limit of, say 1 hour) to a running
    ssh-agent.

    * Put my SSH public keys in with the other stuff on my public key,
    so people can get my SSH public keys (signed with my signing key, of
    course!) from a keyserver just as they can get my PGP public keys.
    (Does/can the OpenSSH format support this?)


----------------------------------------
Lint Tool / Expert System
----------------------------------------

A tool that looks at various option choices and provides an expert
analysis of the security tradeoffs of these choices. For example,
looking at a key and its related information (encryption keys,
identities, trust information), or at the parameters proposed for
generating a key, it could say things like:

    * A 4096-bit key is more secure than a 2048-bit or smaller key, but
    it is not compatable with the following other implementations of
    PGP: [insert list here].

    * A DSA primary key is not as secure as an RSA primary key because
    at the same key length, it takes less computational effort to be
    able to forge messages with a DSA than an RSA key; and if you can
    forge messages in the primary key, you can make as many (bogus)
    subkeys as you want. We recommend usingt an RSA primary key whenever
    possible.


----------------------------------------
API tester
----------------------------------------

There must be a command-line application for testing the API. This
program, bpgtool, has to able to manage:

* get plaintext from file "input"

* searching the file "keylist" (this is not the keyring, just a PGP
  file), find the list of primary keys that are:
	 1. Not expired,
	 2. Associated with an ID containing cjs@cynic.net or droggo@gmail.com

* From primary keys get the most recent non-expired encryption keys,
  or use the primary key if there are no encryption keys at all

* create a new session key, encrypt it with the encryption keys
  generated above, and encrypt the plaintext with it

* fetch the private key 2048R/25808B3A (which will require a
  passprhase to load) from the keyring

* Use that private key to sign the encrypted document (backwards from
  the usual PGP behaviour--do we want to allow this? or is it
  completely out of spec?)

* ascii-armor the encrypted document

* write the encrypted document to the file "output"

This tester would be accesible via an scripting language, probably
(but not definitely) Ruby.


----------------------------------------
Default algorithms
----------------------------------------

* Default symmetric algorithm: AES (?) [reasons].

* Default asymmetric algorithm for encryption: RSA (?) [reasons].

* Default asymmetric algorithm for signing: RSA (?) [reasons].

* Default hashing algorithm will be SHA-256 (?) [reasons].

* Default compression algorithm will be ZIP (?) [reasons].


----------------------------------------
Internal data storage
----------------------------------------

* Messages: we can have an in-memory data structure for buffers, and
always work with it. We can also provide functions to work with files,
but internally taking them into the in-memory data structure
(transparent to the user). [Cons?]

* Keys: in-memory data structure. The key management library maps the
key to that data structure. The data structure would include the
private key, public key, trust level (?), key length, algorithm,
ID... [Cons?]
