Data Signing, Encryption, and Hash Functions
Predefined Hash Types
Encryption Modes:
CosmHashEqSyntax#include "cosm/security.h" s32 CosmHashEq( const cosm_HASH * hashA, const cosm_HASH * hashB ); DescriptionCheck if the hashes are equal. Return Values1 if the hashes are equal, or 0 if they are not equal. ErrorsNone. Examplecosm_HASH hashA, hashB; /* Fill in the hashes ... */ if( !CosmHashEq( &hashA, &hashB ) ) { /* Hashes are not equal */ } CosmPRNGSyntax#include "cosm/security.h" s32 CosmPRNG( cosm_PRNG * prng, void * data, u64 length, const void * salt, u64 salt_length ); DescriptionGenerate 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 ValuesCOSM_PASS on success, or COSM_FAIL on failure. ErrorsNone. Examplecosm_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 ) ); CosmPKIKeyGenSyntax#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 ); DescriptionGenerate 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: 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 ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplevoid 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 */ /* ... */ } CosmPKIKeyLoadSyntax#include "cosm/security.h" s32 CosmPKIKeyLoad( cosm_PKI_KEY * key, u64 * bytes_read, const u8 * buffer, u64 max_bytes, const cosm_HASH * pass_hash ); DescriptionLoad 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 ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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 ); CosmPKIKeySaveSyntax#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 ); DescriptionSave 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 ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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 ); CosmPKIKeyFreeSyntax#include "cosm/security.h" void CosmPKIKeyFree( cosm_PKI_KEY * key ); DescriptionFree all internal key data, and zero the key structure. Return ValuesNone. ErrorsNone. Examplecosm_PKI_KEY key; CosmMemSet( &key, sizeof( cosm_PKI_KEY ), 0 ); /* use the key */ CosmPKIKeyFree( &key ); CosmPKISigLoadSyntax#include "cosm/security.h" s32 CosmPKISigLoad( cosm_PKI_SIG * sig, u64 * bytes_read, const u8 * buffer, u64 max_bytes ); DescriptionLoad 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 ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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 ); CosmPKISigSaveSyntax#include "cosm/security.h" s32 CosmPKISigSave( u8 * buffer, u64 * length, const cosm_PKI_SIG * sig, u64 max_bytes ); DescriptionSave the signature sig into the buffer, writing at most max_bytes bytes. length will be set to the number of bytes written. Return ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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 ); CosmPKISigFreeSyntax#include "cosm/security.h" void CosmPKISigFree( cosm_PKI_SIG * sig ); DescriptionFree all internal data, and zero the signature structure. Return ValuesCOSM_PASS on success, or an error code on failure. ErrorsNone. Examplecosm_PKI_SIG sig; CosmMemSet( &sig, sizeof( cosm_PKI_SIG ), 0 ); /* use the sig */ CosmPKISigFree( &sig ); CosmPKIEncodeSyntax#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 ); DescriptionUse 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
Shared Flags
Return ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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 ); CosmPKIDecodeSyntax#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 ); DescriptionExtract 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
Shared Flags
Return ValuesCOSM_PASS on success, or an error code on failure. Errors
Examplecosm_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-2024.
All rights reserved.
Mithral® and Cosm® are trademarks of
Mithral Communications & Design Inc.
|