Bifroest Mr. Tines MacCTC CTCjava Manual Pages
Bifroest Mr. Tines CTC Home CTClib MacCTC CTCjava Manual


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