Public Key Ciphers
The pkcipher module includes a number of routines used in cipher-independent
PKE-key manipulation. For most purposes this module in entirely internal.
However programmers intending to add further PKE algorithms may need to
refer to this.
Constants
-
MAXPUBNUMS
-
Maximum number of bignums in a public key (currently 4 for ElGamal)
-
MAXSECNUMS
-
Maximum number of bignums in a secret key (currently 4 for RSA)
-
MAXCYPHNUMS
-
Maximum number of bignums in a cyphertext (currently 2 for everything except
RSA)
-
MAXSIGNUMS
-
Maximum number of bignums in a signature (currently 2 for everything except
RSA)
Data Types
-
enum keyStat
-
This type characterises the availability of the full data (bignums)
for a key.
-
KS_MISSING
-
Only encountered as an Id. (The key is not available.)
-
KS_ON_FILE
-
Bignums are in the public key-ring file
-
KS_COMPLETE
-
Bignums are in memory
-
enum PKEsizeParam
-
This datatype provides offsets into a PKEparams
array.
-
PKE_PUB_SIZE
-
Number of MPNs in a public key
-
PKE_SEC_SIZE
-
Number of MPNs in a secret key (in addition to those in the public key).
-
PKE_CIPH_SIZE
-
Number of MPNs in a cyphertext
-
PKE_SIG_SIZE
-
Number of MPNs in a signature
-
PKE_CHAR_NUM
-
Characteristic MPN in the public key. i.e. one defining the key size
-
PKE_SIZE_ARRAY_SIZE
-
The size of a PKEparams array.
-
typedef int PKEparams[PKE_SIZE_ARRAY_SIZE];
-
This is an array (normally constant array) describing the vital statistics
of a PKE cipher. The slots are identified by enumeration type
-
sigStat
-
This type defines the status of a signature with respect to verification.
-
SS_BAD
-
Signature does not match (confirmed this run)
-
SS_SUSPECT
-
Signature does not match (according to file)
-
SS_UNKNOWN
-
Signature has not been checked
-
SS_PROBABLE
-
Signature matchs (according of file)
-
SS_VERIFIED
-
Verified this program run
-
sigDetails
-
Fully defines the contents of a signature packet..
-
byte version;
-
= 0
-
implies invalid or missing
-
= 2
-
PGP 2.5 and earlier
-
= 3
-
PGP 2.6 to 4.x
-
= 4
-
PGP 5.x
-
byte sigClass;
-
signature class
-
byte pk_algor;
-
public key algorithm for authentication
-
byte md_algor;
-
Message digest algorithm
-
ulong timestamp;
-
The date and time at which the signature was generated.
-
byte digestBytes[DIGESTEXTRAS];
-
packed class and timestamp fields PGP code and documentation suggests that
theoretically the digestBytes field could be bigger. Specifically the PGP
code allows for two extra bytes but it is not clear if this ever really
occurs. (OpenPGP declares not)
-
byte checkBytes[2];
-
Results of a 16-bit CRC check, used as a sanity check.
-
byte keyId[KEYFRAGSIZE];
-
Id of the key that made this signature.
-
pubkey * pub_key;
-
Pointer to the record for the public key for this signature (where known).
-
union signature;
-
The encoded cyphertext signature. The format of this varies with algorithm.
(This 'variant' is currently somewhat theoretical as all PKE algorithms
in use, use a number of large integers. The only option in the current
union
is an array of MAXSIGNUMS bignums. The only variant is how many of these
are actually used.)
-
byte digest[MAXHASHSIZE];
-
The message digest of the message being signed or verified.
Public Methods
Algorithm Enquiry Functions
Standard query routines for the validity of the byte describing the algorithm
to use.
-
boolean valid_PKE_algor(byte algor);
-
Returns true if the PKE cipher identified by algor is available
in this program.
-
boolean recognised_PKE_algor(byte
algor);
-
Returns ture if the PKE cipher is recognised as identifying a known cipher,
irrespective of whether the implementation of this cipher is available.
-
int PKEsize(byte algor, PKEsizeParam
purpose);
-
Function to determine the number of bignums required for any given purpose
by any given algorithm. (The key to driving most of this module).
Key Storage Control
Release storage
-
void release_pubkey(pubkey * pub_key);
-
Release heap storage dedicated to bignum data in key, depending on the
algorithm indicated by that structure
-
void release_signature(sigDetails
*sig);
-
Release heap storage dedicated to bignum data in signature, depending on
the algorithm indicated by that structure
-
void release_seckey(seckey * sec_key);
-
Release heap storage dedicated to bignum data in key, depending on the
algorithm indicated by that structure
Structure Initialisation
-
void prepare_pubkey(pubkey * pub_key);
-
Initialise the bignums, as in public key, depending on the algorithm indicated
by that structure.
-
void prepare_signature(sigDetails
* sig);
-
Initialise the bignums, as in signature, depending on the algorithm indicated
by that structure.
-
void prepare_seckey(seckey * sec_key);
-
Initialise the bignums, as in secret key, depending on the algorithm indicated
by that structure.
Structure Assignment
-
void assign_pubkey(pubkey * to, pubkey
* from);
-
Assign the bignums in the source to the target. Note that this copies
the pointers and not the contents. If a release_pubkey is executed
on the source, the destination data will be cleared.
-
void assign_seckey(seckey * to, seckey
* from);
-
Assign the bignums in the source, from to the target to. Note
that this copies the pointers and not the contents. If a release_seckey
is executed on the source, the destination data will be cleared.
I/O operations
-
boolean read_mpn_pubkey(pubkey *
pub_key, DataFileP file);
-
Reads a single bignum from file.
-
boolean read_mpn_summary(byte alg,
recordSummary *summary, DataFileP file);
-
Reads the 'characteristic' - assumed most important - bignum from a public
key. The characteristic bignum is normally the one that defines the
'length' of the key.
-
boolean read_mpn_signature(sigDetails
*sig, DataFileP file);
-
Read the associated bignums for the given structure from the file; read_mpn_summary()
reads the 'characteristic' - assumed most important - bignum from a public
key. Note we no longer assume that this is the first number.
-
boolean read_mpn_seckey(seckey *
sec_key, DataFileP file);
-
Read the associated bignums for the given structure from the file; read_mpn_summary()
reads the 'characteristic' - assumed most important - bignum from a public
key. Note we no longer assume that this is the first number.
-
ushort length_pubkey(pubkey * pub_key);
-
Returns the number of bytes of PGP-classic MPI in the representation of
the bignums in the structure; the value includes 2 bytes per bignum for
a count.
-
ushort length_signature(sigDetails
*sig);
-
Returns the number of bytes of PGP-classic MPI in the representation of
the bignums in the structure; the value includes 2 bytes per bignum for
a count.
-
ushort length_seckey(seckey * sec_key);
-
Returns the number of bytes of PGP-classic MPI in the representation of
the bignums in the structure; the value includes 2 bytes per bignum for
a count.
-
void put_pubkey(byte * buffer, pubkey
* pub_key);
-
Expand from the MPI representation in the buffer into the key structure.
-
boolean write_signature(sigDetails
* sig, DataFileP file);
-
Write the bignum content to the appropriate PGP packet.
-
boolean write_seckey(seckey * sec_key,
DataFileP file);
-
Write the bignum content (encrypted) to the appropriate PGP packet.
-
boolean equate_pubkey(pubkey * right,
pubkey * left);
-
Returns TRUE if the bignum content of the two keys is identical.
-
void move_pubkey(pubkey * to, pubkey
* from);
-
A combination of assigning across the bignum content, followed by clearing
the source.
-
void extractKeyfrag(pubkey * pub_key);
-
Extract the least significant 64-bit section from the most important bignum
in the key (for key ID purposes)
-
void sizePubkey(pubkey * pub_key);
-
Given the bignums, set key the value of the key significance in bits. This
is more important for variable length RSA keys than the fixed 240 bit (and
stronger per bit) elliptic curve system.
-
boolean read_CKcypher(bignump cypher,
DataFileP file, byte algor);
-
Read the public-key encrypted session key pseudo-packet.
-
ushort length_CKcypher(keyDetails
*details);
-
Determine the buffer size required for the public-key encrypted session
key pseudo-packet.
-
boolean write_CKcypher(keyDetails
*details, DataFileP file);
-
Write the public-key encrypted session key pseudo-packet.
-
boolean newPKAkey(keyType * keyType, seckey
* sec_key, pubkey * pub_key);
-
Generate a new public key pair of the type description in keyType.
The following methods are currently located in keyio.c.
-
boolean getConvKey(DataFileP file, long
offset, seckey * sec_key, cv_details * algor, size_t *keylen, byte * *
convKey);
-
Extract the contents of a session key pseudopacket (last three arguments),
starting from the given offset into the file, using the secret key supplied
to decrypt the public key encrypted packet.
-
boolean putConvKey(DataFileP file, byte
version, pubkey * pub_key, cv_details * algor, size_t keylen, byte *convKey);
-
Build the session key pseudopacket, public key encrypt it, and file the
resulting public key encrypted packet.
The following functions are in pkops.c.
-
boolean getSignature(sigDetails * sig);
-
Extract the signature, decrypting if the public key method allows such.
-
boolean verifySignature(sigDetails
* sig, byte * digest)
-
Check whether the supplied signature matches up with the digest computed
from the plaintext.
-
boolean putSignature(sigDetails * sig,
seckey * sec_key);
-
Sign the supplied digest with the key.
Private Methods
-
static byte algtype(pubkey *p)
-
Collapses all the Viacrypt "RSA with restricted use" versions into a single
byte value to simplify determination of algorithm - and hence key representation
- equality.
-
static boolean read_mpn_pub(bignump
number, DataFileP file);
-
Read a plaintext bignum from the given file
-
static boolean write_mpn_pub(bignump
n, DataFileP file)
-
Write a plaintext bignum to the given file
-
static byte * read_mpn_sec(DataFileP
file)
-
Read an encrypted bignum fromthe given file
-
static boolean write_mpn_sec(byte
* data, DataFileP file)
-
Write an encrypted bignum to the given file
The following methods are currently located in pkops.c
-
static boolean extractConvKey(byte
* buffer, short length, cv_details * algor, size_t *keylen, byte * * convKey)
-
Unpick the decrypted session key pseudopacket
-
static boolean all_ff(byte * buffer, int
length)
-
Check the buffer has the hex value 0xFF in each byte buffer[0] tobuffer[length-1].
-
static boolean extractSignature(byte
* buffer, short length, byte signature[MAXHASHSIZE], byte siglen)
-
Unpick a public key decrypted signature packet (used only for invertible
public key signature schemes, like RSA).
-
static boolean formatSessionKey(byte
* buffer, short length, byte version, cv_details * algor, size_t keylen,
byte *key)
-
Build in buffer[length] a session key pseudo-packet for the given PGP format
version, and session key details.
-
static boolean formatSignature(byte
* buffer, short length, byte version, byte signature[MAXHASHSIZE], byte
siglen, boolean useASN)
-
Build a signature packet to the given PGP vserion, with the given hash.
Optionally (i.e. for RSA) use the appropriate ASN value. Strictly the PGP-classic
value is only valid for RSA with MD5.
Dependencies
Each algorithm supported must represent its keys and signatures eventually
as a series of one or more multiple precision integers; and provide routines
to sign, encrypt, verify and decrypt. There is no systematic interface.
The asymmetric algorithms
Currently these supporting routines are defined in rsa.c, with support
in bignum.c, and ec_crypt.c with support in ec_curve.c, ec_field.c and
bignum.c. Each of these encryption algorithms has its own peculiar internal
workings, and where possible, some test material.
The process of adding new algorithms is (as noted in the introductory
remarks) less mechanical, and more widespread, than with other parts of
encryption, but the process should not be too difficult; support for the
Rabin algoithm used by EBP, and ElGamal and Diffie-Hellman from PGP 5.0
will follow shortly, as other engineering for compatibility proceeds
webmaster@bifroest.demon.co.uk