summary |
shortlog | log |
commit |
commitdiff |
tree
first ⋅ prev ⋅ next
W. Trevor King [Thu, 19 Dec 2013 05:09:42 +0000 (21:09 -0800)]
Add a flexible packet-parsing framework
Shunting packet-type processing out to type-specific methods. For
example, 'public-key packet' packets will be parsed by
PGPPacket._parse_public_key_packet.
From the re docs [1]:
'+'
Causes the resulting RE to match 1 or more repetitions of the
preceding RE. ab+ will match 'a' followed by any non-zero number
of 'b's; it will not match just 'a'.
...
\W
For Unicode (str) patterns:
Matches Unicode word characters; this includes most characters
that can be part of a word in any language, as well as numbers
and the underscore. If the ASCII flag is used, only [a-zA-Z0-9_]
is matched (but the flag affects the entire regular expression,
so in such cases using an explicit [a-zA-Z0-9_] may be a better
choice).
For 8-bit (bytes) patterns:
Matches characters considered alphanumeric in the ASCII
character set; this is equivalent to [a-zA-Z0-9_].
[1]: http://docs.python.org/3/library/re.html#regular-expression-syntax
W. Trevor King [Thu, 19 Dec 2013 04:56:42 +0000 (20:56 -0800)]
gpg-migrate.py: Convert PGPPacket 'packet-tag' key to 'type'
And convert the integer to a string using the table from RFC 4880 [1]:
The packet tag denotes what type of packet the body holds. Note
that old format headers can only have tags less than 16, whereas new
format headers can have tags as great as 63. The defined tags (in
decimal) are as follows:
0 -- Reserved - a packet tag MUST NOT have this value
1 -- Public-Key Encrypted Session Key Packet
2 -- Signature Packet
3 -- Symmetric-Key Encrypted Session Key Packet
4 -- One-Pass Signature Packet
5 -- Secret-Key Packet
6 -- Public-Key Packet
7 -- Secret-Subkey Packet
8 -- Compressed Data Packet
9 -- Symmetrically Encrypted Data Packet
10 -- Marker Packet
11 -- Literal Data Packet
12 -- Trust Packet
13 -- User ID Packet
14 -- Public-Subkey Packet
17 -- User Attribute Packet
18 -- Sym. Encrypted and Integrity Protected Data Packet
19 -- Modification Detection Code Packet
60 to 63 -- Private or Experimental Values
[1]: http://tools.ietf.org/search/rfc4880#section-4.3
W. Trevor King [Thu, 19 Dec 2013 04:46:48 +0000 (20:46 -0800)]
Pull PGPPacket header parsing out into _parse_header
This parsing is distinct from the payload parsing, so stash it in a
separate method.
W. Trevor King [Thu, 19 Dec 2013 04:45:21 +0000 (20:45 -0800)]
Add packets_from_bytes to help parse multi-packet streams
W. Trevor King [Thu, 19 Dec 2013 04:44:30 +0000 (20:44 -0800)]
Check for short packets in PGPPacket.from_bytes
When the data is longer than expected, the packet may just be part of
a stream.
W. Trevor King [Thu, 19 Dec 2013 04:37:33 +0000 (20:37 -0800)]
Track data offset in bytes, and extract the packet payload
Return the offset when we're done, because there may be multiple
packets in a stream.
W. Trevor King [Thu, 19 Dec 2013 04:31:15 +0000 (20:31 -0800)]
Extract the packet length from the old-format length header
From RFC 4880 [1]:
Scalar numbers are unsigned and are always stored in big-endian
format. Using n[k] to refer to the kth octet being interpreted, the
value of a two-octet scalar is ((n[0] << 8) + n[1]). The value of a
four-octet scalar is ((n[0] << 24) + (n[1] << 16) + (n[2] << 8) +
n[3]).
The struct big-endian byte-order character is '>' [2].
[1]: http://tools.ietf.org/search/rfc4880#section-3.1
[2]: http://docs.python.org/3/library/struct.html#byte-order-size-and-alignment
W. Trevor King [Thu, 19 Dec 2013 04:05:25 +0000 (20:05 -0800)]
Add PGPPacket._old_format_packet_lengths
From RFC 4880 [1]:
The meaning of the length-type in old format packets is:
0 - The packet has a one-octet length. The header is 2 octets long.
1 - The packet has a two-octet length. The header is 3 octets long.
2 - The packet has a four-octet length. The header is 5 octets long.
3 - The packet is of indeterminate length. The header is 1 octet
long, and the implementation must determine how long the packet
is. If the packet is in a file, this means that the packet
extends until the end of the file. In general, an implementation
SHOULD NOT use indeterminate-length packets except where the end
of the data will be clear from the context, and even then it is
better to use a definite length, or a new format header. The new
format headers described below have a mechanism for precisely
encoding data of indeterminate length.
The struct format characters are [2]:
Format C Type Python type Standard size Notes
B unsigned char integer 1 (3)
H unsigned short integer 2 (3)
I unsigned int integer 4 (3)
3. When attempting to pack a non-integer using any of the integer
conversion codes, if the non-integer has a __index__() method
then that method is called to convert the argument to an integer
before packing.
Changed in version 3.2: Use of the __index__() method for
non-integers is new in 3.2.
[1]: http://tools.ietf.org/search/rfc4880#section-4.2.1
[2]: http://docs.python.org/3/library/struct.html#format-characters
W. Trevor King [Thu, 19 Dec 2013 03:51:10 +0000 (19:51 -0800)]
Extract the packet tag
From RFC 4880 [1]:
The first octet of the packet header is called the "Packet Tag". It
determines the format of the header and denotes the packet contents.
The remainder of the packet header is the length of the packet.
Note that the most significant bit is the leftmost bit, called bit
7. A mask for this bit is 0x80 in hexadecimal.
+---------------+
PTag |7 6 5 4 3 2 1 0|
+---------------+
Bit 7 -- Always one
Bit 6 -- New packet format if set
PGP 2.6.x only uses old format packets. Thus, software that
interoperates with those versions of PGP must only use old format
packets. If interoperability is not an issue, the new packet format
is RECOMMENDED. Note that old format packets have four bits of
packet tags, and new format packets have six; some features cannot
be used and still be backward-compatible.
Also note that packets with a tag greater than or equal to 16 MUST
use new format packets. The old format packets can only express
tags less than or equal to 15.
Old format packets contain:
Bits 5-2 -- packet tag
Bits 1-0 -- length-type
New format packets contain:
Bits 5-0 -- packet tag
[1]: http://tools.ietf.org/search/rfc4880#section-4.2
W. Trevor King [Thu, 19 Dec 2013 03:49:08 +0000 (19:49 -0800)]
Stub out gpg-migrate.py
Following the general approach outlined by Atom Smasher [1], but I'll
just parse the packets directly in Python.
[1]: http://atom.smasher.org/gpg/gpg-migrate.txt