fareqr.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*
  2. * Copyright (c) 2021 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "fareqr.h"
  21. // AES CBC, sha256 message digest, with salt.
  22. // Functions modified from https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption
  23. //
  24. // openssl example commands to encrypt/decrypt:
  25. // msg=";123456789012345?"
  26. // key="oovevobie8woid1Ou3iu6aboochei2AeKoceeCh1iePheuRae4Yai1dahtheegi7"
  27. // openssl enc -aes-256-cbc -in <( echo -n "$msg" ) -out /dev/stdout -pass pass:"$key" -e -base64 -md sha256
  28. //
  29. // ---
  30. //
  31. // to descypt with openssl
  32. //
  33. // openssl aes-256-cbc -d -a -in <( echo "U2FsdGVkX19gpKzk+Y5SGgnQr1uwpUYUpea6nu77wJfG6bD4GZpRneSaxaallz0n" ) -out /dev/stdout -pass pass:"$key" -md sha256
  34. //
  35. static int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
  36. EVP_CIPHER_CTX *ctx;
  37. int len;
  38. int ciphertext_len;
  39. // Create and initialise the context
  40. if(!(ctx = EVP_CIPHER_CTX_new())) { return -1; }
  41. // Initialise the encryption operation. IMPORTANT - ensure you use a key
  42. // and IV size appropriate for your cipher
  43. // In this example we are using 256 bit AES (i.e. a 256 bit key). The
  44. // IV size for *most* modes is the same as the block size. For AES this
  45. // is 128 bits
  46. //
  47. if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { return -2; }
  48. // Provide the message to be encrypted, and obtain the encrypted output.
  49. // EVP_EncryptUpdate can be called multiple times if necessary
  50. //
  51. if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) { return -3; }
  52. ciphertext_len = len;
  53. // Finalise the encryption. Further ciphertext bytes may be written at
  54. // this stage.
  55. //
  56. if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { return -4; }
  57. ciphertext_len += len;
  58. // Clean up
  59. //
  60. EVP_CIPHER_CTX_free(ctx);
  61. return ciphertext_len;
  62. }
  63. static int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) {
  64. EVP_CIPHER_CTX *ctx;
  65. int plaintext_len, len;
  66. // Create and initialise the context
  67. //
  68. if(!(ctx = EVP_CIPHER_CTX_new())) { return -1; }
  69. // Initialise the decryption operation. IMPORTANT - ensure you use a key
  70. // and IV size appropriate for your cipher
  71. // In this example we are using 256 bit AES (i.e. a 256 bit key). The
  72. // IV size for *most* modes is the same as the block size. For AES this
  73. // is 128 bits
  74. //
  75. if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { return -2; }
  76. // Provide the message to be decrypted, and obtain the plaintext output.
  77. // EVP_DecryptUpdate can be called multiple times if necessary.
  78. //
  79. if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) { return -3; }
  80. plaintext_len = len;
  81. // Finalise the decryption. Further plaintext bytes may be written at
  82. // this stage.
  83. //
  84. if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) { return -4; }
  85. plaintext_len += len;
  86. // Clean up
  87. //
  88. EVP_CIPHER_CTX_free(ctx);
  89. return plaintext_len;
  90. }
  91. // Helper function to take secret key/pass (pass_key) and the encoded
  92. // base64 string and decrypt it with AES CBC 256, sha256 message digest.
  93. //
  94. // return the number of bytes decoded on success
  95. // return non-positive number on error
  96. //
  97. static int decode_b64(unsigned char *decrypt_text,
  98. unsigned char *pass_key,
  99. unsigned char *enc_b64) {
  100. int i=0, _ret = 0, r=0;
  101. unsigned char *enc_b = NULL, salt[8];
  102. unsigned char *key = NULL, *iv = NULL, *ciphertext_b = NULL;
  103. size_t b64_sz=0, enc_len=0, enc_size=0, ciphertext_len;
  104. if ((!decrypt_text) || (!pass_key) || (!enc_b64)) { return -9; }
  105. enc_size = Base64decode_len(enc_b64);
  106. if (enc_size < 1) {
  107. _ret=-1;
  108. goto _decode_b64_cleanup;
  109. }
  110. enc_b = (unsigned char *)calloc(enc_size, sizeof(char));
  111. if (!enc_b) {
  112. _ret=-2;
  113. goto _decode_b64_cleanup;
  114. }
  115. Base64decode(enc_b, enc_b64);
  116. enc_len = enc_size-1;
  117. // Check exmpanded string is well formed (has "Salted__" prefix, etc.)
  118. // and extract the salt
  119. //
  120. if (enc_len < 16) {
  121. _ret = -3;
  122. goto _decode_b64_cleanup;
  123. }
  124. if (strncmp(enc_b, "Salted__", 8)!=0) {
  125. _ret = -4;
  126. goto _decode_b64_cleanup;
  127. }
  128. for (i=0; i<8; i++) { salt[i] = enc_b[i+8]; }
  129. // Move past the salt prefix 8 bytes) and 8 bytes of salt
  130. //
  131. ciphertext_b = enc_b + 16;
  132. ciphertext_len = enc_len - 16;
  133. // Allocate iv, key and extract them from the salt and pass phrase
  134. //
  135. iv = (unsigned char *)calloc(256, sizeof(char));
  136. key = (unsigned char *)calloc(256, sizeof(char));
  137. r = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), salt, pass_key, strlen(pass_key), 1, key, iv);
  138. if (!r) {
  139. _ret = -5;
  140. goto _decode_b64_cleanup;
  141. }
  142. r = aes_decrypt(ciphertext_b, ciphertext_len, key, iv, decrypt_text);
  143. if (r<=0) {
  144. _ret = -6;
  145. goto _decode_b64_cleanup;
  146. }
  147. decrypt_text[r] = '\0';
  148. _ret = r;
  149. _decode_b64_cleanup:
  150. if (enc_b) { free(enc_b); }
  151. if (key) { free(key); }
  152. if (iv) { free(iv); }
  153. return _ret;
  154. }
  155. static int encode_b64(unsigned char *enc_b64,
  156. unsigned char *pass_key,
  157. unsigned char *msg) {
  158. int i=0, _ret = 0, r=0;
  159. unsigned char *enc_b = NULL;
  160. unsigned char *key = NULL, *iv = NULL, *ciphertext_b = NULL;
  161. size_t b64_sz=0, enc_len=0, enc_size=0, ciphertext_len;
  162. unsigned char salt[8];
  163. char _pfx[] = "Salted__";
  164. if ((!enc_b64) || (!pass_key) || (!msg)) { return -9; }
  165. for (i=0; i<8; i++) { salt[i] = (unsigned char)(rand() % 256); }
  166. iv = (unsigned char *)calloc(256, sizeof(char));
  167. key = (unsigned char *)calloc(256, sizeof(char));
  168. r = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), salt, pass_key, strlen(pass_key), 1, key, iv);
  169. if (!r) {
  170. _ret = -5;
  171. goto _encode_b64_cleanup;
  172. }
  173. enc_b = (unsigned char *)calloc(2*LINE_BUFFER_SIZE, sizeof(char));
  174. if (!enc_b) {
  175. _ret = -4;
  176. goto _encode_b64_cleanup;
  177. }
  178. for (i=0; i<8; i++) {
  179. enc_b[i] = _pfx[i];
  180. enc_b[i+8] = salt[i];
  181. }
  182. enc_len = aes_encrypt(msg, strlen(msg), key, iv, enc_b+16);
  183. if (enc_len<=0) {
  184. _ret = -6;
  185. goto _encode_b64_cleanup;
  186. }
  187. enc_len += 16;
  188. b64_sz = Base64encode_len(enc_len);
  189. Base64encode(enc_b64, enc_b, enc_len);
  190. _ret = b64_sz;
  191. _encode_b64_cleanup:
  192. if (enc_b) { free(enc_b); }
  193. if (key) { free(key); }
  194. if (iv) { free(iv); }
  195. return _ret;
  196. }
  197. // `fqreqr_lookup_decode` uses the public key portion of `fareqr_s`
  198. // to lookup the private pass/key in the file `seedfn`.
  199. // If found, it then proceeds to decrypt and store the encrypted
  200. // credential in `dst_cred`
  201. //
  202. // returns 0 on success
  203. // returns non zero on error
  204. //
  205. int fareqr_lookup_decode(char *seedfn, char *fareqr_s, char *dst_cred) {
  206. int i, n, r, _ret = 0;;
  207. char *p=NULL, *stop_tok=NULL;
  208. char *enc_str = NULL, *dec_str = NULL, *plain_str=NULL,
  209. *pub_key = NULL, *priv_key = NULL;
  210. if ((!seedfn) || (!fareqr_s) || (!dst_cred)) { return -1; }
  211. if (fareqr_s[0] != '@') { return -2; }
  212. stop_tok = strchr(fareqr_s, '%');
  213. if (!stop_tok) { return -3; }
  214. pub_key = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  215. priv_key = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  216. enc_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  217. dec_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  218. plain_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  219. pub_key[0] = priv_key[0] = enc_str[0] = dec_str[0] = plain_str[0] = '\0';
  220. for (i=0, p = (fareqr_s+1); (i<(LINE_BUFFER_SIZE-1)) && (p<stop_tok) && (*p); p++, i++) {
  221. pub_key[i] = *p;
  222. }
  223. pub_key[i] = '\0';
  224. for (n=0, p = (stop_tok+1); (n<(LINE_BUFFER_SIZE-1)) && (*p) && ((*p) != '$'); p++, n++) {
  225. enc_str[n] = *p;
  226. }
  227. enc_str[n] = '\0';
  228. r = fareqr_lookup_seed_secret(seedfn, pub_key, priv_key);
  229. if (r<0) { _ret = r; }
  230. else {
  231. //r = fareqr_decode(fareqr_s, pub_key, priv_key, dst_cred);
  232. r = decode_b64(dst_cred, priv_key, enc_str);
  233. if (r<0) { _ret = r; }
  234. }
  235. if (pub_key) { free(pub_key); }
  236. if (priv_key) { free(priv_key); }
  237. if (enc_str) { free(enc_str); }
  238. if (dec_str) { free(dec_str); }
  239. if (plain_str) { free(plain_str); }
  240. return _ret;
  241. }
  242. // depreicated (doing away with one-time pads in favor of AES above)
  243. //
  244. int fareqr_encode(char *tok_public, char *tok_secret, char *tok_cred, char *fareqr_str) {
  245. int i, r;
  246. uint8_t x,y,z;
  247. uint8_t *src_data = NULL, *dst_data = NULL;
  248. int src_data_n = 0;
  249. //int dst_data_n = 0;
  250. src_data = (uint8_t *)malloc(sizeof(uint8_t)*LINE_BUFFER_SIZE);
  251. dst_data = (uint8_t *)malloc(sizeof(uint8_t)*LINE_BUFFER_SIZE);
  252. for (i=0; tok_cred[i]; i++) {
  253. x = (uint8_t)tok_secret[i];
  254. y = (uint8_t)tok_cred[i];
  255. z = x^y;
  256. src_data[i] = z;
  257. src_data_n++;
  258. }
  259. for (i=0; i<src_data_n; i++) {
  260. x = (uint8_t)tok_secret[i];
  261. }
  262. //dst_data_n = Base64encode_len(src_data_n);
  263. r = Base64encode((char *)dst_data, (const char *)src_data, src_data_n);
  264. if (r<=0) {
  265. free(src_data);
  266. free(dst_data);
  267. return -1;
  268. }
  269. if (fareqr_str) {
  270. snprintf(fareqr_str, LINE_BUFFER_SIZE-1, "@%s%%%s$", tok_public, dst_data);
  271. }
  272. free(src_data);
  273. free(dst_data);
  274. return 0;
  275. }
  276. // depreicated (doing away with one-time pads in favor of AES above)
  277. //
  278. int fareqr_decode(char *fareqr_s, char *check_pub, char *tok_secret, char *dst_cred) {
  279. int i, n, _ret=0;
  280. char *p, *stop_tok;
  281. int pub_tok_read_len = 0, check_pub_len = 0;
  282. char *enc_str = NULL, *dec_str = NULL, *plain_str=NULL;
  283. uint8_t x,y,z;
  284. if (fareqr_s[0] != '@') { return -1; }
  285. stop_tok = strchr(fareqr_s, '%');
  286. if (!stop_tok) { return -2; }
  287. if (!tok_secret) { return -3; }
  288. if (check_pub) {
  289. check_pub_len = strlen(check_pub);
  290. for ( p = (fareqr_s+1); p < stop_tok; p++) {
  291. if (pub_tok_read_len >= check_pub_len) { return -3; }
  292. if ( (*p) != check_pub[pub_tok_read_len] ) { return -4; }
  293. pub_tok_read_len++;
  294. }
  295. }
  296. enc_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  297. dec_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  298. plain_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  299. for (n=0, p = (stop_tok+1); (*p) && ((*p) != '$'); p++, n++) {
  300. enc_str[n] = *p;
  301. }
  302. enc_str[n] = '\0';
  303. Base64decode(dec_str, enc_str);
  304. for (i=0; dec_str[i]; i++) {
  305. if (tok_secret[i]==0) {
  306. _ret = -5;
  307. goto _fareqr_decode_cleanup;
  308. }
  309. x = (uint8_t)dec_str[i];
  310. y = (uint8_t)tok_secret[i];
  311. z = (x^y);
  312. plain_str[i] = (char)z;
  313. }
  314. plain_str[i]='\0';
  315. if (dst_cred) {
  316. for (i=0; plain_str[i]; i++) {
  317. dst_cred[i] = plain_str[i];
  318. }
  319. dst_cred[i] = '\0';
  320. }
  321. _fareqr_decode_cleanup:
  322. if (enc_str) { free(enc_str); }
  323. if (dec_str) { free(dec_str); }
  324. if (plain_str) { free(plain_str); }
  325. return _ret;
  326. }
  327. // return negative on error or not found
  328. // 0 on success (found)
  329. //
  330. int fareqr_lookup_seed_secret(char *seedfn, char *pub, char *priv) {
  331. int i;
  332. FILE *fp;
  333. char buf[LINE_BUFFER_SIZE] = {0};
  334. int pos = 0, ch=0, line_no=0;
  335. char *tok0_ptr=NULL,
  336. *tok1_ptr=NULL;
  337. fp = fopen(seedfn, "r");
  338. if (!fp) { perror(seedfn); return -2;}
  339. while (!feof(fp)) {
  340. ch = fgetc(fp);
  341. // process line if we reach a newline or eof
  342. //
  343. if (feof(fp) || (ch == '\n')) {
  344. // if the line is empty or a comment, skip
  345. //
  346. if ((pos==0) || (buf[0] == '#')) {
  347. }
  348. // get tokens out of line, using ' ' as the
  349. // delimeter
  350. //
  351. else {
  352. tok0_ptr = buf;
  353. tok1_ptr = strchr(buf, ' ');
  354. if (tok1_ptr) {
  355. *tok1_ptr = '\0';
  356. tok1_ptr++;
  357. // Cechk it against our supplied 'pulbic' key
  358. //
  359. if (strcmp(pub, tok0_ptr)==0) {
  360. // If we've found it, copy it over to the `priv`
  361. // above and return
  362. //
  363. for (i=0; tok1_ptr[i]; i++) {
  364. priv[i] = tok1_ptr[i];
  365. }
  366. priv[i]='\0';
  367. return 0;
  368. }
  369. }
  370. line_no++;
  371. }
  372. pos=0;
  373. buf[0]='\0';
  374. continue;
  375. }
  376. buf[pos] = ch;
  377. pos++;
  378. buf[pos] = '\0';
  379. }
  380. fclose(fp);
  381. return -1;
  382. }
  383. // to compile:
  384. // gcc -D__FAREQR_MAIN__ fareqr.c b64.c -o fareqr
  385. //
  386. #ifdef __FAREQR_MAIN__
  387. #define FAREQR_VERSION "0.1.0"
  388. void show_version(FILE *ofp) {
  389. fprintf(ofp, "fareqr version %s\n", FAREQR_VERSION);
  390. }
  391. void show_help(FILE *ofp) {
  392. show_version(ofp);
  393. fprintf(ofp, "\nusage:\n\n");
  394. fprintf(ofp, " fareqr encode <pubkey> <privatekey> <str>\n");
  395. fprintf(ofp, " fareqr decode <privatekey> <encstr>\n");
  396. fprintf(ofp, " fareqr dbdecode <qrseedfile> <fareqr>\n");
  397. fprintf(ofp, " fareqr version\n");
  398. fprintf(ofp, " fareqr help\n");
  399. fprintf(ofp, "\n");
  400. fprintf(ofp, "fareqr is a program to help with encoding and decoding 'fareqr' strings.\n");
  401. fprintf(ofp, "\n");
  402. fprintf(ofp, "A fareqr string is of the form:\n");
  403. fprintf(ofp, "\n");
  404. fprintf(ofp, " @<pubkey>%%<b64(xor(privkey,credential))>$\n");
  405. fprintf(ofp, "\n");
  406. fprintf(ofp, "Where `<b64(xor(privkey,credential))>` is the base64 encoded XOR of the private key\n");
  407. fprintf(ofp, "and the credential to be presented. The reasoning behind the XOR is to not allow a\n");
  408. fprintf(ofp, "snooper to get credential information if exposed to the string and the base64\n");
  409. fprintf(ofp, "encoding is to make it easily transportable.\n");
  410. fprintf(ofp, "\n");
  411. fprintf(ofp, "The <qrseedfile> is a text file of <pubkey> <privkey> pairs.\n");
  412. fprintf(ofp, "\n");
  413. fprintf(ofp, "Here is some example usage:\n");
  414. fprintf(ofp, "\n");
  415. fprintf(ofp, " $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?'\n");
  416. fprintf(ofp, " @wu9XouSh%%VFl8VF1PV19TXEBeUVxdBl4=\n");
  417. fprintf(ofp, " $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%%VFl8VF1PV19TXEBeUVxdBl4=$'\n");
  418. fprintf(ofp, " ;123456789060535?\n");
  419. fprintf(ofp, " $ echo 'wu9XouSh ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' > ./qr.seed\n");
  420. fprintf(ofp, " $ fareqr dbdecode ./qr.seed '@wu9XouSh%%VFl8VF1PV19TXEBeUVxdBl4=$'\n");
  421. fprintf(ofp, " ;123456789060535?\n");
  422. fprintf(ofp, "\n");
  423. fprintf(ofp, "Where 'wu9XouSh' is the public key, 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' is the private key and\n");
  424. fprintf(ofp, "';123456789060535?' is the credential information to be encoded.\n");
  425. fprintf(ofp, "\n");
  426. fprintf(ofp, "\n");
  427. fflush(ofp);
  428. }
  429. /*
  430. *
  431. * quick test/start:
  432. *
  433. * $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?'
  434. * @wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=
  435. *
  436. * $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'
  437. * ;123456789060535?
  438. *
  439. * $ fareqr dbdecode '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'
  440. * ;123456789060535?
  441. *
  442. */
  443. int main(int argc, char **argv) {
  444. int i, r;
  445. char *tok_public = NULL,
  446. *tok_secret = NULL,
  447. *tok_cred = NULL,
  448. *fareqr_str = NULL;
  449. uint8_t x,y,z;
  450. uint8_t *src_data = NULL, *dst_data = NULL;
  451. int src_data_n = 0, dst_data_n = 0;
  452. char *fn = NULL;
  453. if (argc <= 1) {
  454. show_help(stderr);
  455. exit(1);
  456. }
  457. if (strcmp(argv[1], "encode")==0) {
  458. if (argc>2) {
  459. tok_public = strdup(argv[2]);
  460. if (argc>3) {
  461. tok_secret = strdup(argv[3]);
  462. if (argc>4) {
  463. tok_cred = strdup(argv[4]);
  464. }
  465. }
  466. }
  467. if ((!tok_public) || (!tok_secret) || (!tok_cred)) {
  468. show_help(stderr);
  469. if (tok_public) { free(tok_public); }
  470. if (tok_secret) { free(tok_secret); }
  471. if (tok_cred) { free(tok_cred); }
  472. exit(2);
  473. }
  474. fareqr_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  475. r = fareqr_encode(tok_public, tok_secret, tok_cred, fareqr_str);
  476. if (r==0) {
  477. printf("%s\n", fareqr_str);
  478. }
  479. }
  480. else if (strcmp(argv[1], "decode")==0) {
  481. if (argc>2) {
  482. tok_secret = strdup(argv[2]);
  483. if (argc>3) {
  484. fareqr_str = strdup(argv[3]);
  485. }
  486. }
  487. tok_cred = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  488. tok_cred[0] = '0';
  489. r = fareqr_decode(fareqr_str, tok_public, tok_secret, tok_cred);
  490. if (r<0) {
  491. fprintf(stderr, "error, failed to decode qr fare string (%i)\n", r);
  492. }
  493. else {
  494. printf("%s\n", tok_cred);
  495. }
  496. }
  497. else if (strcmp(argv[1], "dbdecode")==0) {
  498. if (argc>2) {
  499. fn = strdup(argv[2]);
  500. if (argc>3) {
  501. fareqr_str = strdup(argv[3]);
  502. }
  503. }
  504. tok_cred = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  505. tok_cred[0] = '0';
  506. r = fareqr_lookup_decode(fn, fareqr_str, tok_cred);
  507. if (r<0) {
  508. fprintf(stderr, "could not decode '%s' with db '%s', exiting (got %i)\n",
  509. fareqr_str, fn, r);
  510. }
  511. else {
  512. printf("%s\n", tok_cred);
  513. }
  514. }
  515. // test out our AES encryption
  516. //
  517. else if (strcmp(argv[1], "aes-decode")==0) {
  518. if (argc>2) {
  519. tok_secret = strdup(argv[2]);
  520. if (argc>3) {
  521. fareqr_str = strdup(argv[3]);
  522. }
  523. }
  524. tok_cred = (unsigned char *)calloc(LINE_BUFFER_SIZE, sizeof(char));
  525. r = decode_b64(tok_cred, tok_secret, fareqr_str);
  526. if (r<0) {
  527. fprintf(stderr, "could not decode aes base64 string (AES CBC 256, sha256 md) (got %i)\n", r);
  528. }
  529. else {
  530. printf("%s\n", tok_cred);
  531. }
  532. }
  533. // test out our AES encryption
  534. //
  535. else if (strcmp(argv[1], "aes-encode")==0) {
  536. if (argc>2) {
  537. tok_secret = strdup(argv[2]);
  538. if (argc>3) {
  539. tok_cred = strdup(argv[3]);
  540. }
  541. }
  542. printf(">>> '%s' '%s'\n", tok_secret, tok_cred);
  543. fareqr_str = (unsigned char *)calloc(2*LINE_BUFFER_SIZE, sizeof(char));
  544. r = encode_b64(fareqr_str, tok_secret, tok_cred);
  545. if (r<0) {
  546. fprintf(stderr, "could not encode aes base64 string (AES CBC 256, sha256 md) (got %i)\n", r);
  547. }
  548. else {
  549. printf("%s\n", fareqr_str);
  550. }
  551. }
  552. else if (strcmp(argv[1], "help")==0) {
  553. show_help(stdout);
  554. exit(0);
  555. }
  556. else if (strcmp(argv[1], "version")==0) {
  557. show_version(stdout);
  558. exit(0);
  559. }
  560. else {
  561. fprintf(stderr, "unknown operation '%s'\n", argv[1]);
  562. show_help(stderr);
  563. exit(3);
  564. }
  565. if (tok_public) { free(tok_public); }
  566. if (tok_secret) { free(tok_secret); }
  567. if (tok_cred) { free(tok_cred); }
  568. if (fareqr_str) { free(fareqr_str); }
  569. if (src_data) { free(src_data); }
  570. if (dst_data) { free(dst_data); }
  571. if (fn) { free(fn); }
  572. }
  573. #endif