1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00
gnupg/agent/keyformat.txt
Werner Koch 41862f5f13 * protect-tool.c: New option --canonical.
(show_file): Implement it.

* keyformat.txt: Define the created-at attribute for keys.

* ccid-driver.c: Replaced macro DEBUG_T1 by a new debug level.
(parse_ccid_descriptor): Mark SCR335 firmware version 5.18 good.
(ccid_transceive): Arghhh.  The seqno is another bit in the
R-block than in the I block, this was wrong at one place.

* scdaemon.c: New options --debug-ccid-driver and
--debug-disable-ticker.

* app-openpgp.c (do_genkey, do_writekey): Factored code to check
for existing key out into ..
(does_key_exist): .. New function.

* gpg-connect-agent.c (add_definq, show_definq, clear_definq)
(handle_inquire): New.
(read_and_print_response): Handle INQUIRE command.
(main): Implement control commands.
2005-05-20 20:39:36 +00:00

5.1 KiB

keyformat.txt (wk 2001-12-18)

Some notes on the format of the secret keys used with gpg-agent.

Location of keys

The secret keys[1] are stored on a per file basis in a directory below the ~/.gnupg home directory. This directory is named

private-keys-v1.d

and should have permissions 700.

The secret keys are stored in files with a name matching the hexadecimal representation of the keygrip[2].

Unprotected Private Key Format

The content of the file is an S-Expression like the ones used with Libgcrypt. Here is an example of an unprotected file:

(private-key (rsa (n #00e0ce9..[some bytes not shown]..51#) (e #010001#) (d #046129F..[some bytes not shown]..81#) (p #00e861b..[some bytes not shown]..f1#) (q #00f7a7c..[some bytes not shown]..61#) (u #304559a..[some bytes not shown]..9b#) ) (created-at timestamp) (uri http://foo.bar x-foo:whatever_you_want) (comment whatever) )

"comment", "created-at" and "uri" are optional. "comment" is currently used to keep track of ssh key comments. "created-at" is used to keep track of the creation time stamp used with OpenPGP keys; it is optional but required for some operations to calculate the fingerprint of the key. This timestamp should be a string with the number of seconds since Epoch or an ISO time string (yyyymmddThhmmss).

Actually this form should not be used for regular purposes and only accepted by gpg-agent with the configuration option: --allow-non-canonical-key-format. The regular way to represent the keys is in canonical representation[3]:

(private-key (rsa (n #00e0ce9..[some bytes not shown]..51#) (e #010001#) (d #046129F..[some bytes not shown]..81#) (p #00e861b..[some bytes not shown]..f1#) (q #00f7a7c..[some bytes not shown]..61#) (u #304559a..[some bytes not shown]..9b#) ) (uri http://foo.bar x-foo:whatever_you_want) )

Protected Private Key Format

A protected key is like this:

(protected-private-key (rsa (n #00e0ce9..[some bytes not shown]..51#) (e #010001#) (protected mode (parms) encrypted_octet_string) ) (uri http://foo.bar x-foo:whatever_you_want) (comment whatever) )

In this scheme the encrypted_octet_string is encrypted according to the algorithm described after the keyword protected; most protection algorithms need some parameters, which are given in a list before the encrypted_octet_string. The result of the decryption process is a list of the secret key parameters.

The only available protection mode for now is

openpgp-s2k3-sha1-aes-cbc

which describes an algorithm using using AES in CBC mode for encryption, SHA-1 for integrity protection and the String to Key algorithm 3 from OpenPGP (rfc2440).

Example:

(protected openpgp-s2k3-sha1-aes-cbc ((sha1 16byte_salt no_of_iterations) 16byte_iv) encrypted_octet_string )

The encrypted_octet string should yield this S-Exp (in canonical representation) after decryption:

( ( (d #046129F..[some bytes not shown]..81#) (p #00e861b..[some bytes not shown]..f1#) (q #00f7a7c..[some bytes not shown]..61#) (u #304559a..[some bytes not shown]..9b#) ) (hash sha1 #...[hashvalue]...#) )

For padding reasons, random bytes are appended to this list - they can easily be stripped by looking for the end of the list.

The hash is calculated on the concatenation of the public key and secret key parameter lists: i.e it is required to hash the concatenation of these 6 canonical encoded lists for RSA, including the parenthesis and the algorithm keyword.

(rsa (n #00e0ce9..[some bytes not shown]..51#) (e #010001#) (d #046129F..[some bytes not shown]..81#) (p #00e861b..[some bytes not shown]..f1#) (q #00f7a7c..[some bytes not shown]..61#) (u #304559a..[some bytes not shown]..9b#) )

After decryption the hash must be recalculated and compared against the stored one - If they don't match the integrity of the key is not given.

Shadowed Private Key Format

To keep track of keys stored on IC cards we use a third format for private kyes which are called shadow keys as they are only a reference to keys stored on a token:

(shadowed-private-key (rsa (n #00e0ce9..[some bytes not shown]..51#) (e #010001#) (shadowed protocol (info)) ) (uri http://foo.bar x-foo:whatever_you_want) (comment whatever) )

The currently used protocol is "ti-v1" (token info version 1). The second list with the information has this layout:

(card_serial_number id_string_of_key)

More items may be added to the list.

Notes:

[1] I usually use the terms private and secret key exchangeable but prefer the term secret key because it can be visually be better distinguished from the term public key.

[2] The keygrip is a unique identifier for a key pair, it is independent of any protocol, so that the same key can be used with different protocols. PKCS-15 calls this a subjectKeyHash; it can be calculated using Libgcrypt's gcry_pk_get_keygrip ().

[3] Even when canonical representation are required we will show the S-expression here in a more readable representation.