Jonas' blog

IT security & forensics

RSSTwitterGithub

Structure of gpg keys

Creating a new nice pgp key I first needed to examine the exact structure of a pgp key.

I used the batch mode of gpg (gpg --status-fd 1 --no-tty --batch --gen-key) to create the key 0x4B9E3333 with the settings:

Key-Type: default
Subkey-Type: default
Name-Real: Cugu
Name-Email: cugu@cugu.eu
Expire-Date: 2020-05-04
Passphrase: password
%pubring foo.pub
%secring foo.sec
%commit

A nice feature here, is that the short name Cugu is allowed, while in command line mode at least five letters are mandatory.

The created public gpg key consists of five single packets.

Public Key Packet

The first packet contains the public key information as well as creation date. The created key is an RSA key so the public key is the e which is 0x10001 (=65537) in this case. The 2048 bit (256 byte) long n is the modulus for the RSA operation.

The owner of the secret key has the secret RSA exponent d. To sign a message the owner can calculate md mod n = c. Using this public key everyone can afterwards calculate ce mod n = m1 and validate that m1 = m.

99
=======
  01 0D       269 length
  04          Version 4
  53946f6e    Creation Date Timestamp
  01          RSA
  0800        2048
  bfde487046d4d5b5460a4682a21ea8b874675a67ffe5a3a9685d45f02a8ad420
  b08389f200c6e3cae3b113ef81150ef4bacd15f7c496ee5aca41b18d440d8449
  bb791131b3c25ee54c9b10394b4740d70402a9d9316f5ddb9aa741b512b81099
  837b46a7f04d11feaa5b69ed630e8c7a94f6c7754f62634ec1663b00aac3c957
  23798c69abb619be691e0c990d93e83da2c4d2269ebe1fdece5a517c83c0b567
  1e9c4da6010d3b74baada0289b64f24bd6398a6ae652d4b4745ab908955ff04d
  a3f87c5ee087bacef35f6f4507f9becdb16425e4d94ae633168ace98e0eb3110
  ebd9ce358bc07eb20f411b52cb4334cfdd46ee6d6da8f0f10f83e4ff329a4a41
              RSA n
  0011        Padding?
  010001      RSA e

User ID Packet

This second packet contains the data that should be bound to the public key from above.

b4
=======
  13          Length 19
  43756775203c6375677540637567752e65 Cugu <cugu@cugu.eu>
  753e

Signature Packet

This packet binds the User ID Packet to the public key. The content of all the subpackets can be gathered by using pgpdump or reading RFC4880.

The key flags sub packet indicates, that this key can just be used for signing and certification. openpgp shows sc in this case. A capital letter shows, that a sub key is capable of other functions (e.g. capital E -> sub key can be used for encryption)

The most interesting part here is sig(i). i is build by a combination of a lot of information:

  1. The complete Public Key Packet (e.g. 0x99010D…010001)
  2. The user ID Packet, where the length is encoded in 4 byte. (e.g. in our case: 0xb40000001343756775203c6375677540637567752e65753e)
  3. Data from this Signature Packet starting including version till the end of the hashed subpackets (e.g. 0x0413010a…021780)
  4. A trailer starting with 0x04FF and a 4 byte length of the data from the Signature Packet

All this information is concatenated and hashed. This hash is afterwards appended to a combination of 0x1f followed by many 0xff a single 0x00 and a specification of the used hash (e.g. i=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440 + hash)

The value 0x3051300d060960864801650304020305000440 for our hash is specified in RFC4880 5.2.2.

All this values (i=0x1f…) is signed: id mod n = sig(i)

89
=======
  013d        Length 317
  04          Version
  13          Positive certification of a User ID and Public-Key packet.
  01          RSA
  0a          SHA512

  00 27         Length hashed Subpackets 15

    05          Length 5
    02          Subpacket Type (2 = Signature Creation Time)
    53946f6e    Timestamp

    02          Length 2
    1b          Subpacket Type (27 = Key Flags)
    03

    05          Length 5
    09          Subpacket (Type 9 = Key Expiration Time)
    0b1b7832    Timestamp Offset (186349618 + Creation Time)

    05          Length 5
    0b          Subpacket (Type 11 = Preferred Symmetric Algorithms)
    09080703

    05          Length 5
    15          Subpacket (Type 21 = Preferred Hash Algorithms)
    0a09080b

    05          Length 5
    16          Subpacket (Type 22 = Preferred Compression Algorithms)
    02030100

    02          Length 2
    1e          Subpacket (Type 30 = Features)
    01          Modification Detection

    02          Length 2
    17          Subpacket (Type 23 = Key Server Preferences)
    80          0x80 = No-modify

  00 0a         Length unhased Subpackets 10

    09          Length 9
    10          Subpacket (Type 16 = Issuer)
    48c1 f448 4b9e 3333
                last 4 blocks of the fingerprint

  c678        last 2 byte of the hash over m

  0800        2048
  816a53faf1135895ad8890c165a32a1d1166e5df41fa43713f02fafdbc55f4f1
  848038f55f778550acb76ebab3d6323604342445f7224406edab06c93f46c246
  b109b4b18a1ccc71fda28e3f1059d866c2e389f9ab589e76be11e5ef737e1178
  f5675425d5f5c4246a04e76d5dc9dc6b93550f0766a57298ed463a9fc6e8bba8
  3287f3b5c33eebefbf358e32936e0a316be86d56ac96391e796b8eac7091e215
  6a7eae9082369775901c86fcb1ca6c74d8c345d9db6c299923a86d97287209f9
  9bedf83b599e561fff370877dd1a7c6fecd632b2d984e7b1c27fbfc80e3a59e2
  217b0708b161192e194c204506aed50b20485da514dc29df2128f8ac42fe2458
              sig(i)

Public Subkey Packet

This subkey can be used for encryption. Otherwise this and the following signature packet are built the same way as above.

b9
=======
  010d        269 length
  04          Version 4
  53946f6e    Timestamp
  01          RSA
  0800        2048
  aa19801ed96301caaef25633b87eedcecfb31a7363fd798264b1f9fa307728ed
  b50f086404930ecbf03f13d807e181ade29268589eba63c459b6e90388d40169
  29a63d6e06c4f87289aef3269cd5ba9d31bce6f364ea97513611a84e97a85f32
  6b77114e0c4ec3c5249f91fd48783713d0825ef99db56e846562189844454722
  67cd4e64d43fa2a305267c0482b968ec00e8cea00b6464ef6e4117095036779a
  4b713ec1ad04580b4fcebb66ed8afc3a0e6c315f6790a0c6f2277ae8a017fe9e
  67b036cc786d85718cc1d0670dc1c7d688369eb10934e1b3245a183ab70e3068
  80cb3f91c8fd389c5e7f46bfd1e3fb70def93900bfbe2cb59faaa1df311d253f
              512 bit
  0011        Padding?
  010001      RSA e

Signature Packet

89
=======
  0125        293 Length
  04          Version 4
  18          Subkey Binding Signature
  01          RSA
  0a          SHA512

  00 0f         Length hashed Subpackets 15

    05          Length 5
    02          Subpacket Type 2 = Signature Creation Time
    53946f6e    Timestamp

    02          Length 2
    1b          Subpacket Type 27 = Key Flags
    0c          1100

    05          Length 5
    09          Subpacket (Type 9 = Key Expiration Time)
    0b1b7832    Timestamp Offset (186349618 + Creation Time)

  00 0a         Length unhased Subpackets 10

    09          Length 9
    10          Subpacket (Type 16 = Issuer)
    48c1f4484b9e3333
                Last 4 Blocks FP

  c16e        diff

  0800        2048
  a9b0401874d80f839c407b50e5dcb5ee51e5aafc95933fee013631620a61e69d
  63be81e79f35b57cb4cf372ea7bdaa23e9593e18a747101229849cd59517bd75
  e8d2965ccf517420906fb649e6f885f927bcabd9f925b80a31d165b12776260f
  711ed37d10262d1c103b42fd0baead95529d6c2f10cae24d353dc1e9aa2336ce
  9457c4d484eed4416ec1a23a734ca41d146fc79229757a5b7a61f2ac5600cd4c
  f800aa118e77dbd32d20c774021dd70f2efb90f00218593e3b00fe97ecbdfc05
  633fee7c75bb27aa44d76d9c8c047e7bb1c1d07212c668639bbab1ed9c1288f9
  b914da5f600baaa22e911338205c58b2bc1d3282ff54e7801eb8889284686eb3