mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
237 lines
8.5 KiB
Plaintext
237 lines
8.5 KiB
Plaintext
|
|
|
|
* For packet version 3 we calculate the keyids this way:
|
|
RSA := low 64 bits of n
|
|
ELGAMAL := build a v3 pubkey packet (with CTB 0x99) and calculate
|
|
a rmd160 hash value from it. This is used as the
|
|
fingerprint and the low 64 bits are the keyid.
|
|
|
|
* Revocation certificates consists only of the signature packet;
|
|
"import" knows how to handle this. The rationale behind it is
|
|
to keep them small.
|
|
|
|
|
|
|
|
|
|
Layout of the TrustDB
|
|
=====================
|
|
FIXME: use a directory record as top node instead of the pubkey record
|
|
|
|
The TrustDB is build from fixed length records, where the first bytes
|
|
describes the record type. All numeric values are stored in network
|
|
byte order. The length of each record is 40 bytes. The first record of
|
|
the DB is always of type 1 and this is the only record of this type.
|
|
|
|
Record type 0:
|
|
--------------
|
|
Unused record, can be reused for any purpose.
|
|
|
|
Record type 1:
|
|
--------------
|
|
Version information for this TrustDB. This is always the first
|
|
record of the DB and the onyl one with type 1.
|
|
1 byte value 1
|
|
3 bytes 'gpg' magic value
|
|
1 byte Version of the TrustDB
|
|
3 byte reserved
|
|
1 u32 locked by (pid) 0 = not locked.
|
|
1 u32 timestamp of trustdb creation
|
|
1 u32 timestamp of last modification
|
|
1 u32 timestamp of last validation
|
|
(Used to keep track of the time, when this TrustDB was checked
|
|
against the pubring)
|
|
1 u32 reserved
|
|
1 byte marginals needed
|
|
1 byte completes needed
|
|
1 byte max. cert depth
|
|
If any of this 3 values are changed, all cache records
|
|
muts be invalidated.
|
|
9 bytes reserved
|
|
|
|
|
|
Record type 2: (directory record)
|
|
--------------
|
|
Informations about a public key certificate.
|
|
These are static values which are never changed without user interaction.
|
|
|
|
1 byte value 2
|
|
1 byte reserved
|
|
8 bytes keyid (We keep it here to speed up searching by keyid)
|
|
1 u32 Local-Id. This is simply the record number of this record.
|
|
1 u32 pubkey (record number of it)
|
|
1 u32 cache record
|
|
1 u32 sigrecord
|
|
1 byte No signatures flag (used to avoid duplicate building).
|
|
13 byte reserved
|
|
|
|
|
|
Record type 3:
|
|
--------------
|
|
Informations about a public key certificate.
|
|
These are static values which are never changed without user interaction.
|
|
|
|
1 byte value 3
|
|
1 byte reserved
|
|
1 u32 owner This is used to bind all records for
|
|
a given certificate together. It is valid only in this TrustDB
|
|
and usefull if we have duplicate keyids
|
|
It points back to the directory node.
|
|
1 byte pubkey algorithm
|
|
1 byte reserved
|
|
20 bytes fingerprint of the public key
|
|
1 byte ownertrust:
|
|
3 byte reserved
|
|
|
|
|
|
Record type 4: (cache record)
|
|
--------------
|
|
Used to bind the trustDB to the concrete instance of keyblock in
|
|
a pubring. This is used to cache informations.
|
|
|
|
1 byte value 4
|
|
1 byte reserved
|
|
1 u32 Local-Id.
|
|
8 bytes keyid of the primary key (needed?)
|
|
1 byte cache-is-valid the following stuff is only
|
|
valid if this is set.
|
|
1 byte reserved
|
|
20 bytes rmd160 hash value over the complete keyblock
|
|
This is used to detect any changes of the keyblock with all
|
|
CTBs and lengths headers. Calculation is easy if the keyblock
|
|
is optained from a keyserved: simply create the hash from all
|
|
received data bytes.
|
|
|
|
1 byte number of untrusted signatures.
|
|
1 byte number of marginal trusted signatures.
|
|
1 byte number of fully trusted signatures.
|
|
(255 is stored for all values greater than 254)
|
|
1 byte Trustlevel
|
|
0 = undefined (not calculated)
|
|
1 = unknown
|
|
2 = not trusted
|
|
3 = marginally trusted
|
|
4 = fully trusted
|
|
5 = ultimately trusted (have secret key too).
|
|
|
|
Record type 5 (sigrec)
|
|
-------------
|
|
Used to keep track of valid key signatures. Self-signatures are not
|
|
stored.
|
|
|
|
1 byte value 5
|
|
1 byte reserved
|
|
1 u32 For Local-Id (points back to the directory record)
|
|
1 u32 chain: next sigrec of this owner or 0 to indicate the
|
|
last sigrec.
|
|
6 times
|
|
1 u32 Local_id of signators pubkey record
|
|
1 byte reserved
|
|
|
|
|
|
Record Type 6 (hash table)
|
|
-------------
|
|
Due to the fact that we use the keyid to lookup keys, we can
|
|
implement quick access by some simple hash methods, and avoid
|
|
the overhead gdbm. A property of keyids is that they can be
|
|
used directly as hash value (They can be considered as strong
|
|
random numbers.
|
|
What we use is a dynamic multilevel architecture, which combines
|
|
Hashtables, record lists, and linked list.
|
|
|
|
This record is a hashtable of 256 entries; a special property
|
|
is, that all these records are adjacent stored to make up one
|
|
big table. The hash value is simple the 1st, 2nd, ... byte of
|
|
the keyid (depending on the indirection level).
|
|
|
|
1 byte value 5
|
|
1 byte reserved
|
|
n u32 recnum; n depends on th record length:
|
|
n = (reclen-2)/4 which yields 9 for the current record length
|
|
of 40 bytes.
|
|
|
|
the total number of surch record which makes up the table is:
|
|
m = (256+n-1) / n
|
|
which is 29 for a record length of 40.
|
|
|
|
To look up a key we use its lsb to get the recnum from this
|
|
hashtable and look up this addressed record:
|
|
- If this record is another hashtable, we use 2nd lsb
|
|
to index this hast table and so on.
|
|
- if this record is of hashlist, we lwalk thru these
|
|
reclist record until we found one whos hash fields
|
|
matches the MSB of our keyid, and lookup this record
|
|
- if this record is a dir record, we compare the
|
|
keyid and if this is correct, we get the keyrecod and compare
|
|
the fingerprint to decide wether it is the requested key;
|
|
if this is not the correct dir record, we look at the next
|
|
dir record which is linked by the link field.
|
|
|
|
Record type 7 (hash list)
|
|
-------------
|
|
see hash table for an explanation.
|
|
|
|
1 byte value 6
|
|
1 byte reserved
|
|
1 u32 chain next hash list record
|
|
n times n = (reclen-6)/5
|
|
1 byte hash
|
|
1 u32 recnum
|
|
|
|
For the current record length of 40, n is 6
|
|
|
|
|
|
|
|
|
|
Packet Headers
|
|
===============
|
|
|
|
GNUPG uses PGP 2 packet headers and also understand OpenPGP packet header.
|
|
There is one enhavement used ith the old style packet headers:
|
|
|
|
CTB bits 10, the "packet-length length bits", have values listed in
|
|
the following table:
|
|
|
|
00 - 1-byte packet-length field
|
|
01 - 2-byte packet-length field
|
|
10 - 4-byte packet-length field
|
|
11 - no packet length supplied, unknown packet length
|
|
|
|
As indicated in this table, depending on the packet-length length
|
|
bits, the remaining 1, 2, 4, or 0 bytes of the packet structure field
|
|
are a "packet-length field". The packet-length field is a whole
|
|
number field. The value of the packet-length field is defined to be
|
|
the value of the whole number field.
|
|
|
|
A value of 11 is currently used in one place: on compressed data.
|
|
That is, a compressed data block currently looks like <A3 01 . . .>,
|
|
where <A3>, binary 10 1000 11, is an indefinite-length packet. The
|
|
proper interpretation is "until the end of the enclosing structure",
|
|
although it should never appear outermost (where the enclosing
|
|
structure is a file).
|
|
|
|
+ This will be changed with another version, where the new meaning of
|
|
+ the value 11 (see below) will also take place.
|
|
+
|
|
+ A value of 11 for other packets enables a special length encoding,
|
|
+ which is used in case, where the length of the following packet can
|
|
+ not be determined prior to writing the packet; especially this will
|
|
+ be used if large amounts of data are processed in filter mode.
|
|
+
|
|
+ It works like this: After the CTB (with a length field of 11) a
|
|
+ marker field is used, which gives the length of the following datablock.
|
|
+ This is a simple 2 byte field (MSB first) containig the amount of data
|
|
+ following this field, not including this length field. After this datablock
|
|
+ another length field follows, which gives the size of the next datablock.
|
|
+ A value of 0 indicates the end of the packet. The maximum size of a
|
|
+ data block is limited to 65534, thereby reserving a value of 0xffff for
|
|
+ future extensions. These length markers must be insereted into the data
|
|
+ stream just before writing the data out.
|
|
+
|
|
+ This 2 byte filed is large enough, because the application must buffer
|
|
+ this amount of data to prepend the length marker before writing it out.
|
|
+ Data block sizes larger than about 32k doesn't make any sense. Note
|
|
+ that this may also be used for compressed data streams, but we must use
|
|
+ another packet version to tell the application that it can not assume,
|
|
+ that this is the last packet.
|
|
|