Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

# sapphire.cpp

    00001 // sapphire.cpp -- modified by Wei Dai from:
    00002
    00003 /* sapphire.cpp -- the Saphire II stream cipher class.
    00004    Dedicated to the Public Domain the author and inventor:
    00005    (Michael Paul Johnson).  This code comes with no warranty.
    00006    Use it at your own risk.
    00007    Ported from the Pascal implementation of the Sapphire Stream
    00008    Cipher 9 December 1994.
    00009    Added hash pre- and post-processing 27 December 1994.
    00010    Modified initialization to make index variables key dependent,
    00011    made the output function more resistant to cryptanalysis,
    00012    and renamed to Sapphire II 2 January 1995
    00013 */
    00014
    00015 #include "pch.h"
    00016 #include "sapphire.h"
    00017
    00018 NAMESPACE_BEGIN(CryptoPP)
    00019
    00020 byte SapphireBase::keyrand(unsigned int limit,
    00021                                                    const byte *user_key,
    00022                                                    byte keysize,
    00023                                                    byte *rsum,
    00024                                                    unsigned *keypos)
    00025 {
    00026         unsigned u,             // Value from 0 to limit to return.
    00027                 retry_limiter,      // No infinite loops allowed.
    00028                 mask;               // Select just enough bits.
    00029
    00030         retry_limiter = 0;
    00031         mask = 1;               // Fill mask with enough bits to cover
    00032         while (mask < limit)    // the desired range.
    00033                 mask = (mask << 1) + 1;
    00034         do
    00035                 {
    00036                 *rsum = cards[*rsum] + user_key[(*keypos)++];
    00037                 if (*keypos >= keysize)
    00038                         {
    00039                         *keypos = 0;            // Recycle the user key.
    00040                         *rsum += keysize;   // key "aaaa" != key "aaaaaaaa"
    00041                         }
    00042                 u = mask & *rsum;
    00043                 if (++retry_limiter > 11)
    00044                         u %= limit;     // Prevent very rare long loops.
    00045                 }
    00046         while (u > limit);
    00047         return u;
    00048 }
    00049
    00050 SapphireBase::SapphireBase()
    00051         : cards(256)
    00052 {
    00053 }
    00054
    00055 SapphireBase::SapphireBase(const byte *key, unsigned int keysize)
    00056         : cards(256)
    00057 {
    00058         assert(keysize < 256);
    00059         // Key size may be up to 256 bytes.
    00060         // Pass phrases may be used directly, with longer length
    00061         // compensating for the low entropy expected in such keys.
    00062         // Alternatively, shorter keys hashed from a pass phrase or
    00063         // generated randomly may be used. For random keys, lengths
    00064         // of from 4 to 16 bytes are recommended, depending on how
    00065         // secure you want this to be.
    00066
    00067         int i;
    00068         byte rsum;
    00069         unsigned keypos;
    00070
    00071         // Start with cards all in order, one of each.
    00072
    00073         for (i=0;i<256;i++)
    00074                 cards[i] = i;
    00075
    00076         // Swap the card at each position with some other card.
    00077
    00078         keypos = 0;         // Start with first byte of user key.
    00079         rsum = 0;
    00080         for (i=255;i;i--)
    00081                 std::swap(cards[i], cards[keyrand(i, key, keysize, &rsum, &keypos)]);
    00082
    00083         // Initialize the indices and data dependencies.
    00084         // Indices are set to different values instead of all 0
    00085         // to reduce what is known about the state of the cards
    00086         // when the first byte is emitted.
    00087
    00088         rotor = cards[1];
    00089         ratchet = cards[3];
    00090         avalanche = cards[5];
    00091         last_plain = cards[7];
    00092         last_cipher = cards[rsum];
    00093
    00094         rsum = 0;
    00095         keypos = 0;
    00096 }
    00097
    00098 SapphireBase::~SapphireBase()
    00099 {
    00100         rotor = ratchet = avalanche = last_plain = last_cipher = 0;
    00101 }
    00102
    00103 void SapphireEncryption::ProcessString(byte *outString, const byte *inString, unsigned int length)
    00104 {
    00105         while(length--)
    00106                 *outString++ = SapphireEncryption::ProcessByte(*inString++);
    00107 }
    00108
    00109 void SapphireEncryption::ProcessString(byte *inoutString, unsigned int length)
    00110 {
    00111         while(length--)
    00112         {
    00113                 *inoutString = SapphireEncryption::ProcessByte(*inoutString);
    00114                 inoutString++;
    00115         }
    00116 }
    00117
    00118 void SapphireDecryption::ProcessString(byte *outString, const byte *inString, unsigned int length)
    00119 {
    00120         while(length--)
    00121                 *outString++ = SapphireDecryption::ProcessByte(*inString++);
    00122 }
    00123
    00124 void SapphireDecryption::ProcessString(byte *inoutString, unsigned int length)
    00125 {
    00126         while(length--)
    00127         {
    00128                 *inoutString = SapphireDecryption::ProcessByte(*inoutString);
    00129                 inoutString++;
    00130         }
    00131 }
    00132
    00133 SapphireHash::SapphireHash(unsigned int hashLength)
    00134         : hashLength(hashLength)
    00135 {
    00136         Init();
    00137 }
    00138
    00139 void SapphireHash::Init()
    00140 {
    00141         // This function is used to initialize non-keyed hash
    00142         // computation.
    00143
    00144         int i, j;
    00145
    00146         // Initialize the indices and data dependencies.
    00147
    00148         rotor = 1;
    00149         ratchet = 3;
    00150         avalanche = 5;
    00151         last_plain = 7;
    00152         last_cipher = 11;
    00153
    00154         // Start with cards all in inverse order.
    00155
    00156         for (i=0, j=255;i<256;i++,j--)
    00157                 cards[i] = (byte) j;
    00158 }
    00159
    00160 void SapphireHash::Update(const byte *input, unsigned int length)
    00161 {
    00162         while(length--)
    00163                 SapphireEncryption::ProcessByte(*input++);
    00164 }
    00165
    00166 void SapphireHash::TruncatedFinal(byte *hash, unsigned int size)
    00167 {
    00168         ThrowIfInvalidTruncatedSize(size);
    00169
    00170         for (int i=255; i>=0; i--)
    00171                 ProcessByte((byte) i);
    00172
    00173         for (unsigned int j=0; j<size; j++)
    00174                 hash[j] = ProcessByte(0);
    00175
    00176         Init();
    00177 }
    00178
    00179 NAMESPACE_END