Skip to content

Commit cafde01

Browse files
committed
Added support to generate priv/pub RSA key pair with xcrypt tool
1 parent 1b46af5 commit cafde01

File tree

2 files changed

+126
-13
lines changed

2 files changed

+126
-13
lines changed

examples/xcrypt.c

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
8889
static 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

145159
static 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

194208
static 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)
257283
static 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+
344453
int 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

src/xver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#define XUTILS_VERSION_MAX 2
1414
#define XUTILS_VERSION_MIN 4
15-
#define XUTILS_BUILD_NUMBER 36
15+
#define XUTILS_BUILD_NUMBER 37
1616

1717
#ifdef __cplusplus
1818
extern "C" {

0 commit comments

Comments
 (0)