我正在尝试编写一个程序,将十六进制输入转换为base64编码输出。更具体地说,输入:
0x49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
(这是"我像一个有毒的蘑菇一样杀死你的大脑"在ASCII中 - 这对以后很重要!)
以下代码是我提出的;它可能过于复杂,但在我的脑海里,每一步都是有道理的。现在,它可以使用简单的输入,例如0x4d616e,但不适用于较长的字符串。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
void base64encode(char * data) {
size_t data_size = strlen(data);
size_t last_block_size = data_size%3;
size_t padding_chars = last_block_size==0?0:3-last_block_size;
size_t num_blocks = last_block_size==0?data_size/3:(data_size/3)+1;
int i1,i2,i3,i4 = 0;
uint32_t * blocks = malloc(sizeof(uint32_t)*num_blocks);
memset(blocks,0,sizeof(uint32_t)*num_blocks);
for(int i=0; i<strlen(data); i++)
blocks[i/3] |= data[i] << (2-(i%3))*8;
for (int i=0; i<num_blocks; i++){
i1 = (blocks[i] & 0xfc0000) >> 18;
i2 = (blocks[i] & 0x03f000) >> 12;
i3 = ((i==num_blocks-1) && (padding_chars==2))?64:(blocks[i] & 0x000fc0) >> 6;
i4 = ((i==num_blocks-1) && (padding_chars>=1))?64:(blocks[i] & 0x00003f);
printf("%c%c%c%c",b64[i1],b64[i2],b64[i3],b64[i4]);
}
free(blocks);
}
int hex_char_to_raw (char c) {
switch (c) {
case '0': return 0x0;
case '1': return 0x1;
case '2': return 0x2;
case '3': return 0x3;
case '4': return 0x4;
case '5': return 0x5;
case '6': return 0x6;
case '7': return 0x7;
case '8': return 0x8;
case '9': return 0x9;
case 'A': return 0xA;
case 'B': return 0xB;
case 'C': return 0xC;
case 'D': return 0xD;
case 'E': return 0xE;
case 'F': return 0xF;
default: return -1;
}
}
void hex_to_raw(char * data) {
for (int i=2; i < strlen(data); i++){
if ( (data[i]<48) || ((data[i]>57)&&(data[i]<65)) || ((data[i]>70)&&(data[i]<97)) || (data[i]>102) ) {
printf("ERROR: Invalid Hex Character '%c' in input at character %d\n",data[i],i-1);
return;
} else if ( (data[i] <= 102) && (data[i] >= 97) )
data[i] = data[i]-32; // Transform all lower case letters to corresponding upper case letters
}
char * buffer = malloc(sizeof(char)*(strlen(data)-2));
for (int i=2; i <= strlen(data); i++) {
if (i != strlen(data))
buffer[i-2] = data[i];
else
buffer[i-2] = '\0';
}
printf("%s\n",buffer);
char * binary = malloc(sizeof(char)*(strlen(buffer)/2));
printf("%zu %zu %zu %zu\n",sizeof(char)*(strlen(data)-2),sizeof(char)*(strlen(buffer)/2),strlen(buffer), strlen(data));
for (int i=0; i < strlen(buffer); i=i+2) {
printf("\ti=%u i/2=%u buffer[i]=%c buffer[i+1]=%c\n",i,i/2,buffer[i],buffer[i+1]);
binary[i/2] = (hex_char_to_raw(buffer[i]) << 4) | (hex_char_to_raw(buffer[i+1]));
}
free(buffer);
printf("%s\n", binary);
base64encode(binary);
free(binary);
}
int main (int argc, char * argv[]) {
if (argc != 2) {
printf("usage: %s [input]\n",argv[0]);
return 0;
}
hex_to_raw(argv[1]);
printf("\n");
return 0;
}
当我运行此代码时,我得到以下内容:
andrew@Andrews-MacBook-Air Sat Jun 04 02:11:55 ~/Documents/Cryptopals Challenges/Set 1/Challenge 1
-> ./test 0x49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
49276D206B696C6C696E6720796F757220627261696E206C696B65206120706F69736F6E6F7573206D757368726F6F6D
96 48 96 98
i=0 i/2=0 buffer[i]=4 buffer[i+1]=9
i=2 i/2=1 buffer[i]=2 buffer[i+1]=7
i=4 i/2=2 buffer[i]=6 buffer[i+1]=D
i=6 i/2=3 buffer[i]=2 buffer[i+1]=0
i=8 i/2=4 buffer[i]=6 buffer[i+1]=B
i=10 i/2=5 buffer[i]=6 buffer[i+1]=9
i=12 i/2=6 buffer[i]=6 buffer[i+1]=C
i=14 i/2=7 buffer[i]=6 buffer[i+1]=C
i=16 i/2=8 buffer[i]=6 buffer[i+1]=9
i=18 i/2=9 buffer[i]=6 buffer[i+1]=E
i=20 i/2=10 buffer[i]=6 buffer[i+1]=7
i=22 i/2=11 buffer[i]=2 buffer[i+1]=0
i=24 i/2=12 buffer[i]=7 buffer[i+1]=9
i=26 i/2=13 buffer[i]=6 buffer[i+1]=F
i=28 i/2=14 buffer[i]=7 buffer[i+1]=5
i=30 i/2=15 buffer[i]=7 buffer[i+1]=2
i=32 i/2=16 buffer[i]=2 buffer[i+1]=0
i=34 i/2=17 buffer[i]=6 buffer[i+1]=2
i=36 i/2=18 buffer[i]=7 buffer[i+1]=2
i=38 i/2=19 buffer[i]=6 buffer[i+1]=1
i=40 i/2=20 buffer[i]=6 buffer[i+1]=9
i=42 i/2=21 buffer[i]=6 buffer[i+1]=E
i=44 i/2=22 buffer[i]=2 buffer[i+1]=0
i=46 i/2=23 buffer[i]=6 buffer[i+1]=C
i=48 i/2=24 buffer[i]=6 buffer[i+1]=9
i=50 i/2=25 buffer[i]=6 buffer[i+1]=B
i=52 i/2=26 buffer[i]=6 buffer[i+1]=5
i=54 i/2=27 buffer[i]=2 buffer[i+1]=0
i=56 i/2=28 buffer[i]=6 buffer[i+1]=1
i=58 i/2=29 buffer[i]=2 buffer[i+1]=0
i=60 i/2=30 buffer[i]=7 buffer[i+1]=0
i=62 i/2=31 buffer[i]=6 buffer[i+1]=F
i=64 i/2=32 buffer[i]=6 buffer[i+1]=9
i=66 i/2=33 buffer[i]=7 buffer[i+1]=3
i=68 i/2=34 buffer[i]=6 buffer[i+1]=F
i=70 i/2=35 buffer[i]=6 buffer[i+1]=E
i=72 i/2=36 buffer[i]=6 buffer[i+1]=F
i=74 i/2=37 buffer[i]=7 buffer[i+1]=5
i=76 i/2=38 buffer[i]=7 buffer[i+1]=3
i=78 i/2=39 buffer[i]=2 buffer[i+1]=0
i=80 i/2=40 buffer[i]=6 buffer[i+1]=D
i=82 i/2=41 buffer[i]=7 buffer[i+1]=5
i=84 i/2=42 buffer[i]=7 buffer[i+1]=3
i=86 i/2=43 buffer[i]=6 buffer[i+1]=8
i=88 i/2=44 buffer[i]=7 buffer[i+1]=2
i=90 i/2=45 buffer[i]=6 buffer[i+1]=F
i=92 i/2=46 buffer[i]=6 buffer[i+1]=F
i=94 i/2=47 buffer[i]=6 buffer[i+1]=D
i=96 i/2=48 buffer[i]=I buffer[i+1]='
i=98 i/2=49 buffer[i]=m buffer[i+1]=
i=100 i/2=50 buffer[i]=k buffer[i+1]=i
i=102 i/2=51 buffer[i]=l buffer[i+1]=l
i=104 i/2=52 buffer[i]=i buffer[i+1]=n
i=106 i/2=53 buffer[i]=g buffer[i+1]=
i=108 i/2=54 buffer[i]=y buffer[i+1]=o
i=110 i/2=55 buffer[i]=u buffer[i+1]=r
i=112 i/2=56 buffer[i]= buffer[i+1]=b
i=114 i/2=57 buffer[i]=r buffer[i+1]=a
i=116 i/2=58 buffer[i]=i buffer[i+1]=n
i=118 i/2=59 buffer[i]= buffer[i+1]=l
i=120 i/2=60 buffer[i]=i buffer[i+1]=k
i=122 i/2=61 buffer[i]=e buffer[i+1]=
i=124 i/2=62 buffer[i]=a buffer[i+1]=
i=126 i/2=63 buffer[i]=p buffer[i+1]=o
i=128 i/2=64 buffer[i]=i buffer[i+1]=s
i=130 i/2=65 buffer[i]=o buffer[i+1]=n
i=132 i/2=66 buffer[i]=o buffer[i+1]=u
i=134 i/2=67 buffer[i]=s buffer[i+1]=
i=136 i/2=68 buffer[i]=m buffer[i+1]=u
i=138 i/2=69 buffer[i]=s buffer[i+1]=h
i=140 i/2=70 buffer[i]=r buffer[i+1]=o
i=142 i/2=71 buffer[i]=o buffer[i+1]=m
i=144 i/2=72 buffer[i]=? buffer[i+1]=?
i=146 i/2=73 buffer[i]=? buffer[i+1]=?
i=148 i/2=74 buffer[i]=? buffer[i+1]=?
i=150 i/2=75 buffer[i]=? buffer[i+1]=?
i=152 i/2=76 buffer[i]=? buffer[i+1]=?
i=154 i/2=77 buffer[i]=? buffer[i+1]=?
i=156 i/2=78 buffer[i]=? buffer[i+1]=?
i=158 i/2=79 buffer[i]=? buffer[i+1]=?
i=160 i/2=80 buffer[i]=? buffer[i+1]=?
i=162 i/2=81 buffer[i]=? buffer[i+1]=?
i=164 i/2=82 buffer[i]=? buffer[i+1]=?
i=166 i/2=83 buffer[i]=? buffer[i+1]=?
i=168 i/2=84 buffer[i]=? buffer[i+1]=?
i=170 i/2=85 buffer[i]=? buffer[i+1]=?
i=172 i/2=86 buffer[i]=? buffer[i+1]=?
i=174 i/2=87 buffer[i]=? buffer[i+1]=?
i=176 i/2=88 buffer[i]=? buffer[i+1]=?
i=178 i/2=89 buffer[i]=? buffer[i+1]=?
i=180 i/2=90 buffer[i]=? buffer[i+1]=?
i=182 i/2=91 buffer[i]=? buffer[i+1]=?
i=184 i/2=92 buffer[i]=? buffer[i+1]=?
i=186 i/2=93 buffer[i]=? buffer[i+1]=?
i=188 i/2=94 buffer[i]=? buffer[i+1]=?
i=190 i/2=95 buffer[i]=? buffer[i+1]=
I'm killing your brain like a poisonous mushroom????????????????????????????????????????????????
SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t////////////////////////////////////////////////////////////////
它循环太多次并且使用buffer
数据乱码我似乎也得到了十六进制输入的ASCII版本。我无法看到这种情况如何发生,除了我对hex_char_to_raw
的调用必须发生的事情。一些printf
语句是我尝试调试代码以查看发生了什么,我已经打印了我传递给malloc
的值以查看正在分配的内容以及某些中间值变量
令我感到困惑的是,如果我使用更简单的十六进制字符串,它将起作用。如果我用0x4d616e(&#34; Man&#34;)
运行它,这是输出andrew@Andrews-MacBook-Air Sat Jun 04 02:11:56 ~/Documents/Cryptopals Challenges/Set 1/Challenge 1
-> ./test 0x4d616e
4D616E
6 3 6 8
i=0 i/2=0 buffer[i]=4 buffer[i+1]=D
i=2 i/2=1 buffer[i]=6 buffer[i+1]=1
i=4 i/2=2 buffer[i]=6 buffer[i+1]=E
Man
TWFu
如果有人能指出我找到正在发生的事情的方向,我将非常感激。我确信它是一个小东西,但我一直在看这段代码,以至于我认为一双新眼睛可能会有用。
答案 0 :(得分:-2)
Hans-Martin Mosner表示你的错,我补充了一些细节。 第一个错误:
char * buffer = malloc(sizeof(char)*(strlen(data)-2));
for (int i=2; i <= strlen(data); i++) {
if (i != strlen(data))
buffer[i-2] = data[i];
else
buffer[i-2] = '\0';
}
例如,&#34; 0x4d616e&#34;
长度是8,还不够&#39; \ 0&#39;。所以缓冲区的大小是6。
当你在运行时
buffer[i-2] = '\0';
i-2 = 6,它超过了缓冲区的大小。
第二个错误:
for (int i=0; i < strlen(buffer); i=i+2) {
printf("\ti=%u i/2=%u buffer[i]=%c buffer[i+1]=%c\n",i,i/2,buffer[i],buffer[i+1]);
binary[i/2] = (hex_char_to_raw(buffer[i]) << 4) | (hex_char_to_raw(buffer[i+1]));
}
在此代码中,您不能添加&#39; \ 0&#39;在缓冲区结束;所以当你使用printf buffer时,会显示许多不可读的代码。
您应该在for(){...}之后添加binary[i/2] = '\0';
。
当然,你应该在malloc二进制时添加1。