/* ==========================================================================
* Program : keygen
* Author : migf1
* Language : C (C99)
* Description : a simple, slow & and rather unsafe generator of unique keys
* Source files : keygen.c
* gcc options : -std=c99
* CmdLn Usage : keygen [ >fname.txt ]
*
* Extra Notes :
*
* In the source code, you may easily...
* - change the size and the total count of the generated keys
* - exclude/include any of the available char-sets from the key generation process
* - demand at least 1 char from any of the available char-sets to be present
* in every generated key (even if the char-set is generally excluded )
*
* ==========================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#define KEYSIZE 10+1 // μέγεθος κλειδιού
#define NKEYS 15 // πλήθος κλειδιών
// Bitflag Options for the program (do not touch them, unless you are a programer)
#define DEMAND_LOWER (1 << 0) // 0x01
#define DEMAND_UPPER (1 << 1) // 0x02
#define DEMAND_DIGITS (1 << 2) // 0x04
#define DEMAND_SPECL (1 << 3) // 0x08
#define USE_LOWER (1 << 4) // 0x10
#define USE_UPPER (1 << 5) // 0x20
#define USE_DIGITS (1 << 6) // 0x40
#define USE_SPECL (1 << 7) // 0x80
// Available Char-Sets (you may freely add or remove chars in any of those sets)
#define POOL_LOWER "abcdefghijklmnopqrstuvwxyz"
#define POOL_UPPER "ABCDEGFHIJKLMNOPQRSTUVWXYZ"
#define POOL_DIGITS "0123456789"
#define POOL_SPECL "/?.,><|!@#$%^&*()_+=-~;:][}{ \\\""
// -------------------------------------------------------------------------------------
// Return true if the cstring keys[ istop ] is not already contained between the
// 0th and the (istop-1)th element of the keys[] array of cstrings,
// otherwise return false
//
_Bool unique_key( const int istop, char keys[ NKEYS ][ KEYSIZE ] )
{
register int ikey = 0;
for (; ikey < istop; ikey++)
if ( strcmp( keys
[ikey
], keys
[istop
] ) == 0 ) return false;
return true;
}
// -------------------------------------------------------------------------------------
// This function makes sure that requested demands for keys to contain
// at least 1 char from any of the available char-sets are fulfilled
//
void apply_demanded( const unsigned char demand, char *key, const size_t keylen )
{
int i; char c;
_Bool iused[ keylen ]; // map for used i (pos)
memset(iused
, false, keylen
); // zero the map
/*
* if demanded, put a LOWER-case letter inside the key
*/
if ( demand & DEMAND_LOWER )
{
c
= POOL_LOWER
[ rand() % strlen(POOL_LOWER
) ]; // random LOWR letter i
= rand() % keylen
; // random pos in key key[ i ] = c; // put letter at pos
iused[ i ] = true; // mark pos as used
}
/*
* if demanded, put an UPPER-case letter inside the key
*/
if ( demand & DEMAND_UPPER )
{
c
= POOL_UPPER
[ rand() % strlen(POOL_UPPER
) ]; // random UPPR letter do {
i
= rand() % keylen
; // random pos in key } while( iused[ i ] == true ); // make sure it's unused
key[ i ] = c; // put letter at pos
iused[ i ] = true; // mark pos as used
}
/*
* if demanded, put a DIGIT inside the key
*/
if ( demand & DEMAND_DIGITS )
{
c
= POOL_DIGITS
[ rand() % strlen(POOL_DIGITS
) ];// random digit do {
i
= rand() % keylen
; // random pos in key } while( iused[ i ] == true ); // make sure it's unused
key[ i ] = c; // put digit at pos
iused[ i ] = true; // mark pos as used
}
/*
* if demanded, put a SPECIAL CHAR inside the key
*/
if ( demand & DEMAND_SPECL)
{
c
= POOL_SPECL
[ rand() % strlen(POOL_SPECL
) ]; // random special char do {
i
= rand() % keylen
; // random pos in key } while( iused[ i ] == true ); // make sure it's unused
key[ i ] = c; // put digit at pos
iused[ i ] = true; // mark pos as used
}
return;
}
// -------------------------------------------------------------------------------------
// Calc and return the appropriate size for the pool, based on the values of the USE_
// bits contained in: options
//
size_t pool_calcsize( const unsigned char options )
{
size_t ret = 0;
if ( options & USE_LOWER ) // make room for lower-case letters
if ( options & USE_UPPER ) // make room for upper-case letters
if ( options & USE_DIGITS ) // make room for digits
if ( options & USE_SPECL ) // make room for special chars
return ++ret; // make room for '\0' at the end
}
// -------------------------------------------------------------------------------------
// Initialize the chars pool, based on the values of the USE_ bits contained in: options.
// Return the initialized pool (which is as a cstring)
//
char *pool_init( char *pool, const size_t poolsize, const unsigned char options )
{
if ( !pool )
return NULL;
memset( pool
, 0, poolsize
); // clear the pool
if ( options & USE_LOWER ) // include lower-case letters
strncat( pool
, POOL_LOWER
, poolsize
-1 );
if ( options & USE_UPPER ) // include upper-case letters
strncat( pool
, POOL_UPPER
, poolsize
-1 );
if ( options & USE_DIGITS ) // include digits
strncat( pool
, POOL_DIGITS
, poolsize
-1 );
if ( options & USE_SPECL ) // include special chars
strncat( pool
, POOL_SPECL
, poolsize
-1 );
return pool;
}
// -------------------------------------------------------------------------------------
int main( void )
{
/*
* To disable any of the following options, delete or comment-out its
* corresponding line below.
*
* USE_ options specify whether you want chars from that particular
* char-set to participate in the key generation process or not
*
* DEMAND_ options specify whether yoy want at least 1 char of that
* particular char-set to be included in every generated key or not
*
* Note that you can disable a USE_ option without disabling its
* corresponding DEMAND_ option. In such cases, the disabled char-set
* does not generally participate in the generation process, but 1
* of its chars (picked randomly) will be present inside every key,
* at a random position.
*
* To completely prevent a char-set from participating in the
* the generation process, delete both its USE_ and its DEMAND_ option
*/
unsigned char options = // bit-flagged byte
DEMAND_LOWER // ... demand lower letter
+ DEMAND_UPPER // ... demand upper letter
+ DEMAND_DIGITS // ... demand digit
+ DEMAND_SPECL // ... demand special char
+ USE_LOWER // ... use lower letters
+ USE_UPPER // ... use upper letters
+ USE_DIGITS // ... use digits
+ USE_SPECL // ... use special chars
;
const size_t POOLSIZE = pool_calcsize(options); // calc the size of chars pool
char pool[ POOLSIZE ]; // the pool itself (cstring)
char keys[ NKEYS ][ KEYSIZE ] = { {0, 0} }; // array of (cstring) keys
int i=0, ikey=0; // i for chars, ikey for keys
srand( time(NULL
) ); // init the pseudo-random seed
pool_init( pool, POOLSIZE, options ); // initialize the chars pool
for (ikey=0; ikey < NKEYS; ikey++ ) // generate & store keys
{ // into the keys[NKEYS] array
do { // ...
for (i=0; i < KEYSIZE-1; i++) // ... generate a key
keys
[ ikey
][ i
] = pool
[ rand() % (POOLSIZE
-1) ]; } while ( !unique_key(ikey, keys) ); // ... make sure it is unique
// apply any char demands
apply_demanded( options, keys[ikey], KEYSIZE-1 );
puts( keys
[ikey
] ); // print the generated key }
return 0;
}