-----BEGIN PGP SIGNED MESSAGE-----
OpenPGP Comments - Bill Stewart, bill(_dot_)stewart(_at_)pobox(_dot_)com,
12/2/97
Based on 11/97 draft-ietf-openpgp-formats-00.txt ,
plus some mailing list discussion.
===================================================
Structural comment - the draft is a bottom-up document,
rather than a top-down document. That generally makes the
syntax clearer, in that you never use a FooObject as a component
of a BarObject until you've seen the syntax for the FooObject,
but it's difficult to use for recursive structures,
and it's extremely difficult to do a good job of explaining the
semantics, at least when the context and meaning are as
closely intertwined as they are here. I say this partly as
a call for careful, clear writing, and partly as an apology for
stuff I get wrong because I don't quite follow it :-)
====================================================
Major missing capability - support for Stealth formats.
I suppose that, since I haven't written up a proposal by now,
I can't complain (:-), but it'd be nice to leave this open
for OpenPGPv2 or something.
=============
Various packed number formats - it's probably cleaner to
describe these up front, or at least before they're used.
=============
3.3 Counted Strings -
"A counted string consists of a length and
then N octets of string data"
How long is the length field? What's its format?
I'm guessing it's one of the various variable-length-packed-number
formats used in PGP, but you need to specify which one.
3.4 Time Fields - Y2038 problem - Also 5.2.2.2, 5.5.2. 5.9
Using Unix-style "seconds since 1970" dates as the only format is
not a bright thing to do in 1997.... A couple of alternatives:
a) Define a new format, like "yyyymmdd,milliseconds of day" or
"microseconds since 1AD/01/01/00:00:00" (easy fit in 64bits) or
"yyyymmddhhmmss.nanosec", that'll be good for all
reasonable applications (are microseconds enough??)
b) Time values below 10,000,000 are days since 1AD/01/01
(assumes 1 day granularity is enough, and no PGP in first
115 days of 1970 :-) Or hours since 1AD/01/01/00:00:00.
(Another packed number format - sigh :-)
c) At very minimum, make the times modulo-2**32, with values
assumed to be later than ~1990, and validity intervals
adjusted appropriately. That still limits you to
68-year usage, or 34 for safety, which is unfortunately
a real problem for long-term e-commerce.
d) Use the notation field in signatures if you really care...
There's also the problem that times can't be trusted,
so you shouldn't depend on them too strongly.
3.5.1.3 / 3.5.3.3 Iterated-Salted
What a blazingly ugly design! Is it really necessary to use
a byte-count in a special one-octet-floating-point format,
rather than using an iteration count? Probably saves one
multiplication when preparing the argument for a hash,
at the cost of a couple masks and shifts and adds a hunk of code.
Especially with the "Conventionally Encrypted Session Key"
available, the extra complexity seems unnecessary.
If anybody's really using this option, it probably should be kept,
but as a MAY read, DEPRECATED generate. Otherwise reserve the
S2K-type indicator 0x03 and drop it.
4.2 Packet Headers - Packet Length.
I'd rather have seen a cleaner format for the length,
but that's a job for OpenPGPv2 to clean up.
(In particular, I'd like to see a format that allows for
padding to multiples of 4 or 8 octets.)
Meanwhile, it appears that the Partial Body Length can
support indefinite-length material, which is critical,
since it allows PGP to be used with streaming input such as
speech that goes on for a long time, (though the particular
encoding is inefficient if the data comes in natural chunk sizes
that aren't powers of 2 (or at least 3*2**n), or compresses
to irregular sizes.) It's worth noting this kind of application
in the draft, to encourage OpenPGP implementations to be designed
in ways that aren't limited by temp files with maximum lengths.
4.3 Packet Tags / 5.1 Encrypted Session Key Packet - (nitpick)
should "Encrypted Session Key Packet" be renamed
"Public Key Encrypted Session Key Packet" now that
there's also a "Conventionally Encrypted Session Key Packet"?
Also, the "Name Packet" (Tag 13) is yet another packet that's
later called a "UserID Packet". My personal preference is to
call it a "User Data Packet" - see 5.11 for discussion.
5.1 Encrypted Session Key Packet - Traffic Analysis Risk -
The KeyID field, as defined, leads to a major traffic analysis risk,
but the format doesn't depend critically on the value in the field.
At a previous Bay Area Cypherpunks meeting, somebody from PGP
mentioned a request from some freedom fighter users that KeyIDs
be shorter, because the current tyrannical government was
using them to identify who to torture into decrypting messages -
having PGP was incriminating enough, but with short KeyIDs,
e.g. 0-3 or 0-16, it's possible to reduce decryption workload
without indentifying the user of the message.
Some obvious alternative implementations are to keep the field
for compatibility, while specifying that the
- - the receiver of a message MAY attempt decryption regardless
of the value in the field, regardless of whether
it's intended for him or not.
- - the sender must output a value in the field that
- -- SHOULD be the KeyID, but
- -- MAY be all-0, for which the receiver SHOULD/MAY decrypt
- -- MAY be Z=1-63 bits of leading 0 followed by the low-order
64-Z bits of the intended recipient's KeyID, which the
receiver SHOULD/MAY decrypt if it matches his KeyID's low bits.
- -- MAY be some other prearranged value, e.g. a multicast code,
which the receiver MAY decide to attempt to decrypt.
Since this just requires permission in the spec, rather than
needing specific implementation, and since the main negative impact
on non-implementing users is attempting to decrypt
an occasional message that wasn't intended for them that they
happened to receive, I'd like to ask that it be included.
5.2 Signature Packet
===== documentation comments
This section deals with some of the most complex parts of PGP.
It needs to address where the signature packets fall in the
grand scheme of things, e.g. needs enough BNF here or elsewhere to say
Signed_Thing::= Signed_Key | Signed_Doc | One_Pass_Signed_Doc
Signed_Key ::= one Public Key Packet (Tag 6) FOLLOWED BY
one or more Signature_Packet(Tag 2)
Signed_Doc ::= one Signature_Packet(Tag 2) FOLLOWED BY
one Data_Packet
Data_Packet ::= Compressed_Data_Packet(Tag 8) |
Literal Data Packet
One_Pass_Signed_Doc::= one One_Pass_Signature_Packet(Tag4) FOLLOWED BY
one Data_Packet FOLLOWED BY
one Signature Packet
(Correcting this as needed.)
It also would be nice to put some of the semantic issues in the
front section here - at very least, the definition of
"self-signature".
Also, while PGP 2.6.2 uses Version 3 Signature Packets,
either section 5.2 or 5.2.1 should indicate that it only supports
RSA and not also the DSA signatures.
=== proposed semantic issues for 5.2:
Implementations SHOULD support generation of V3 signatures,
and PROBABLY (??) SHOULD generate them when encrypting to RSA keys,
or at least RSA keys received from a Public Key Packet Version 3.
Implementations SHOULD NOT generate V3 signatures for non-RSA keys?
5.2.2 Version 4 Signature Packet Format
The format does not contain a KeyID field, and does not
document how to find the KeyID from the various Public Key types --
there needs to be at least a reference to the section
currently numbered 8.2.
The subpacket stuff is confusing (no surprise, it's new.)
The descriptions of the Hashed and Unhashed subpacket data should be
- - one or more hashed subpackets
- - zero or more unhashed subpackets
or else these two lines and their preceding lines should be replaced by
- - hashed_subpacket block
- - unhashed_subpacket block
and the definitions of the subpacket blocks (here or in 5.2.2.1) should be
- - Two-octet octet count for following subpacket data.
- - zero or more (un)hashed subpackets
5.2.2.1 - Signature Subpacket Specification
I'm assuming the "Two-octet octet count" in this section is the
same field as in 5.2.2? (Should be anyway.) Only should appear once.
The description up front needs to say something like
- -------------
Some subpacket types are mandatory, others are optional.
Some subpacket types only apply to self-signatures.
Some subpacket types can appear multiple times, others just once.
Some subpacket types are always hashed, some are always unhashed.
(Are any of them optionally hashed?)
A hashed subpacket MUST be in the hashed_subpacket block, and
an unhashed subpacket MUST/MAY appear in the unhashed_subpacket block.
- -------------
The header format description is clumsy, and should be restructured.
Replace the
- subpacket type (1 octet):
If bit 7 is set, subpacket understanding is critical,
with
- subpacket_type_and_criticality_flag (1 octet)
bit 7 - Criticality Flag
bits 6-0 - subpacket type.
I'd recommend that the table of subpacket types indicate
which of these attributes apply to it, e.g.:
- --------------
2 = signature creation time, (hashed,mandatory,once)
3 = signature expiration time, (hashed,optional,once)
4 = exportable, (hashed,optional,once)
5 = trust signature, (hashed,????,????)
6 = regular expression, (hashed,optional,once)
7 = revocable, (hashed,optional,once)
9 = key expiration time, (hashed,optional,once,self)
10 = reserved for PGP use (hashed,optional,multiple,self)
11 = preferred symmetric algorithms, (hashed,optional,once)
12 = revocation key, (hashed,optional,????,self)
16 = issuer key ID, (unhashed,mandatory,once)
20 = notation data, (unhashed,optional,multiple)
21 = preferred hash algorithms, (hashed,optional,once)
22 = preferred compression algorithms, (hashed,optional,once)
23 = key server preferences, (hashed,optional,once,self)
24 = preferred key server hashed,optional,once,self)
- ------------
Semantics Question - is support for optional subpacket types MUST?
or only SHOULD or MAY?
Is support for types not defined here MAY or MUST NOT?
It would be nice to reserve some of this space for
user-defined functions, though it's a tossup whether the best mechanism
is to define additional numbers (e.g. reserve 64-127 or 96-127)
or to use the notation data with user-specified values (better?).
The Criticality Flag stuff is confusing. I think I understand it better
now than I did before, so here's what I think it means (and if
I'm wrong, I hope somebody will rewrite it so it sinks in next time:-)
The Criticality Flag is a request from the signer to the
recipient's OpenPGP implementation for strict semantic support
for optional and undefined subpacket types.
If the recipient's implementation does not recognize or
recognizes but does not implement a subpacket type
for which the signer has set the Criticality Flag
- For a Signed_Doc or One_Pass_Signed_Doc, the implementation
? SHOULD ignore the Criticality Flag
? SHOULD use the implementation-defined bad-signature
handling response.
- For a Signed_Public_Key,
Define a Valid Self-Signature as
The packet contains an Issuer KeyID subpacket,
The implementation must calculate the Key's KeyID
The Issuer KeyID matches the Key's KeyID
The implementation must calculate the signature
for the public key packet, using the public key,
as described in Section #.##
The calculated signature matches.
Depending on whether the signature is a self-signature,
- If the Signature Packet is not a Self-Signature,
--- the implementation SHOULD discard the Signature Packet
--- the implementation SHOULD invoke error-handling
- If the Signature Packet is a Valid Self-Signature,
--- the implementation MUST? discard the Signature Packet
--- the implementation SHOULD? invalidate the
entire key that the Signature signs,
at least if it's a brand-new key
--- the implementation SHOULD NOT? continue to use
the key, at least if it's new.
--- the implementation SHOULD invoke error-handling
- If the Signature Packet is an INVALID Self-Signature,
the implementation MUST discard the signature
but PROBABLY SHOULD NOT? invalidate the key,
unless it's a brand-new key.
5.2.2.2 Signature Subpacket Types
(it'd be nice to number these, especially since you've got numbers :-)
I've already discussed Y2038 problems above, so assume they apply
here as well.
- - Signature Creation Time - MANDATORY?
Or MAY this be optional, at least for environments like
smartcards that may really not know what time it is.
- - Preferred {sym,hash,comp} - array of one-octet values
The syntax for an array needs to be specified!
Is it "Some counter field and COUNT octets"?
Or "Null-terminated bunch of octets"?
- - Exportability - needs a definition of export/import.
- - Trust Signature - this invokes a bunch of complex semantics,
which aren't explained very deeply in the one paragraph.
If they're defined stably enough to really belong in this
document, they should either be described here,
or (better) in an appendix, or There should be a pointer
to some document elsewhere that explains what all this
"meta-introducer" stuff is about and why it's different
from simply being one signature higher up the food chain.
- - Additional Recipient Request - the community seems to have
stabilized on the view that this should be
Reserved For <Somebody's> Use.
- - Notation Data - I'm unclear on the flag syntax. Is it
- First Octet - ALWAYS 0x80 or RESERVED
2nd-4th Octets - 0x00, Reserved, MUST ignore
- or - First Octet - 0x00 or 0x80 or implementation-defined
2nd-4th Octets - implementation-defined
I'd prefer the latter. Also, since this is an obvious
extension mechanism for software, we ought to define
some way to specify that the Notation is intended for
implementation-defined software use. Perhaps
0x00 - Something special
0x80 - Human-readable, non-software
0x01-0x7f - Reserved for future OpenPGP use
0x81-0xff - user-defined
- - Preferred Key Server - Currently self-signature only -
I suggest we also permit this for non-self-signatures,
so signers can indicate where they serve their keys
and maybe even where they store revocation certificates.
- - Key Server Preferences - I'm guessing a more functional definition
would be something like
- No-Modify - Key Server SHOULD NOT change any data
in the key server records for a key that
sets this field.
- - [Unclear context:] Implementations SHOULD implement a "preference"
and MAY implement a "request."
? It's not clear to me what this statement is referring to.
The "preferences" indicated above were the hash/symmetric/public
algorithms and the key servers; the only "request" I saw
was the "Additional Recipient Request".
It's also not clear what it means - does it mean that
implementations SHOULD implement the ability to accept input
packets containing preferences (perhaps obeying them),
and MAY implement the ability to generate output packets
containing the preferences?
- - JDCC Note - specifying negative preferences - Is specifying
only Triple-DES good enough? Or should we do something hokey
like making algorithm numbers 128-255 (or -1 - -128)
indicate that you really don't want alg&0x80 (or -alg)?
I lean towards the former, especially since there are
MUST defaults available, though it would be nice to say
CAST5,IDEA,-3DES so that the sender whose preferences are
3DES,Blowfish,DSASubliminal,CAST5 will know to pick CAST5
even though she likes 3DES better. That's too subtle, though.
Perhaps the negotiation rule should be
Sender SHOULD pick the algorithm supported by both
sender and receiver that the receiver prefers,
but MAY selfishly pick any algorithm supported by
both sender and receiver.
- - JDCC Note - revoking user name / user data - there isn't enough context
at this point in the document to indicate that - we've only
had hints and allegations that there really are user data packets
that are signed :-) So it needs to be later in the document.
- - JDCC Note - PGP3 other subpacket types - did it go as far as
specifying the subpacket numbers or subpacket names?
Should we reserve those numbers now?
e.g. 42 - answer subpacket - reserved for later
- - 5.2.3 Signature Types -
- - JDCC Note - What should we do about defined-but-not-implemented types?
These types 0x11-0x13 follow the "UserID Identifies A Body" model,
rather than the more general "Key Asserts Some Attribute" model
that folks like Carl Ellison have advocated (which I prefer.)
(See comments on 5.11 suggesting calling it "User Data".)
I'd recommend that we do one of two things:
1) Junk them now, stick to generic certifications,
and use either notations subpackets or other as-yet undefined
subpacket types to indicate special attributes of signatures.
We've got enough syntactical hooks already.
2) Define more syntactical hooks :-)
Keep them, and also reserve 0x14-0x1f for signature types:
implementations SHOULD/MAY accept Signature types 0x10-0x1f
as signatures on keys, MAY handle them specially, and
MAY output them (if there's a good reason.)
Alternatively (now that I've ranted against the critical bit :-),
SHOULD accept 0x10-0x17, SHOULD reject unrecognized 0x18-0x1f,
or maybe keep 0x10-0x1f for signatures you SHOULD accept and
0x80-0xff for user-defined signature types which should
be rejected if unrecognized.
- - JDCC Note - Timestamp Signatures? - Reserve for future use?
I'm not sure how a timestamp signature is different from any
other document signature, since there's already a timestamp
in the signature field. Sounds like a better job for a notation?
But somebody may make a good argument to the contrary.
Also, it's a bit odd that compressed data fields don't have
timestamps in them but literal data fields do.
- - JDCC Note - Key-only signature that doesn't cover user name -
I'm not sure what the semantics of this are,
except perhaps they're useful for self-signatures
or binding notation-based attributes to the key.
You could just as well sign a key with the user name
and ignore the user name when using the key?
On the other hand, if you want the feature,
it probably needs to be a separate signature type
so you know not to include the hash of the user name.
- - 5.3 Conventionally Encrypted Session Key (Tag 3)
It's a bit disappointing that this uses an all-zero IV,
but it's presumably already implemented.
The problem is that it gives an octet of relatively-well-known
plaintext in the encrypted session key - the algorithm ID.
It's not much use for a Bad Guy, but it's there.
- - 5.5 Key Material Packet
Some good BNF descriptions would really help here.
- - 5.5.2 - Public Key Packet Formats
Implementations SHOULD accept V3 public key packets and
MUST accept V4 public key packets?
Another minor weakness with V3 keys is that the validity period
is limited to 64k days (assuming unsigned short?),
and some applications may find 200 years a bit limiting :-)
More importantly, it doesn't allow defining keys with
very short expiration times, e.g. 1 hour or 30 seconds.
V4 keys
- The Y2038 problem is here too...
- Is this a good place to specify that implementations
MUST support DSA and El-Gamal, and SHOULD support RSA?
- - 5.5.3 - Secret Key Packet Formats
- Does this belong in the standard? Is the Secret Key Packet
ever transmitted outside the implementation?
Or is it really an implementation detail that doesn't need
to be part of a standard? I agree that it's convenient to
read your PGP Version N secret keyring with PGP Version N+1,
but to me that only rates a SHOULD and not a MUST.
In particular, there may be environments in which the
applications don't store their secret keys in files,
and don't transmit them to anyone, especially for
transient communications applications,
and there are applications that want more security than the
standard PGP implementation uses for storing its secret keys
(e.g. the UserName is visible in the secret key ring.)
Also, there may be applications that only need to
verify signatures, or only need to public-key encrypt data,
or maybe even only need to symmetric-key encrypt data,
but don't need to public-key decrypt or sign data,
and it would be nice for them to say they're OpenPGP compliant.
- Does "CFB" refer to standard CFB, or PGP-hacked CFB-variant?
- - 5.6 - Compressed Data Packet (Tag 8)
According to section 7.2, a Compressed Data Packet
should be decompressible into a valid OpenPGP message,
while this section only specifies that it contain
an RFC1951 DEFLATE block containing "some set of packets".
The spec should state at this point that the contents
of the DEFLATE block must be a valid OpenPGP message,
or more precisely, that
an OpenPGP program writing a Compressed Data Packet
MUST use a valid OpenPGP message as the contents, and that
an OpenPGP program reading a Compressed Data Packet
SHOULD assume that the decompressed contents are valid
and attempt to interpret them.
- - 5.7 - Symmetrically Encrypted Data Packet (Tag 9)
Will this packet _always_ contain either a literal or compressed?
Or will it at least always contain some PGP packets?
(For instance, you might use it to encrypt secret keys....)
Should OP be _required_ to always interpret any PGP packets in it?
- - 5.8 - Should this now say "NA" or "OP" or "McAfee" :-)
- - 5.9 - Literal Data Packet (Tag 11)
- Is it "__CONSOLE" or "_CONSOLE" (I assume one _, but it's
easy for underscores to get kerned together.)
- Perhaps the example should mention displaying on a CRT
as well as not saving it on a disk?
- Y2038 time problems again.
- The semantics are arbitrary and the syntax doesn't
indicate which choice was the sender made here - if anyone cares.
- Implements SHOULD NOT believe what they read :-)
- - 5.10 - Trust Packet (Tag 12)
Since these packets aren't exported and shouldn't be imported,
it's not clear this belongs in the standard.
The trust packet and the trust signature subpacket in 5.2.2.2
both have complex semantics that aren't very well documented.
At least these are internal-use only, though, so who cares?
I agree that they should be implementation-dependent.
I also agree that the trust packet should be signed by the user -
but the standards document has not yet told us where the
trust packet is syntactically - is it attached to one key,
in which case there's a key to self-sign with?
Is it free-floating in the public key file (more likely)?
(In which case there's no "self" to self-sign them...).
It's even worse than it appears - other people's public keys
are used in a context where you're either encrypting to them,
or checking the validity of their signatures, so there's
no need to use anybody's private keys to be able to check against,
and the instance of PGP may not even have any private key at all.
An implementation might require a private key to unlock a
secret key ring without too much annoyance, but doing so to
unlock the pubkey file seems a bit paranoid.
- - 5.11 - UserID / UserName / User Data
I'd suggest the term "User Data". Unlike "User ID" or "User Name",
it doesn't imply the "True Name" or "One Key, One Body" model
of how public keys are used - but it does imply that the data is
picked by the user, which is not only a less authoritarian model,
but more reflective of reality than some of the other terms.
It also makes it potentially less clear what the certifier
is certifying, but that also reflects reality.
Requiring UTF-8 is probably not bad - we need to be sure the field
always gets protected if it's being transmitted across
non-8-bit-safe media, which gets back to the armor-vs-mime wars.
We should at least require that a conforming implementation
MUST NOT munge the string except in automatically reversible ways
(such as MIME-Quoted-Printable or armoring the whole thing),
and should do any key-related transactions in full-8-bit.
There is one security-related problem of permitting
arbitrary characters - users can put newlines in their key strings,
or backspaces, or ANSI terminal-control escape sequences,
or other things that can encourage the user interface to lie
to the unsuspecting recipient. Banning those might be good.
- - 6.1 - Public-Key Algorithm Constants
Elliptic Curve - Yeah, they probably deserve some numbers.
Perhaps reserve 20-29 for future Elliptic Curve.
Leaving ElGamal signatures unmentioned is probably good,
but if you want to use them, anybody seeing the "16" for
ElGamal in a signature context ought to get the idea.
ElGamal signatures and DSA signatures both have subliminal
channel problems; perhaps we should allocate some symmetric-key
algorithm identifiers for those :-)
- - 6.2 - Symmetric-Key Algorithm Identifiers
By the way, how DOES PGP generate 3-key 3DES keys, since
168 bits of key is just bigger than a 160-bit hash?
Or does it use 2-key only? S2K is limited to the hash length.
- - 7 - Packet Composition
My preference is to have this section up front.
- - 7.1 - Transferable Public Keys
The BNF needs to be beefed up. In particular,
if each Subkey can be followed by one or more revocation sigs
as well as one or more normal signatures.
Also, are the signatures on the Subkeys required?
Are they required to be self-signed by the preceding public key?
Again, my recommendation of the term "User Data" for "UserID".
JDCC's note near the end of section 5.2.2.2 on
revocable User Data is in scope at this point.
The syntax looks very clearly like a revocation signature
immediately following the user data would apply to that data,
rather than to the whole key, and it calls for zero or more packets
so there's clearly room. The catch is making sure the
implementation doesn't choke when seeing a revocation instead
of either a signature or a subkey. I would definitely recommend
that if a implementation sees a revocation sig immediately following
a User Data field, that it MAY/SHOULD revoke that User Data,
though the meaning of "revoke" may not be precisely defined. :-)
On the other hand, it's probably too early to generate such
(certainly needs testing with popular implementations first.)
On the other hand, there's the operational queston of what
revoking a User Data means. It probably means that
PGP should notify the user before trying to use that key
with that name. But signatures are signed by keys,
not by names, so rejecting signatures by that key when
there are other User Data fields active is a mistake.
And PGP 5.0 doesn't always tell you who signed some key anyway.
If a Key/UserData pair is signed by a certifier's key,
and you receive a revocation for that UserData signed by
the certifier's key, you SHOULD discard or ignore the certification.
- - 7.2 - BNF should go a layer or two deeper.
- - 8 Key Formats -
This appears to overlap substantially with 7.1. Why both?
Also, 7.1 permits zero or more subkeys, while 8 V4 requires one.
Can the number be zero? Or more than one?
- - 8.2 KeyIDs and Fingerprints
Probably should also repeat the V3 fingerprint format here.
It's also worth noting that the KeyID and fingerprint
are both calculated rather than stored in the data;
implementations may choose to cache this information for
internal use, though there's no mechanism for export/import,
and keyservers would definitely want to.
- - 9 - Security Considerations
Traffic analysis should be mentioned here, since PGP does
little to stop it and doesn't have stealth built in.
Talking about the fingerprint hacks may be useful here.
===============================================================================
=
-----BEGIN PGP SIGNATURE-----
Version: PGP for Personal Privacy 5.0
Charset: noconv
iQBVAwUBNIU6H/thU5e7emAFAQGOVAH7BWXLYorrBwaXohonVC1cg0R53nMgOrX1
PfvQ0EcmEIhjqf3GJ8Z7cL5z98oT3Gl5BN8+rR7+iN3/S+EfZezf2w==
=fzBe
-----END PGP SIGNATURE-----
Thanks!
Bill
Bill Stewart, stewarts(_at_)ix(_dot_)netcom(_dot_)com
Regular Key PGP Fingerprint D454 E202 CBC8 40BF 3C85 B884 0ABE 4639