如何将 char 数组转换为结构?
Posted
技术标签:
【中文标题】如何将 char 数组转换为结构?【英文标题】:How to cast a char array into a structure? 【发布时间】:2021-09-05 18:01:25 【问题描述】:我正在尝试将 RSA 私钥从文件读取到结构中。我正在使用mpi_read_string()
将这些密钥加载到 RSA 上下文中。因此,每个单独的键都必须以空值结尾。为了在从文件中读取每个键时实现这一点,我在每个键的末尾连接\0
。
综上,我将文件的所有内容读入unsigned char * buffer
,对每一行进行标记,在每行末尾连接\0
,并将其存储到unsigned char no_label_key_array[]
。我也有一个结构struct RSA_KEY
。我正在尝试将此unsigned char no_label_key_array[]
分配到结构中。
rsa_priv.txt
包含以下内容,
N = D0C2ACDCF780B1E4846054BDA700F18D567247FE8BC5BA4FBCAB814E619DA63A20F65A58EE89FC0824DC9367C5725BDDC596065F1C8868E99C896F3A0CF7D7F0A785E668F2568F19BAFB8FF3BA5CDF487544EFE71010BEDB4EE16EDC3AF0A71391AD3194B42D3FD40B4E0DE12A22D8188AF03FF4E36D37BA1DA1F3C57188E60DA38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A47451783931D643CE736DD1BAB40C5523858BB067FB9E490DCB5FDBBB03B9D68A8998C1347E237C477AA14B0997A84708CED05A9E24C7072B838F753
E = 010001
D = 21AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427B029AF629EED23C99726F0A0C3CEA1229E4099B588CE676975D25
P = FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCC7D57221CD9394C64585653664976174CAE2E7DC6A7B03DE09599B5D9501927ACC4EED5F5CBC5870E31A051AF9842945A0168E35
Q = D32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D084CFA423E04C90C5966AC391A47F10E823C71B9716856B05BC12160DF0BA96300F8ADDC0D59E54E9CBDC7AC0EA6747DBA46C067
DP = 2004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B608858354C999A26A4BF7F1543408EF6C1B439E9643604C2848162590A0A245CC834B977C72D10979010EBE5E177D884F04E450C51
DQ = 9A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734C5FCFDF719ABFBC459DF1B7379CB45EEC2E4BA3BF88D93CB82DF532C86FEC646420B1B21054BAE84AAA36DDFF9BF43EDFDD063B9
QP = E7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
我有以下代码,
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define KEY_LEN 256
typedef struct RSA_KEY
unsigned char N[KEY_LEN];
unsigned char E[KEY_LEN];
unsigned char D[KEY_LEN];
unsigned char P[KEY_LEN];
unsigned char Q[KEY_LEN];
unsigned char DP[KEY_LEN];
unsigned char DQ[KEY_LEN];
unsigned char QP[KEY_LEN];
RSA_, *RSA_PTR;
int main()
int j;
unsigned char * buffer = 0;
long length;
FILE * fp = fopen ("rsa_priv.txt", "rb");
if (fp)
fseek (fp, 0, SEEK_END);
length = ftell (fp);
fseek (fp, 0, SEEK_SET);
buffer = calloc (1,length+1);
if (buffer)
fread (buffer, 1, length, fp);
fclose (fp);
// removing label from the keys
// tokenize key and read into rsa context
const char s[3] = "= ";
char *token;
int k=0, size_tok;
char n='\0';
// following buffer will hold the private key without any level
unsigned char *final_token= calloc(1, length+1);
// get the first token
token = strtok(buffer, s);
// walk through other tokens
while( token != NULL )
size_tok = strlen(token);
switch (k)
case 1:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 3:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 5:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 7:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 9:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 11:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 13:
strncat(token, &n,1);
strcat(final_token,token);
break;
case 15:
strncat(token, &n,1);
strcat(final_token,token);
break;
k=k+1;
token = strtok(NULL, "= \n");
//printf("RSA keys without label \n %s",final_token);
// coping final token to a char array,
unsigned char no_label_key_array[strlen(final_token)];
memcpy(no_label_key_array,final_token,sizeof(no_label_key_array));
//printf("no_label_key_array \n %s",no_label_key_array);
// assigning char array to a structure
RSA_PTR rsa_ptr;
rsa_ptr = (RSA_PTR)no_label_key_array;
printf("rsa_ptr.N--> %s\n",rsa_ptr->N);
printf("\n");
printf("rsa_ptr.E--> %s\n",rsa_ptr->E);
printf("\n");
printf("rsa_ptr.DQ--> %s\n",rsa_ptr->DQ);
printf("\n");
printf("rsa_ptr.QP--> %s\n",rsa_ptr->QP);
return 0;
此代码生成以下输出:
rsa_ptr.N - > D0C2ACDCF780B1E4846054BDA700F18D567247FE8BC5BA4FBCAB814E619DA63A20F65A58EE89FC0824DC9367C5725BDDC596065F1C8868E99C896F3A0CF7D7F0A785E668F2568F19BAFB8FF3BA5CDF487544EFE71010BEDB4EE16EDC3AF0A71391AD3194B42D3FD40B4E0DE12A22D8188AF03FF4E36D37BA1DA1F3C57188E60DA38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A47451783931D643CE736DD1BAB40C5523858BB067FB9E490DCB5FD21AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F 822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCCD32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D02004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983 P>
rsa_ptr.E - > A38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A474521AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCCD32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D02004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E 5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983 P>
2004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983 P>
9A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983 P>
抱歉,我无法将输出格式化为单个块。
从输出中,我可以看到即使在连接\0
之后我的输出也不正确?
所以我的问题是,我是否正确连接?我可以像我一样将无符号字符数组转换为结构吗?如果没有,我该怎么做?
【问题讨论】:
您确实知道可以在switch
中组合多个case
标签?如case 1: case 3: case 5: /* Do something common for all cases... */ break;
@Someprogrammerdude,我现在这样做。感谢您的建议。
N = ...
、E = ...
等是否保证是文件中的单独行?
@Zoso,是的。它们将始终位于单独的一行中。
好吧,你还假设KEY_LEN
是256,而N
的值是512 len。这是疏忽吗?
【参考方案1】:
你有几个错误:
您在这里没有正确使用字符串:unsigned char no_label_key_array[strlen(final_token)];
这是一个非常常见的常见问题解答,我们几乎每天都会收到。请阅读How should character arrays be used as strings?
rsa_ptr = (RSA_PTR)no_label_key_array
是一个严格的别名违规。你不能像这样在类型之间疯狂转换。 What is the strict aliasing rule? 解决方案是将您的结构与一个与结构相同大小的原始unsigned char
数组放在一个联合中。
其他问题:
将指针隐藏在typedef
后面是非常糟糕的做法。它完全没有任何作用,只是让你的代码更难阅读。 RSA*
是理想的 C 代码,typedef RSA_PTR
只会让情况变得更糟。
switch
可以替换为查找表,以减少代码重复,提高可读性和性能,如下所示:
unsigned int k; // needs to be unsigned
const bool accepted [16] =
[ 1] = true, [ 3] = true, [ 5] = true, [ 7] = true,
[ 9] = true, [11] = true, [13] = true, [15] = true,
;
... // assign something to k
if(k<16 && accepted[k]) // replace the whole switch with this
strncat(token, &n,1);
strcat(final_token,token);
【讨论】:
以上是关于如何将 char 数组转换为结构?的主要内容,如果未能解决你的问题,请参考以下文章