📄 diamond.cpp
字号:
#include "pch.h"
#include "diamond.h"
NAMESPACE_BEGIN(CryptoPP)
class Diamond2SboxMaker
{
public:
Diamond2SboxMaker(const byte *external_key, unsigned int key_size,
unsigned int rounds, bool lite);
void MakeSbox(byte *sbox, CipherDir direction);
private:
unsigned int keyrand(unsigned int max_value, const byte *prevSbox);
void makeonebox(byte *s, unsigned int i, unsigned int j);
CRC32 crc;
const byte *const key;
const unsigned keysize;
unsigned keyindex;
const unsigned numrounds;
const unsigned roundsize; // Number of bytes in one round of substitution boxes
const unsigned blocksize;
};
Diamond2SboxMaker::Diamond2SboxMaker(const byte *external_key, unsigned int key_size, unsigned int rounds,
bool lite)
: key(external_key),
keysize(key_size),
keyindex(0),
numrounds(rounds),
roundsize(lite ? 2048 : 4096),
blocksize(lite ? 8 : 16)
{
assert((rounds * blocksize) <= 255);
}
// Returns uniformly distributed pseudorandom value based on key[], sized keysize
inline unsigned int Diamond2SboxMaker::keyrand(unsigned int max_value, const byte *prevSbox)
{
if (!max_value) return 0;
unsigned int mask, prandvalue, i;
// Create a mask to get the minimum number of
// bits to cover the range 0 to max_value.
for (i=max_value, mask=0; i > 0; i = i >> 1)
mask = (mask << 1) | 1;
assert(i==0);
do
{
if (prevSbox)
crc.UpdateByte(prevSbox[key[keyindex++]]);
else
crc.UpdateByte(key[keyindex++]);
if (keyindex >= keysize)
{
keyindex = 0; /* Recycle thru the key */
crc.UpdateByte(byte(keysize));
crc.UpdateByte(byte(keysize >> 8));
}
prandvalue = (unsigned int)~crc.GetCrc() & mask;
if ((++i>97) && (prandvalue > max_value)) /* Don't loop forever. */
prandvalue -= max_value; /* Introduce negligible bias. */
}
while (prandvalue > max_value); /* Discard out of range values. */
return prandvalue;
}
void Diamond2SboxMaker::makeonebox(byte *s, unsigned int i, unsigned int j)
{
bool filled[256];
byte *sbox = s + (roundsize*i) + (256*j);
byte *prevSbox = (i||j) ? sbox-256 : 0;
unsigned m;
for (m = 0; m < 256; m++) /* The filled array is used to make sure that */
filled[m] = false; /* each byte of the array is filled only once. */
for (int n = 255; n >= 0 ; n--) /* n counts the number of bytes left to fill */
{
// pos is the position among the UNFILLED
// components of the s array that the number n should be placed.
unsigned pos = keyrand(n, prevSbox);
unsigned p=0;
while (filled[p]) p++;
for (m=0; m<pos; m++)
{
p++;
while (filled[p]) p++;
}
assert(p<256);
sbox[p] = n;
filled[p] = true;
}
}
void Diamond2SboxMaker::MakeSbox(byte *s, CipherDir direction)
{
unsigned int i, j, k;
for (i = 0; i < numrounds; i++)
for (j = 0; j < blocksize; j++)
makeonebox(s, i, j);
if (direction==DECRYPTION)
{
SecByteBlock si(numrounds * roundsize);
for (i = 0; i < numrounds; i++)
for (j = 0; j < blocksize; j++)
for (k = 0; k < 256; k++)
*(si + (roundsize * i) + (256 * j) + *(s + (roundsize * i) + (256 * j) + k)) = k;
memcpy(s, si, numrounds * roundsize);
}
}
Diamond2Base::Diamond2Base(const byte *key, unsigned int key_size,
unsigned int rounds, CipherDir direction)
: numrounds(rounds),
s(numrounds * ROUNDSIZE)
{
Diamond2SboxMaker m(key, key_size, rounds, false);
m.MakeSbox(s, direction);
}
inline void Diamond2Base::substitute(int round, byte *y) const
{
const byte *sbox = s + (ROUNDSIZE*round);
y[0] = sbox[0*256+y[0]];
y[1] = sbox[1*256+y[1]];
y[2] = sbox[2*256+y[2]];
y[3] = sbox[3*256+y[3]];
y[4] = sbox[4*256+y[4]];
y[5] = sbox[5*256+y[5]];
y[6] = sbox[6*256+y[6]];
y[7] = sbox[7*256+y[7]];
y[8] = sbox[8*256+y[8]];
y[9] = sbox[9*256+y[9]];
y[10] = sbox[10*256+y[10]];
y[11] = sbox[11*256+y[11]];
y[12] = sbox[12*256+y[12]];
y[13] = sbox[13*256+y[13]];
y[14] = sbox[14*256+y[14]];
y[15] = sbox[15*256+y[15]];
}
#ifdef DIAMOND_USE_PERMTABLE
inline void Diamond2Base::permute(byte *a)
{
#ifdef IS_LITTLE_ENDIAN
word32 temp0 = (a[0] | (word32(a[10])<<24)) & 0x80000001;
#else
word32 temp0 = ((word32(a[0])<<24) | a[10]) & 0x01000080;
#endif
temp0 |= permtable[0][a[1]] |
permtable[1][a[2]] | permtable[2][a[3]] |
permtable[3][a[4]] | permtable[4][a[5]] |
permtable[5][a[6]] | permtable[6][a[7]] |
permtable[7][a[8]] | permtable[8][a[9]];
#ifdef IS_LITTLE_ENDIAN
word32 temp1 = (a[4] | (word32(a[14])<<24)) & 0x80000001;
#else
word32 temp1 = ((word32(a[4])<<24) | a[14]) & 0x01000080;
#endif
temp1 |= permtable[0][a[5]] |
permtable[1][a[6]] | permtable[2][a[7]] |
permtable[3][a[8]] | permtable[4][a[9]] |
permtable[5][a[10]] | permtable[6][a[11]] |
permtable[7][a[12]] | permtable[8][a[13]];
#ifdef IS_LITTLE_ENDIAN
word32 temp2 = (a[8] | (word32(a[2])<<24)) & 0x80000001;
#else
word32 temp2 = ((word32(a[8])<<24) | a[2]) & 0x01000080;
#endif
temp2 |= permtable[0][a[9]] |
permtable[1][a[10]] | permtable[2][a[11]] |
permtable[3][a[12]] | permtable[4][a[13]] |
permtable[5][a[14]] | permtable[6][a[15]] |
permtable[7][a[0]] | permtable[8][a[1]];
#ifdef IS_LITTLE_ENDIAN
word32 temp3 = (a[12] | (word32(a[6])<<24)) & 0x80000001;
#else
word32 temp3 = ((word32(a[12])<<24) | a[6]) & 0x01000080;
#endif
((word32 *)a)[3] = temp3 | permtable[0][a[13]] |
permtable[1][a[14]] | permtable[2][a[15]] |
permtable[3][a[0]] | permtable[4][a[1]] |
permtable[5][a[2]] | permtable[6][a[3]] |
permtable[7][a[4]] | permtable[8][a[5]];
((word32 *)a)[0] = temp0;
((word32 *)a)[1] = temp1;
((word32 *)a)[2] = temp2;
}
inline void Diamond2Base::ipermute(byte *a)
{
#ifdef IS_LITTLE_ENDIAN
word32 temp0 = (a[9] | (word32(a[3])<<24)) & 0x01000080;
#else
word32 temp0 = ((word32(a[9])<<24) | a[3]) & 0x80000001;
#endif
temp0 |= ipermtable[0][a[2]] |
ipermtable[1][a[1]] | ipermtable[2][a[0]] |
ipermtable[3][a[15]] | ipermtable[4][a[14]] |
ipermtable[5][a[13]] | ipermtable[6][a[12]] |
ipermtable[7][a[11]] | ipermtable[8][a[10]];
#ifdef IS_LITTLE_ENDIAN
word32 temp1 = (a[13] | (word32(a[7])<<24)) & 0x01000080;
#else
word32 temp1 = ((word32(a[13])<<24) | a[7]) & 0x80000001;
#endif
temp1 |= ipermtable[0][a[6]] |
ipermtable[1][a[5]] | ipermtable[2][a[4]] |
ipermtable[3][a[3]] | ipermtable[4][a[2]] |
ipermtable[5][a[1]] | ipermtable[6][a[0]] |
ipermtable[7][a[15]] | ipermtable[8][a[14]];
#ifdef IS_LITTLE_ENDIAN
word32 temp2 = (a[1] | (word32(a[11])<<24)) & 0x01000080;
#else
word32 temp2 = ((word32(a[1])<<24) | a[11]) & 0x80000001;
#endif
temp2 |= ipermtable[0][a[10]] |
ipermtable[1][a[9]] | ipermtable[2][a[8]] |
ipermtable[3][a[7]] | ipermtable[4][a[6]] |
ipermtable[5][a[5]] | ipermtable[6][a[4]] |
ipermtable[7][a[3]] | ipermtable[8][a[2]];
#ifdef IS_LITTLE_ENDIAN
word32 temp3 = (a[5] | (word32(a[15])<<24)) & 0x01000080;
#else
word32 temp3 = ((word32(a[5])<<24) | a[15]) & 0x80000001;
#endif
((word32 *)a)[3] = temp3 | ipermtable[0][a[14]] |
ipermtable[1][a[13]] | ipermtable[2][a[12]] |
ipermtable[3][a[11]] | ipermtable[4][a[10]] |
ipermtable[5][a[9]] | ipermtable[6][a[8]] |
ipermtable[7][a[7]] | ipermtable[8][a[6]];
((word32 *)a)[0] = temp0;
((word32 *)a)[1] = temp1;
((word32 *)a)[2] = temp2;
}
#else // DIAMOND_USE_PERMTABLE
inline void Diamond2Base::permute(byte *x)
{
byte y[16];
y[0] = (x[0] & 1) | (x[1] & 2) | (x[2] & 4) |
(x[3] & 8) | (x[4] & 16) | (x[5] & 32) |
(x[6] & 64) | (x[7] & 128);
y[1] = (x[1] & 1) | (x[2] & 2) | (x[3] & 4) |
(x[4] & 8) | (x[5] & 16) | (x[6] & 32) |
(x[7] & 64) | (x[8] & 128);
y[2] = (x[2] & 1) | (x[3] & 2) | (x[4] & 4) |
(x[5] & 8) | (x[6] & 16) | (x[7] & 32) |
(x[8] & 64) | (x[9] & 128);
y[3] = (x[3] & 1) | (x[4] & 2) | (x[5] & 4) |
(x[6] & 8) | (x[7] & 16) | (x[8] & 32) |
(x[9] & 64) | (x[10] & 128);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -