The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sapphire.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * sapphire.cpp - the Saphire II stream cipher class
4  *
5  * $Id: sapphire.cpp 3786 2020-08-30 11:35:14Z scribe $
6  *
7  * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org)
8  * CrossWire Bible Society
9  * P. O. Box 2528
10  * Tempe, AZ 85280-2528
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the
14  * Free Software Foundation version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  */
22 
23 /******************************************************************************
24  *
25  * Original license notice & credits:
26  * Dedicated to the Public Domain the author and inventor:
27  * (Michael Paul Johnson). This code comes with no warranty.
28  * Use it at your own risk.
29  * Ported from the Pascal implementation of the Sapphire Stream
30  * Cipher 9 December 1994.
31  * Added hash pre- and post-processing 27 December 1994.
32  * Modified initialization to make index variables key dependent,
33  * made the output function more resistant to cryptanalysis,
34  * and renamed to Sapphire II 2 January 1995
35  *
36  */
37 
38 #include <string.h>
39 
40 #include "sapphire.h"
41 
43 
44 unsigned char Sapphire::keyrand(int limit,
45  unsigned char *user_key,
46  unsigned char keysize,
47  unsigned char *rsum,
48  unsigned *keypos)
49  {
50  unsigned u, // Value from 0 to limit to return.
51  retry_limiter, // No infinite loops allowed.
52  mask; // Select just enough bits.
53 
54  if (!limit) return 0; // Avoid divide by zero error.
55  retry_limiter = 0;
56  mask = 1; // Fill mask with enough bits to cover
57  while (mask < (unsigned)limit) // the desired range.
58  mask = (mask << 1) + 1;
59  do
60  {
61  *rsum = cards[*rsum] + user_key[(*keypos)++];
62  if (*keypos >= keysize)
63  {
64  *keypos = 0; // Recycle the user key.
65  *rsum += keysize; // key "aaaa" != key "aaaaaaaa"
66  }
67  u = mask & *rsum;
68  if (++retry_limiter > 11)
69  u %= limit; // Prevent very rare long loops.
70  }
71  while (u > (unsigned)limit);
72  return u;
73  }
74 
75 void Sapphire::initialize(unsigned char *key, unsigned char keysize)
76  {
77  // Key size may be up to 256 bytes.
78  // Pass phrases may be used directly, with longer length
79  // compensating for the low entropy expected in such keys.
80  // Alternatively, shorter keys hashed from a pass phrase or
81  // generated randomly may be used. For random keys, lengths
82  // of from 4 to 16 bytes are recommended, depending on how
83  // secure you want this to be.
84 
85  int i;
86  unsigned char toswap, swaptemp, rsum;
87  unsigned keypos;
88 
89  // If we have been given no key, assume the default hash setup.
90 
91  if (keysize < 1)
92  {
93  hash_init();
94  return;
95  }
96 
97  // Start with cards all in order, one of each.
98 
99  for (i=0;i<256;i++)
100  cards[i] = i;
101 
102  // Swap the card at each position with some other card.
103 
104  toswap = 0;
105  keypos = 0; // Start with first byte of user key.
106  rsum = 0;
107  for (i=255;i>=0;i--)
108  {
109  toswap = keyrand(i, key, keysize, &rsum, &keypos);
110  swaptemp = cards[i];
111  cards[i] = cards[toswap];
112  cards[toswap] = swaptemp;
113  }
114 
115  // Initialize the indices and data dependencies.
116  // Indices are set to different values instead of all 0
117  // to reduce what is known about the state of the cards
118  // when the first byte is emitted.
119 
120  rotor = cards[1];
121  ratchet = cards[3];
122  avalanche = cards[5];
123  last_plain = cards[7];
124  last_cipher = cards[rsum];
125 
126  toswap = swaptemp = rsum = 0;
127  keypos = 0;
128  }
129 
131  {
132  // This function is used to initialize non-keyed hash
133  // computation.
134 
135  int i, j;
136 
137  // Initialize the indices and data dependencies.
138 
139  rotor = 1;
140  ratchet = 3;
141  avalanche = 5;
142  last_plain = 7;
143  last_cipher = 11;
144 
145  // Start with cards all in inverse order.
146 
147  for (i=0, j=255;i<256;i++,j--)
148  cards[i] = (unsigned char) j;
149  }
150 
151 Sapphire::Sapphire(unsigned char *key, unsigned char keysize)
152  {
153  if (key && keysize)
154  initialize(key, keysize);
155  }
156 
157 void Sapphire::burn(void)
158  {
159  // Destroy the key and state information in RAM.
160  memset(cards, 0, 256);
162  }
163 
165  {
166  burn();
167  }
168 
169 unsigned char Sapphire::encrypt(unsigned char b)
170  {
171  // Picture a single enigma rotor with 256 positions, rewired
172  // on the fly by card-shuffling.
173 
174  // This cipher is a variant of one invented and written
175  // by Michael Paul Johnson in November, 1993.
176 
177  unsigned char swaptemp;
178 
179  // Shuffle the deck a little more.
180 
181  ratchet += cards[rotor++];
182  swaptemp = cards[last_cipher];
186  cards[rotor] = swaptemp;
187  avalanche += cards[swaptemp];
188 
189  // Output one byte from the state in such a way as to make it
190  // very hard to figure out which one you are looking at.
191 
192  last_cipher = b^cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^
194  cards[last_cipher] +
195  cards[avalanche])&0xFF]];
196  last_plain = b;
197  return last_cipher;
198  }
199 
200 unsigned char Sapphire::decrypt(unsigned char b)
201  {
202  unsigned char swaptemp;
203 
204  // Shuffle the deck a little more.
205 
206  ratchet += cards[rotor++];
207  swaptemp = cards[last_cipher];
211  cards[rotor] = swaptemp;
212  avalanche += cards[swaptemp];
213 
214  // Output one byte from the state in such a way as to make it
215  // very hard to figure out which one you are looking at.
216 
217  last_plain = b^cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^
219  cards[last_cipher] +
220  cards[avalanche])&0xFF]];
221  last_cipher = b;
222  return last_plain;
223  }
224 
225 void Sapphire::hash_final(unsigned char *hash, // Destination
226  unsigned char hashlength) // Size of hash.
227  {
228  int i;
229 
230  for (i=255;i>=0;i--)
231  encrypt((unsigned char) i);
232  for (i=0;i<hashlength;i++)
233  hash[i] = encrypt(0);
234  }
235 
void burn(void)
Definition: sapphire.cpp:157
#define SWORD_NAMESPACE_START
Definition: defs.h:39
unsigned char avalanche
Definition: sapphire.h:54
unsigned char cards[256]
Definition: sapphire.h:53
unsigned char encrypt(unsigned char b=0)
Definition: sapphire.cpp:169
void hash_final(unsigned char *hash, unsigned char hashlength=20)
Definition: sapphire.cpp:225
void initialize(unsigned char *key, unsigned char keysize)
Definition: sapphire.cpp:75
void hash_init(void)
Definition: sapphire.cpp:130
Sapphire(unsigned char *key=NULL, unsigned char keysize=0)
Definition: sapphire.cpp:151
unsigned char last_cipher
Definition: sapphire.h:54
unsigned char last_plain
Definition: sapphire.h:54
unsigned char decrypt(unsigned char b)
Definition: sapphire.cpp:200
unsigned char rotor
Definition: sapphire.h:54
unsigned char keyrand(int limit, unsigned char *user_key, unsigned char keysize, unsigned char *rsum, unsigned *keypos)
Definition: sapphire.cpp:44
#define SWORD_NAMESPACE_END
Definition: defs.h:40
unsigned char ratchet
Definition: sapphire.h:54