Author Topic: replacements of gpg.trid.xml pkr.trid.xml for PGP/GPG Public Keyring  (Read 3581 times)

jenderek

  • Sr. Member
  • ****
  • Posts: 361
Hello,

some days ago i checked on my systems PGP/GPG public key rings and
some non keys starting with byte 0x99.

When i run trid on inspected examples these all are described at least
as "GNU Privacy Guard public keyring" (see appended output/trid-old.txt).

A patched file(1) command with debugging lines identifies public keys
correctly as something like "PGP/GPG key public ring" and non key
examples like Basic.Image, Beauty.320, Pic.Icons as "data" ( see
output/file-debug.txt).

What is wrong here? By gpg.trid.xml files are identified as "GNU Privacy
Guard public keyring" by XML construct:
   <Bytes>99</Bytes>
   <Pos>0</Pos>

Here only first byte is used. That means by that weak pattern every
file starting with byte 0x99 like Pic.Icons is described as public
key. So this definition file is too general. So i look for more
characteristic bytes by looking at documentations. According to RFC
4880 found for example at http://tools.ietf.org/html/rfc4880 this byte
value must be interpreted as packet type by converting hex value in
binary and then interpreting 3 bit groups like:
99h
10;0110;01
2=old packet type;6=Public-Key Packet;1=two-octet length

That means at offset 1 key packet body length is stored as 2 byte
value in big endian notation.

With that knowledge we now know what is described by pkr.trid.xml with
pattern:
   <Bytes>9901</Bytes>
   <Pos>0</Pos>

That identifies PGP or GPG public keys with a packet body length of 01??h.
or in other words packet body length is in range from 256=100h til 511=1FFh.

Theoretically now i can create definition files starting with pattern
   <Bytes>9900</Bytes>
   <Pos>0</Pos>

save it as gpg-0x0.trid.xml for "PGP/GPG public key rings with body
length 0x00??" and then increment upper byte of body length by 1 and
repeat procedure until i caught all observed body lengths.

So first i look at body length conditions. The packet body consist of
some bytes storing information like version, used algorithms, time
stamps, etc. But most space in packet body is occupied by
Multi-precision Integers (MPI). The MPI depends on key bit length and
used algorithms.

So for "old" keys (that are Pretty Good Privacy also called PGP) with
typical bit sizes (384, 768, 1024 ) we get a packet body length of
0x00??. For "new" GPG keys with typical bit sizes (1024, 2048) we get
packet body lengths like 0x01?? 0x02??.

So there exist a kind of correlation between body length and packet
type. So low body length is probably PGP and high values targets to
GPG public key, but this correlation is not clear defined.
So for testing purpose i also create "exotic" public key rings with
very high/low key bit sizes.

So for body length 0x01?? i can get 3 different public key types.
PUBRING263_10.PGP with 2048 bits and length 0x010d,
PUBRING50DSS3210.PKR with 1024 bits and length 0x01a2. Third type is
test12-.gpg with 2048 bits and length 0x010d.

So the body length can not be used in a general way to distinguish
public keys. According to documentation a two-octet body header
encodes packet lengths in range from 192~00C0h to 8383~20BFh.

So i look for other characteristic bytes. At the beginning of packet
body a one-octet version number is stored. In the documentation it is
not exactly expressed what values can occur here. But in document i
see 3 sentences givings hints:

* PGP 2.0 through 2.5 generated V2 Public-Key packets.
* Version 3 were first generated by PGP 2.6.
* Version 4 first appeared in PGP 5.0 and
  are the preferred version for OpenPGP.

So i found in inspected examples these three values V= 2, 3, 4.

Because i am no PGP expert i do not know if there exist first public
keys with version value 0 or 1. But bad examples starting with byte
value 0x99 like Basic.Image (V=153) Beauty.320 (V=136) Pic.Icons
(V=153) are skipped by looking for valid versions values.

Most of the informations can be easily verified
(see output/gpg--list-packets.txt) by running a command like:
   gpg -v --debug 0x02 --list-packets < PUBRING263_10.PGP

So examples PUBRING21-2.PGP PUBRING21.PGP (2.1) with version 2 are
described by pgp-v2.trid.xml with additional XML construct:
   <Bytes>02</Bytes>
   <Pos>3</Pos>

All these examples are created with Pretty Good Privacy ( abbreviated
as PGP). That is used as file name extension which is shown by line:
   <Ext>PGP</Ext>
Added also for mime type according to IANA by line:
   <Mime>application/pgp-keys</Mime>

Examples PUBRING263.PGP PUBRING263_10.PGP PUBRING.PGP( 2.6.3) with
version value 3 are described by pgp-v3.trid.xml with additional XML
construct:
   <Bytes>03</Bytes>
   <Pos>3</Pos>

Most examples were created with PGP, but i found one example
pubring-j.gpg with other file name extension. Maybe it is was done by
migration steps from PGP to GPG. So mention 2 file name extensions by:
   <Ext>GPG/PGP</Ext>

Remaining examples like PUBRING50DSS3210.PKR package-keyring.gpg
(found in etc sub directory of some emacs editor packages) are created
with PGP above/equal 5.0 or GPG. So you can not distinguish between
PGP or GPG. So i choose as file type text phrases "Pretty Good
Privacy/GNU Privacy Guard (GPG) Public Keyring (v4)".

PGP seems to use now "pkr" filename extension as abbreviation for
public key ring instead "pgp". That is expressed by:
   <Ext>GPG/PKR</Ext>

The version value 4 is described in pkr-v4.trid.xml by XML construct
with additional XML construct:
   <Bytes>04</Bytes>
   <Pos>3</Pos>

So i only use 2 bytes for identifications which is maybe still not
unique enough. So maybe somebody in the future may create sub branch
definitions like pkr-UsedAlgo-v4.trid.xml. In packet body the used
Public-Key algorithms is stored as byte value. According to section
9.1 of RFC there exist only about a dozen of algorithms. Most of them
are exotic types. So in real world examples i see value 1 ( that is
RSA Encrypt or Sign) and also 17 (that is Digital Signature Algorithm
abbreviated as DSA ) in version 4. This value is stored at offset 8 in
version 4 and 10 for other versions. So mentions these facts in remark
line.

Afterwards comes a series of multi precision integers comprising the
key material. According to section 3.2 about "Multiprecision Integers"
in documentation an MPI consists of two pieces: a two-octet scalar
that is the length of the MPI in bits followed by a string of octets
that contain the actual integer. In most cases the size of first MPI
pkey[0] is identical with public key size. So mention this fact also
in remark line. For version 4 used key bit size is a multiple of 256
for all standard key sizes ( 1024~400h, 2048~800h, 3072~C00h,
4096~1000h ). That means low byte of 1st MPI size is null. This is
expressed by XML construct:
   <Bytes>00</Bytes>
   <Pos>10</Pos>

With this additional test artificial bad examples like 9901-v4.bin are
skipped.

With new 3 trid definition files all inspected public key are now
recognized and non key examples are not misidentified (see appended
output/trid-new.txt). TrID definition, some examples and output are
stored in archive pgp_99.zip. I hope that the XML files can be used in
future version of triddefs.

With best wishes
J?rg Jenderek

Mark0

  • Administrator
  • Hero Member
  • *****
  • Posts: 2667
    • Mark0's Home Page
Re: replacements of gpg.trid.xml pkr.trid.xml for PGP/GPG Public Keyring
« Reply #1 on: March 03, 2018, 10:07:04 PM »
Many thanks as usual!