Reputation: 325
I'm trying to read RSA private keys from a file into a structure. I'm using mpi_read_string()
to load these keys into RSA context. Therefore, each individual keys has to be null-terminated. To achieve this upon reading each keys from the file, I concatenate \0
at the end of each keys.
In summary, I read all the content of a file into an unsigned char * buffer
, tokenize each line, concatenate \0
at the end of each line, and store it into unsigned char no_label_key_array[]
. I also have a structure struct RSA_KEY
. I'm trying to assign this unsigned char no_label_key_array[]
into the structure.
rsa_priv.txt
contains the following,
N = D0C2ACDCF780B1E4846054BDA700F18D567247FE8BC5BA4FBCAB814E619DA63A20F65A58EE89FC0824DC9367C5725BDDC596065F1C8868E99C896F3A0CF7D7F0A785E668F2568F19BAFB8FF3BA5CDF487544EFE71010BEDB4EE16EDC3AF0A71391AD3194B42D3FD40B4E0DE12A22D8188AF03FF4E36D37BA1DA1F3C57188E60DA38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A47451783931D643CE736DD1BAB40C5523858BB067FB9E490DCB5FDBBB03B9D68A8998C1347E237C477AA14B0997A84708CED05A9E24C7072B838F753
E = 010001
D = 21AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427B029AF629EED23C99726F0A0C3CEA1229E4099B588CE676975D25
P = FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCC7D57221CD9394C64585653664976174CAE2E7DC6A7B03DE09599B5D9501927ACC4EED5F5CBC5870E31A051AF9842945A0168E35
Q = D32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D084CFA423E04C90C5966AC391A47F10E823C71B9716856B05BC12160DF0BA96300F8ADDC0D59E54E9CBDC7AC0EA6747DBA46C067
DP = 2004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B608858354C999A26A4BF7F1543408EF6C1B439E9643604C2848162590A0A245CC834B977C72D10979010EBE5E177D884F04E450C51
DQ = 9A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734C5FCFDF719ABFBC459DF1B7379CB45EEC2E4BA3BF88D93CB82DF532C86FEC646420B1B21054BAE84AAA36DDFF9BF43EDFDD063B9
QP = E7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
I have the following code,
#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;
}
This code generates the following output:
rsa_ptr.N--> D0C2ACDCF780B1E4846054BDA700F18D567247FE8BC5BA4FBCAB814E619DA63A20F65A58EE89FC0824DC9367C5725BDDC596065F1C8868E99C896F3A0CF7D7F0A785E668F2568F19BAFB8FF3BA5CDF487544EFE71010BEDB4EE16EDC3AF0A71391AD3194B42D3FD40B4E0DE12A22D8188AF03FF4E36D37BA1DA1F3C57188E60DA38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A47451783931D643CE736DD1BAB40C5523858BB067FB9E490DCB5FD21AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCCD32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D02004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
rsa_ptr.E--> A38C25329E48805FC7FF524761A6F010E737B927D8F67383274F8E600167A52A042E1DCA3335150C090803F9D96F6E63BEBFB153516E863F5B4CB02104077834FC5EC31A474521AFE07431CE47269083F8F8B7ABCBCEDA6DCB975457BE6662942C64091586FEE755C9A3832EAA0868665DB507A41A15F1EDF12E44ECF03D0E61111D457D730FA700D0FB0B6C13607C0F5F1DDDEB61AE9019E53A9C998F2AD5924430EEA3E9DA1B0E5F2B575DDBE86C4096B5C87661F7A7E7F7F21D0701509BBA881B4AE463F6F18C7F04AB742319E2D7319EECA136EEB0CF7B2BFA87E3A0E69FBC0E5FDC7EE6271EB2CA09DDBF7C8B57D951762708D76890E62858C1D5FC5B7E40D50913CE7797BD80F6A398FB92703FBDD33FBCB129B86E54F13EC14DA68BE139634DD1E9C01F01751C427FD1120F3E183DF72779B9B4A29FF9157C89FF8204988B6FB1211642B4D59B6A1BB306E81C040F0F822B41765FC4435A46B5090700E72B9720481EACF3624885D7A263CAC0CA559954E9382FCCD32E15E032B256C7DE0BDB585379EB897343ABFB8C7A86A3D798C13AE3E3F048A50DA9D7C31EB65A588CF6B9911F7B41D6F154F99B4F64839E110C30BA4B79286A4A3A3F7F0169A1D3A21F0D02004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
2004DECA7CAA16C780E2AB4F42E91716A847B53940948FB24CA2EEAD9BE7D1F7BC9B701FF29744E5E05E30E7B2775EE222C1DAC492CF692F47EAB82EE786CFCA23FE5A86DA42C186E69E3B6089A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
9A035E48E8305041EB9AD21994A7B233C8306E59429689632C7567573FA4993521CAD93756422BD3B008FE574F939A1CE659931387455B94F1CE950964946E841F208B628B89C83411588734CE7A5BC150E6A20E52920C6F24FC872B1893ED9268AA506D86EC3AA6E3B377E5F6AE0D686751CE40F684435C6F64F31888861389CE430FB271EE81D0067ED8A1BD8096FB3E4AF5839383F26F99916EED4D80CFA9B5901350A9C0AAD4E348EBCC559F92434C71DA864C13371626D9F29998748BB3C47BED31471B73ABF2E27B983
Sorry, that I could not format the output into a single block.
From the output, I can see that even after concatenating \0
my outputs are not right?
So my question is, am I concatenating correctly? and Can I cast an unsigned char array to a structure like the way I did? If not, how can I do that?
Upvotes: 0
Views: 239
Reputation: 213513
You have several bugs:
unsigned char no_label_key_array[strlen(final_token)];
This is a very common FAQ that we get almost every day. Please read How should character arrays be used as strings?rsa_ptr = (RSA_PTR)no_label_key_array
is a strict aliasing violation. You can't convert wildly between types like this. What is the strict aliasing rule? The solution is to put your struct in a union together with a raw unsigned char
array of the same size as the struct.Other issues:
It is very bad practice to hide pointers behind typedef
. It achieves absolutely nothing but turns your code harder to read. RSA*
is ideal C code, a typedef RSA_PTR
will only make it worse.
The switch
can be replaced with a look-up table, for reduced code repetition, increased readability and performance, like this:
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);
}
Upvotes: 2