/* sapphire.cpp -- the Saphire II stream cipher class. Dedicated to the Public Domain the author and inventor: (Michael Paul Johnson). This code comes with no warranty. Use it at your own risk. Ported from the Pascal implementation of the Sapphire Stream Cipher 9 December 1994. Added hash pre- and post-processing 27 December 1994. Modified initialization to make index variables key dependent, made the output function more resistant to cryptanalysis, and renamed to Sapphire II 2 January 1995 */ #ifdef UNIX #include #include #else #include #endif #include "sapphire.h" unsigned char sapphire::keyrand(int limit, unsigned char *user_key, unsigned char keysize, unsigned char *rsum, unsigned *keypos) { unsigned u, // Value from 0 to limit to return. retry_limiter, // No infinite loops allowed. mask; // Select just enough bits. if (!limit) return 0; // Avoid divide by zero error. retry_limiter = 0; mask = 1; // Fill mask with enough bits to cover while (mask < (unsigned)limit) // the desired range. mask = (mask << 1) + 1; do { *rsum = cards[*rsum] + user_key[(*keypos)++]; if (*keypos >= keysize) { *keypos = 0; // Recycle the user key. *rsum += keysize; // key "aaaa" != key "aaaaaaaa" } u = mask & *rsum; if (++retry_limiter > 11) u %= limit; // Prevent very rare long loops. } while (u > (unsigned)limit); return u; } void sapphire::initialize(unsigned char *key, unsigned char keysize) { // Key size may be up to 256 bytes. // Pass phrases may be used directly, with longer length // compensating for the low entropy expected in such keys. // Alternatively, shorter keys hashed from a pass phrase or // generated randomly may be used. For random keys, lengths // of from 4 to 16 bytes are recommended, depending on how // secure you want this to be. int i; unsigned char toswap, swaptemp, rsum; unsigned keypos; // If we have been given no key, assume the default hash setup. if (keysize < 1) { hash_init(); return; } // Start with cards all in order, one of each. for (i=0;i<256;i++) cards[i] = i; // Swap the card at each position with some other card. toswap = 0; keypos = 0; // Start with first byte of user key. rsum = 0; for (i=255;i>=0;i--) { toswap = keyrand(i, key, keysize, &rsum, &keypos); swaptemp = cards[i]; cards[i] = cards[toswap]; cards[toswap] = swaptemp; } // Initialize the indices and data dependencies. // Indices are set to different values instead of all 0 // to reduce what is known about the state of the cards // when the first byte is emitted. rotor = cards[1]; ratchet = cards[3]; avalanche = cards[5]; last_plain = cards[7]; last_cipher = cards[rsum]; toswap = swaptemp = rsum = 0; keypos = 0; } void sapphire::hash_init(void) { // This function is used to initialize non-keyed hash // computation. int i, j; // Initialize the indices and data dependencies. rotor = 1; ratchet = 3; avalanche = 5; last_plain = 7; last_cipher = 11; // Start with cards all in inverse order. for (i=0, j=255;i<256;i++,j--) cards[i] = (unsigned char) j; } sapphire::sapphire(unsigned char *key, unsigned char keysize) { if (key && keysize) initialize(key, keysize); } void sapphire::burn(void) { // Destroy the key and state information in RAM. memset(cards, 0, 256); rotor = ratchet = avalanche = last_plain = last_cipher = 0; } sapphire::~sapphire() { burn(); } unsigned char sapphire::encrypt(unsigned char b) { #ifdef USBINARY // Picture a single enigma rotor with 256 positions, rewired // on the fly by card-shuffling. // This cipher is a variant of one invented and written // by Michael Paul Johnson in November, 1993. unsigned char swaptemp; // Shuffle the deck a little more. ratchet += cards[rotor++]; swaptemp = cards[last_cipher]; cards[last_cipher] = cards[ratchet]; cards[ratchet] = cards[last_plain]; cards[last_plain] = cards[rotor]; cards[rotor] = swaptemp; avalanche += cards[swaptemp]; // Output one byte from the state in such a way as to make it // very hard to figure out which one you are looking at. last_cipher = b^cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^ cards[cards[(cards[last_plain] + cards[last_cipher] + cards[avalanche])&0xFF]]; last_plain = b; return last_cipher; #else return b; #endif } unsigned char sapphire::decrypt(unsigned char b) { unsigned char swaptemp; // Shuffle the deck a little more. ratchet += cards[rotor++]; swaptemp = cards[last_cipher]; cards[last_cipher] = cards[ratchet]; cards[ratchet] = cards[last_plain]; cards[last_plain] = cards[rotor]; cards[rotor] = swaptemp; avalanche += cards[swaptemp]; // Output one byte from the state in such a way as to make it // very hard to figure out which one you are looking at. last_plain = b^cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^ cards[cards[(cards[last_plain] + cards[last_cipher] + cards[avalanche])&0xFF]]; last_cipher = b; return last_plain; } void sapphire::hash_final(unsigned char *hash, // Destination unsigned char hashlength) // Size of hash. { int i; for (i=255;i>=0;i--) encrypt((unsigned char) i); for (i=0;i