我正在制作一个加密算法(只是为了好玩),这取决于我用密钥播种的伪随机数生成器。 PRNG应该为相同的种子(初始化密钥)产生相同的序列,但是当我在encrypt
和decrypt
方法中声明它们并调用它们时,这种情况就不会发生。
crypto.hpp:
#ifndef CRYPTO_HPP
#define CRYPTO_HPP
#include <cstdlib>
#include <cstdint>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include "quadrant.hpp"
static const uint8_t sbox1[256] = {
0x68,0x81,0x90,0xf4,0x2f,0x47,0xdc,0xb1,0xe2,0xff,0xe3,0x88,0xeb,0xcb,0xba,0x9c,
0xc0,0x0a,0xd4,0x78,0x2c,0xc6,0x5c,0x33,0xea,0x8f,0x15,0x22,0x38,0xf1,0xbe,0xc4,
0x82,0x30,0xb6,0xa4,0x8c,0x11,0xe6,0xe5,0x13,0x1d,0xa0,0x67,0x75,0x06,0x8d,0xf7,
0x54,0x3f,0x48,0x4f,0x66,0x16,0x07,0x28,0xbc,0x91,0xb9,0xe7,0x0d,0xb3,0xa6,0x7f,
0x2a,0x2d,0xe4,0xb7,0x98,0x1f,0x5b,0x87,0x1e,0xc9,0x6d,0x51,0x3a,0x99,0x04,0xee,
0x03,0xac,0xfa,0x52,0x57,0x29,0x21,0x2e,0xbf,0x94,0xcc,0xcd,0x92,0xb5,0xc7,0x9e,
0xc5,0xbb,0xd7,0xd8,0x60,0xed,0x20,0x26,0xb8,0x45,0x6a,0x01,0x34,0xa9,0x69,0xc1,
0xda,0xf5,0xfe,0x23,0x5f,0x70,0x9a,0x95,0x1c,0xd9,0xa3,0x8a,0x61,0xce,0x79,0x93,
0xd5,0x9b,0x4d,0xf0,0xc2,0x10,0x14,0x1b,0x18,0x0e,0xef,0xfd,0x71,0xab,0x12,0x9f,
0x44,0xf2,0x3b,0xaa,0xca,0x59,0x3c,0x0f,0x37,0x0b,0x85,0xdf,0xfc,0x2b,0x43,0x6c,
0x42,0x00,0x89,0x53,0xae,0xd6,0x3d,0x02,0xe9,0x7c,0x62,0xe0,0x8b,0xb2,0x5a,0x7a,
0x6e,0xd0,0x6f,0xec,0xde,0x5d,0x4b,0x84,0x31,0x0c,0x3e,0x7d,0x8e,0x96,0x27,0xcf,
0x74,0xaf,0x58,0xa1,0xa8,0x65,0x72,0x9d,0x09,0x73,0x49,0x6b,0xa7,0xe1,0xe8,0xf8,
0x80,0xf3,0x97,0xf9,0x4e,0x86,0x55,0x63,0xd2,0xdd,0x25,0x50,0x83,0xc8,0x05,0x08,
0x7b,0xa5,0x4a,0x76,0x64,0x5e,0x35,0x1a,0xad,0x17,0xf6,0xc3,0xdb,0xb4,0xfb,0x7e,
0x39,0x24,0xd3,0x32,0x36,0xa2,0x19,0x46,0x56,0x77,0xd1,0x40,0x4c,0x41,0xbd,0xb0
};
static const uint8_t sbox2[256] = {
0x9f,0x33,0x84,0x4d,0xd8,0x04,0xdf,0x5e,0xd5,0xb0,0x55,0x82,0x26,0x57,0x2d,0x0d,
0x19,0x36,0xdc,0xbd,0x5c,0xe9,0x4f,0x45,0xac,0xf0,0xca,0x25,0xc4,0x93,0xee,0xf9,
0x68,0x34,0x0e,0x11,0x5d,0x00,0x2b,0xaa,0xa7,0xcb,0xb7,0x3d,0x32,0xc9,0xbe,0x0a,
0x47,0xea,0x70,0xe2,0x88,0x46,0x10,0xd2,0xfd,0xd3,0x49,0x38,0x83,0x5b,0xb2,0xdb,
0x22,0xef,0x7d,0xfa,0x9c,0xda,0x4b,0x9a,0xb5,0x2f,0xc6,0xf4,0x9d,0xc8,0x92,0x1c,
0xd0,0xbf,0x7b,0xfb,0x64,0x97,0x90,0x24,0xb4,0x52,0x73,0xa2,0x6f,0x80,0x61,0x23,
0x99,0x59,0xad,0x35,0x63,0x1d,0x06,0xe7,0x3a,0x30,0x27,0x89,0x91,0x7e,0xab,0xb3,
0xb9,0xa8,0x71,0x72,0xfe,0xdd,0xd4,0x14,0xc5,0x6b,0xf3,0x4c,0x3c,0x5f,0xa5,0x74,
0x8f,0x21,0x41,0x50,0x0b,0x1e,0x43,0x18,0x62,0xe0,0xcf,0x12,0xd7,0x8e,0xde,0x03,
0xbc,0xe1,0x6d,0x1a,0xfc,0xd6,0x66,0xc1,0x15,0x9b,0xb8,0x29,0xbb,0xc3,0x0f,0x08,
0x9e,0x81,0x96,0x4a,0x16,0x94,0xe5,0x75,0x86,0x60,0x67,0xf7,0x44,0x7c,0x77,0x05,
0xff,0x95,0xf1,0xc0,0x02,0x7f,0xe6,0xa9,0xaf,0x5a,0x01,0xc2,0xe8,0x39,0x58,0x85,
0xec,0xcc,0x07,0x53,0xa4,0x28,0xf8,0xba,0x4e,0x98,0x79,0x17,0xd9,0x1f,0x40,0xa0,
0xf5,0x20,0xe3,0x2e,0xeb,0x56,0xa1,0x7a,0x31,0x8b,0x8d,0xd1,0x2c,0x8c,0x42,0x0c,
0x87,0xa3,0x78,0x6e,0xf2,0xcd,0x8a,0x3f,0xce,0xae,0x09,0xf6,0xb6,0x6a,0xc7,0x51,
0x48,0x6c,0x65,0x1b,0x76,0x3e,0xa6,0x3b,0x37,0x54,0x2a,0x13,0xe4,0x69,0xed,0xb1
};
static const uint8_t sbox3[256] = {
0x34,0x8c,0x07,0x0d,0xda,0xf8,0xa6,0x13,0xd6,0xf5,0xb2,0x58,0xc6,0x04,0xe3,0x3f,
0xf1,0x8a,0x15,0x69,0xa9,0x50,0x82,0x91,0x1b,0x27,0xed,0x32,0x99,0xd0,0x73,0x5a,
0xc3,0xbe,0xbf,0xc0,0x40,0x1f,0xf9,0xd5,0xb4,0x66,0x9e,0x02,0xce,0xb0,0xb9,0x20,
0xe8,0x68,0x01,0xa0,0xe6,0x7d,0x19,0xd7,0x35,0x62,0x74,0x7e,0x3c,0xa2,0x71,0x3d,
0xbc,0x08,0xb8,0x2a,0x81,0xbd,0x12,0x83,0xb1,0x98,0x41,0x88,0x00,0x06,0xb6,0x64,
0xbb,0x9d,0x87,0x1a,0x6e,0x2c,0x3a,0x4b,0x96,0x14,0x29,0xe1,0xa8,0xf2,0x6b,0x5e,
0x53,0xdf,0x23,0x51,0xcf,0x9c,0xab,0xf7,0xf6,0xfe,0x4c,0x78,0x6c,0xcc,0x4a,0x57,
0x09,0x8e,0x67,0x33,0xd2,0x6a,0xaf,0x80,0x8f,0xa3,0x0e,0x86,0x4f,0xea,0xc8,0xba,
0x45,0x95,0xe7,0x49,0x94,0xe2,0xd8,0x3b,0xcb,0x05,0x9f,0xdc,0x2f,0x26,0xf4,0x2d,
0xe5,0x61,0x6d,0x56,0x38,0x22,0x60,0x72,0x8d,0xf3,0x37,0x63,0xeb,0x7f,0x46,0xaa,
0x5c,0x4e,0xd4,0x7b,0xfd,0x76,0xec,0x11,0x28,0x5f,0x21,0x2e,0xe0,0x16,0x4d,0x0f,
0x77,0xef,0x52,0x2b,0xb5,0x39,0xca,0x93,0x84,0x3e,0x7c,0x6f,0xfc,0xf0,0x75,0x55,
0xd1,0xc1,0xee,0x9b,0xa1,0xb3,0xff,0x5d,0x42,0x79,0xa5,0x70,0x44,0xd3,0x31,0x90,
0x25,0x5b,0xc9,0x7a,0x65,0x10,0xa4,0x47,0xac,0x30,0x17,0x0a,0x8b,0xdd,0xe9,0x0b,
0x9a,0xc7,0xc4,0xde,0x89,0x92,0xdb,0xb7,0xad,0x18,0x43,0xfa,0x0c,0x1c,0x1d,0x24,
0xfb,0xcd,0xd9,0x48,0x54,0xc2,0xae,0x97,0x1e,0x03,0xa7,0x36,0xc5,0x59,0x85,0xe4
};
class cipher
{
private:
// Initialize key
static void key_sched(const char* key,uint32_t ks,uint32_t s_k[16]) // Key length: 256 bits = 32 bytes
{
uint32_t i, j;
int ix, iy;
uint8_t tk[2*ks];
uint32_t s_aux[16];
uint32_t mask[16] = { // Based on decimal part of Phi
0x3779b97f,0x4a7c15f3,0x9cc0605c,0xedc83410,
0x82276bf3,0xa27251f8,0x6c6a11d0,0xc18e9527,
0x67f0b153,0xd27b7f03,0x47045b5b,0xf1827f01,
0x886f0928,0x403002c1,0xd64ba40f,0x335e36f0
};
for (i=0;i<16;i++)
s_aux[i] = 0x0;
for (i=0;i<ks;i++)
{
tk[2*i ] = sbox1[key[i]];
tk[2*i+1] = sbox2[key[i]];
}
for (i=0;i<2*ks;i++)
{
ix = i%4; iy = i/4;
s_aux[iy] |= uint32_t(tk[i]) << (8*(3-ix));
}
uint32_t tmp;
for (i=0;i<16;i++)
{
s_k[i] = (s_aux[i] << 13) | (s_aux[(i+1)%16] >> 18);
s_k[i] ^= mask[i];
tmp = s_k[i];
s_k[i] = ((uint32_t)sbox3[(tmp>>24)&0xff] << 24) |
((uint32_t)sbox3[(tmp>>16)&0xff] << 16) |
((uint32_t)sbox3[(tmp>> 8)&0xff] << 8) |
((uint32_t)sbox3[(tmp>> 0)&0xff] << 0);
}
}
public:
// Encrypt
static void encrypt(const char* data,uint32_t ds,uint8_t* out,const char* key,uint32_t ks)
{
std::cout << "Key used: " << key << "\n";
uint32_t seed_k[16];
key_sched(key,ks,seed_k);
// PRNG seeded by key
quadrant krng(seed_k[ 0],seed_k[ 1],seed_k[ 2],seed_k[ 3],seed_k[ 4],seed_k[ 5],seed_k[ 6],seed_k[ 7],
seed_k[ 8],seed_k[ 9],seed_k[10],seed_k[11],seed_k[12],seed_k[13],seed_k[14],seed_k[15]);
std::cout << "[encrypt] Test krng(): " << krng() << "\n";
// do encryption...
}
// Decrypt
static void decrypt(uint8_t* data,uint32_t ds,uint8_t* out,const char* key,uint32_t ks)
{
std::cout << "Key used: " << key << "\n";
uint32_t seed_k[16];
key_sched(key,ks,seed_k);
// PRNG seeded by key
quadrant krng(seed_k[ 0],seed_k[ 1],seed_k[ 2],seed_k[ 3],seed_k[ 4],seed_k[ 5],seed_k[ 6],seed_k[ 7],
seed_k[ 8],seed_k[ 9],seed_k[10],seed_k[11],seed_k[12],seed_k[13],seed_k[14],seed_k[15]);
std::cout << "[decrypt] Test krng(): " << krng() << "\n";
// do decryption...
}
};
#endif
ctest.cpp:
#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <string>
#include "crypto.hpp"
using namespace std;
int main()
{
string ptx = "Plaintext";
string key = "Key";
uint8_t* encr;
uint8_t* decr;
uint32_t esiz = 0;
cipher::encrypt(
ptx.c_str(),ptx.length(),
encr,esiz,
key.c_str(),key.length()
);
cipher::decrypt(encr,esiz,decr,key.c_str(),key.length());
}
我做的PRNG(quadrant.hpp
)是here。
此外,这是它的输出(返回的krng()
值不相同):
Key used: Key
[encrypt] Test krng(): 2213112449
Key used: Key
[decrypt] Test krng(): 2237675595
如何解决这个问题?
编辑:现在我在cipher
课程之外初始化PRNG,并将其播种到方法中。因此,即使在多次运行期间,它也能正确地为方法生成相同的序列。也就是说,我解决了它。
增强代码:
static quadrant krng;
class cipher
{
private:
static void key_sched(const char* key,uint32_t ks,uint32_t s_k[16])
{
// the same function as above
}
public:
static void encrypt(const char* data,uint32_t ds,uint8_t* out,const char* key,uint32_t ks)
{
uint32_t seed_k[16];
key_sched(key,ks,seed_k);
krng.seed(
seed_k[ 0],seed_k[ 1],seed_k[ 2],seed_k[ 3],
seed_k[ 4],seed_k[ 5],seed_k[ 6],seed_k[ 7],
seed_k[ 8],seed_k[ 9],seed_k[10],seed_k[11],
seed_k[12],seed_k[13],seed_k[14],seed_k[15]
);
std::cout << "[encrypt] Test krng(): " << krng() << "\n";
// do encryption...
}
static void decrypt(uint8_t* data,uint32_t ds,uint8_t* out,const char* key,uint32_t ks)
{
uint32_t seed_k[16];
key_sched(key,ks,seed_k);
krng.seed(
seed_k[ 0],seed_k[ 1],seed_k[ 2],seed_k[ 3],
seed_k[ 4],seed_k[ 5],seed_k[ 6],seed_k[ 7],
seed_k[ 8],seed_k[ 9],seed_k[10],seed_k[11],
seed_k[12],seed_k[13],seed_k[14],seed_k[15]
);
std::cout << "[decrypt] Test krng(): " << krng() << "\n";
// do decryption...
}
};
答案 0 :(得分:3)
编辑3:
在quadrant
中有初始化声明 uint32_t mx[16];
应该改为
uint32_t mx[16]={0};
在cipher
:
使用这种类型的函数key
长度预计为16.如果它少于那么你最终得到未定义的变量。
此函数仅初始化4个字符:
std::string key = "Key";
请改为尝试:
char key[16] = { 0 };
strcpy(key, "Key");
确认字符串小于16(为nul终结符留出空间)。这种方式密钥总是"Key\0\0\0\0\0\0\0\0\0\0\0\0\0"
考虑这个功能:
//Key length: 256 bits = 32 bytes
static void key_sched(const char* key,uint32_t ks,uint32_t s_k[16])
{
uint32_t i, j;
int ix, iy;
uint8_t tk[2*ks];
uint32_t s_aux[16];
...
}
首先,您评论“密钥长度:256位= 32字节”,但在这种情况下,您显然需要16个字节。
其次,s_aux
未初始化。似乎部分仍然没有初始化。将其更改为uint32_t s_aux[16]={0};
其他变量也应该初始化。例如:
int main()
{
std::string ptx = "Plaintext";
char key[16] = { 0 };
strcpy(key, "Key");
uint8_t* encr = 0;
uint8_t* decr = 0;
uint32_t esiz = 0;
cipher::encrypt(ptx.c_str(), ptx.length(), encr, key, 16);
cipher::decrypt(encr, esiz, decr, key, 16);
}
<小时/> 编辑:使用此函数
to_hexstring
检查seed_k 的内容
std::string to_hexstring(const uint32_t* buf, int buflen)
{
std::string result;
for (int i = 0; i < buflen; i++)
{
char temp[16];
sprintf_s(temp, "%08X-", buf[i]);
result += temp;
}
return result;
}
进行以下更改:
static void encrypt(const char*, uint32_t, uint8_t*, const char* key, uint32_t ks)
{
std::cout << "Key used: " << key << "\n";
uint32_t seed_k[16];
key_sched(key, ks, seed_k);
cout << to_hexstring(seed_k, 16) << endl;//<== Add this here
...
}
static void decrypt(uint8_t*, uint32_t, uint8_t*, const char* key, uint32_t ks)
{
std::cout << "Key used: " << key << "\n";
uint32_t seed_k[16];
key_sched(key, ks, seed_k);
cout << to_hexstring(seed_k, 16) << endl;//<== Add this here
...
}
现在您应该能够检查seed_k
seed_k
后来输入quadrant
,如果seed_k
不相同,则quadrant
结果也不相同。