/* 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 WIN32
#include <memory.h>
#endif
#ifdef UNIX
#include <memory.h>
#include <unistd.h>
#else
#ifndef _MSC_VER
#include <mem.h>
#endif
#endif
#ifdef _WIN32_WCE
#include <string.h>
#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<hashlength;i++)
hash[i] = encrypt(0);
}