1*43a5ec4eSXin LI 2*43a5ec4eSXin LI#------------------------------------------------------------------------------ 3*43a5ec4eSXin LI# $File: pgp-binary-keys,v 1.2 2021/04/26 15:56:00 christos Exp $ 4*43a5ec4eSXin LI# pgp-binary-keys: This file handles pgp binary keys. 5*43a5ec4eSXin LI# 6*43a5ec4eSXin LI# An PGP certificate or message doesn't have a fixed header. Instead, 7*43a5ec4eSXin LI# they are sequences of packets: 8*43a5ec4eSXin LI# 9*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc4880#section-4.3 10*43a5ec4eSXin LI# 11*43a5ec4eSXin LI# whose order conforms to a grammar: 12*43a5ec4eSXin LI# 13*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc4880#section-11 14*43a5ec4eSXin LI# 15*43a5ec4eSXin LI# Happily most packets have a few fields that are constrained, which 16*43a5ec4eSXin LI# allow us to fingerprint them with relatively high certainty. 17*43a5ec4eSXin LI# 18*43a5ec4eSXin LI# A PGP packet is described by a single byte: the so-called CTB. The 19*43a5ec4eSXin LI# high-bit is always set. If bit 6 is set, then it is a so-called 20*43a5ec4eSXin LI# new-style CTB; if bit 6 is clear, then it is a so-called old-style 21*43a5ec4eSXin LI# CTB. Old-style CTBs have only four bits of type information; bits 22*43a5ec4eSXin LI# 1-0 are used to describe the length. New-style CTBs have 6 bits of 23*43a5ec4eSXin LI# type information. 24*43a5ec4eSXin LI# 25*43a5ec4eSXin LI# Following the CTB is the packet's length in bytes. If we blindly 26*43a5ec4eSXin LI# advance the file cursor by this amount past the end of the length 27*43a5ec4eSXin LI# information we come to the next packet. 28*43a5ec4eSXin LI# 29*43a5ec4eSXin LI# Data Structures 30*43a5ec4eSXin LI# =============== 31*43a5ec4eSXin LI# 32*43a5ec4eSXin LI# New Style CTB 33*43a5ec4eSXin LI# ------------- 34*43a5ec4eSXin LI# 35*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc4880#section-4.2.2 36*43a5ec4eSXin LI# 37*43a5ec4eSXin LI# 76543210 38*43a5ec4eSXin LI# ||\----/ 39*43a5ec4eSXin LI# || tag 40*43a5ec4eSXin LI# |always 1 41*43a5ec4eSXin LI# always 1 42*43a5ec4eSXin LI# 43*43a5ec4eSXin LI# Tag bits 7 and 6 set 44*43a5ec4eSXin LI# 0 0xC0 -- Reserved - a packet tag MUST NOT have this value 45*43a5ec4eSXin LI# 1 0xC1 -- Public-Key Encrypted Session Key Packet 46*43a5ec4eSXin LI# 2 0xC2 -- Signature Packet 47*43a5ec4eSXin LI# 3 0xC3 -- Symmetric-Key Encrypted Session Key Packet 48*43a5ec4eSXin LI# 4 0xC4 -- One-Pass Signature Packet 49*43a5ec4eSXin LI# 5 0xC5 -- Secret-Key Packet 50*43a5ec4eSXin LI# 6 0xC6 -- Public-Key Packet 51*43a5ec4eSXin LI# 7 0xC7 -- Secret-Subkey Packet 52*43a5ec4eSXin LI# 8 0xC8 -- Compressed Data Packet 53*43a5ec4eSXin LI# 9 0xC9 -- Symmetrically Encrypted Data Packet 54*43a5ec4eSXin LI# 10 0xCA -- Marker Packet 55*43a5ec4eSXin LI# 11 0xCB -- Literal Data Packet 56*43a5ec4eSXin LI# 12 0xCC -- Trust Packet 57*43a5ec4eSXin LI# 13 0xCD -- User ID Packet 58*43a5ec4eSXin LI# 14 0xCE -- Public-Subkey Packet 59*43a5ec4eSXin LI# 17 0xD1 -- User Attribute Packet 60*43a5ec4eSXin LI# 18 0xD2 -- Sym. Encrypted and Integrity Protected Data Packet 61*43a5ec4eSXin LI# 19 0xD3 -- Modification Detection Code Packet 62*43a5ec4eSXin LI# 60 to 63 -- Private or Experimental Values 63*43a5ec4eSXin LI# 64*43a5ec4eSXin LI# The CTB is followed by the length header, which is densely encoded: 65*43a5ec4eSXin LI# 66*43a5ec4eSXin LI# if length[0] is: 67*43a5ec4eSXin LI# 0..191: one byte length (length[0]) 68*43a5ec4eSXin LI# 192..223: two byte length ((length[0] - 192) * 256 + length[2] + 192 69*43a5ec4eSXin LI# 224..254: four byte length (big endian interpretation of length[1..5]) 70*43a5ec4eSXin LI# 255: partial body encoding 71*43a5ec4eSXin LI# 72*43a5ec4eSXin LI# The partial body encoding is similar to HTTP's chunk encoding. It 73*43a5ec4eSXin LI# is only allowed for container packets (SEIP, Compressed Data and 74*43a5ec4eSXin LI# Literal). 75*43a5ec4eSXin LI# 76*43a5ec4eSXin LI# Old Style CTB 77*43a5ec4eSXin LI# ------------- 78*43a5ec4eSXin LI# 79*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc4880#section-4.2.1 80*43a5ec4eSXin LI# 81*43a5ec4eSXin LI# CTB: 82*43a5ec4eSXin LI# 83*43a5ec4eSXin LI# 76543210 84*43a5ec4eSXin LI# ||\--/\/ 85*43a5ec4eSXin LI# || | length encoding 86*43a5ec4eSXin LI# || tag 87*43a5ec4eSXin LI# |always 0 88*43a5ec4eSXin LI# always 1 89*43a5ec4eSXin LI# 90*43a5ec4eSXin LI# Tag: 91*43a5ec4eSXin LI# 92*43a5ec4eSXin LI# Tag bit 7 set, bits 6, 1, 0 clear 93*43a5ec4eSXin LI# 0 0x80 -- Reserved - a packet tag MUST NOT have this value 94*43a5ec4eSXin LI# 1 0x84 -- Public-Key Encrypted Session Key Packet 95*43a5ec4eSXin LI# 2 0x88 -- Signature Packet 96*43a5ec4eSXin LI# 3 0x8C -- Symmetric-Key Encrypted Session Key Packet 97*43a5ec4eSXin LI# 4 0x90 -- One-Pass Signature Packet 98*43a5ec4eSXin LI# 5 0x94 -- Secret-Key Packet 99*43a5ec4eSXin LI# 6 0x98 -- Public-Key Packet 100*43a5ec4eSXin LI# 7 0x9C -- Secret-Subkey Packet 101*43a5ec4eSXin LI# 8 0xA0 -- Compressed Data Packet 102*43a5ec4eSXin LI# 9 0xA4 -- Symmetrically Encrypted Data Packet 103*43a5ec4eSXin LI# 10 0xA8 -- Marker Packet 104*43a5ec4eSXin LI# 11 0xAC -- Literal Data Packet 105*43a5ec4eSXin LI# 12 0xB0 -- Trust Packet 106*43a5ec4eSXin LI# 13 0xB4 -- User ID Packet 107*43a5ec4eSXin LI# 14 0xB8 -- Public-Subkey Packet 108*43a5ec4eSXin LI# 109*43a5ec4eSXin LI# Length encoding: 110*43a5ec4eSXin LI# 111*43a5ec4eSXin LI# Value 112*43a5ec4eSXin LI# 0 1 byte length (following byte is the length) 113*43a5ec4eSXin LI# 1 2 byte length (following two bytes are the length) 114*43a5ec4eSXin LI# 2 4 byte length (following four bytes are the length) 115*43a5ec4eSXin LI# 3 indeterminate length: natural end of packet, e.g., EOF 116*43a5ec4eSXin LI# 117*43a5ec4eSXin LI# An indeterminate length is only allowed for container packets 118*43a5ec4eSXin LI# (SEIP, Compressed Data and Literal). 119*43a5ec4eSXin LI# 120*43a5ec4eSXin LI# Certificates 121*43a5ec4eSXin LI# ------------ 122*43a5ec4eSXin LI# 123*43a5ec4eSXin LI# We check the first three packets to determine if a sequence of 124*43a5ec4eSXin LI# OpenPGP packets is likely to be a certificate. The grammar allows 125*43a5ec4eSXin LI# the following prefixes: 126*43a5ec4eSXin LI# 127*43a5ec4eSXin LI# [Primary Key] [SIG] (EOF or another certificate) 128*43a5ec4eSXin LI# [Primary Key] [SIG] [User ID] [SIG]... 129*43a5ec4eSXin LI# [Primary Key] [SIG] [User Attribute] [SIG]... 130*43a5ec4eSXin LI# [Primary Key] [SIG] [Subkey] [SIG]... 131*43a5ec4eSXin LI# [Primary Key] [User ID] [SIG]... 132*43a5ec4eSXin LI# [Primary Key] [User Attribute] [SIG]... 133*43a5ec4eSXin LI# [Primary Key] [Subkey] [SIG]... 134*43a5ec4eSXin LI# 135*43a5ec4eSXin LI# Any number of marker packets are also allowed between each packet, 136*43a5ec4eSXin LI# but they are not normally used and we don't currently check for 137*43a5ec4eSXin LI# them. 138*43a5ec4eSXin LI# 139*43a5ec4eSXin LI# The keys and subkeys may be public or private. 140*43a5ec4eSXin LI# 141*43a5ec4eSXin LI 142*43a5ec4eSXin LI# Key packets and signature packets are versioned. There are two 143*43a5ec4eSXin LI# packet versions that we need to worry about in practice: v3 and v4. 144*43a5ec4eSXin LI# v4 packets were introduced in RFC 2440, which was published in 1998. 145*43a5ec4eSXin LI# It also deprecated v3 packets. There are no actively used v3 146*43a5ec4eSXin LI# certificates (GnuPG removed the code to support them in November 147*43a5ec4eSXin LI# 2014). But there are v3 keys lying around and it is useful to 148*43a5ec4eSXin LI# identify them. The next version of OpenPGP will introduce v5 keys. 149*43a5ec4eSXin LI# The document has not yet been standardized so changes are still 150*43a5ec4eSXin LI# possible. But, for our purposes, it appears that v5 data structures 151*43a5ec4eSXin LI# will be identical to v4 data structures modulo the version number. 152*43a5ec4eSXin LI# 153*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc2440 154*43a5ec4eSXin LI# https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000358.html 155*43a5ec4eSXin LI# https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-key-material-packet 156*43a5ec4eSXin LI 157*43a5ec4eSXin LI 158*43a5ec4eSXin LI 159*43a5ec4eSXin LI 160*43a5ec4eSXin LI# The first packet has to be a public key or a secret key. 161*43a5ec4eSXin LI# 162*43a5ec4eSXin LI# New-Style Public Key 163*43a5ec4eSXin LI0 ubyte =0xC6 OpenPGP Public Key 164*43a5ec4eSXin LI>&0 use primary_key_length_new 165*43a5ec4eSXin LI# New-Style Secret Key 166*43a5ec4eSXin LI0 ubyte =0xC5 OpenPGP Secret Key 167*43a5ec4eSXin LI>&0 use primary_key_length_new 168*43a5ec4eSXin LI# Old-Style Public Key 169*43a5ec4eSXin LI0 ubyte&0xFC =0x98 OpenPGP Public Key 170*43a5ec4eSXin LI>&-1 use primary_key_length_old 171*43a5ec4eSXin LI# Old-Style Secret Key 172*43a5ec4eSXin LI0 ubyte&0xFC =0x94 OpenPGP Secret Key 173*43a5ec4eSXin LI>&-1 use primary_key_length_old 174*43a5ec4eSXin LI 175*43a5ec4eSXin LI# Parse the length, check the packet's body and finally advance to the 176*43a5ec4eSXin LI# next packet. 177*43a5ec4eSXin LI 178*43a5ec4eSXin LI# There are 4 different new-style length encodings, but the partial 179*43a5ec4eSXin LI# body encoding is only acceptable for the SEIP, Compressed Data, and 180*43a5ec4eSXin LI# Literal packets, which isn't valid for any packets in a certificate 181*43a5ec4eSXin LI# so we ignore it. 182*43a5ec4eSXin LI0 name primary_key_length_new 183*43a5ec4eSXin LI>&0 ubyte <192 184*43a5ec4eSXin LI#>>&0 ubyte x (1 byte length encoding, %d bytes) 185*43a5ec4eSXin LI>>&0 use pgp_binary_key_pk_check 186*43a5ec4eSXin LI>>>&(&-1.B) use sig_or_component_1 187*43a5ec4eSXin LI>&0 ubyte >191 188*43a5ec4eSXin LI>>&-1 ubyte <225 189*43a5ec4eSXin LI# offset = ((offset[0] - 192) << 8) + offset[1] + 192 (for the length header) 190*43a5ec4eSXin LI# raw - (192 * 256 - 192) 191*43a5ec4eSXin LI# = 48960 192*43a5ec4eSXin LI#>>>&0 ubeshort x (2 byte length encoding, %d bytes) 193*43a5ec4eSXin LI>>>&1 use pgp_binary_key_pk_check 194*43a5ec4eSXin LI>>>>&(&-2.S-48960) use sig_or_component_1 195*43a5ec4eSXin LI>&0 ubyte =255 196*43a5ec4eSXin LI#>>&0 belong x (5 byte length encoding, %d bytes) 197*43a5ec4eSXin LI>>&4 use pgp_binary_key_pk_check 198*43a5ec4eSXin LI>>>&(&-4.L) use sig_or_component_1 199*43a5ec4eSXin LI# Partial body encoding (only valid for container packets). 200*43a5ec4eSXin LI# >&0 ubyte >224 201*43a5ec4eSXin LI# >>&0 ubyte <255 partial body encoding 202*43a5ec4eSXin LI 203*43a5ec4eSXin LI# There are 4 different old-style length encodings, but the 204*43a5ec4eSXin LI# indeterminate length encoding is only acceptable for the SEIP, 205*43a5ec4eSXin LI# Compressed Data, and Literal packets, which isn't valid for any 206*43a5ec4eSXin LI# packets in a certificate. 207*43a5ec4eSXin LI0 name primary_key_length_old 208*43a5ec4eSXin LI#>&0 ubyte x (ctb: %x) 209*43a5ec4eSXin LI>&0 ubyte&0x3 =0 210*43a5ec4eSXin LI#>>&0 ubyte x (1 byte length encoding, %d bytes) 211*43a5ec4eSXin LI>>&1 use pgp_binary_key_pk_check 212*43a5ec4eSXin LI>>>&(&-1.B) use sig_or_component_1 213*43a5ec4eSXin LI>&0 ubyte&0x3 =1 214*43a5ec4eSXin LI#>>&0 ubeshort x (2 byte length encoding, %d bytes) 215*43a5ec4eSXin LI>>&2 use pgp_binary_key_pk_check 216*43a5ec4eSXin LI>>>&(&-2.S) use sig_or_component_1 217*43a5ec4eSXin LI>&0 ubyte&0x3 =2 218*43a5ec4eSXin LI#>>&0 ubelong x (4 byte length encoding, %d bytes) 219*43a5ec4eSXin LI>>&4 use pgp_binary_key_pk_check 220*43a5ec4eSXin LI>>>&(&-4.L) use sig_or_component_1 221*43a5ec4eSXin LI 222*43a5ec4eSXin LI# Check the Key. 223*43a5ec4eSXin LI# 224*43a5ec4eSXin LI# https://tools.ietf.org/html/rfc4880#section-5.5.2 225*43a5ec4eSXin LI0 name pgp_binary_key_pk_check 226*43a5ec4eSXin LI# Valid versions are: 2, 3, 4. 5 is proposed in RFC 4880bis. 227*43a5ec4eSXin LI# Anticipate a v6 / v7 format that like v5 is compatible with v4. 228*43a5ec4eSXin LI# key format in a decade or so :D. 229*43a5ec4eSXin LI>&0 ubyte >1 230*43a5ec4eSXin LI>>&-1 ubyte <8 231*43a5ec4eSXin LI>>>&-1 byte x Version %d 232*43a5ec4eSXin LI# Check that keys were created after 1990. 233*43a5ec4eSXin LI# (1990 - 1970) * 365.2524 * 24 * 60 * 60 = 631156147 234*43a5ec4eSXin LI>>>&0 bedate >631156147 \b, Created %s 235*43a5ec4eSXin LI>>>>&-5 ubyte >3 236*43a5ec4eSXin LI>>>>>&4 use pgp_binary_key_algo 237*43a5ec4eSXin LI>>>>&-5 ubyte <4 238*43a5ec4eSXin LI>>>>>&6 use pgp_binary_key_algo 239*43a5ec4eSXin LI 240*43a5ec4eSXin LI# Print out the key's algorithm and the number of bits, if this is 241*43a5ec4eSXin LI# relevant (ECC keys are a fixed size). 242*43a5ec4eSXin LI0 name pgp_binary_key_algo 243*43a5ec4eSXin LI>0 clear x 244*43a5ec4eSXin LI>&0 ubyte =1 \b, RSA (Encrypt or Sign, 245*43a5ec4eSXin LI>>&0 ubeshort x \b %d bits) 246*43a5ec4eSXin LI>&0 ubyte =2 \b, RSA (Encrypt, 247*43a5ec4eSXin LI>>&0 ubeshort x \b %d bits) 248*43a5ec4eSXin LI>&0 ubyte =3 \b, RSA (Sign, 249*43a5ec4eSXin LI>>&0 ubeshort x \b %d bits) 250*43a5ec4eSXin LI>&0 ubyte =16 \b, El Gamal (Encrypt, 251*43a5ec4eSXin LI>>&0 ubeshort x \b %d bits) 252*43a5ec4eSXin LI>&0 ubyte =17 \b, DSA 253*43a5ec4eSXin LI>>&0 ubeshort x \b (%d bits) 254*43a5ec4eSXin LI>&0 ubyte =18 \b, ECDH 255*43a5ec4eSXin LI>&0 ubyte =19 \b, ECDSA 256*43a5ec4eSXin LI>&0 ubyte =20 \b, El Gamal (Encrypt or Sign, 257*43a5ec4eSXin LI>>&0 ubeshort x \b %d bits) 258*43a5ec4eSXin LI>&0 ubyte =22 \b, EdDSA 259*43a5ec4eSXin LI>&0 default x 260*43a5ec4eSXin LI>>&0 ubyte x \b, Unknown Algorithm (%#x) 261*43a5ec4eSXin LI 262*43a5ec4eSXin LI# Match all possible second packets. 263*43a5ec4eSXin LI0 name sig_or_component_1 264*43a5ec4eSXin LI#>0 ubyte x (ctb: %x) 265*43a5ec4eSXin LI>&0 ubyte =0xC2 266*43a5ec4eSXin LI>>0 ubyte x \b; Signature 267*43a5ec4eSXin LI>>&0 use sig_or_component_1_length_new 268*43a5ec4eSXin LI>&0 ubyte =0xCD 269*43a5ec4eSXin LI>>0 ubyte x \b; User ID 270*43a5ec4eSXin LI>>&0 use sig_or_component_1_length_new 271*43a5ec4eSXin LI>&0 ubyte =0xCE 272*43a5ec4eSXin LI>>0 ubyte x \b; Public Subkey 273*43a5ec4eSXin LI>>&0 use sig_or_component_1_length_new 274*43a5ec4eSXin LI>&0 ubyte =0xC7 275*43a5ec4eSXin LI>>0 ubyte x \b; Secret Subkey 276*43a5ec4eSXin LI>>&0 use sig_or_component_1_length_new 277*43a5ec4eSXin LI>&0 ubyte =0xD1 278*43a5ec4eSXin LI>>0 ubyte x \b; User Attribute 279*43a5ec4eSXin LI>>&0 use sig_or_component_1_length_new 280*43a5ec4eSXin LI>&0 ubyte&0xFC =0x88 281*43a5ec4eSXin LI>>0 ubyte x \b; Signature 282*43a5ec4eSXin LI>>&-1 use sig_or_component_1_length_old 283*43a5ec4eSXin LI>&0 ubyte&0xFC =0xB4 284*43a5ec4eSXin LI>>0 ubyte x \b; User ID 285*43a5ec4eSXin LI>>&-1 use sig_or_component_1_length_old 286*43a5ec4eSXin LI>&0 ubyte&0xFC =0xB8 287*43a5ec4eSXin LI>>0 ubyte x \b; Public Subkey 288*43a5ec4eSXin LI>>&-1 use sig_or_component_1_length_old 289*43a5ec4eSXin LI>&0 ubyte&0xFC =0x9C 290*43a5ec4eSXin LI>>0 ubyte x \b; Secret Subkey 291*43a5ec4eSXin LI>>&-1 use sig_or_component_1_length_old 292*43a5ec4eSXin LI 293*43a5ec4eSXin LI# Copy of 'primary_key_length_new', but calls cert_packet_3. 294*43a5ec4eSXin LI0 name sig_or_component_1_length_new 295*43a5ec4eSXin LI>&0 ubyte <192 296*43a5ec4eSXin LI#>>&0 ubyte x (1 byte new length encoding, %d bytes) 297*43a5ec4eSXin LI>>&(&-1.B) use cert_packet_3 298*43a5ec4eSXin LI>&0 ubyte >191 299*43a5ec4eSXin LI>>&-1 ubyte <225 300*43a5ec4eSXin LI# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header) 301*43a5ec4eSXin LI# raw - (192 * 256 - 192 - 1) 302*43a5ec4eSXin LI# = 48959 303*43a5ec4eSXin LI#>>>&-1 ubeshort x (2 byte new length encoding, %d bytes) 304*43a5ec4eSXin LI>>>&(&-1.S-48959) use cert_packet_3 305*43a5ec4eSXin LI>&0 ubyte =255 306*43a5ec4eSXin LI#>>&0 belong x (5 byte new length encoding, %d bytes) 307*43a5ec4eSXin LI>>&(&-4.L) use cert_packet_3 308*43a5ec4eSXin LI# Partial body encoding (only valid for container packets). 309*43a5ec4eSXin LI# >&0 ubyte >224 310*43a5ec4eSXin LI# >>&0 ubyte <255 partial body encoding 311*43a5ec4eSXin LI 312*43a5ec4eSXin LI0 name sig_or_component_1_length_old 313*43a5ec4eSXin LI#>&0 ubyte x (ctb: %x) 314*43a5ec4eSXin LI>&0 ubyte&0x3 =0 315*43a5ec4eSXin LI#>>&0 ubyte x (1 byte old length encoding, %d bytes) 316*43a5ec4eSXin LI>>&(&0.B+1) use cert_packet_3 317*43a5ec4eSXin LI>&0 ubyte&0x3 =1 318*43a5ec4eSXin LI#>>&0 ubeshort x (2 byte old length encoding, %d bytes) 319*43a5ec4eSXin LI>>&(&0.S+2) use cert_packet_3 320*43a5ec4eSXin LI>&0 ubyte&0x3 =2 321*43a5ec4eSXin LI#>>&0 ubelong x (4 byte old length encoding, %d bytes) 322*43a5ec4eSXin LI>>&(&0.L+4) use cert_packet_3 323*43a5ec4eSXin LI 324*43a5ec4eSXin LI# Copy of above. 325*43a5ec4eSXin LI0 name cert_packet_3 326*43a5ec4eSXin LI#>0 ubyte x (ctb: %x) 327*43a5ec4eSXin LI>&0 ubyte =0xC2 328*43a5ec4eSXin LI>>0 ubyte x \b; Signature 329*43a5ec4eSXin LI>>&0 use cert_packet_3_length_new 330*43a5ec4eSXin LI>&0 ubyte =0xCD 331*43a5ec4eSXin LI>>0 ubyte x \b; User ID 332*43a5ec4eSXin LI>>&0 use cert_packet_3_length_new 333*43a5ec4eSXin LI>&0 ubyte =0xCE 334*43a5ec4eSXin LI>>0 ubyte x \b; Public Subkey 335*43a5ec4eSXin LI>>&0 use cert_packet_3_length_new 336*43a5ec4eSXin LI>&0 ubyte =0xC7 337*43a5ec4eSXin LI>>0 ubyte x \b; Secret Subkey 338*43a5ec4eSXin LI>>&0 use cert_packet_3_length_new 339*43a5ec4eSXin LI>&0 ubyte =0xD1 340*43a5ec4eSXin LI>>0 ubyte x \b; User Attribute 341*43a5ec4eSXin LI>>&0 use cert_packet_3_length_new 342*43a5ec4eSXin LI>&0 ubyte&0xFC =0x88 343*43a5ec4eSXin LI>>0 ubyte x \b; Signature 344*43a5ec4eSXin LI>>&-1 use cert_packet_3_length_old 345*43a5ec4eSXin LI>&0 ubyte&0xFC =0xB4 346*43a5ec4eSXin LI>>0 ubyte x \b; User ID 347*43a5ec4eSXin LI>>&-1 use cert_packet_3_length_old 348*43a5ec4eSXin LI>&0 ubyte&0xFC =0xB8 349*43a5ec4eSXin LI>>0 ubyte x \b; Public Subkey 350*43a5ec4eSXin LI>>&-1 use cert_packet_3_length_old 351*43a5ec4eSXin LI>&0 ubyte&0xFC =0x9C 352*43a5ec4eSXin LI>>0 ubyte x \b; Secret Subkey 353*43a5ec4eSXin LI>>&-1 use cert_packet_3_length_old 354*43a5ec4eSXin LI 355*43a5ec4eSXin LI# Copy of above. 356*43a5ec4eSXin LI0 name cert_packet_3_length_new 357*43a5ec4eSXin LI>&0 ubyte <192 358*43a5ec4eSXin LI#>>&0 ubyte x (1 byte new length encoding, %d bytes) 359*43a5ec4eSXin LI>>&(&-1.B) use pgp_binary_keys_end 360*43a5ec4eSXin LI>&0 ubyte >191 361*43a5ec4eSXin LI>>&-1 ubyte <225 362*43a5ec4eSXin LI# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header) 363*43a5ec4eSXin LI# raw - (192 * 256 - 192 - 1) 364*43a5ec4eSXin LI# = 48959 365*43a5ec4eSXin LI#>>>&-1 ubeshort x (2 byte new length encoding, %d bytes) 366*43a5ec4eSXin LI>>>&(&-1.S-48959) use pgp_binary_keys_end 367*43a5ec4eSXin LI>&0 ubyte =255 368*43a5ec4eSXin LI#>>&0 belong x (5 byte new length encoding, %d bytes) 369*43a5ec4eSXin LI>>&(&-4.L) use pgp_binary_keys_end 370*43a5ec4eSXin LI 371*43a5ec4eSXin LI0 name cert_packet_3_length_old 372*43a5ec4eSXin LI#>&0 ubyte x (ctb: %x) 373*43a5ec4eSXin LI>&0 ubyte&0x3 =0 374*43a5ec4eSXin LI#>>&0 ubyte x (1 byte old length encoding, %d bytes) 375*43a5ec4eSXin LI>>&(&0.B+1) use pgp_binary_keys_end 376*43a5ec4eSXin LI>&0 ubyte&0x3 =1 377*43a5ec4eSXin LI#>>&0 ubeshort x (2 byte old length encoding, %d bytes) 378*43a5ec4eSXin LI>>&(&0.S+2) use pgp_binary_keys_end 379*43a5ec4eSXin LI>&0 ubyte&0x3 =2 380*43a5ec4eSXin LI#>>&0 ubelong x (4 byte old length encoding, %d bytes) 381*43a5ec4eSXin LI>>&(&0.L+4) use pgp_binary_keys_end 382*43a5ec4eSXin LI 383*43a5ec4eSXin LI# We managed to parse the first three packets of the certificate. Declare 384*43a5ec4eSXin LI# victory. 385*43a5ec4eSXin LI0 name pgp_binary_keys_end 386*43a5ec4eSXin LI>0 byte x \b; OpenPGP Certificate 387*43a5ec4eSXin LI!:mime application/pgp-keys 388*43a5ec4eSXin LI!:ext pgp/gpg/pkr/asd 389