我正在编写一个程序,一次从文本文件中读取4个字符,将它们打包成一个整数,通过将整数移到右边3个单位来“加密”整数,然后将加密的整数写入二进制文件。
原始代码:
#include <stdio.h>
#include <limits.h>
#include "encoding.h"
#define KEY 3
int encrypt(int a);
int pack(char a, char b, char d, char c);
void encoding(char itxt[], char obin[]){
char four[4];
FILE *inp=fopen(itxt,"r");
if(!inp){printf("Unable to open %c", inp); return 1;}
FILE *outp=fopen(obin,"wb");
if(!outp){printf("Unable to open %c\n", obin); return 1;}
while(fgets(four, 4, inp) != NULL){
int a;
a = pack(four[0], four[1], four[2], four[3]);
a = encrypt(a);
fwrite(&a, sizeof(int), 1, outp);
}
printf("Encoding complete!\n");
fclose(inp);
fclose(outp);
}
int pack(char a, char b, char c, char d){
int p = a;
p = (p<<CHAR_BIT) | b;
p = (p<<CHAR_BIT) | c;
p = (p<<CHAR_BIT) | d;
return p;
}
int encrypt(int a){
int obin = a>>KEY;
return obin;
}
代码编译但不会在二进制文件中写入任何内容。任何反馈,提示或提示将不胜感激。
提前致谢!
*编辑:
#include <stdio.h>
#include <limits.h>
#include "encoding.h"
#define KEY 3
unsigned int encrypt(int a);
unsigned int pack(char a, char b, char d, char c);
void encoding(char itxt[], char obin[]){
char four[4];
FILE *inp=fopen(itxt,"r");
if(!inp){printf("Unable to open %c", inp); return 1;}
FILE *outp=fopen(obin,"wb");
if(!outp){printf("Unable to open %c\n", obin); return 1;}
while(fread(&four, sizeof(char), 4, inp) != NULL){
unsigned int a;
a = pack(four[0], four[1], four[2], four[3]);
a = encrypt(a);
fwrite(&a, sizeof(unsigned int), 1, outp);
}
printf("Encoding complete!\n");
fclose(inp);
fclose(outp);
}
unsigned int pack(char a, char b, char c, char d){
int p = a;
p = (p<<CHAR_BIT) | b;
p = (p<<CHAR_BIT) | c;
p = (p<<CHAR_BIT) | d;
return p;
}
unsigned int encrypt(int a){
int obin = (a>>KEY) | (a<<(CHAR_BIT*sizeof(a)-KEY));
return obin;
}
答案 0 :(得分:1)
编辑后的代码非常接近可操作性。这是一个似乎有效的温和修改版本。困难在于没有解码功能来检查加密是否可解密。
enc37.c
#include <stdio.h>
#include <limits.h>
#define KEY 3
unsigned int encrypt(unsigned int a);
unsigned int pack(unsigned char a, unsigned char b, unsigned char d, unsigned char c);
void encoding(const char itxt[], const char obin[]);
void encoding(const char itxt[], const char obin[])
{
char four[4];
FILE *inp = fopen(itxt, "r");
if (!inp)
{
fprintf(stderr, "Unable to open %s\n", itxt);
return;
}
FILE *outp = fopen(obin, "wb");
if (!outp)
{
fclose(inp);
fprintf(stderr, "Unable to open %s\n", obin);
return;
}
while (fread(&four, sizeof(char), 4, inp) == 4)
{
unsigned int a;
a = pack(four[0], four[1], four[2], four[3]);
a = encrypt(a);
fwrite(&a, sizeof(unsigned int), 1, outp);
}
printf("Encoding complete!\n");
fclose(inp);
fclose(outp);
}
unsigned int pack(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
unsigned int p = a;
p = (p << CHAR_BIT) | b;
p = (p << CHAR_BIT) | c;
p = (p << CHAR_BIT) | d;
return p;
}
unsigned int encrypt(unsigned int a)
{
unsigned int obin = (a >> KEY) | (a << (CHAR_BIT * sizeof(a) - KEY));
return obin;
}
int main(int argc, char **argv)
{
char *i_file = "/dev/stdin";
char *o_file = "/dev/stdout";
if (argc == 3)
{
i_file = argv[1];
o_file = argv[2];
}
encoding(i_file, o_file);
return 0;
}
参数列表处理允许您在命令行上指定输入和输出的文件名,但它默认为从标准输入读取并写入标准输出。
dec37.c
#include <stdio.h>
#include <limits.h>
#define KEY 3
typedef unsigned char Byte;
typedef unsigned int Uint;
Uint decrypt(Uint a);
Uint pack(Byte a, Byte b, Byte d, Byte c);
void unpack(Uint value, Byte *data);
void decoding(const char ibin[], const char otxt[]);
void decoding(const char ibin[], const char otxt[])
{
FILE *inp = fopen(ibin, "rb");
if (!inp)
{
fprintf(stderr, "Unable to open %s\n", ibin);
return;
}
FILE *outp = fopen(otxt, "w");
if (!outp)
{
fclose(inp);
fprintf(stderr, "Unable to open %s\n", otxt);
return;
}
Uint value;
while (fread(&value, sizeof(value), 1, inp) == 1)
{
Byte four[4];
value = decrypt(value);
unpack(value, four);
fwrite(four, sizeof(four), 1, outp);
}
printf("Decoding complete!\n");
fclose(inp);
fclose(outp);
}
void unpack(Uint value, Byte *data)
{
data[0] = (value >> (3 * CHAR_BIT)) & 0xFF;
data[1] = (value >> (2 * CHAR_BIT)) & 0xFF;
data[2] = (value >> (1 * CHAR_BIT)) & 0xFF;
data[3] = (value >> (0 * CHAR_BIT)) & 0xFF;
}
Uint decrypt(Uint a)
{
Uint obin = (a << KEY) | (a >> (CHAR_BIT * sizeof(a) - KEY));
return obin;
}
int main(int argc, char **argv)
{
char *i_file = "/dev/stdin";
char *o_file = "/dev/stdout";
if (argc == 3)
{
i_file = argv[1];
o_file = argv[2];
}
decoding(i_file, o_file);
return 0;
}
如果加密程序为enc37
且解密程序为dec37
,则可以运行以下命令:
$ ./enc37 enc37.txt enc37.bin
$ ./dec37 enc37.bin dec37.txt
$ diff enc37.txt dec37.txt
$
只要输入文件(enc37.txt
)是4个字节长的倍数。我在不同时间使用enc37.c
和dec37.c
作为输入文件。
您也可以按相反的顺序使用解密和加密程序,并且仍然可以进行往返转换。
答案 1 :(得分:1)
您不应该将潜在签名的负整数向右移;所有此类char
应转换为unsigned long
,而不是 int
; int
不仅可以存储负数数字(我确定你不想要,但这也会导致基于底层整数表示的微妙不同的行为)。还有截断; int
无法移植存储四个8位八位字节,其中_ unsigned long
可以。
CHAR_BIT*sizeof(a)-KEY
似乎可能会违反填充,而不是您可能会遇到这些问题。尽管如此,应该修复它们以避免浪费时间调试看似模糊不清且难以修补的问题。
您可以将unsigned long
拆分为您想要的两个组件(让我们称之为head
和tail
),为您提供head
和{{1}的面具来自tail
。
ULONG_MAX
......或
unsigned long head_mask = ULONG_MAX >> key,
tail_mask = ~head_mask;
...等等。这些将生成按位相反的掩码,然后您可以使用unsigned long head_mask = ULONG_MAX << key,
tail_mask = ~head_mask;
操作(按原样)提取两组字符。 &
需要head_mask
向右移动以使其符合要求,但至少这可以保证您定义明确的内容。