1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
#include <stdlib.h>
#include <string.h>
#include "sb_crypt.h"
static unsigned char keyrand(GOACryptState *state, int limit,
unsigned char *user_key,
unsigned char keysize,
unsigned char *rsum,
unsigned *keypos)
{
unsigned int 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 = (unsigned char)(state->cards[*rsum] + user_key[(*keypos)++]);
if (*keypos >= keysize)
{
*keypos = 0; // Recycle the user key.
*rsum = (unsigned char)(*rsum + keysize); // key "aaaa" != key "aaaaaaaa"
}
u = mask & *rsum;
if (++retry_limiter > 11)
u %= (unsigned int)limit; // Prevent very rare long loops.
}
while (u > (unsigned)limit);
return (unsigned char)(u);
}
void GOAHashInit(GOACryptState *state)
{
// This function is used to initialize non-keyed hash
// computation.
int i, j;
// Initialize the indices and data dependencies.
state->rotor = 1;
state->ratchet = 3;
state->avalanche = 5;
state->last_plain = 7;
state->last_cipher = 11;
// Start with state->cards all in inverse order.
for (i=0, j=255;i<256;i++,j--)
state->cards[i] = (unsigned char) j;
}
void GOACryptInit(GOACryptState *state, 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)
{
GOAHashInit(state);
return;
}
// Start with state->cards all in order, one of each.
for (i=0;i<256;i++)
state->cards[i] = (unsigned char)(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(state, i, key, keysize, &rsum, &keypos);
swaptemp = state->cards[i];
state->cards[i] = state->cards[toswap];
state->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 state->cards
// when the first byte is emitted.
state->rotor = state->cards[1];
state->ratchet = state->cards[3];
state->avalanche = state->cards[5];
state->last_plain = state->cards[7];
state->last_cipher = state->cards[rsum];
toswap = swaptemp = rsum = 0;
keypos = 0;
}
unsigned char GOAEncryptByte(GOACryptState *state, unsigned char b)
{
// Picture a single enigma state->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.
state->ratchet = (unsigned char)(state->ratchet + state->cards[state->rotor++]);
swaptemp = state->cards[state->last_cipher];
state->cards[state->last_cipher] = state->cards[state->ratchet];
state->cards[state->ratchet] = state->cards[state->last_plain];
state->cards[state->last_plain] = state->cards[state->rotor];
state->cards[state->rotor] = swaptemp;
state->avalanche = (unsigned char)(state->avalanche + state->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.
/*
state->last_cipher = b^state->cards[(state->cards[state->ratchet] + state->cards[state->rotor]) & 0xFF] ^
state->cards[state->cards[(state->cards[state->last_plain] +
state->cards[state->last_cipher] +
state->cards[state->avalanche])&0xFF]];
*/
state->last_cipher = (unsigned char)(b^state->cards[(state->cards[state->avalanche] + state->cards[state->rotor]) & 0xFF] ^
state->cards[state->cards[(state->cards[state->last_plain] +
state->cards[state->last_cipher] +
state->cards[state->ratchet])&0xFF]]);
state->last_plain = b;
return state->last_cipher;
}
void GOAEncrypt(GOACryptState *state, unsigned char *bp, int len)
{
int i;
for (i = 0 ; i < len ; i++)
{
bp[i] = GOAEncryptByte(state, bp[i]);
}
}
unsigned char GOADecryptByte(GOACryptState *state, unsigned char b)
{
unsigned char swaptemp;
// Shuffle the deck a little more.
state->ratchet = (unsigned char)(state->ratchet + state->cards[state->rotor++]);
swaptemp = state->cards[state->last_cipher];
state->cards[state->last_cipher] = state->cards[state->ratchet];
state->cards[state->ratchet] = state->cards[state->last_plain];
state->cards[state->last_plain] = state->cards[state->rotor];
state->cards[state->rotor] = swaptemp;
state->avalanche = (unsigned char)(state->avalanche + state->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.
/*
state->last_plain = b^state->cards[(state->cards[state->ratchet] + state->cards[state->rotor]) & 0xFF] ^
state->cards[state->cards[(state->cards[state->last_plain] +
state->cards[state->last_cipher] +
state->cards[state->avalanche])&0xFF]];
*/
//crt - change this around
state->last_plain = (unsigned char)(b^state->cards[(state->cards[state->avalanche] + state->cards[state->rotor]) & 0xFF] ^
state->cards[state->cards[(state->cards[state->last_plain] +
state->cards[state->last_cipher] +
state->cards[state->ratchet])&0xFF]]);
state->last_cipher = b;
return state->last_plain;
}
void GOADecrypt(GOACryptState *state, unsigned char *bp, int len)
{
int i;
for (i = 0 ; i < len ; i++)
{
bp[i] = GOADecryptByte(state, bp[i]);
}
}
void GOAHashFinal(GOACryptState *state, unsigned char *outputhash, // Destination
unsigned char hashlength) // Size of hash.
{
int i;
for (i=255;i>=0;i--)
GOAEncryptByte(state, (unsigned char) i);
for (i=0;i<hashlength;i++)
outputhash[i] = GOAEncryptByte(state, 0);
}
|