Skip to content

Instantly share code, notes, and snippets.

@laomaiweng
Last active January 14, 2023 01:14
Show Gist options
  • Save laomaiweng/cb1d154857bb417afd7ad35f03e33881 to your computer and use it in GitHub Desktop.
Save laomaiweng/cb1d154857bb417afd7ad35f03e33881 to your computer and use it in GitHub Desktop.
#!/bin/bash
die() {
echo "error: $*"
exit 1
} >&2
if [[ $# != 1 || "$1" =~ ^(-h|--help)$ ]]; then
echo "usage: ${0##*/} <recipient>"
exit 1
fi
recipient="$1"
[[ -n "$recipient" ]] || die "missing recipient"
output="$(mktemp --tmpdir)"
echo "output: $output"
echo
declare -i i=0
while true; do
((i++))
printf "\r>>>>>>>> run $i"
gpg2 --yes --encrypt -r "$recipient" -o "$output" <<<'o hai'
if python -m pgparse "$output" | grep -q 'length = 523' &>/dev/null; then
echo
python -m pgparse "$output"
break
fi
done
set args --yes --encrypt -r $GPGRECIPIENT -o foo.gpg <<<"o hai"
set confirm on
break build-packet.c:344
commands
silent
printf "---> nbits = %d\n", gcry_mpi_get_nbits(a)
continue
end
break build-packet.c:347 if nbytes != 514
# don't quit if we hit our breakpoint
set $_exitcode = -1
run
if $_exitcode != -1
quit
end
import argparse
import enum
from construct import *
class PacketTag(enum.IntEnum):
Reserved = 0
PublicKeyEncryptedSessionKeyPacket = 1
SignaturePacket = 2
SymmetricKeyEncryptedSessionKeyPacket = 3
OnePassSignaturePacket = 4
SecretKeyPacket = 5
PublicKeyPacket = 6
SecretSubkeyPacket = 7
CompressedDataPacket = 8
SymmetricallyEncryptedDataPacket = 9
MarkerPacket = 10
LiteralDataPacket = 11
TrustPacket = 12
UserIDPacket = 13
PublicSubkeyPacket = 14
UserAttributePacket = 17
SymEncryptedAndIntegrityProtectedDataPacket = 18
ModificationDetectionCodePacket = 19
NewPacketTag = FocusedSeq('tag',
'tag' / Byte,
Check(this.tag & 0xc0 == 0xc0)
)
OldPacketTag = FocusedSeq('tag',
'tag' / Byte,
Check(this.tag & 0xc0 == 0x80)
)
def old_packet_length_type(this):
sizes = [1, 2, 4, None]
return sizes[this._tag_byte & 3]
OldPacketHeader = Struct(
'_tag_byte' / OldPacketTag,
'tag' / Enum(Computed(lambda this: (this._tag_byte >> 2) & 0xf), PacketTag),
'length' / BytesInteger(lambda this: old_packet_length_type(this), signed=False, swapped=False)
)
NewPacketLength1 = FocusedSeq('length',
'len0' / Byte,
Check(this.len0 < 192),
'length' / Computed(this.len0)
)
NewPacketLength2 = FocusedSeq('length',
'len0' / Byte,
'len1' / Byte,
Check(lambda this: 192 <= this.len0 <= 223),
'length' / Computed(lambda this: ((this.len0 - 192) << 8) + this.len1 + 192)
)
NewPacketLength5 = FocusedSeq('length',
Const(255, Byte),
'length' / Int32ub
)
NewPacketLengthPartial = FocusedSeq('length',
'len0' / Byte,
Check(lambda this: 224 <= this.len0 < 255),
'length' / Computed(lambda this: 1 << (this.len0 & 0x1f))
)
NewPacketLength = Select(NewPacketLength1, NewPacketLength2, NewPacketLength5, NewPacketLengthPartial)
NewPacketHeader = Struct(
'_tag_byte' / NewPacketTag,
'tag' / Enum(Computed(this._tag_byte & 0x3f), PacketTag),
'length' / NewPacketLength
)
PacketHeader = Select(OldPacketHeader, NewPacketHeader)
class PubKeyAlgo(enum.IntEnum):
PUBKEY_ALGO_RSA = 1
PUBKEY_ALGO_RSA_E = 2 # RSA encrypt only (legacy)
PUBKEY_ALGO_RSA_S = 3 # RSA sign only (legacy)
PUBKEY_ALGO_ELGAMAL_E = 16 # Elgamal encrypt only
PUBKEY_ALGO_DSA = 17
PUBKEY_ALGO_ECDH = 18 # RFC-6637
PUBKEY_ALGO_ECDSA = 19 # RFC-6637
PUBKEY_ALGO_ELGAMAL = 20 # Elgamal encrypt+sign (legacy)
# 21 # reserved by OpenPGP
PUBKEY_ALGO_EDDSA = 22 # EdDSA (not yet assigned)
PUBKEY_ALGO_PRIVATE10 = 110
PublicKeyEncryptedSessionKeyPacket = Struct(
'version' / Const(3, Byte),
'keyid' / Hex(Bytes(8)),
'pubkey_algo' / Enum(Byte, PubKeyAlgo),
'encrypted_session_key' / Struct(
'nbits' / Int16ub,
'data' / Bytes(this._._.header.length - 10 - 2)
)
)
Packet = Struct(
'header' / PacketHeader,
'body' / Switch(this.header.tag,
{
PacketTag.PublicKeyEncryptedSessionKeyPacket.name: PublicKeyEncryptedSessionKeyPacket,
},
default=Bytes(this.header.length)
)
)
def main(args):
print(GreedyRange(Packet).parse(args.path.read()))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Construct-based PGP parser')
parser.add_argument('path', type=argparse.FileType('rb'), help='PGP file to parse')
main(parser.parse_args())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment