[Cosm Logo]

Data Signing, Encryption, and Hash Functions

Predefined Hash Types

COSM_HASH_CRC32
32-bits, for error checking only. CCITT Standard.
COSM_HASH_MD5
128-bits, preferred for checksums.
COSM_HASH_SHA1
160-bits, preferred for signing hashes.
COSM_HASH_SHA256
256-bits, preferred for RSA operations.

Encryption Modes:

COSM_CRYPTO_MODE_CFB
8-bit cipher-feedback, for stream data.
COSM_CRYPTO_MODE_CBC
Cipher block chainging, for files.
COSM_CRYPTO_MODE_ECB
Electronic codebook, for keys and random.

CosmHashEq

Syntax

#include "cosm/security.h"
s32 CosmHashEq( const cosm_HASH * hashA, const cosm_HASH * hashB );

Description

Check if the hashes are equal.

Return Values

1 if the hashes are equal, or 0 if they are not equal.

Errors

None.

Example

  cosm_HASH hashA, hashB;

  /* Fill in the hashes ... */

  if( !CosmHashEq( &hashA, &hashB ) )
  {
    /* Hashes are not equal */
  }


CosmPRNG

Syntax

#include "cosm/security.h"
s32 CosmPRNG( cosm_PRNG * prng, void * data, u64 length,
  const void * salt, u64 salt_length );

Description

Generate length bytes of deterministic psuedo-random data. Initialization of the generator is done by feeding it salt_length bytes of salt. Any salt fed to the generator will be used before the data is generated, and is also cumulative, so it can be called repeatedly with additional salt to provide more initial randomness. Given the same salt, the same bytes will always come out.

Return Values

COSM_PASS on success, or COSM_FAIL on failure.

Errors

None.

Example

  cosm_PRNG rnd;
  u8 bytes[32];
  cosmtime mytime;

  CosmMemSet( &rnd, sizeof( cosm_PRNG ), 0 );

  /* seed it */
  CosmPRNG( &rnd, NULL, (u64) 0,
    &mytime, sizeof( cosmtime ) );

  /* get some bytes */
  CosmPRNG( &rnd, bytes, sizeof( bytes ),
    NULL, 0 );

  /* OR - do both at once */
  CosmPRNG( &rnd, bytes, sizeof( bytes ),
    &mytime, sizeof( cosmtime ) );

CosmPKIKeyGen

Syntax

#include "cosm/security.h"
s32 CosmPKIKeyGen( cosm_PKI_KEY * public_key, cosm_PKI_KEY * private_key,
  u32 bits, const u8 * rnd_bits, u64 id, const utf8 * alias,
  cosmtime create, cosmtime expire,
  void (*callback)( s32, s32, void * ), void * callback_param );

Description

Generate public_key and private_key with a bits bit n. Please read this entire description, as many parameters have special meanings and restrictions. Knowing what you're doing before using any PKI functions would be a very good idea.

bits must be at least 512, and a power of 2. Keys of 1024 bits are now suspected to be breakable by large organizations and governments, and 512 bit keys are breakable with a few computers in a few weeks, so 2048 is the smallest key recommended.

rnd_bits should be bits bits of random data. It is VERY important that the user take great care to make sure that these bits are truely random, and not based on any data such as the time. CosmPRNG and CosmEntropy are also not enough on their own.

create is the time of key creation and should always be the current time. expire is the expiration time of the keys. CosmPKIEncode will not be allowed with an expired key. Most keys should have a lifetime of 1 year.

The id on a key has specific ranges and meanings:
0 to 2^31-1: human local ID.
2^31 to 2^32-1: machine local ID.
2^32 to 2^63-1: human global Cosm-assigned ID.
2^63 to 2^64-1: machine global Cosm-assigned ID.
When printed in hex, local IDs are 8 digits, and global ID are 16 digits. Local ID are use within each organization, often something like an employee number, or a customer number for example. Global IDs should not be used to identify people once they are in a local domain, the local ID should be used instead for privacy and security reasons. That something is using a human ID does NOT imply they are an adult that can sign contracts, nor any form of intelligence.

A key is uniquely identified by the bits, id, and create. This means that keys should not be generated more then once a second, this should not be a big concern. You should also never generate a key with a id you haven't been assigned, because it will not result in a valid key.

alias is a max 31 character utf8 string that has no special meaning except to the key's owner as a tool to quickly tell keys apart. No special meaning should be given beyond that.

callback and callback_param provide information on the possibly long key generation process. They work as decribed in CosmBNPrimeGen, with the added calls of callback( 3, 0, callback_param ) when the keypair test begins and callback( 4, 0, callback_param ) when the test finishes. Note that 2 primes will be generated during key creation.

The user-relevant (only) elements of cosm_PKI_KEY are:

typedef struct cosm_PKI_KEY
{
  u16 pkt_type;     /* == COSM_PKI_PUBLIC or COSM_PKI_PRIVATE */
  u16 pkt_version;
  u32 bits;
  s64 create;
  u64 id;
  s64 expire;
  ascii alias[32];
  ...
} cosm_PKI_KEY;

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid or wrong size.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  void my_progress( s32 type, s32 count, void * param )
  {
    switch( type )
    {
      case 0:
        CosmPrint( "." );
        break;
      case 1:
        CosmPrint( "+" );
        break;
      case 2:
        CosmPrint( "\n" );
        break;
      case 3:
        CosmPrint( "[testing keypair..." );
        break;
      case 4:
        CosmPrint( "]\n" );
        break;
      default:
        break;
    }
  }

  void example( void )
  {
    const ascii alias[32];
    cosm_PKI_KEY pub, pri;
    cosmtime create, expire;
    u8 rnd_bits[256];

    /* set create, and expire in a year */
    CosmSystemClock( &create );
    _COSM_SET128( expire, 0000000001E13380, 0000000000000000 );
    expire = CosmS128Add( create, expire );

    /* get user data and carefully construct rnd_bits */

    /* set alias to make a key for at work, employee id = 42 */
    CosmStrCopy( alias, "Salt Mines #2002", 32LL );

    /* generate a key */
    CosmMemSet( &pub, sizeof( cosm_PKI_KEY ), 0 );
    CosmMemSet( &pri, sizeof( cosm_PKI_KEY ), 0 );
    if ( CosmPKIKeyGen( &pub, &pri, 2048, rnd_bits,
      (u64) 42, alias, create, expire, my_progress, NULL )
      != COSM_PASS )
    {
      /* key generation failed */
    }

    /* save the keys, or use them as ephemeral keys */

    /* ... */
  }

CosmPKIKeyLoad

Syntax

#include "cosm/security.h"
s32 CosmPKIKeyLoad( cosm_PKI_KEY * key, u64 * bytes_read,
  const u8 * buffer, u64 max_bytes, const cosm_HASH * pass_hash );

Description

Load the key from the buffer into key, reading at most max_bytes bytes. bytes_read will be set to the number of bytes that were in the key.

Loading private keys also requires the COSM_HASH_SHA256 hash of the users passphrase pass_hash in order to decrypt the private data. When loading a public key pass_hash is ignored.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid or wrong size.
COSM_PKI_ERROR_PASSPHRASE
Passphrase hash was incorrect.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_PKI_KEY pub, pri;
  cosm_HASH pass_hash;
  u8 save_buf[4096];
  u64 len;

  /* read key from file etc. */

  /* loading a public key */
  if ( CosmPKIKeyLoad( &pub, &len, save_buf,
    sizeof( save_buf ), NULL ) != COSM_PASS )
  {
    /* Load failed */
  }

  /* hash passphrase into pass_hash with COSM_HASH_SHA256 */

  /* loading a private key */
  if ( CosmPKIKeyLoad( &pri, &len, save_buf,
    sizeof( save_buf ), &data_hash ) != COSM_PASS )
  {
    /* Load failed */
  }

  /* free keys */
  CosmPKIKeyFree( &pub );
  CosmPKIKeyFree( &pri );

CosmPKIKeySave

Syntax

#include "cosm/security.h"
s32 CosmPKIKeySave( u8 * buffer, u64 * length, const cosm_PKI_KEY * key,
  const u64 max_bytes, const u8 * rnd_bytes,
  const cosm_HASH * pass_hash );

Description

Save the key key into the buffer, writing at most max_bytes bytes. length will be set to the number of bytes written.

Private keys also requite 16 bytes of random data rnd_bytes, and a hash pass_hash which is the COSM_HASH_SHA256 hash of the users passphrase in order to encrypt the private data. When saving a public key these two parameters are ignored.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid or wrong size.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_PKI_KEY pub, pri;
  cosm_HASH pass_hash;
  u8 save_buf[4096];
  u64 len;

  /* generate a keypair - if we load keys we dont need to re-save them */

  /* saving a public key */
  if ( CosmPKIKeySave( save_buf, &len, &pub,
    sizeof( save_buf ), NULL, NULL ) != COSM_PASS )
  {
    /* Save failed */
  }

  /* write save_buf to file etc. */

  /* generate 16 random bytes for the rnd_bytes */

  /* hash passphrase into pass_hash with COSM_HASH_SHA256 */

  /* saving a private key */
  if ( CosmPKIKeySave( save_buf, &len, &pri,
    sizeof( save_buf ), rnd_bits, &pass_hash )
    != COSM_PASS )
  {
    /* Save failed */
  }

  /* write save_buf to file etc. */

  /* free keys */
  CosmPKIKeyFree( &pub );
  CosmPKIKeyFree( &pri );

CosmPKIKeyFree

Syntax

#include "cosm/security.h"
void CosmPKIKeyFree( cosm_PKI_KEY * key );

Description

Free all internal key data, and zero the key structure.

Return Values

None.

Errors

None.

Example

  cosm_PKI_KEY key;

  CosmMemSet( &key, sizeof( cosm_PKI_KEY ), 0 );

  /* use the key */

  CosmPKIKeyFree( &key );

CosmPKISigLoad

Syntax

#include "cosm/security.h"
s32 CosmPKISigLoad( cosm_PKI_SIG * sig, u64 * bytes_read,
  const u8 * buffer, u64 max_bytes );

Description

Load the signature from the buffer into sig, reading at most max_bytes bytes. bytes_read will be set to the number of bytes that were in the signature.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid or wrong size.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_PKI_SIG sig;
  u8 save_buf[4096];
  u64 len;

  if ( CosmPKISigLoad( &sig, &len, save_buf, 4096LL )
    != COSM_PASS )
  {
    /* failure to read signature */
  }

  /* use signature for key or verification */

  /* free signature */
  CosmPKISigFree( &sig );

CosmPKISigSave

Syntax

#include "cosm/security.h"
s32 CosmPKISigSave( u8 * buffer, u64 * length, const cosm_PKI_SIG * sig,
  u64 max_bytes );

Description

Save the signature sig into the buffer, writing at most max_bytes bytes. length will be set to the number of bytes written.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid or wrong size.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_PKI_SIG sig;
  u8 save_buf[4096];
  u64 len;

  /* load or create signature */

  if ( CosmPKISigSave( save_buf, &len, &sig, 4096LL )
    != COSM_PASS )
  {
    /* failure to write signature */
  }

  /* free signature */
  CosmPKISigFree( &sig );

CosmPKISigFree

Syntax

#include "cosm/security.h"
void CosmPKISigFree( cosm_PKI_SIG * sig );

Description

Free all internal data, and zero the signature structure.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

None.

Example

  cosm_PKI_SIG sig;

  CosmMemSet( &sig, sizeof( cosm_PKI_SIG ), 0 );

  /* use the sig */

  CosmPKISigFree( &sig );

CosmPKIEncode

Syntax

#include "cosm/security.h"
s32 CosmPKIEncode( cosm_PKI_SIG * sig, const cosm_HASH * hash,
  cosmtime timestamp, u8 type, u8 shared, const cosm_PKI_KEY * key );

Description

Use the key to encode the hash data, timestamp (in seconds), type, and shared flag into the signature sig. A signature of type COSM_PKI_SIG_MESSAGE needs a public key, all other types need a private key to encode. You should always use COSM_HASH_SHA256 to generate the hash for signatures. Care should be taken in chosing the type and shared flag you use.

The user-relevant (only) elements of cosm_PKI_SIG are:

typedef struct cosm_PKI_SIG
{
  u16 pkt_type;     /* == COSM_PKI_SIG */
  u16 pkt_version;
  u32 bits;
  s64 create;
  u64 id;
  s64 timestamp;
  u8 type;
  u8 shared;
  cosm_BN sig;
} cosm_PKI_SIG;

Signature Types

COSM_PKI_SIG_MESSAGE
Sending hash data to the key owner.
COSM_PKI_SIG_SIGN
Signer signs data.
COSM_PKI_SIG_KNOWN
Signer untrusted but known data.
COSM_PKI_SIG_WEAK
Signer weakly trusts the data.
COSM_PKI_SIG_STRONG
Signer strongly trusts the data.
COSM_PKI_SIG_TIMESTAMP
Signer says data existed at time only.
COSM_PKI_SIG_REVOKE
Signer revokes the matching signature.

Shared Flags

COSM_PKI_SHARED_NO
Signatere is valid to signer only.
COSM_PKI_SHARED_YES
Signatere is valid to any reader.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_EXPIRED
Key is expired.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_HASH data_hash, sig_hash;
  cosm_PKI_KEY pri;
  cosm_PKI_SIG sig;
  cosmtime sig_time;
  u8 sig_type;
  u8 share;

  /* hash the data into data_hash (use COSM_HASH_SHA256) */

  /* load private key into pub with CosmPKIKeyLoad() */

  /* get the current time */
  CosmSystemClock( &time_now );

  /* Sign the hash */
  if ( CosmPKIEncode( &sig, &data_hash, time_now,
    COSM_PKI_SIG_SIGN, COSM_PKI_SHARED_YES, &pri ) != COSM_PASS )
  {
    /* Encoding failed */
  }

  /* save the signature with CosmPKISigSave() */

  /* free the key and sig */
  CosmPKIKeyFree( &key );
  CosmPKISigFree( &sig );

CosmPKIDecode

Syntax

#include "cosm/security.h"
s32 CosmPKIDecode( cosm_HASH * hash, cosmtime * timestamp, u8 * type,
  u8 * shared, const cosm_PKI_SIG * sig, const cosm_PKI_KEY * key );

Description

Extract the hash, timestamp, type, and shared flag from the signature sig using the key. A COSM_PASS from this function does NOT mean the signature is valid, only that it was decoded correctly. A signature of type COSM_PKI_SIG_MESSAGE needs a private key, all other types need a public key to decode.

It is important to understand that the undecoded parameters of a signature (sig.timestamp, sig.type, sig.shared) are MEANINGLESS, because they can be trivially modified by an attacker. Only use the decoded values.

Signature Types

COSM_PKI_SIG_MESSAGE
Sending hash data to the key owner.
COSM_PKI_SIG_SIGN
Signer signs data.
COSM_PKI_SIG_KNOWN
Signer untrusted but known data.
COSM_PKI_SIG_WEAK
Signer weakly trusts the data.
COSM_PKI_SIG_STRONG
Signer strongly trusts the data.
COSM_PKI_SIG_TIMESTAMP
Signer says data existed at time only.
COSM_PKI_SIG_REVOKE
Signer revokes the matching signature.

Shared Flags

COSM_PKI_SHARED_NO
Signatere is valid to signer only.
COSM_PKI_SHARED_YES
Signatere is valid to any reader.

Return Values

COSM_PASS on success, or an error code on failure.

Errors

COSM_PKI_ERROR_PARAM
Invalid parameter.
COSM_PKI_ERROR_MEMORY
Internal error, usually memory.
COSM_PKI_ERROR_FORMAT
Key or signature is invalid.
COSM_PKI_ERROR_NO_CRYPTO
Compiled with -DNO_CRYPTO.

Example

  cosm_HASH data_hash, sig_hash;
  cosm_PKI_KEY pub;
  cosm_PKI_SIG sig;
  cosmtime sig_time;
  u8 sig_type;
  u8 share;

  /* hash the data into data_hash (use COSM_HASH_SHA256) */

  /* load public key into pub with CosmPKIKeyLoad() */

  /* load the signature into sig with CosmPKISigLoad() */

  if ( CosmPKIDecode( &sig_hash, &sig_time, &sig_type, &share,
    &sig, &pub ) != COSM_PASS )
  {
    /* decode failed */
  }

  /* now verify the signature */
  if ( !CosmHashEq( &data_hash, &sig_hash ) )
  {
    /* Signature was not for the data we hashed */
  }

  /*
    sig_time, sig_type, and share are now what
    the signer set them to, and effect what it means.
  */

  CosmPKIKeyFree( &key );
  CosmPKISigFree( &sig );

© Copyright Mithral Communications & Design Inc. 1995-2017. All rights reserved. Mithral® and Cosm® are trademarks of Mithral Communications & Design Inc.
Document last modified: Jun 01, 2012