~apreiml/himitsu-pgp

9bcff3285b1c3f464e09759382e18607e7f6c094 — Armin Preiml 10 months ago ef4899c master
add DESIGN.md
1 files changed, 129 insertions(+), 0 deletions(-)

A DESIGN.md
A DESIGN.md => DESIGN.md +129 -0
@@ 0,0 1,129 @@
# OpenPGP

OpenPGP keys are bundles of multiple keypairs. The structure of a bunde is

 * main key: usually for signing messages or subkeys
 * one or more identities (eg. email address)
 * one or more subkeys (keys for encryption, authentication)

Each of the keypairs can have a revocation certificate attached.

Each of the keypairs have different identifiers. Note that the RFC for v6 is
still a draft.

  * fingerprint:
  	- v4 = sha1 hash of the public key packet (key parameters + created at)
	- v6 = sha256 hash of the public key packet (key paramters + created at)
  * key id 
  	- v3 = low 64 bits of public modulus (in case of RSA)
	- v4 = low 64 bits of the fingerprint
	- v6 = first 64 bits of the fingerprint
  * keygrip:
  	sha1 hash of the public modulus (in case of RSA). Not part of the 
	standard, but used in gpg agent to select keys.

Note that one must not assume that any of the following is unique:
  * fingerprint 
      - (v4) sha1 is broken, though i don't know how hard it is
          to find a collision of public keys within the public
          key size space
      - (v6) the draft rfc says:

          > Note that there is a much smaller, but still
          > non-zero, that two different keys have
          > the same fingerprint.

          I wonder if this is an issue, since sha256 provides 128
          bit collision resistance.
  * key id: value space is too little
  * keygrip: sha1 is broken (collisions)

# Himitsu storage format

Given the outline above, I suggest to use the following format to store pgp
keys.

 * proto=pgp
 * userid= first user id
 * createdat= creation date
 * id4= key id of v4 id.
 * fp4= hex of fingerprint (v4) of the main key
 * pub=base64{...} stored as OpenPGP transferable public key 
 * priv!=base64{...} 
	Only extracted private key parameters (not a pgp format). The private
	parameters are intertwined with the public keys. When imporint the a
	public key bundle needs to be created and stored as pub. Import file
	needs to be trimmed down to only contain private parameters and store
	them as priv.

userid, id4, fp4, fp6 are tools for the users to select keys using himitsu
queries. The other tools will always request all key bundles and iterate
through the key ids, fingerprints and keygrips of those main and sub-keys.

Here's how it might work with the hipgp tools:

 * hipgp-agent: 
	On key selection the hipgp-agent will query all keys having priv!
	without decrypting and then calculate keygrips of all main and subkeys.
	When the key is found/selected it will call himitus to decrypt the
	private key. The agent itself does not cache the private keys. This
	is done by himitsu if something like
	https://todo.sr.ht/~sircmpwn/himitsu/44 is implemented.
 
 * hipgp import: 
 	Select all keys and check for dupes: If same main key is found, this
	may be an update. Also check keygrips, fingerprints and even compare
	the public key parameters, just to be sure that no collision occurs.

	Consider disallowing image attribute subpackets, or warn about them,
	since they've been exploited to find id collisions.

	Should it check duplicate identities? 

	Hipgp will also be able to import revocation certificates and will
	revoke stored keys. A revoked key will still be in the store, but
	key operations will fail unless special options are provided.

 * hipgp sign/encrypt:
	Warn on dupe identities? Use one or all?

 * hipgp decrypt/verify:
 	Try all key candidates. On verify: print matching key info.

# Key selection

The challenge is how to find the right keys for each operation. This chapter
outlines possible key queries for each operation.

## Sign

User must select a key. Following selection methods could be handy:

 * select private key via identity. e.g. sign as apreiml@strohwolke.at
 	- what if I have multiple private keys for this identity?
 * select private key via a himitsu query.
 * configure a default key to skip previous steps.

## Encrypt
 
A file can encrypted using one or more public keys.

 * select public keys via identities
 	- should hipgp warn if there a multiple keys for one identity?
 * select public keys via himitsu query
 * select public keys by providing a public key file.

## Verify

One-pass signature packets provide the key id on top of a sig file. In case of
ed25519, which requires the key to initalize the hash function, all public keys
with given key id will need to be tried.

The fingerprint is found in the signature packet at the end of signature files
or external signatures, which can be used to further restrict candidate keys.

## Decrypt

Each file has a session key, that is encrypted with all public keys the message
is intended for. Key id is provided, to find the matching private key.