From ca6c57a3346fa64d0a5107d915af1884e7bddc22 Mon Sep 17 00:00:00 2001
From: "Neal H. Walfield" <neal@gnu.org>
Date: Tue, 1 Sep 2020 15:50:43 +0200
Subject: [PATCH] Improve detection of OpenPGP binary keys.

  - Handle new format keys (introduced in RFC 2440 in 1998).

  - Be more robust.

  - Don't print the prefix of the MPI, because it has nothing to do
    with the key's fingerprint and is only confusing.
---
 magic/Magdir/pgp                              |  48 +--
 magic/Magdir/pgp-binary-keys                  | 385 ++++++++++++++++++
 magic/Makefile.am                             |   1 +
 tests/Makefile.am                             |  18 +-
 tests/pgp-binary-key-v2-phil.result           |   1 +
 tests/pgp-binary-key-v2-phil.testfile         | Bin 0 -> 975 bytes
 tests/pgp-binary-key-v3-lutz.result           |   1 +
 tests/pgp-binary-key-v3-lutz.testfile         | Bin 0 -> 11722 bytes
 tests/pgp-binary-key-v4-dsa.result            |   1 +
 tests/pgp-binary-key-v4-dsa.testfile          | Bin 0 -> 1677 bytes
 ...-binary-key-v4-ecc-no-userid-secret.result |   1 +
 ...inary-key-v4-ecc-no-userid-secret.testfile | Bin 0 -> 794 bytes
 tests/pgp-binary-key-v4-ecc-rev.result        |   0
 tests/pgp-binary-key-v4-ecc-secret-key.result |   1 +
 .../pgp-binary-key-v4-ecc-secret-key.testfile | Bin 0 -> 494 bytes
 tests/pgp-binary-key-v4-rsa-key.result        |   1 +
 tests/pgp-binary-key-v4-rsa-key.testfile      | Bin 0 -> 3695 bytes
 ...pgp-binary-key-v4-rsa-no-userid-rev.result |   0
 ...-binary-key-v4-rsa-no-userid-secret.result |   1 +
 ...inary-key-v4-rsa-no-userid-secret.testfile | Bin 0 -> 5907 bytes
 tests/pgp-binary-key-v4-rsa-secret-key.result |   1 +
 .../pgp-binary-key-v4-rsa-secret-key.testfile | Bin 0 -> 3695 bytes
 22 files changed, 412 insertions(+), 48 deletions(-)
 create mode 100644 magic/Magdir/pgp-binary-keys
 create mode 100644 tests/pgp-binary-key-v2-phil.result
 create mode 100644 tests/pgp-binary-key-v2-phil.testfile
 create mode 100644 tests/pgp-binary-key-v3-lutz.result
 create mode 100644 tests/pgp-binary-key-v3-lutz.testfile
 create mode 100644 tests/pgp-binary-key-v4-dsa.result
 create mode 100644 tests/pgp-binary-key-v4-dsa.testfile
 create mode 100644 tests/pgp-binary-key-v4-ecc-no-userid-secret.result
 create mode 100644 tests/pgp-binary-key-v4-ecc-no-userid-secret.testfile
 create mode 100644 tests/pgp-binary-key-v4-ecc-rev.result
 create mode 100644 tests/pgp-binary-key-v4-ecc-secret-key.result
 create mode 100644 tests/pgp-binary-key-v4-ecc-secret-key.testfile
 create mode 100644 tests/pgp-binary-key-v4-rsa-key.result
 create mode 100644 tests/pgp-binary-key-v4-rsa-key.testfile
 create mode 100644 tests/pgp-binary-key-v4-rsa-no-userid-rev.result
 create mode 100644 tests/pgp-binary-key-v4-rsa-no-userid-secret.result
 create mode 100644 tests/pgp-binary-key-v4-rsa-no-userid-secret.testfile
 create mode 100644 tests/pgp-binary-key-v4-rsa-secret-key.result
 create mode 100644 tests/pgp-binary-key-v4-rsa-secret-key.testfile

diff --git a/magic/Magdir/pgp b/magic/Magdir/pgp
index 069c82eb..84aebd5a 100644
--- a/magic/Magdir/pgp
+++ b/magic/Magdir/pgp
@@ -1,54 +1,10 @@
+# Handling of binary PGP keys is in pgp-binary-keys.
 
 #------------------------------------------------------------------------------
 # $File: pgp,v 1.21 2020/03/20 17:11:05 christos Exp $
 # pgp:  file(1) magic for Pretty Good Privacy
 # see https://lists.gnupg.org/pipermail/gnupg-devel/1999-September/016052.html
 #
-# Update: Joerg Jenderek
-# Note: verified by `gpg -v --debug 0x02 --list-packets < PUBRING263_10.PGP`
-#0		byte	0x99		MAYBE PGP 0x99
-0		byte	0x99
-# 99h~10;0110;01~2=old packet type;tag 6=Public-Key Packet;1=two-octet length
-# A two-octet body header encodes packet lengths of 192~00C0h - 8383~20BFh
-#>1		ubeshort	x		\b, body length 0x%.4x
-# skip Basic.Image Beauty.320 Pic.Icons by looking for low version number
-#>3		ubyte		x		\b, V=%u
-#>3		ubyte		<5		VERSION OK
->3		ubyte		<5
-# next packet type often b4h~(tag 13)~User ID Packet, b0h~(tag 12)~Trust packet
-#>>(1.S+3)	ubyte	x		\b, next packet type 0x%x
-# skip 9900-v4.bin 9902-v4.bin by looking for valid second packet type (bit 7=1)
-#>>(1.S+3)	ubyte	>0x7F		TYPE OK,
->>(1.S+3)	ubyte	>0x7F
-# old versions 2,3 implies Pretty Good Privacy
->>>3		ubyte		<4		PGP key public ring (v%u)
-!:mime		application/pgp-keys
-!:ext		pgp/ASD
->>>>4		beldate		x		created %s
-# days that this key is valid. If this number is zero, then it does not expire
->>>>8		ubeshort	>0		\b, %u days valid
->>>>8		ubeshort	=0		\b, not expire
-# display key algorithm 1~RSA (Encrypt or Sign)
->>>>10		use		key_algo
-# Multiprecision Integers (MPI) size
->>>>11		ubeshort	x		%u bits
-# MPI
->>>>13		ubequad		x		MPI=0x%16.16llx...
-# new version implies Pretty Good Privacy (PGP) >= 5.0 or Gnu Privacy Guard (GPG)
->>>3		ubyte		>3		PGP/GPG key public ring (v%u)
-!:mime		application/pgp-keys
-!:ext		pgp/gpg/pkr/asd
->>>>4		beldate		x		created %s
-# display key algorithm 17~DSA
->>>>8		use		key_algo
-# Multiprecision Integers (MPI) size
->>>>9		ubeshort	x		%u bits
->>>>11		ubequad		x		MPI=0x%16.16llx...
-
-0       beshort         0x9501                  PGP key security ring
-!:mime	application/x-pgp-keyring
-0       beshort         0x9500                  PGP key security ring
-!:mime	application/x-pgp-keyring
 0	beshort		0xa600			PGP encrypted data
 #!:mime	application/pgp-encrypted
 #0	string		-----BEGIN\040PGP	text/PGP armored data
@@ -582,8 +538,6 @@
 
 # PGP RSA (e=65537) secret (sub-)key header
 
-0	byte	0x95			PGP Secret Key -
->1	use	pgpkey
 0	byte	0x97			PGP Secret Sub-key -
 >1	use	pgpkey
 0	byte	0x9d
diff --git a/magic/Magdir/pgp-binary-keys b/magic/Magdir/pgp-binary-keys
new file mode 100644
index 00000000..6735da6f
--- /dev/null
+++ b/magic/Magdir/pgp-binary-keys
@@ -0,0 +1,385 @@
+# This file handles pgp binary keys.
+#
+# An PGP certificate or message doesn't have a fixed header.  Instead,
+# they are sequences of packets:
+#
+#   https://tools.ietf.org/html/rfc4880#section-4.3
+#
+# whose order conforms to a grammar:
+#
+#   https://tools.ietf.org/html/rfc4880#section-11
+#
+# Happily most packets have a few fields that are constrained, which
+# allow us to fingerprint them with relatively high certainty.
+#
+# A PGP packet is described by a single byte: the so-called CTB.  The
+# high-bit is always set.  If bit 6 is set, then it is a so-called
+# new-style CTB; if bit 6 is clear, then it is a so-called old-style
+# CTB.  Old-style CTBs have only four bits of type information; bits
+# 1-0 are used to describe the length.  New-style CTBs have 6 bits of
+# type information.
+#
+# Following the CTB is the packet's length in bytes.  If we blindly
+# advance the file cursor by this amount past the end of the length
+# information we come to the next packet.
+#
+# Data Structures
+# ===============
+#
+# New Style CTB
+# -------------
+#
+# https://tools.ietf.org/html/rfc4880#section-4.2.2
+#
+#   76543210
+#   ||\----/
+#   ||  tag
+#   |always 1
+#   always 1
+#
+#      Tag   bits 7 and 6 set
+#       0       0xC0        -- Reserved - a packet tag MUST NOT have this value
+#       1       0xC1        -- Public-Key Encrypted Session Key Packet
+#       2       0xC2        -- Signature Packet
+#       3       0xC3        -- Symmetric-Key Encrypted Session Key Packet
+#       4       0xC4        -- One-Pass Signature Packet
+#       5       0xC5        -- Secret-Key Packet
+#       6       0xC6        -- Public-Key Packet
+#       7       0xC7        -- Secret-Subkey Packet
+#       8       0xC8        -- Compressed Data Packet
+#       9       0xC9        -- Symmetrically Encrypted Data Packet
+#       10      0xCA        -- Marker Packet
+#       11      0xCB        -- Literal Data Packet
+#       12      0xCC        -- Trust Packet
+#       13      0xCD        -- User ID Packet
+#       14      0xCE        -- Public-Subkey Packet
+#       17      0xD1        -- User Attribute Packet
+#       18      0xD2        -- Sym. Encrypted and Integrity Protected Data Packet
+#       19      0xD3        -- Modification Detection Code Packet
+#       60 to 63 -- Private or Experimental Values
+#
+# The CTB is followed by the length header, which is densely encoded:
+#
+#   if length[0] is:
+#     0..191: one byte length (length[0])
+#     192..223: two byte length ((length[0] - 192) * 256 + length[2] + 192
+#     224..254: four byte length (big endian interpretation of length[1..5])
+#     255: partial body encoding
+#
+# The partial body encoding is similar to HTTP's chunk encoding.  It
+# is only allowed for container packets (SEIP, Compressed Data and
+# Literal).
+#
+# Old Style CTB
+# -------------
+#
+#  https://tools.ietf.org/html/rfc4880#section-4.2.1
+#
+# CTB:
+#
+#   76543210
+#   ||\--/\/
+#   ||  |  length encoding
+#   ||  tag
+#   |always 0
+#   always 1
+#
+# Tag:
+#
+#      Tag   bit 7 set, bits 6, 1, 0 clear
+#       0       0x80        -- Reserved - a packet tag MUST NOT have this value
+#       1       0x84        -- Public-Key Encrypted Session Key Packet
+#       2       0x88        -- Signature Packet
+#       3       0x8C        -- Symmetric-Key Encrypted Session Key Packet
+#       4       0x90        -- One-Pass Signature Packet
+#       5       0x94        -- Secret-Key Packet
+#       6       0x98        -- Public-Key Packet
+#       7       0x9C        -- Secret-Subkey Packet
+#       8       0xA0        -- Compressed Data Packet
+#       9       0xA4        -- Symmetrically Encrypted Data Packet
+#       10      0xA8        -- Marker Packet
+#       11      0xAC        -- Literal Data Packet
+#       12      0xB0        -- Trust Packet
+#       13      0xB4        -- User ID Packet
+#       14      0xB8        -- Public-Subkey Packet
+#
+# Length encoding:
+#
+#     Value
+#       0      1 byte length (following byte is the length)
+#       1      2 byte length (following two bytes are the length)
+#       2      4 byte length (following four bytes are the length)
+#       3      indeterminate length: natural end of packet, e.g., EOF
+#
+# An indeterminate length is only allowed for container packets
+# (SEIP, Compressed Data and Literal).
+#
+# Certificates
+# ------------
+#
+# We check the first three packets to determine if a sequence of
+# OpenPGP packets is likely to be a certificate.  The grammar allows
+# the following prefixes:
+#
+#   [Primary Key] [SIG] (EOF or another certificate)
+#   [Primary Key] [SIG]            [User ID]        [SIG]...
+#   [Primary Key] [SIG]            [User Attribute] [SIG]...
+#   [Primary Key] [SIG]            [Subkey]         [SIG]...
+#   [Primary Key] [User ID]        [SIG]...
+#   [Primary Key] [User Attribute] [SIG]...
+#   [Primary Key] [Subkey]         [SIG]...
+#
+# Any number of marker packets are also allowed between each packet,
+# but they are not normally used and we don't currently check for
+# them.
+#
+# The keys and subkeys may be public or private.
+#
+
+# Key packets and signature packets are versioned.  There are two
+# packet versions that we need to worry about in practice: v3 and v4.
+# v4 packets were introduced in RFC 2440, which was published in 1998.
+# It also deprecated v3 packets.  There are no actively used v3
+# certificates (GnuPG removed the code to support them in November
+# 2014).  But there are v3 keys lying around and it is useful to
+# identify them.  The next version of OpenPGP will introduce v5 keys.
+# The document has not yet been standardized so changes are still
+# possible.  But, for our purposes, it appears that v5 data structures
+# will be identical to v4 data structures modulo the version number.
+#
+#   https://tools.ietf.org/html/rfc2440
+#   https://lists.gnupg.org/pipermail/gnupg-announce/2014q4/000358.html
+#   https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-key-material-packet
+
+
+
+
+# The first packet has to be a public key or a secret key.
+#
+# New-Style Public Key
+0	ubyte			=0xC6	OpenPGP Public Key
+>&0	use			primary_key_length_new
+# New-Style Secret Key
+0	ubyte			=0xC5	OpenPGP Secret Key
+>&0	use			primary_key_length_new
+# Old-Style Public Key
+0	ubyte&0xFC		=0x98	OpenPGP Public Key
+>&-1	use			primary_key_length_old
+# Old-Style Secret Key
+0	ubyte&0xFC		=0x94	OpenPGP Secret Key
+>&-1	use			primary_key_length_old
+
+# Parse the length, check the packet's body and finally advance to the
+# next packet.
+
+# There are 4 different new-style length encodings, but the partial
+# body encoding is only acceptable for the SEIP, Compressed Data, and
+# Literal packets, which isn't valid for any packets in a certificate
+# so we ignore it.
+0		name		primary_key_length_new
+>&0		ubyte		<192
+#>>&0		ubyte		x		(1 byte length encoding, %d bytes)
+>>&0		use		pgp_binary_key_pk_check
+>>>&(&-1.B)	use		sig_or_component_1
+>&0		ubyte		>191
+>>&-1		ubyte		<225
+# offset = ((offset[0] - 192) << 8) + offset[1] + 192 (for the length header)
+# raw - (192 * 256 - 192)
+# = 48960
+#>>>&0		ubeshort		x	(2 byte length encoding, %d bytes)
+>>>&1		use		pgp_binary_key_pk_check
+>>>>&(&-2.S-48960)	use	sig_or_component_1
+>&0		ubyte		=255
+#>>&0   	belong		x		(5 byte length encoding, %d bytes)
+>>&4		use		pgp_binary_key_pk_check
+>>>&(&-4.L)	use		sig_or_component_1
+# Partial body encoding (only valid for container packets).
+# >&0		ubyte	>224
+# >>&0		ubyte		<255		partial body encoding
+
+# There are 4 different old-style length encodings, but the
+# indeterminate length encoding is only acceptable for the SEIP,
+# Compressed Data, and Literal packets, which isn't valid for any
+# packets in a certificate.
+0		name		primary_key_length_old
+#>&0		ubyte		x		(ctb: %x)
+>&0		ubyte&0x3	=0
+#>>&0    	ubyte		x		(1 byte length encoding, %d bytes)
+>>&1		use		pgp_binary_key_pk_check
+>>>&(&-1.B)	use		sig_or_component_1
+>&0		ubyte&0x3	=1
+#>>&0    	ubeshort	x		(2 byte length encoding, %d bytes)
+>>&2		use		pgp_binary_key_pk_check
+>>>&(&-2.S)	use		sig_or_component_1
+>&0		ubyte&0x3	=2
+#>>&0    	ubelong	x		(4 byte length encoding, %d bytes)
+>>&4		use		pgp_binary_key_pk_check
+>>>&(&-4.L)	use		sig_or_component_1
+
+# Check the Key.
+#
+# https://tools.ietf.org/html/rfc4880#section-5.5.2
+0		name		pgp_binary_key_pk_check
+# Valid versions are: 2, 3, 4.  5 is proposed in RFC 4880bis.
+# Anticipate a v6 / v7 format that like v5 is compatible with v4.
+# key format in a decade or so :D.
+>&0		ubyte		>1
+>>&-1		ubyte		<8
+>>>&-1		byte		x		Version %d
+# Check that keys were created after 1990.
+# (1990 - 1970) * 365.2524 * 24 * 60 * 60 = 631156147
+>>>&0		bedate		>631156147      \b, Created %s
+>>>>&-5		ubyte		>3
+>>>>>&4		use		pgp_binary_key_algo
+>>>>&-5		ubyte		<4
+>>>>>&6		use		pgp_binary_key_algo
+
+# Print out the key's algorithm and the number of bits, if this is
+# relevant (ECC keys are a fixed size).
+0		name		pgp_binary_key_algo
+>0		clear		x
+>&0		ubyte		=1	\b, RSA (Encrypt or Sign,
+>>&0		ubeshort	x	\b %d bits)
+>&0		ubyte		=2	\b, RSA (Encrypt,
+>>&0		ubeshort	x	\b %d bits)
+>&0		ubyte		=3	\b, RSA (Sign,
+>>&0		ubeshort	x	\b %d bits)
+>&0		ubyte		=16	\b, El Gamal (Encrypt,
+>>&0		ubeshort	x	\b %d bits)
+>&0		ubyte		=17	\b, DSA
+>>&0		ubeshort	x	\b (%d bits)
+>&0		ubyte		=18	\b, ECDH
+>&0		ubyte		=19	\b, ECDSA
+>&0		ubyte		=20	\b, El Gamal (Encrypt or Sign,
+>>&0		ubeshort	x	\b %d bits)
+>&0		ubyte		=22	\b, EdDSA
+>&0		default         x
+>>&0		ubyte		x	\b, Unknown Algorithm (0x%x)
+
+# Match all possible second packets.
+0	name		sig_or_component_1
+#>0	ubyte		x	(ctb: %x)
+>&0	ubyte		=0xC2
+>>0	ubyte		x	\b; Signature
+>>&0	use		sig_or_component_1_length_new
+>&0	ubyte		=0xCD
+>>0	ubyte		x	\b; User ID
+>>&0	use		sig_or_component_1_length_new
+>&0	ubyte		=0xCE
+>>0	ubyte		x	\b; Public Subkey
+>>&0	use		sig_or_component_1_length_new
+>&0	ubyte		=0xC7
+>>0	ubyte		x	\b; Secret Subkey
+>>&0	use		sig_or_component_1_length_new
+>&0	ubyte		=0xD1
+>>0	ubyte		x	\b; User Attribute
+>>&0	use		sig_or_component_1_length_new
+>&0	ubyte&0xFC	=0x88
+>>0	ubyte		x	\b; Signature
+>>&-1	use		sig_or_component_1_length_old
+>&0	ubyte&0xFC	=0xB4
+>>0	ubyte		x	\b; User ID
+>>&-1	use		sig_or_component_1_length_old
+>&0	ubyte&0xFC	=0xB8
+>>0	ubyte		x	\b; Public Subkey
+>>&-1	use		sig_or_component_1_length_old
+>&0	ubyte&0xFC	=0x9C
+>>0	ubyte		x	\b; Secret Subkey
+>>&-1	use		sig_or_component_1_length_old
+
+# Copy of 'primary_key_length_new', but calls cert_packet_3.
+0		name		sig_or_component_1_length_new
+>&0		ubyte		<192
+#>>&0		ubyte		x		(1 byte new length encoding, %d bytes)
+>>&(&-1.B)	use		cert_packet_3
+>&0		ubyte		>191
+>>&-1		ubyte		<225
+# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header)
+# raw - (192 * 256 - 192 - 1)
+# = 48959
+#>>>&-1		ubeshort		x	(2 byte new length encoding, %d bytes)
+>>>&(&-1.S-48959)	use	cert_packet_3
+>&0		ubyte		=255
+#>>&0   	belong		x		(5 byte new length encoding, %d bytes)
+>>&(&-4.L)	use		cert_packet_3
+# Partial body encoding (only valid for container packets).
+# >&0		ubyte	>224
+# >>&0		ubyte		<255		partial body encoding
+
+0		name		sig_or_component_1_length_old
+#>&0		ubyte		x		(ctb: %x)
+>&0		ubyte&0x3	=0
+#>>&0    	ubyte		x		(1 byte old length encoding, %d bytes)
+>>&(&0.B+1)	use		cert_packet_3
+>&0		ubyte&0x3	=1
+#>>&0    	ubeshort	x		(2 byte old length encoding, %d bytes)
+>>&(&0.S+2)	use		cert_packet_3
+>&0		ubyte&0x3	=2
+#>>&0    	ubelong	x		(4 byte old length encoding, %d bytes)
+>>&(&0.L+4)	use		cert_packet_3
+
+# Copy of above.
+0	name		cert_packet_3
+#>0	ubyte		x	(ctb: %x)
+>&0	ubyte		=0xC2
+>>0	ubyte		x	\b; Signature
+>>&0	use		cert_packet_3_length_new
+>&0	ubyte		=0xCD
+>>0	ubyte		x	\b; User ID
+>>&0	use		cert_packet_3_length_new
+>&0	ubyte		=0xCE
+>>0	ubyte		x	\b; Public Subkey
+>>&0	use		cert_packet_3_length_new
+>&0	ubyte		=0xC7
+>>0	ubyte		x	\b; Secret Subkey
+>>&0	use		cert_packet_3_length_new
+>&0	ubyte		=0xD1
+>>0	ubyte		x	\b; User Attribute
+>>&0	use		cert_packet_3_length_new
+>&0	ubyte&0xFC	=0x88
+>>0	ubyte		x	\b; Signature
+>>&-1	use		cert_packet_3_length_old
+>&0	ubyte&0xFC	=0xB4
+>>0	ubyte		x	\b; User ID
+>>&-1	use		cert_packet_3_length_old
+>&0	ubyte&0xFC	=0xB8
+>>0	ubyte		x	\b; Public Subkey
+>>&-1	use		cert_packet_3_length_old
+>&0	ubyte&0xFC	=0x9C
+>>0	ubyte		x	\b; Secret Subkey
+>>&-1	use		cert_packet_3_length_old
+
+# Copy of above.
+0		name		cert_packet_3_length_new
+>&0		ubyte		<192
+#>>&0		ubyte		x		(1 byte new length encoding, %d bytes)
+>>&(&-1.B)	use		pgp_binary_keys_end
+>&0		ubyte		>191
+>>&-1		ubyte		<225
+# offset = ((offset[0] - 192) << 8) + offset[1] + 192 + 1 (for the length header)
+# raw - (192 * 256 - 192 - 1)
+# = 48959
+#>>>&-1		ubeshort		x	(2 byte new length encoding, %d bytes)
+>>>&(&-1.S-48959)	use	pgp_binary_keys_end
+>&0		ubyte		=255
+#>>&0   	belong		x		(5 byte new length encoding, %d bytes)
+>>&(&-4.L)	use		pgp_binary_keys_end
+
+0		name		cert_packet_3_length_old
+#>&0		ubyte		x		(ctb: %x)
+>&0		ubyte&0x3	=0
+#>>&0    	ubyte		x		(1 byte old length encoding, %d bytes)
+>>&(&0.B+1)	use		pgp_binary_keys_end
+>&0		ubyte&0x3	=1
+#>>&0    	ubeshort	x		(2 byte old length encoding, %d bytes)
+>>&(&0.S+2)	use		pgp_binary_keys_end
+>&0		ubyte&0x3	=2
+#>>&0    	ubelong	x		(4 byte old length encoding, %d bytes)
+>>&(&0.L+4)	use		pgp_binary_keys_end
+
+# We managed to parse the first three packets of the certificate.  Declare
+# victory.
+0		name		pgp_binary_keys_end
+>0		byte		x		\b; OpenPGP Certificate
+!:mime		application/pgp-keys
+!:ext		pgp/gpg/pkr/asd
diff --git a/magic/Makefile.am b/magic/Makefile.am
index b5b53c39..5a37e7e5 100644
--- a/magic/Makefile.am
+++ b/magic/Makefile.am
@@ -227,6 +227,7 @@ $(MAGIC_FRAGMENT_DIR)/pdp \
 $(MAGIC_FRAGMENT_DIR)/perl \
 $(MAGIC_FRAGMENT_DIR)/pgf \
 $(MAGIC_FRAGMENT_DIR)/pgp \
+$(MAGIC_FRAGMENT_DIR)/pgp-binary-keys \
 $(MAGIC_FRAGMENT_DIR)/pkgadd \
 $(MAGIC_FRAGMENT_DIR)/plan9 \
 $(MAGIC_FRAGMENT_DIR)/plus5 \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e84ca136..b38a25b3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -33,6 +33,14 @@ zstd-v0.8-22.testfile \
 zstd-v0.8-23.testfile \
 zstd-v0.8-F4.testfile \
 zstd-v0.8-FF.testfile \
+pgp-binary-key-v2-phil.testfile \
+pgp-binary-key-v3-lutz.testfile \
+pgp-binary-key-v4-dsa.testfile \
+pgp-binary-key-v4-ecc-no-userid-secret.testfile \
+pgp-binary-key-v4-ecc-secret-key.testfile \
+pgp-binary-key-v4-rsa-key.testfile \
+pgp-binary-key-v4-rsa-no-userid-secret.testfile \
+pgp-binary-key-v4-rsa-secret-key.testfile \
 CVE-2014-1943.result \
 JW07022A.mp3.result \
 escapevel.result \
@@ -71,7 +79,15 @@ zstd-v0.8-21.result \
 zstd-v0.8-22.result \
 zstd-v0.8-23.result \
 zstd-v0.8-F4.result \
-zstd-v0.8-FF.result
+zstd-v0.8-FF.result \
+pgp-binary-key-v2-phil.result \
+pgp-binary-key-v3-lutz.result \
+pgp-binary-key-v4-dsa.result \
+pgp-binary-key-v4-ecc-no-userid-secret.result \
+pgp-binary-key-v4-ecc-secret-key.result \
+pgp-binary-key-v4-rsa-key.result \
+pgp-binary-key-v4-rsa-no-userid-secret.result \
+pgp-binary-key-v4-rsa-secret-key.result
 
 T = $(top_srcdir)/tests
 check-local:
diff --git a/tests/pgp-binary-key-v2-phil.result b/tests/pgp-binary-key-v2-phil.result
new file mode 100644
index 00000000..9a0c0959
--- /dev/null
+++ b/tests/pgp-binary-key-v2-phil.result
@@ -0,0 +1 @@
+OpenPGP Public Key Version 2, Created Fri May 21 05:20:00 1993, RSA (Encrypt or Sign, 1024 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v2-phil.testfile b/tests/pgp-binary-key-v2-phil.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..7c0952e64c5f02b7afefc49b1d4951b91707eef8
GIT binary patch
literal 975
zcmV;=12FuV0F44G{APdv009I5r#N?xVK<tEGrwn8V&tr4sk+sswcJUQKv@yEw2;(W
zBoMZzT>walo&Wa&4+7EIsX<XId^=@^ice1km@S4g4tjb6n=+ysz+@B91uBX1#_;x(
zIqGjGSBvHlnB?qPEI5rc(r<SkmK9`w$W>8VOcey-Y4vmpWqE|S$EjxB00j}WB2Z{)
zY-w;HQZ67`X>Dy~a&2L5ZXi5xa(X~vV{I;Pa%Vn?0F?p-5G)=%T=dESfsN-P*#QC8
zw*&t~7>hjK9iHDTo7$PQtp`1YbcOd>;E0la9Tn$miYUY^BCtuvXE|qU?yM5tDoA`e
z=O6ulnTKhFdV2DiAMUIWpYsurpCr$F4lVz35agxosx6zi<npplPm)iZs}@rca!^_<
zLEZIAtSJ%GY+G5xS3~+wvqPIWP8BZH6Vz>q0AK<I5G)-_+R8nl{f1hn^8o?GQ36<n
zQ*j^_2TmG5wwx=e1PHC0^m+<Ht!pIN9SYrhl0T#-G;C!Y>8V7WE2?Eofb?*+e8@D4
zt12^#>qDd2uWFUhg~MZsqRE3%CnAXel>!A2EBt3h;&t8*|7Z6L0Rf8t1OTDpy~Ae8
zy&&wina6(6Jt`?(7@5C3?7TE8G65*Llp>|n!(>~Z#=xGxh8IeP6Rl_fcTz~+=`9nc
zemQ%b#acKu$2%4-EN~|sof-TDEG^Dd)1FV8s?g?At4X5x&)I}1l-4uYPz{3_q<$y>
zFCim8nx%pM{t#njA8_mfrMrm$l>!A2E@Nqj#Vto|4Zo0W0RcFn1O6rS4_{hJ?;OFf
zR+fUT={TeHRV@ipROBEcmb4j0&SCzY7zkVFF+wl!n@)hOiWzGZyCg;0Lm+2`_@Alz
zIcbUAQzFhD+f8}3A!Xc0AABck^BzfFpmfYB*EC<eB3%W^dR+1oehOC_P#vQZ$|h>S
zDRZ|jOSk(>3x3lbFvW=gRRRSNE#%cVRRw1HO$<)q0Rb$g0sb#Y+zQu;gcY|p0$N`v
zGYtL<tMW~gW&1u1xxi!WwoqB;!3>gbrhxuWWih{}9mB|5407O5KkQk4yjFqjd)J8o
zl>!A2Ez22;WqE|S$EjxB0Rg!)1O6tHjqc_Hz;=aOJUlZsXKCR%-Ka2p1|*Ij%fb6e
z1eH8>cLr2hra~yYPw#9-SoOaal}WuoK@(Y#449@M9hBP>IV2X^w9ML|e#?$Vhqmiy
xKc%)PeA>*Kb|{mwx4eKTskIg8nNdWYD5HG7@Pi_LIn89J;5Lz_BruFl9}H`pu<`%^

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v3-lutz.result b/tests/pgp-binary-key-v3-lutz.result
new file mode 100644
index 00000000..5a8dba96
--- /dev/null
+++ b/tests/pgp-binary-key-v3-lutz.result
@@ -0,0 +1 @@
+OpenPGP Public Key Version 3, Created Mon Mar 17 11:14:30 1997, RSA (Encrypt or Sign, 1127 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v3-lutz.testfile b/tests/pgp-binary-key-v3-lutz.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..90aa2dcc36ac39c006478e88fcf125eaf9830f91
GIT binary patch
literal 11722
zcmY+KV|ZO_*S6Qn3LD$D8{25oq_J(=YS7qfY&(r@w6WdTw)v&I`#bjY{+&P0<DA!=
z_ZYX5Q$Z~Bl!*WU5ZqKMYDpf6A!<=(F1|angC0=2qePMI>`FzgH{Hp?B50-fjO}%M
zy(=znFc)Y1?3jJ{^}CL;;)UyBt|Oc+gg(nvc5A3o#luIFX`Dt33+r6T?1+s{qTxGd
ztjKDRoHi>Vq0LR@{ly9>!9hvQ+c23It%}N}6@xTDHb>h(UihUj1@FU5td0!bZ|Ha!
z00eR!skF0`2a%|)jg7H`nZBW=F%hrT`x8NPOGkPOV;g-2BV+y$0T2WdOO=S{U=qHV
z)x?PfG8n2mARR{cwWDBqoaxvzN`_N)weyCjrVEh0<^r+Bu!*6MVc0n`@wvwhMf>(C
zL>wFm84Lgk0mk-g&k*nd2FaK!6g*<TA)Z$VkV)_1G5>8XJXBFI>1go=j~H{>$r6xB
zxnUwvJ>=V0y-`zZ_4bl~40-PGe>h2hIN`aLzWrRrs#EQN3>5zXLG<qVQ(=y<ftULe
z)h2!sQ9!0Z=1CQFYzxwXPe1A>A*)FJWBaiG!x{O*$?KU!Y2e+LC&mP%!yZ0t?ZZFB
zh*E|gy}mWxs}4}&0J58I7bQeqUl29KN$tDI-{8n7{Ehw(=k^b$e4z{b+ocsMn;RfY
zZ-VIBIdW0k9?PQ;qCm|Y;rE_8Ap0nCDS)-wYmu;vM&Da=$+$U8#p6E?yJc<pA5Mpg
z@M3S!rTtt1AUo$Wz5=iGtPHUWs_2VnY%B7WM*|>})Mp+Y_Y-)+mxx}muXNV}gPq2T
z|8Y1hl$`!>y4ptcfHn@ko#22Bv}YIR(Ww`>d$+#HPh9NiwG9?0fJ|a$hv|UiVMfV-
zrteqD-z6Al_4xjW<MP$=59g7-R7WCD-J?<*kR41LPLzWw?O91_E2tga>1_Z(t^&yN
zpaZt^-9idIT)ONk@FB8dFuH5}52xTp`VVI#Q5!2%){Ar@0g%1=!fz<@;HJq*XRjn~
zr>Eh~zM%xj<a{=Zd(J0h^xe*{J#9`f0ZE^(|Ht8ZY2*IG;V?HPTg58IUBLrnQXGrd
zW5d01P|ENhb$iIKP4o&}1F{55&rb;sWhnztKe_Mddy;y4?TY`$;cd9$`@_*JcS!mz
z)nscw3&;|`hzdMm*Ca2*2*FVf6R9l2|Ahj`QhjWsW8z<+m$$exX(u#qky-m>{2zy(
z9+&zLM~uM%tZvL{NrfDc4p)ltZS`Uhhedlh(}D?AdM3?95s>Am@G=*D;-f-tU6Y?9
z<5N`ZIz|3JoEF^HKb&YY1#)%++GW8JK=u+Ma6)dI&IOyI7Yrey;$j+&A^?y{j?dt%
zC6JjV5^?)UoWQ`U(x&C`KaKzu8tfm=klk`}56lOH(lbEzIs4$9s?s6(&kqKV++>gi
zV5p<-Pqz$>@V+%-RD7PPmuKt7n?b!udHjzf8Y1}5I7Pu(@<A6vPU^`7WVr{i`4#bI
z6|RNdNT8hVMUMFvm;th5TMDb5<u<e}D>sK>xpiqsr^f!g7s}u9F0hXS@yCZIZ8Y9l
zViIx@@_n3=M-r-lEu(Q@#}Sjsu&FVzVx$7H>jcaM^{7KClP%XGW$48yKGtgvymL_h
za`^5!r~h!$##FD3vb;{?asgSAb&CPqa01cs>P7y_twtQwqc%@~ELU}~>ktb_!30(G
zPXh4Qyn=pBSO0PN3v`YCaM%xU_>Hj2v$){_nM@uAp^+`Th>gR~DQ#|Y#*jdJE<h$n
zNpM%XS(Q7jxAj~+$y3N<ua?$-905$xtv?(UYj(O*7}tHBNI*KYmq(MS$85w^Y7kux
zmL_CtGtMd?%XIZM-VOYsrNAd78E1Uu8~M;L-T&cWsYU(a@X$OhU^ieV2^9mf?2cX%
za(Ix?oh_SsXZjDW>jK6z0T~47@DJ4Dte|fzLwNVQmdc@q+<X7S>0na$!x@Su+PL!J
zQC9`MS7IX*h}wttNa_=M$MM4uw<+F25<qtK*V%;LpOz_DeN>Z4*5g6c8ZUpo*S|Rn
zp7?S7;kdml!wO7?pP5SlvRvZ);2qmIf3aD5u?OQE&vN?id;?@R*Z-20xIYen94#5{
zfF5EGjggf8k0T^BZ19iIEQZ1La8O}l6CgV<|JTwoT|zq(Ni#vZ<!nBtO$p+Aea<!*
znhIFP*6q*LwLF#%e6EK|`;Q~i{7Lf<=d&$d+2ZKAq(KlMyY-Z9ELs)SQk5n{Rus&J
z9VnMm2*_?18u-=dtvLBJVmRHD(;rhD4ALgV83cjCIxZoK{1D(&u%N^S1adKfy-63f
zd|9I0!q%^gZ&=l7eAIzjQzeUv9r_%HYb#a{zd{;goLU&h8}@k@d<nrW`!(Nry12TH
zjclHW!C)~WG!&ii;sR@WGzIPkIwFNKrM`P$DHVTBOC=fi+<;Da#y=$Py<c*q@<{PV
zH(uWR3oQbH78sx{$P*14=cL^Je2Z>zmHOu5AN_<dV<5UT7$)HyGUH(!l+k;`s_9S)
zPokred=HxRhx+mwT5o|)&$G*c%+K?PIY`34zOB-=;S~%(ke?{H2<*vZk>fr`_>L2E
zNU}sgAUf9##EtjOjGhCihb;Orf`vmmfM-HeO?p8CJt6UboC=PKWxaRvZ>m!3fxrYY
z&;c-X<<;_+5kSnJ5LY&_r}%lp?fc4)&*r~cW6cBWXK-S$1Z=*)3Hv+<U8Pye3OoL=
zPNMEk>sK_Zg&~N}*W97cy(N27!SvKDZ1-dEo9hkEH2I>=s&ZA0>QhQw_<E$Nftuhu
zV=Cdh_k>H+bW<G`XVnN@2&l6{ihPUr4oLumKw>RM2rgC2DA%w^3j_kyLP5{4sR#^9
z>pmeva}tg;`_<DG2ivE_&o-qdN73jW`g!=K7(2)M9#<;6d~4%oy@Q`>Q!whApI2=r
zx_7Q@LoqN@UmY>wRKH7S{jjnV@L$fZ*d@LVv;f&Td>kn%14TcFP_c5$Qm;<yQSpHP
zG)X;(??S5dvh~#Zsh;<n-;zQpB;n6|r-c3x#%j7t?@RO(5IEro4v50|Q8tU_SD`f>
z$8*HCFkJr`!g6D2OeA4|wGSdzH^;EEaKutdkf4lhRT_!0sdNC^)NflU&xVJ>B!7f}
zD)V!BeFJbVKp#*+EQVo31gmZZzpl#@X-EMdO7+yBs~E>pTe{cPPIEqp6G-M$xIzGT
z#i9&mRZX$}wMqbEs`al{Uq`^uuo&ypd_fKn7ytu$69eH3`N)$Lab?{I9<V<*I#DR^
zJteV5eo4omEQ6PlJcQ$l|AG9)8jht6j!*VBq<^Qa7ac^65+JP0biNvm;%*6l6wAkk
zpJ=96J%ae#*F+CixD)wQ_v5w>W_j4gcYPA-q$2t0odj<t8EPilL3>2PI>x3ljKUvY
zZhPgBWPi1;zKp7^@!LFK!hQt;5xKzu!G%uMtQPRL#@mbi7knj#zE}`Hza#y`#tT$K
zF6%l!3o6VG>?U7p@Tp-h%ES7~hZJ^>J90^$2${ZFg)fLY-TzU5g?L|G#2iv#|4S}z
z<fkhkd5qt-=5TC{OCA#kTd(*<P<F+g#zS*`g8043&tie2E9xYRAeVj#glWOo(0{a8
zKR%*MuRVetmDa=pfoqDOH;;-SVolRcw{SYy@YnM=_q{Fw)yW<qAg2TvobP=7`C@f+
z6i~79*Nvm-{GhWX)u`&n1Mp{6=#)vZ*yl<%!x=o($R!r8WLAWQ{v-6cHaADzOI&M#
zb*P`KXL6eMWrx*h&n9!q<eQ0|Ul!DVlwbV}bU=|$Gk03@W#82iOZ=;qP?5~A-{0_H
zr~v^4?zV#7yfTAAgs;d%W%$QE!n3edv&aV(CS7-HA9k|T&W_TApe4IfbA#GJWE0MK
zvVLgICbG}+SxR4udT0qwPJUns^>=nm>^heSA@_vKf3a5EourgqBhLHEknkCQ==OkR
z)R^>UzAw0`_reD%T^(@GH=!=q9aWpMK@*d{h{Wt5@>i<_-=477QiW=G?*<6u$OH%E
z8+9kH&LHkXLC1$G36$a_f`lIoI9dA7Mj?Y=5{h=)ROP@@7iru}m;EO&iat7XJ*3$i
zSF_&>yzE|Pwxq8Q)1);lo~@CP2oL2o;GYalnoGqTXk1MGx}kDOcS%jEtguHHNU$Gw
zdh~bASm`@{8Q^Uac*1uZC!dF;4Kbhpt5q7hxvk%P8$E{nULc4NL9d*N%)6vPy_g>(
zoj{Xm=WG0aIo3|o`|EHjhEc4Tk16G}#Vjz={Pd||&jL$)TwK-AsT0gME8lAC^iMjN
zKjMmkFA8c7g&ytOP@ZAZP!9b*ag#uXQkxfg)oIF-z!d$xK_K-Y6iA{<#mKV+jqvh)
zHo$-@YMFiE(R+a}^KR;|R>em;aEh<)Q6D5Hfxr;h_q5zpLM@H;K7c{CJ(P<LC0wxJ
z8!1Gl#lBV%nWS2$z^_EmhOUKifXVbAKo&l=<(zxF@H)EC5!3O48;4iz7?R5v4CdYt
zKl_&5`1myy`}LK?SrNNLR-F4^p*Z9?O%$BZ3fxHTS!kenYiQwA2wbSl-}!$IoDn^w
z?T4Ped;M4IrEv$Hikt;+NgD{13<SN|$tCzZVIo|kY8vyNI*{Yv`a;$_rO=E+{Vt$5
zW{|SW*1SiHy~em`6h?82shz5ZmnmsBmu!ONE1gNXF?46XD!^XP{^}%U%n~R9wpl;t
z3T5#|7s|dKV<-hX)`jG)mlNz8-UEJr2Pvde!l!?d>aWRf+#3l7!D7*)Q?YXXSE~{?
zBfO!iAj-#t7zjKd0=;R9rC^RJqlH=PM~aK09F)9LEk6ky1R~)D!$yMpH(Tlil?IAK
zDi=*q%=z0;qCd23z?7DZQ+Zs8haUOkTWBI{z0hRH1a8UwG7QfSX&8fOKWTuBh+@zf
zc`Rw*amPQwifAjJ?_D)KX2E=B)N;&4`goUCdb3`r0Ev-$LrniytD3g-%=(+qxgYj>
zTFgH{Z=V^mAC(>z;;HM6KX$R&y%JEgx?FS89ETnCT}deniajr!M2(^jVaWqNeA-?h
zXhcRR;5jVgX)$@!muPqF-b>n|)gxXfR|&K>KPQav8N7P?baqn;@zU{aoh35Y?JEsk
zX%?Rg4MbD!T1`+~*)??*2E%8sB)lBoGR6<ah<tywI<s!xoXuS~$jrNeK&C;^n*sjR
zhiLrIZ<a@R(uUCCGjCL?e)E~4Fg2PzEp*OYHm=z#bOPf38|}TV87!IFDXRG{B_4r1
zB<PZ}Kk)k(BOWI%wh<|d{qR@BKM9OBL4%#Tdqr#F7I~T`#E~i{uaRHd(LrNw>Mnd`
zfKW>Nc;WSgc7F@|1sjB)TYDP{hX0Qid!$_-i!(lfGq3o2T1{o|&F7{v1J`Q>Ecx(8
zs>#c+)6c|r+N<WNV3vc9pr_0@X3&FTeKRbsPWTNxZGdyMT($Bl+<up<w*kFgh=o-f
z3rratiVvO8oP>Y`ekoGUB??2`5N|$rNVTML6X~PdYol(vZ2DfAzCeCC|8f<3zB-X<
zBRAx-x)g7}_vZ{4|9`bk2_*%w#nWKQ;ekMsInXQrKo~(5aZ2R`XN}@XVU^Clu&9C0
z<*Bwh)2~`xwT0eI+FSP_(+a~|L)y(HQHEH>w>6BL2~^$nq1P=Af{!r{<t99y2dyKl
zJ?z3Rf{WWza!DIDjNv^E-(2Z33Cmx0&6d#QE=1$5D(8VY>^8bBEQHcz1P^Ar_7j=7
zmtZx2wF)-f`@ZybEUQs%0D%OSpf?#l-zcu+fWjjSvNd#zNe9mL;wk<sE*2SXqAWkY
zhy~YO$5QuwIe2&z;v>S$b)SYs+N`y+MIz+B6H`S=$PetVGj7vJ`jNV<u%b1^y;Em~
z^oBPM>EKQG7hTil7!ZRH@~h_g+)TqSZaS!0U^kvm5ML)VyvKOLs4I1vWd9Zj_C{ZB
zOkVpv)Wu-F_W~jF{>%UFg<kS`@kz$ZgD>;@8XYvF#J7#vs9Yy<M{d7zP3K}}6s=sB
zmc3Z$Z2VhV)eB!4YfOg)C%>Yso^JyO{D>bHM-DQ`U^sd;L#m6cxcfID2i02Qw=HNU
zN}d7l07{15VP$o3yVRi%D=x<~jTj6oX&2daVkhM<Jh^DUWl8=?izAE=Q$tc2p)RKG
zy_|kG0ta;2eh=C}6LUJMiaS(E?x4$$L__Yv{*wKD!vr6>ZV$7vX+sxnFoCZZT%<nx
z14A47E-F<W8flV+>eadk2$QnY{R&6Mhe->R)#ariFMJ55hL^o_eHOgR^4)mEaN!b`
zVA`2&Na>gK-KDOE?gSr>tLaFv@Qe_@1%qz#e5B-Gt#HpGq|9Gzmu(XLK%j&i=uH^b
za|NdDiG7&}nRJ9PoBNScp}T5AgQ8wyti&Ep+KucInf;DEkMNpU6%t|}Z>lMgQ)px;
zpp4+)X6>VGqj%ex6StT`idSiSNdxS1mqf@|aDfhVd|ELJj-jZDP#XuMe?su9Vx`MV
z^^dBNY!)#O2{e3(g!<2)VMHSItr!2*N}L)D^1$b|Sbpz`xu~Ew%RvCP^1!DR7$P?7
zRbJ<SdP6@BCCt-e!iZg}l9<EMdu0$p%t(5)xCXH)TS0AhBSOs_b8F4407%ADS4+C;
zXg_9y586(YL*(PO6R2~IV5iLdbQm*+q_U+9At_-*j=w#2k7Nii_10ai5PEANEwj}j
z&`X#EPttA|GdghfS1aNux+Zb@glb_^9tcF20=+4XupY!q(>!$d`hqNdSj@7QL5|R_
z^N2T<_VKaP2MJ>)#K#&S>blo4lSsbh6aM7!AjzU1il5}Fi`%kric&rZg}qiHOky&4
zu64=7m9>o!f?O-=5nO8~3~w-uHPP_f3LPY?5{z70(Rb{!NFVcET+}=AAx;o`c0i{W
zzSMuTP`J18xZsY)7sninLxDi<SI{%!;0oz?z99iCzJ`K%#zqSDMko6kDvtB?c+d#s
z+__rR+^EtHTXLs;gtjqmoC#eCU@t}@k4EZF6G!r!n(nkp8oaWX)WA%xxStu=_tW7$
z3>xtiWrZjtH@0V}!kEZnO8UeDsWFpS0;THE;d{Bor~ZPer7W*$xyCF_U#FEnTBxiH
zJ}$jrVk}EjNn-EK2k>4X%5#BJZPg(sYN*)r%3sZU;EkJ2b*%|qf>9NMlCM00HO|=T
zWayqe6>93@A2ot!59rhsuy&&m?`&e&yg;ZdUM|6_^}H%xjk;;(!fpq*%<*!NHe>2b
zzoytiX(hyh!w)?S>>CkbM2~|~(~C7dBhW91BO1q}xW{x)i~REbYL(4*Oq|&3#>=9N
zzR$OKL9aYzaZRafrWV-lZ>^F#j+#sz0W&`_K6oa<(7m{1*ilj5+LAeMehsg=f@W++
zZVQ-IRa;D>eBQa-#+F*WDf_<C=?f%Zl!yMjO+}s+5ota1LR?7`hbBdS=^>hw&vo^^
z-q;R%kZq<V|7$qAnsEpk2ozO}7TG=<^8tYj(&+jhE%qqsCR*@@>oc6^_jUZwW6+x}
ze?>qgNgwrU5h=pYJck{X&5+P#0D=QiEKRK(wuSoxZpsgvVG22^>%p01-orX!f1mH^
zwt;qQbf|^|9i|i7A<onGeDZfIvz@e2ZYY6*3osz7z=9b^^bvGO&dXoZkw3Dv83eZP
z#~>x?EODmVQ&m%CU{+8`*#!clIrh8%YQ=14TJnHyD3WL2C(Q~X?<=2i4a9o|M}sc)
z;H+(}$cMp`v6{vd*nKZzc5SqXJ<|DG(C-8*g~@hyLnu2Wz6YN`AnqmV)Ue*rnMo0i
z$*Vni$r651duODEWDlwh>n`R)y}&M)dA8}X&xKHi$`)?)Q%CaFvCxvV#ae}9<C_CJ
zLA&|4H$=Y7C%P23W{JOA@fAm(7_Q?BdJ_|Xz~$edH&MLctybZJPZ#ncHPwBdh=<)P
zHrq5jIe@eq6vmFyEc`V_4IQ!epb%vf?_eznZrx_;*;xk}=9_pl8}UTzUy)sE;hJjZ
z^Y!aagmM!$OW@CIGdq(6mZQfu{_XtoP`lnt@E`N!2u9HcV?}Ia09HGp7f2IX3d0Q$
zO_Sh1RsU+`h_B@8>zEBbd#wP0C48V4d|%tz1_&JQ;`Z3!S*BENk2pIdxT+(iu-FdR
z`jR<`Ony!d$umxus>oaRiJ7ofzsKCv3h|yh>1tHxH|fDlMEf(>>sFCQuIIM&TWg}s
z#hK6&$RK?ED2@cv+}$ME##C^5J!8F1H|vp0x^H-7S^Y#R6(+B5p}+te@UP>>|7dZ9
zO|0FVC4J4jk$Z2|f<&Mfr2CI8BvZ?IxLLHpZ;#V#S36ILbr5<98LFs$!pfkm+*Z3F
znB!Ahwpb%{r8Vv_2J_}QMkyb<3X6rt(Xg<+o*&Vv*ESK`uBTSeoxG2XxtgM~%M3le
zX33LZ=_o2qe(`mt*&$Hw9;lc*D%7J-;v$(nRGO`XoX<i!$afw7GigTU2)9&zp^u3x
zj`1W10&%uLFL-qfWzyq^m{>I6qF!Z<)8U*R*^hg=8|S%3592LAzZ^|^zB)#`D)bH#
zA;GARoM+Bl*C%IWr@~p3!wqF$#Lz{3z?^MiWS+x};<Q{7J)Pz5h?7jXD7CtRQnB1{
zCA8H*9`yF&{&L~mm;!xcZeYyz1DrU-z2}<gUOS~SpgAP>&(_HMY1aQgLwfItvEW9q
zzZ>VrUBj7M7=IX#Fu43y?o))DT{ue<S<$j5X<PeUhl}V|X0d!(-&<JK-P61w8>ZG8
zJ*rvk;M_7`|3vy*NkG&@FB?|jqMhrlO=|my2tioUL&5&nvQ`F#u5cZ-(^cH-lX)Ci
z)S;DJ#e5hJOH{6KrE%=A9GQ=_)3fO5bH0gDb*G&S3n%w6N=W^m+8VVpz)uc1Q)lLU
z|Dv*U;IHK4!xOo29H98p)^2P43Ot$a*0&Utv|zjMrM}Ga0J%~9D3r{6eLW4L{f*-k
zOH+2gP87uU$9%zkx0g!T<qL71{oLT9iLZq5mDLWyXYEssyV_%CB}>pELT6BlPZQx-
zbCXhTlZPINu6*P?`nigpNtzl92sG<ChSagfP#2caIr<n@79o8t8!boTJ1Y#v%m$}6
zWOa3&bzeeCCk8|2{zN<fWwU}{MmkQd_`UXGbU*@u^{`3w<pdBKLZs&nohxzL!4d9(
z#G60ho$0h>*OF8hc|J%OlybX>A7@3*-Az^eVnJQSeRVkmi-r9(7Hq78eMbjwQmD}Z
z*Buxkq!(omkip!F{N#ZOeO-pYLde6EE`q-c%`#M=7gc0Nel<*)4t|q}vLRbMne#K#
zKEK34HQc+UYl$QI?Wa6IjX+rOmN++&K@&QvkxP^XE<Z%2*?uCAlz=aA{hLc5{?&x`
z-OI?DYflUk7AIeETt@t5W60&7oyX9A8`Y=c2?~cDVjwUJ5^~Qh|8CkqH2R2GlLtZ{
zn{(U{!eK0-B|qb`_6yK`jC#$ESS+nx??!NTf#jC7v|So5;AMQ;&ODt$>LJi^>9=Ce
z*WX`sn0>7gFIzO1K)=V3Te1pnGAyg0KM80-B{pB=!QS|DK{IbtRLI_?i<6{CcDkiT
z^u!Es2RkEUC1v=0$AfuN^QQ3=|5k*=HK-ogo+mTcBU{lx4^yXoc}#LGap_V#)8z1p
z7TE+7(>wf-53vQI9(!)DG{Atq#Icn<i2noj)}XoNAzGozGqbhg_y#KKt{k(R3H+^I
zPACu^3<8xsuDZl>YlG^e*CQ7Y$le9@49#N_vdGRIW~I~(i<gMTjfIg<Rmg`*RYS~?
zfy3=C!Ab~L(Vf}yn+Nyk%^8iBIKCQ;M1w1TFZ?|6{M0Y69{Pj(PN?;nAxj(A2Jcmv
zK>BQ51NP<t9k~1HTE!C@@p#8Bb7vxhhZR>pWi_lbggeZ14cnaO=@@wyllQI(FqK!#
zH!y~OE|rEPc_kxe-U;GqSR}o&UCIQb`wQyNWLCF%aUoV*8GlApqVcItJX>3E!sA0}
z`r4F93Z;bU>Y{E6L4{A%;@d)*RJ3T2q*^e8CxxyyV*{<6aYkfgdNE+k0EDnw5<_1l
z-qBn5ZTLgI;_hMR{lHiN-2w|tz<VzL)DJ3Tm}NUIt}CDSWuyfRG@uxoPQ2cQsW5GK
zTrksHN+%a3sYl%mY#%plR(lzFG*x*NkMdhIf?y#pxGLI8RU>uo<)DV{7#<qkoEwW?
zdYR?<*E4xgQF~|ss+L7`PzG*Ije>!m^xNel<dHfNGtN@1-j2w{?ct&>F(O{!$<U@-
zxv|#D#D3#xVfz)kl*bJmPZwgO0L#o&K={@P^h@G6dR^$$c(cu>reCqf16|%Cq`1`f
zq>xuqIU1*`2?K%Db5g!riLSQ?@oPl`zL5lf%!&U*SuMi`M5cul9ty%u+R5(Ym81pb
z-h9J1dImIXnow#DMRuaVFODavik+wS;+yL@Ok;VgYYJxHGH3qH<($2R-3z1e17q+G
z5GYp$^=8kRzL$PHk!reOFOKl)ufoCcI7Ni2zVlU6Mf}!#uUB(>0%ya1oKn+CwI}m5
zh3Ql8W$s0Gc*dajVN#?yF_yx<#aUk)?UoUkM&W(uY&*1@pSf09SAB7D{`c4<zV_B_
z(%|cbm9(lZO0&GarksO}aGLoWXS#Up)pPmf!_w^61Q&6O>AUz%3G#yOJ4JpOlP0+>
zu>z~ObgkW}u*rH#g(dT{FkipMV*kB7c#Y+s9w@opjz~lhZQ;MmJqO;L34Dv8?mIIQ
zpK-pLB>u=GC4;!X5oz<9$7{*(XVhr%%O+04Ea!NNCIsKHQ_}n#oDj#=J-r?L=?ir4
zJ$S|6Tv*Fo=sF6cd;*!6eSknJNT^pzV$3*7qgT>9>s?cO-Ah~4L}O_jXD|G1aB3vC
zh>vNIzZPgzEgeK#O=|`)9olpI8x#C{0$&DFS^e7*KmL9VsFG|wAcc)3VnV6@6hH0+
zS8~Exj&KxlRL4fh{U9@d>$;&{XJ)$}_%#2}61ut9M27cySKjji=4UjksIk=-b>h4w
zh#`Z8cA^~qN)wLRo%0l%nV?FUsR`FHutwp)0lnDixr(bXG|$}J)Nro5w(B^nQ76IB
zz{(z<=)fg+<z~t5Vjf$|#$_^3rU)pFpZQql(}=xkW=*K)=D8cFUZgr0vDmSLCD@zG
zr9nmb;ru<=Pc*Q>qRsrC3c`tne{*5O)O16fuBlOl^TvK(Kd3^zc`Yt!DwH)SMgbL=
z1_Ma)c)2esZ99){XHlHr9>0LOxo_|-H|Pwj;|!k>wSQNNkj${w+$3MMrRYR&u3}}2
zgk-c*Zvq0w(S&z{1P^wjLCf|8tV8G5xWczBvBl>RMw>3l<b00ojgOvD!K{3rZ5eC5
zQpGVUnSSUMAEx<54{z2g^|@yG=4`87=LF*G><=Ou#gsZWxQODd2b_!w1)Xqr{M6!U
z|Ad{)H&!ag`gOHDAv(j;1~bNrm(2_dwccbiaIjj(ZylGgch>iACaO4_(}8NNv9_B3
zW2k*~27&1ma5P$DWnyOer?F0V;15DP#2x%X(3=0V99b{{>A$%M+I}iMhR9PsKHmZY
zXYrt3*<KGunIhmC6wTNeqFhPOw-tw~jzU0)57cP<DCPxeB3?^=%Kk+wa2&UoNLP-w
z#+`d>dCzjnM5$j@(~nHU(tN=WF1l7C64qaZZL`UIFPJw>n2+k@F_f!s*fZVJZ<oi*
zE?|QVvXMOeh@x?NLC0($3%1xz0ELzn_X|#aocsb{>6}+<{3_HdcKx8sZ0K%V6Gtq4
z2U9J=)t&UHYa^1&fAnl7aeMk;b~Rjvva37cm6foEk>FViT&>vVONYRSVUiYPlEyrJ
zSXMX%;{oJ(#>Jpgb@0?<yh<z{s6i^pQ2?n~WVPzSr;>u!Mk%t-vm-5f)tE?_g%uR{
zZ!Xe_hvl_cy=37c?@gG|AL>oxhvE3zM1jPE>M|DM3T~cn&ArQm`%LJo9DhRS>rDp5
za~qwTh}DQdgVp|(%~_WYfXOuU+cGRLB5a*|$Q8YZ;B6gXP}Ds}pa9d42R((Hf1sUF
zD|4TH)?Z#OVRARmAVcrgPsaq;Tj+~5w}atuL<B}DTN<b%ak}j*f$;go<_AIi{7>X=
zydn(#lk5UfgqiDv=5e7w*WVOy#4uS`!^6%&3ij)^Y3!?twM-^^wCA=*n9fwAT&V*D
zO?c+ziSF)&`iZx<U0-et!mt~OXfx2be%?2EK$~6{ibc6(6is~{VA~?prCyFvtBm>>
z=oEr4=yljc6ev32RD^N$Hy8FeXt^p&D#PUSP-h?zOBU)09R8q)ny9G6-xzt_U!ucE
z^{nsc`6r2d(r&+%gEp!Vr3RHW-sh3AA0gAQ7KZ^hzdA`yEYHHOIpAQY2avg1@8Kc$
z0OIRNRL;th9vk^Nm`okLBL%T9C`o0cWgl-jeP<@KsI(MeP>Fc*o~?M&t%68YSUNT`
z$eEk&zh}2VD;y;`S_x(gep@B|)O{!uklcoLh)yvt_4ItrSyx>0rMiWKB1QC=|J4A>
z%3?WAb^<LItCptf@EG4tWT&h3*JlG_SqP{)6c!OVNmnq8+Lf-Q%e-nJns)%(*aK0n
zB4_EdBBk*4mJD@Vu7jJB0;Zw59b}nsX*5jhRGoCd-+qM33XHnQx8Mt0;W$TrKjGko
zdSxc%-qz+`AZWi{{$9LN&llvFTE)66mnwF(C1=c`NK1%$QO)~PTqv-eH}UP6mzc}0
z&`q4Ifqp!<-}E^+>FQ#~fX%!866tEwvz1W!6uu}%8!YyYo)#?qWhpEZT8Ypc+XheQ
zWj&V-ucgJYhBXyad8S%kDk$ysJ7J(2W}XxvIJO#1pxzqM%MkXFVe}<=ql&|vZpnUF
zm@gPy$RWzHuC74GgfH#0osmRX>PAS)Z=&ks?R{-}CO-%w;k!lhA%)}nAv>Z`tZi96
z5=P^pGH$e30Bs>7x!OnO`zAiC3qwT%?3%V)R=GhoJ2*=f@JrD`%Ia&;;H=FOZ^D26
z7gSckKq8ofhYw*6GVl8~9$HYZWXXIrGkHyx*oxXM{G61rlw7(}uMpqzHgSc<fmwy(
z-*>@x2gkO+&`E-o2x${XUs0s|oHEI84R0EpGftU3I8U<3_Pk6yZTfrMF#>%F@2D^}
zmjVQj3|m$5iRA7zNq92PhU3hoq7)U3qgnIKAwyKAMjj!Vt@bmZEsyFcJ^6`s_VJ&a
zDnpWFGf;DTx<drUPrmlkA*b^~D90u2><p3yk<8UV<^34)y5h7+!Vk1nSr2Wt(LfD9
zt<X*%;HhRz!96Evy+h;;&z73t*a&nDjr5Yu;6NNk8WqUUntg~S@OZ{!PB~w@iXpj7
zK$x^cW@ko)fTuQ~jBCQh|2LNkNd+vMx&q1e+V`F1eqyLM3C4nJk3%DhzNPb@FI?Jr
zT%7pT@b#*Ex-hTpkcr`vJ20cKyo2^%SEU>%)0<gcG(PstTfha%7x5w26#Q=I-rny_
z7w8wShQcuspr|Z}_4eQ8Fq+Ya!EeZ!Ec1@Zk%`p>K-Wt_<00PDj|VM$W&3e$+M*O>
z_Bpw)-kp#PQO$1M^yON$ax!JG6g~1_DG}FlieUY=Oc9Zx>{Hl5UA_c()|cr!(jV0%
zcn5@|B*vr&TR9()xg-g=TG*+p=`>t#QjnB#zQ^|Y2-&PEi0ZlV5ZhgP_TnjNOfHpB
zXI9=RpUEN5_VGGw<&2T!Xg}oL9|W3SWX89UVq?t*(f`ebBXnbBW6(l}nhNcGUUxJM
z^-4RtG+4&htMK7z!ie0X{Sb}gLSu^ad$KuspSsq!V=oKE5-W=IYoN;J4~aBT^Pcjo
z(ITrv^hKBIl_(q|ab1bChrq|v*ixgR^L+4vh6}hQ%f~}#R*a9^g<C<lT2Xr8Q1TDx
zk;cc28llYG{7IcMw|q{KWa3Iq=R}wXuOYV8>l%cPH5#p}95WI*l$Q4eoIQfXQPBXX
z-y@w{59iT%BGyT2Hw>H;<V3{lA2dD$1~Pr0t%y3q1*66D4<Tl|-tn;3UK2B92#3sN
zZq?JxW8PQJIJjAcx;9CFjN>HxY*2?fGJZ-!KAO*yNOa(rJ1S9W831;zCO*qwLB0NO
zE@5$$?|qwcS!RwN2-InYdO?Mq;truvxpV6~va4BN&wDL=HF>Hn-yHKurW#LpzYn06
zde$9q2Y!<NwTc*V)fcW1yo4SH>7dSgb*%@nCrQ&qw5cZRmYk;>94xG^n)n)WnuSMS
zq!inZ-_usR!HgnJ(ej>DV)^r-NKRDA7isoL$<pw?ix+6qkwrn*&!^E)rb={R&iD#?
z5eo@<bO(ZS(RQs95^b`c#@-^WF?e;RR?{^`we%5Lqov?F<)Mz{=?nT!7~KVK-Sns&
zz_Zt<q)YMCzSiZ&_sOYntwFlA*vVw79T)T{#P}zaAj9%?Oo$QalPc=j80b?gwhpec
zdR@F1$H;u%t)hYDh|y4BIye&WpPRBW%vB%$+<ck|;-$8JJ=FTN3HwUy=(dn84GpA+
zkul(BQ8DOqOWMAE9)=E*w~4@I(asjEyw2^^``Iq^<El9h!MbYECsx33lnplveBIwq
zZ7D4?@W_!e@$jj-MPbdZ8(X@jO=lXJwS%#}-+-q-t~x)#Ih(O5Ln$J?wu!1A>WAhv
zZ=zX^26*bm;klt1dEt~AdMj4@TlqoOBUU&p8)hK8_@Kj$ostV=ZHIbxszVqm#AdHK
zSYu}qJ}Pv)&<7rK(l7K%9r~b_*tz<jX5~L4>imrvbhN_Xs3N=_HHJ#7<QJnSq_RkF
zjq5FvBK1!!XI&UPa-<nq_iMPHWm-F;Iq)fpg9m@-I?To$D$`y`_VZ~$oPRd#X?i>#
z8O)-Ivyl(S`W$42{Aq!SH$qfM^xOKa{n>XYBGl93G-E20?8cS}FqFkDxQN9Pp%4N1
zlXiNdEHq@SkW^pgC`At*uGa;@-c9J(Yr7^g*i+M0f;F7r5n>XtH!Ta_xT2y^f4esq
RbtZ|Uvp3uaKmEwx{||sjqtgHY

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-dsa.result b/tests/pgp-binary-key-v4-dsa.result
new file mode 100644
index 00000000..e309526e
--- /dev/null
+++ b/tests/pgp-binary-key-v4-dsa.result
@@ -0,0 +1 @@
+OpenPGP Public Key Version 4, Created Mon Apr  7 22:23:01 1997, DSA (1024 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-dsa.testfile b/tests/pgp-binary-key-v4-dsa.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..310efce0a0916f47d3edcada2049509a3cc981fe
GIT binary patch
literal 1677
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
X^Q7Zj?;sg)1KSfR&kot*QMT-r`MCq4

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-ecc-no-userid-secret.result b/tests/pgp-binary-key-v4-ecc-no-userid-secret.result
new file mode 100644
index 00000000..9d075017
--- /dev/null
+++ b/tests/pgp-binary-key-v4-ecc-no-userid-secret.result
@@ -0,0 +1 @@
+OpenPGP Secret Key Version 4, Created Wed Aug 26 20:52:13 2020, EdDSA; Signature; Secret Subkey; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-ecc-no-userid-secret.testfile b/tests/pgp-binary-key-v4-ecc-no-userid-secret.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..289a291542e5f577ec334788088ded0fb6929152
GIT binary patch
literal 794
zcmX>a!4mIwx>k%+n~jl$@s>M3BO|+mLa|Mu^vBO7QuCKMC`p<|d|CS4=a1o&tP?&g
zN!O0vy28NlPrp$!<>-+E&n_;jj8JFETTpUU;O)0myTy({Rh4qz0^bO_9BOBg7vo}(
zU~K|fz}m^Wq<=3HHz$)Q7t?G;COJk1MNR<`_3M`!nEDoqDYD%Abm!WSJs-|~h*dL&
z2_N~!$gp6YLYc-6scGBR@I=hHeABIR`wxldrA=x#gk_tmUcGH(_@7^Ud}h2=JENY{
zTo;-6$Pce=_6RMmpZh5x`=5`c+aLDh*u2QXBmT<tZ+A|B!#CNZ&u+}9Q#T8l#bCL3
z<}y<!>zORc42%r#+IU}NiTa<Dj$ig@(f9Ad8XH3n+iL7!J?CrdI@@+p5Wm`?0~Rb2
zKtBqh_;EH9$agakzAIb6A_-K*22lm__X*~MH-8=f{0ZpqnACghChdNL@msfFh6$@|
zXZUBig`Z8wd*(m)l(`2FUHT;we&w2>bN6f;t7UVeRy3=uWMsHuwQS4h8K-87mmAE=
z^UZ5_(^>Ib=4{K0_#(dNKk_ax;Rw{OYm5v%Okw{bQ>vCa=G5jJEqhXav*7U7GY6Xt
zo;*<!`IY(Fi;>}SY}%=m>$CSK9)I4M|5|x-qwKV=;kz~}{W&<r&bi_v@9|i0x)I_6
zr<>`ajI5x9ld(q5Lt^1HE4`362@>LE9CJGkrM0I#43Yo0ar&QakMx-tIXD>@{<}%f
zW(eE0&p;_8{nf5jXXWa+*694J7k%sIXFK7b73U6q?n8~(0+xrkWRrS_kzuaq*GpyZ
z?%fnMQ2FF@X|2EZO}^eUG7V=I342+jv1fk)rr@2uS|9Ed1Q-1jX7daFB+<W;<7}D2
P`whi6M4PrUF6IINT}x7!

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-ecc-rev.result b/tests/pgp-binary-key-v4-ecc-rev.result
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/pgp-binary-key-v4-ecc-secret-key.result b/tests/pgp-binary-key-v4-ecc-secret-key.result
new file mode 100644
index 00000000..ff323a7a
--- /dev/null
+++ b/tests/pgp-binary-key-v4-ecc-secret-key.result
@@ -0,0 +1 @@
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:07:46 2020, EdDSA; User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-ecc-secret-key.testfile b/tests/pgp-binary-key-v4-ecc-secret-key.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..f53f47af95a7e26d141d98a898bcc33dbbeeb381
GIT binary patch
literal 494
zcmbOd!4mJNwn>arn~jl$@s>M3BO|+m0b9o`Ci!JsCWV-9y>mogQ26=YT)F)<{E>}Y
zgx;J8k7i)_D=ueL&{%p;F2VM;QT38n(W<G3e?@(mtM;2^vZj1+krv;_EsCxw<%vZp
z3eFitnZ*juiADK23O1=J4#^;vUVc%!UB@&QVKEK{J26ETp*-&=`^1h3oA@RyVV|RM
z)+<fzIx7>%X-v}0tenh;(ivE}IXT#w*hINFIk=fv#F&^FndBIm#2Xm6I0ax@x|10h
zUPRS!)P-EKmcBUqV0DG{)j8&YU6U+LwkFOq4}Fy0F2KmJ&v54k<`12@JT4K-Dj)0l
zn5@ojdG2twu>CCmiqCKDndZcT14W1n94OO68CgN0^4;m<-R7f-JDD?jeO-k%_wSVb
z_sX|S<J`;hUK3eAa~Co*a<DTn{Li1O|8~QUmUhpF^F!UkgXbQ|UoDjrq44;^g-HeC
zlNMwMhICZ0NC3U9K)~BP$R2yB$?(5Y>;1#^+P$X=Lf@HAZLW9(H0ya<JYRZmcGN$k
rpmW^}|1_RIJo@>*h7$wJHizB!_{D2xd-3Gu?Yb<aa5Q&Q?{gLaQ%$#n

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-rsa-key.result b/tests/pgp-binary-key-v4-rsa-key.result
new file mode 100644
index 00000000..c22310fb
--- /dev/null
+++ b/tests/pgp-binary-key-v4-rsa-key.result
@@ -0,0 +1 @@
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-rsa-key.testfile b/tests/pgp-binary-key-v4-rsa-key.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..7b70497d27f2fe9c83be8ad5fd7e6f1849b35683
GIT binary patch
literal 3695
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
G=>GxH2@ewh

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-rsa-no-userid-rev.result b/tests/pgp-binary-key-v4-rsa-no-userid-rev.result
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/pgp-binary-key-v4-rsa-no-userid-secret.result b/tests/pgp-binary-key-v4-rsa-no-userid-secret.result
new file mode 100644
index 00000000..c3c2ae22
--- /dev/null
+++ b/tests/pgp-binary-key-v4-rsa-no-userid-secret.result
@@ -0,0 +1 @@
+OpenPGP Secret Key Version 4, Created Sat Aug 22 20:13:52 2020, RSA (Encrypt or Sign, 3072 bits); Signature; Secret Subkey; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-rsa-no-userid-secret.testfile b/tests/pgp-binary-key-v4-rsa-no-userid-secret.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..7d5a7b465f4069c74fb8c200ae4dfd2ea8fe36fc
GIT binary patch
literal 5907
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
RePgl0P0?du>??tL{{iWnPmllr

literal 0
HcmV?d00001

diff --git a/tests/pgp-binary-key-v4-rsa-secret-key.result b/tests/pgp-binary-key-v4-rsa-secret-key.result
new file mode 100644
index 00000000..c22310fb
--- /dev/null
+++ b/tests/pgp-binary-key-v4-rsa-secret-key.result
@@ -0,0 +1 @@
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
diff --git a/tests/pgp-binary-key-v4-rsa-secret-key.testfile b/tests/pgp-binary-key-v4-rsa-secret-key.testfile
new file mode 100644
index 0000000000000000000000000000000000000000..7b70497d27f2fe9c83be8ad5fd7e6f1849b35683
GIT binary patch
literal 3695
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
G=>GxH2@ewh

literal 0
HcmV?d00001

-- 
2.20.1

