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
|
#ifndef CRYPTOPP_SAPPHIRE_H
#define CRYPTOPP_SAPPHIRE_H
#include "seckey.h"
#include "secblock.h"
NAMESPACE_BEGIN(CryptoPP)
/// base class, do not use directly
class SapphireBase : public VariableKeyLength<16, 1, 255>
{
protected:
SapphireBase();
SapphireBase(const byte *userKey, unsigned int keyLength);
~SapphireBase();
inline void ShuffleCards()
{
ratchet += cards[rotor++];
byte 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];
}
// These variables comprise the state of the state machine.
SecByteBlock cards; // A permutation of 0-255.
byte rotor, // Index that rotates smoothly
ratchet, // Index that moves erratically
avalanche, // Index heavily data dependent
last_plain, // Last plain text byte
last_cipher; // Last cipher text byte
private:
byte keyrand(unsigned int limit, const byte *user_key, byte keysize, byte *rsum, unsigned *keypos);
};
/// <a href="http://www.weidai.com/scan-mirror/cs.html#Sapphire-II">Sapphire-II Cipher</a>
class SapphireEncryption : public StreamTransformation, public SapphireBase
{
public:
SapphireEncryption(const byte *userKey, unsigned int keyLength=DEFAULT_KEYLENGTH)
: SapphireBase(userKey, keyLength) {}
inline byte ProcessByte(byte b)
{
ShuffleCards();
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;
}
void ProcessString(byte *outString, const byte *inString, unsigned int length);
void ProcessString(byte *inoutString, unsigned int length);
protected:
SapphireEncryption() {} // for SapphireHash
};
/// <a href="http://www.weidai.com/scan-mirror/cs.html#Sapphire-II">Sapphire-II cipher</a>
class SapphireDecryption : public StreamTransformation, public SapphireBase
{
public:
SapphireDecryption(const byte *userKey, unsigned int keyLength=DEFAULT_KEYLENGTH)
: SapphireBase(userKey, keyLength) {}
inline byte ProcessByte(byte b)
{
ShuffleCards();
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 ProcessString(byte *outString, const byte *inString, unsigned int length);
void ProcessString(byte *inoutString, unsigned int length);
};
/// Sapphire Random Number Generator
class SapphireRNG : public RandomNumberGenerator, private SapphireEncryption
{
public:
SapphireRNG(const byte *seed, unsigned int seedLength)
: SapphireEncryption(seed, seedLength) {}
inline byte GetByte() {return SapphireEncryption::ProcessByte(0);}
};
//! Sapphire Hash
/*! Digest Length = 160 bits */
class SapphireHash : public HashTransformation, private SapphireEncryption
{
public:
SapphireHash(unsigned int hashLength=20);
void Update(const byte *input, unsigned int length);
void TruncatedFinal(byte *hash, unsigned int size);
unsigned int DigestSize() const {return hashLength;}
private:
void Init();
const unsigned int hashLength;
};
NAMESPACE_END
#endif
|