gpt4 book ai didi

c++ - 跨c套接字的Blowfish加解密

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:19:21 28 4
gpt4 key购买 nike

我正在使用河豚的以下实现(从中间切掉一些东西)来加密和解密消息。我试图在大端机器 (SunOS 5.10) 上加密消息,然后通过套接字将其发送到小端机器 (linux)。我可以在同一台机器和不同的 linux 机器上加密和解密,但我无法让它在这两台机器之间工作。

因为 blowfish 实现似乎将消息分解为 DWords,每个 DWords 包含两个 32 位整数,我一直在将我的加密消息分解为 32 位整数,对每个应用 htonl(),通过网络发送它们,对每个应用 ntohl(),然后尝试解密。结果并不漂亮,但有趣的是,解密后大部分正确的字符都出现了,但它们是乱码,并且在某些地方出现了一些额外的乱码。我真的无法想象我可能会错过什么。

/********** blowfish.h **********/

#ifndef ___BLOWFISH_H___
#define ___BLOWFISH_H___


#define NUM_SUBKEYS 18
#define NUM_S_BOXES 4
#define NUM_ENTRIES 256

#define MAX_STRING 256
#define MAX_PASSWD 56 // 448bits

#ifdef BIG_ENDIAN
struct WordByte
{
unsigned int zero:8;
unsigned int one:8;
unsigned int two:8;
unsigned int three:8;
};
#endif

#ifdef LITTLE_ENDIAN
struct WordByte
{
unsigned int three:8;
unsigned int two:8;
unsigned int one:8;
unsigned int zero:8;
};
#endif

union Word
{
unsigned int word;
WordByte byte;
};

struct DWord
{
Word word0;
Word word1;
};


class Blowfish
{
private:
unsigned int PA[NUM_SUBKEYS];
unsigned int SB[NUM_S_BOXES][NUM_ENTRIES];

void Gen_Subkeys(char *);
inline void BF_En(Word *,Word *);
inline void BF_De(Word *,Word *);

public:
Blowfish();
~Blowfish();

void Reset();
void Set_Passwd(char * = NULL);
void Encrypt(void *,unsigned int);
void Decrypt(void *,unsigned int);
};


#endif



/********** blowfish.cc **********/

#include <iostream.h>
#include <string.h>
#include "blowfish.h"


#define F(x) (((SB[0][x.byte.zero] + SB[1][x.byte.one]) ^ SB[2][x.byte.two]) + SB[3][x.byte.three])


void Blowfish::Gen_Subkeys(char *Passwd)
{
unsigned int i,j,len=strlen(Passwd);
Word Work,null0,null1;

if (len > 0)
{
j = 0;
for (i=0;i<NUM_SUBKEYS;i++)
{
Work.byte.zero = Passwd[(j++)%len];
Work.byte.one = Passwd[(j++)%len];
Work.byte.two = Passwd[(j++)%len];
Work.byte.three = Passwd[(j++)%len];
PA[i] ^= Work.word;
}

null0.word = null1.word = 0;

for (i=0;i<NUM_SUBKEYS;i+=2)
{
BF_En(&null0,&null1);
PA[i] = null0.word;
PA[i+1] = null1.word;
}

for (j=0;j<NUM_S_BOXES;j++)
for (i=0;i<NUM_ENTRIES;i+=2)
{
BF_En(&null0,&null1);
SB[j][i] = null0.word;
SB[j][i+1] = null1.word;
}
}

Work.word = null0.word = null1.word = 0;
Passwd = NULL;
len = 0;
}

void Blowfish::BF_En(Word *x1,Word *x2)
{
Word w1=*x1,w2=*x2;

w1.word ^= PA[0];
w2.word ^= F(w1)^PA[1]; w1.word ^= F(w2)^PA[2];
w2.word ^= F(w1)^PA[3]; w1.word ^= F(w2)^PA[4];
w2.word ^= F(w1)^PA[5]; w1.word ^= F(w2)^PA[6];
w2.word ^= F(w1)^PA[7]; w1.word ^= F(w2)^PA[8];
w2.word ^= F(w1)^PA[9]; w1.word ^= F(w2)^PA[10];
w2.word ^= F(w1)^PA[11]; w1.word ^= F(w2)^PA[12];
w2.word ^= F(w1)^PA[13]; w1.word ^= F(w2)^PA[14];
w2.word ^= F(w1)^PA[15]; w1.word ^= F(w2)^PA[16];
w2.word ^= PA[17];

*x1 = w2;
*x2 = w1;
}

void Blowfish::BF_De(Word *x1,Word *x2)
{
Word w1=*x1,w2=*x2;

w1.word ^= PA[17];
w2.word ^= F(w1)^PA[16]; w1.word ^= F(w2)^PA[15];
w2.word ^= F(w1)^PA[14]; w1.word ^= F(w2)^PA[13];
w2.word ^= F(w1)^PA[12]; w1.word ^= F(w2)^PA[11];
w2.word ^= F(w1)^PA[10]; w1.word ^= F(w2)^PA[9];
w2.word ^= F(w1)^PA[8]; w1.word ^= F(w2)^PA[7];
w2.word ^= F(w1)^PA[6]; w1.word ^= F(w2)^PA[5];
w2.word ^= F(w1)^PA[4]; w1.word ^= F(w2)^PA[3];
w2.word ^= F(w1)^PA[2]; w1.word ^= F(w2)^PA[1];
w2.word ^= PA[0];

*x1 = w2;
*x2 = w1;
}


Blowfish::Blowfish()
{
Reset();
}

Blowfish::~Blowfish()
{
Reset();
}


void Blowfish::Reset()
{
unsigned int i,j;

unsigned int PA_Init[NUM_SUBKEYS] =
{
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
};

unsigned int SB_Init[NUM_S_BOXES][NUM_ENTRIES] =
{
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
...
...
...
};

for (i=0;i<NUM_SUBKEYS;i++)
PA[i] = PA_Init[i];

for (j=0;j<NUM_S_BOXES;j++)
for (i=0;i<NUM_ENTRIES;i++)
SB[j][i] = SB_Init[j][i];
}

void Blowfish::Set_Passwd(char *Passwd)
{
char New_Passwd[MAX_STRING];
unsigned int i,len;

if (Passwd == NULL)
{
do
{
cout << "\aEnter your password: ";
cin.get(New_Passwd,MAX_STRING,'\n');
len = strlen(New_Passwd);
}
while (len > MAX_PASSWD);
Passwd = New_Passwd;
}
else
len = strlen(Passwd);

Reset();
if (len > 0)
Gen_Subkeys(Passwd);

for (i=0;i<MAX_STRING;i++)
New_Passwd[i] = '\0';
Passwd = NULL;
len = 0;
}

void Blowfish::Encrypt(void *Ptr,unsigned int N_Bytes)
{
unsigned int i;
DWord *Work;

if (N_Bytes%8)
{
cerr << "\aBlowfish requires the input to be a multiple of 8 bytes (64 bits) to work.\n";
return;
}

N_Bytes /= 8;
Work = (DWord *)Ptr;

for (i=0;i<N_Bytes;i++)
{
BF_En(&Work->word0,&Work->word1);
Work++;
}

Work = NULL;
}

void Blowfish::Decrypt(void *Ptr,unsigned int N_Bytes)
{
unsigned int i;
DWord *Work;

if (N_Bytes%8)
{
cerr << "\aBlowfish requires the input to be a multiple of 8 bytes (64 bits) to work.\n";
return;
}

N_Bytes /= 8;
Work = (DWord *)Ptr;
for (i=0;i<N_Bytes;i++)
{
BF_De(&Work->word0,&Work->word1);
Work++;
}

Work = NULL;
}

以下是大端机器上的加密字符串:

11010011 11110110 01100110 10001101 01010011 11000110 00010001 11110110 00011010 11001010 00011111 00100001 10110000 10110100 10110000 11110000 11111100 11000010 00110011 00001111 10011110 01100111 00010101 10000101 00001010 01111110 10000101 00011100 10010010 10111010 10010111 11111001 00111101 01011100 00000010 01010011 11100000 11001101 11111010 00111100 00011101 10001001 01010111 01011010 11100001 10101111 10001100 10111001 00011111111100 10010111011011010001101 11010100 11101111101110110110111110111111111111111111111111110100111010011101100011010001000101000101011101 00110100

这是我通过网络将它发送到小端机器后的加密字符串:

10001101 01100110 11110110 11010011 11110110 00010001 11000110 01010011 00100001 00011111 11001010 00011010 11110000 10110000 10110100 10110000 00001111 00110011 11000010 11111100 10000101 00010101 01100111 10011110 00011100 10000101 01111110 00001010 11111001 10010111 10111010 10010010 01010011 00000010 01011100 00111101 00111100 11111010 11001101 11100000 01011010 01010111 10001001 00011101 10111001 10001100 10101111 11100001 01101110 10010101 10111100 00011111 11010001 11101110 11010100 10001101 01111000 10100111 11111110 10111011 01000001 00110100 01011101 11010001 00010001 10010011 01111100 01011011 01100000 10111100 10011011 10100011

最后,这是字符串需要的内容,以便在小端机器上成功解密它(即这是我在小端机器上加密原始字符串时得到的,而不是大端机器):

10001101 10111011 10110010 10111000 01110001 11000110 00110110 10101110 11000011 11000100 00001010 10011110 11111101 10101000 01110011 10110110 00011001 10000011 11111000 11010001 01101001 00101100 10110001 00010001 11101101 10001011 01101110 01101011 11110001 01101010 00111010 00010110 11101111 01001111 11001100 00011101 01101010 11110000 00110000 01110100 10111010 01000101 01011001 11111001 11011101 01000011 10000110 01000001 11101110 00100001 00111000 00101001 11110011 00001111 01000011 11000000 10110010 10011101 11110000 00000001 10001011 10110101 10010011 01010010 01110100 11100000 10010011 10111101 00111110 00100001 10101111 11010000

我目前正在尝试比较字符串,但找不到模式。

最佳答案

我认为您的问题是您尝试使用字节字符串输入而不以某种方式对其进行字节序更正,以便在不同的字节序平台上进行相同的数学计算:

void Blowfish::Encrypt(void *Ptr,unsigned int N_Bytes)
{
unsigned int i;
DWord *Work;

if (N_Bytes%8)
{
cerr << "\aBlowfish requires the input to be a multiple of 8 bytes (64 bits) to work.\n";
return;
}

N_Bytes /= 8;
Work = (DWord *)Ptr; // NOTE: this won't work on some archs if Ptr isn't properly aligned on a 32b boundary

for (i=0;i<N_Bytes;i++)
{
Work->word0 = ntohl(Work->word0); // necessary to convert byte string to same number on different archs
Work->word1 = ntohl(Work->word1);
BF_En(&Work->word0, &Work->word1);
Work->word0 = htonl(Work->word0); // leave all encryptions in network byte order
Work->word1 = htonl(Work->word1);
Work++;
}

Work = NULL;
}

void Blowfish::Decrypt(void *Ptr,unsigned int N_Bytes)
{
unsigned int i;
DWord *Work;

if (N_Bytes%8)
{
cerr << "\aBlowfish requires the input to be a multiple of 8 bytes (64 bits) to work.\n";
return;
}

N_Bytes /= 8;
Work = (DWord *)Ptr; // NOTE: this won't work on some archs if Ptr isn't properly aligned on a 32b boundary

for (i=0;i<N_Bytes;i++)
{
Work->word0 = ntohl(Work->word0); // necessary to convert byte string to same number on different archs
Work->word1 = ntohl(Work->word1);
BF_De(&Work->word0, &Work->word1);
Work->word0 = htonl(Work->word0); // leave all decryptions in network byte order
Work->word1 = htonl(Work->word0);
Work++;
}

Work = NULL;
}

请注意,使用上述代码,您无需再担心应用程序级别的数据字节顺序问题。相同的输入字节串应该在两个平台上加密/解密为相同的输出字节串。

关于c++ - 跨c套接字的Blowfish加解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28803799/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com