@@ -35,9 +35,10 @@ typedef struct
3535 char sOutput [XPATH_MAX ];
3636 char sInput [XPATH_MAX ];
3737 char sText [XSTR_MID ];
38+ char sPair [XSTR_MID ];
3839 char sKey [XSTR_MID ];
3940
40- size_t nAESKeyLen ;
41+ size_t nKeySize ;
4142 xbool_t bDecrypt ;
4243 xbool_t bForce ;
4344 xbool_t bPrint ;
@@ -88,26 +89,34 @@ static char *XCrypt_WhiteSpace(const int nLength)
8889static void XCrypt_DisplayUsage (const char * pName )
8990{
9091 int nLength = strlen (pName ) + 6 ;
92+ xbool_t bRSA = XFALSE ;
93+
94+ #ifdef _XUTILS_USE_SSL
95+ bRSA = XTRUE ;
96+ #endif
9197
9298 xlog ("==============================================================" );
9399 xlog (" Crypt/Decrypt file or text - v%d.%d build %d (%s)" ,
94100 XCRYPT_VER_MAX , XCRYPT_VER_MIN , XCRYPT_BUILD_NUM , __DATE__ );
95101 xlog ("==============================================================" );
96102
97103 xlog ("Usage: %s [-c <ciphers>] [-i <input>] [-o <output>]" , pName );
98- xlog (" %s [-k <key >] [-t <text> ] [-K <key-file> ]" , XCrypt_WhiteSpace (nLength ));
99- xlog (" %s [-a] [-d ] [-f] [-p] [-h] [-v] \n" , XCrypt_WhiteSpace (nLength ));
104+ xlog (" %s [-t <text >] [-d] [-f ] [-p] [-s] [-h] [-v ]" , XCrypt_WhiteSpace (nLength ));
105+ xlog (" %s [-K <keyfile> ] [-k <key>] %s \n" , XCrypt_WhiteSpace (nLength ), bRSA ? "[-g <pub:priv>]" : XSTR_EMPTY );
100106
101107 xlog ("Options are:" );
102108 xlog (" -c <ciphers> # Encrypt/Decrypt ciphers (%s*%s)" , XSTR_CLR_RED , XSTR_FMT_RESET );
103109 xlog (" -i <input> # Input file path to encrtypt/decrypt" );
104110 xlog (" -o <output> # Output file path to write data" );
111+ #ifdef _XUTILS_USE_SSL
112+ xlog (" -g <pub:priv> # Gemerate key pair for RSA" );
113+ #endif
114+ xlog (" -K <keyfile> # Encrypt/Decrypt key file" );
105115 xlog (" -k <key> # Encrypt/Decrypt key" );
106- xlog (" -K <key-file> # Encrypt/Decrypt key file" );
107116 xlog (" -t <text> # Text to encrtypt/decrypt" );
108- xlog (" -a # AES key length (default: 128)" );
109117 xlog (" -d # Decryption mode" );
110118 xlog (" -f # Force overwrite output" );
119+ xlog (" -s # Key size for AES %s" , bRSA ? "and RSA" : XSTR_EMPTY );
111120 xlog (" -h # Display output as a HEX" );
112121 xlog (" -p # Printf output to stdout" );
113122 xlog (" -v # Version and usage\n" );
@@ -138,23 +147,28 @@ static void XCrypt_DisplayUsage(const char *pName)
138147 xlog ("%sNotes:%s" , XSTR_CLR_YELLOW , XSTR_FMT_RESET );
139148 xlog ("%s1%s) If you do not specify an argument key (-k <key>)," , XSTR_FMT_BOLD , XSTR_FMT_RESET );
140149 xlog ("the program will prompt you to enter the it securely.\n" );
150+ #ifdef _XUTILS_USE_SSL
141151 xlog ("%s2%s) You can use key file for RSA encrypt/decrypt with -K argument," , XSTR_FMT_BOLD , XSTR_FMT_RESET );
142152 xlog ("%s%s -dc rsa -i crypted.bin -o decrypted.txt -K rsa_priv.pem%s\n" , XSTR_FMT_DIM , pName , XSTR_FMT_RESET );
153+ xlog ("%s3%s) You can generate a pair of RSA private and public keys with -g argument." , XSTR_FMT_BOLD , XSTR_FMT_RESET );
154+ xlog ("Option for -g argument is two path of public/private keys separated by \":\"," );
155+ xlog ("%s%s -g \"./id_rsa.pub:./id_rsa.priv\" -s 2048%s\n" , XSTR_FMT_DIM , pName , XSTR_FMT_RESET );
156+ #endif
143157}
144158
145159static xbool_t XCrypt_GetKey (xcrypt_args_t * pArgs , xcrypt_key_t * pKey )
146160{
147161 if (xstrused (pArgs -> sKeyFile ))
148162 {
149163 pKey -> nLength = XPath_Read (pArgs -> sKeyFile , (uint8_t * )pArgs -> sKey , sizeof (pArgs -> sKey ));
150- if (pKey -> nLength && pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nAESKeyLen ;
164+ if (pKey -> nLength && pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nKeySize ;
151165 pArgs -> sKeyFile [0 ] = XSTR_NUL ;
152166 }
153167
154168 if (xstrused (pArgs -> sKey ))
155169 {
156170 pKey -> nLength = xstrncpy (pKey -> sKey , sizeof (pKey -> sKey ), pArgs -> sKey );
157- if (pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nAESKeyLen ;
171+ if (pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nKeySize ;
158172 return pKey -> nLength ? XTRUE : XFALSE ;
159173 }
160174
@@ -185,14 +199,26 @@ static xbool_t XCrypt_GetKey(xcrypt_args_t *pArgs, xcrypt_key_t *pKey)
185199 }
186200 }
187201
188- if (pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nAESKeyLen ;
202+ if (pKey -> eCipher == XC_AES ) pKey -> nLength = pArgs -> nKeySize ;
189203 else pKey -> nLength = strlen (pKey -> sKey );
190204
191205 return XTRUE ;
192206}
193207
194208static XSTATUS XCrypt_ValidateArgs (xcrypt_args_t * pArgs )
195209{
210+ if (xstrused (pArgs -> sPair ))
211+ {
212+ if (xstrsrc (pArgs -> sPair , ":" ) <= 0 )
213+ {
214+ xlogw ("Invalid option for -g argument: %s" , pArgs -> sPair );
215+ xlogi ("Specify private and public key paths separated by \":\"" );
216+ return XSTDERR ;
217+ }
218+
219+ return XSTDOK ;
220+ }
221+
196222 if ((!pArgs -> bPrint &&
197223 !xstrused (pArgs -> sOutput )) ||
198224 (!xstrused (pArgs -> sText ) &&
@@ -257,10 +283,9 @@ static XSTATUS XCrypt_ValidateArgs(xcrypt_args_t *pArgs)
257283static xbool_t XCrypt_ParseArgs (xcrypt_args_t * pArgs , int argc , char * argv [])
258284{
259285 memset (pArgs , 0 , sizeof (xcrypt_args_t ));
260- pArgs -> nAESKeyLen = XAES_KEY_LENGTH ;
261286 int nChar = 0 ;
262287
263- while ((nChar = getopt (argc , argv , "c:i:o:k:K:t:a :d1:f1:h1:p1:s1:v1" )) != -1 )
288+ while ((nChar = getopt (argc , argv , "c:i:o:g: k:K:t:s :d1:f1:h1:p1:s1:v1" )) != -1 )
264289 {
265290 switch (nChar )
266291 {
@@ -273,6 +298,11 @@ static xbool_t XCrypt_ParseArgs(xcrypt_args_t *pArgs, int argc, char *argv[])
273298 case 'o' :
274299 xstrncpy (pArgs -> sOutput , sizeof (pArgs -> sOutput ), optarg );
275300 break ;
301+ #ifdef _XUTILS_USE_SSL
302+ case 'g' :
303+ xstrncpy (pArgs -> sPair , sizeof (pArgs -> sPair ), optarg );
304+ break ;
305+ #endif
276306 case 'k' :
277307 xstrncpy (pArgs -> sKey , sizeof (pArgs -> sKey ), optarg );
278308 break ;
@@ -282,8 +312,8 @@ static xbool_t XCrypt_ParseArgs(xcrypt_args_t *pArgs, int argc, char *argv[])
282312 case 't' :
283313 xstrncpy (pArgs -> sText , sizeof (pArgs -> sText ), optarg );
284314 break ;
285- case 'a ' :
286- pArgs -> nAESKeyLen = atoi (optarg );
315+ case 's ' :
316+ pArgs -> nKeySize = atoi (optarg );
287317 break ;
288318 case 'd' :
289319 pArgs -> bDecrypt = XTRUE ;
@@ -304,6 +334,16 @@ static xbool_t XCrypt_ParseArgs(xcrypt_args_t *pArgs, int argc, char *argv[])
304334 }
305335 }
306336
337+ if (!pArgs -> nKeySize )
338+ {
339+ #ifdef _XUTILS_USE_SSL
340+ pArgs -> nKeySize = xstrused (pArgs -> sPair ) ?
341+ XRSA_KEY_SIZE : XAES_KEY_LENGTH ;
342+ #else
343+ pArgs -> nKeySize = XAES_KEY_LENGTH ;
344+ #endif
345+ }
346+
307347 XSTATUS nStatus = XCrypt_ValidateArgs (pArgs );
308348 if (!nStatus ) XCrypt_DisplayUsage (argv [0 ]);
309349 return nStatus == XSTDOK ? XTRUE : XFALSE ;
@@ -341,6 +381,75 @@ xbool_t XCrypt_Callback(xcrypt_cb_type_t eType, void *pData, void *pCtx)
341381 return XFALSE ;
342382}
343383
384+ #ifdef _XUTILS_USE_SSL
385+ XSTATUS XCrypt_GeneratePair (xcrypt_args_t * pArgs )
386+ {
387+ xarray_t * pArr = xstrsplit (pArgs -> sPair , ":" );
388+ if (pArr == NULL || pArr -> nUsed < 2 )
389+ {
390+ xloge ("Failed to parse RSA key pair option: %s" , pArgs -> sPair );
391+ XArray_Clear (pArr );
392+ return XSTDERR ;
393+ }
394+
395+ xrsa_key_t pair ;
396+ XRSA_InitKey (& pair );
397+
398+ if (XRSA_GenerateKeys (& pair , pArgs -> nKeySize , XRSA_PUB_EXP ) <= 0 )
399+ {
400+ xloge ("Failed to generate RSA key pair: %s" , pArgs -> sPair );
401+ XArray_Clear (pArr );
402+ return XSTDERR ;
403+ }
404+
405+ const char * pPubKeyPath = XArray_GetData (pArr , 0 );
406+ const char * pPrivKeyPath = XArray_GetData (pArr , 1 );
407+
408+ if (XPath_Exists (pPubKeyPath ) && pArgs -> bForce == XFALSE )
409+ {
410+ xlogw ("File already exists: %s" , pPubKeyPath );
411+ xlogi ("Use option -f to force overwrite output" );
412+
413+ XRSA_FreeKey (& pair );
414+ XArray_Clear (pArr );
415+ return XSTDERR ;
416+ }
417+
418+ if (XPath_Exists (pPrivKeyPath ) && pArgs -> bForce == XFALSE )
419+ {
420+ xlogw ("File already exists: %s" , pPubKeyPath );
421+ xlogi ("Use option -f to force overwrite output" );
422+
423+ XRSA_FreeKey (& pair );
424+ XArray_Clear (pArr );
425+ return XSTDERR ;
426+ }
427+
428+ if (XPath_Write (pPubKeyPath , "cw" , (uint8_t * )pair .pPublicKey , pair .nPubKeyLen ) <= 0 )
429+ {
430+ xloge ("Failed to public key file: %s (%s)" , pPubKeyPath , strerror (errno ));
431+ XRSA_FreeKey (& pair );
432+ XArray_Clear (pArr );
433+ return XSTDERR ;
434+ }
435+
436+ if (XPath_Write (pPrivKeyPath , "cw" , (uint8_t * )pair .pPrivateKey , pair .nPrivKeyLen ) <= 0 )
437+ {
438+ xloge ("Failed to private key file: %s (%s)" , pPrivKeyPath , strerror (errno ));
439+ XRSA_FreeKey (& pair );
440+ XArray_Clear (pArr );
441+ return XSTDERR ;
442+ }
443+
444+ xlogi ("Generated public key: %s" , pPubKeyPath );
445+ xlogi ("Generated private key: %s" , pPrivKeyPath );
446+
447+ XRSA_FreeKey (& pair );
448+ XArray_Clear (pArr );
449+ return XSTDOK ;
450+ }
451+ #endif
452+
344453int main (int argc , char * argv [])
345454{
346455 xlog_defaults ();
@@ -349,6 +458,10 @@ int main(int argc, char* argv[])
349458 xcrypt_args_t args ;
350459 if (!XCrypt_ParseArgs (& args , argc , argv )) return XSTDERR ;
351460
461+ #ifdef _XUTILS_USE_SSL
462+ if (xstrused (args .sPair )) return XCrypt_GeneratePair (& args );
463+ #endif
464+
352465 xbyte_buffer_t buffer ;
353466 XByteBuffer_Init (& buffer , 0 , 0 );
354467
0 commit comments