/* * Copyright (c) 2021 Clementine Computing LLC. * * This file is part of PopuFare. * * PopuFare is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PopuFare is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with PopuFare. If not, see . * */ #include "fareqr.h" int fareqr_encode(char *tok_public, char *tok_secret, char *tok_cred, char *fareqr_str) { int i, r; uint8_t x,y,z; uint8_t *src_data = NULL, *dst_data = NULL; int src_data_n = 0, dst_data_n = 0; src_data = (uint8_t *)malloc(sizeof(uint8_t)*LINE_BUFFER_SIZE); dst_data = (uint8_t *)malloc(sizeof(uint8_t)*LINE_BUFFER_SIZE); for (i=0; tok_cred[i]; i++) { x = (uint8_t)tok_secret[i]; y = (uint8_t)tok_cred[i]; z = x^y; src_data[i] = z; src_data_n++; } for (i=0; i= check_pub_len) { return -3; } if ( (*p) != check_pub[pub_tok_read_len] ) { return -4; } pub_tok_read_len++; } } enc_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE); dec_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE); plain_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE); for (n=0, p = (stop_tok+1); (*p) && ((*p) != '$'); p++, n++) { enc_str[n] = *p; } enc_str[n] = '\0'; Base64decode(dec_str, enc_str); for (i=0; dec_str[i]; i++) { if (tok_secret[i]==0) { return -5; } x = (uint8_t)dec_str[i]; y = (uint8_t)tok_secret[i]; z = (x^y); plain_str[i] = (char)z; } plain_str[i]='\0'; printf("%s\n", plain_str); if (dst_cred) { for (i=0; dec_str[i]; i++) { dst_cred[i] = dec_str[i]; } dst_cred[i] = '\0'; } free(enc_str); free(dec_str); free(plain_str); return 0; } // return negative on error or not found // 0 on success (found) // int fareqr_lookup_seed_secret(char *seedfn, char *pub, char *priv) { int i; FILE *fp; char buf[LINE_BUFFER_SIZE] = {0}; int pos = 0, ch=0, line_no=0, src_n; char *p = NULL; char *tok0_ptr=NULL, *tok1_ptr=NULL; uint8_t z; fp = fopen(seedfn, "r"); if (!fp) { perror(seedfn); return -2;} while (!feof(fp)) { ch = fgetc(fp); // process line if we reach a newline or eof // if (feof(fp) || (ch == '\n')) { // if the line is empty or a comment, skip // if ((pos==0) || (buf[0] == '#')) { } // get tokens out of line, using ' ' as the // delimeter // else { tok0_ptr = buf; tok1_ptr = strchr(buf, ' '); if (tok1_ptr) { *tok1_ptr = '\0'; tok1_ptr++; // Cechk it against our supplied 'pulbic' key // if (strcmp(pub, tok0_ptr)==0) { // If we've found it, copy it over to the `priv` // above and return // for (i=0; tok1_ptr[i]; i++) { priv[i] = tok1_ptr[i]; } priv[i]='\0'; return 0; } } line_no++; } pos=0; buf[0]='\0'; continue; } buf[pos] = ch; pos++; buf[pos] = '\0'; } fclose(fp); return -1; } // to compile: // gcc -D__FAREQR_MAIN__ fareqr.c b64.c -o fareqr // #ifdef __FAREQR_MAIN__ void show_help(FILE *ofp) { fprintf(ofp, "\nusage:\n\n"); fprintf(ofp, " fareqr encode \n"); fprintf(ofp, " fareqr decode \n"); fprintf(ofp, " fareqr dbdecode \n"); fprintf(ofp, " fareqr help\n"); fprintf(ofp, "\n"); fprintf(ofp, "fareqr is a program to help with encoding and decoding 'fareqr' strings.\n"); fprintf(ofp, "\n"); fprintf(ofp, "A fareqr string is of the form:\n"); fprintf(ofp, "\n"); fprintf(ofp, " @%%$\n"); fprintf(ofp, "\n"); fprintf(ofp, "Where `` is the base64 encoded XOR of the private key\n"); fprintf(ofp, "and the credential to be presented. The reasoning behind the XOR is to not allow a\n"); fprintf(ofp, "snooper to get credential information if exposed to the string and the base64\n"); fprintf(ofp, "encoding is to make it easily transportable.\n"); fprintf(ofp, "\n"); fprintf(ofp, "The is a text file of pairs.\n"); fprintf(ofp, "\n"); fprintf(ofp, "Here is some example usage:\n"); fprintf(ofp, "\n"); fprintf(ofp, " $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?'\n"); fprintf(ofp, " @wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=\n"); fprintf(ofp, " $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'\n"); fprintf(ofp, " ;123456789060535?\n"); fprintf(ofp, " $ echo 'wu9XouSh ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' > ./qr.seed\n"); fprintf(ofp, " $ fareqr dbdecode ./qr.seed 'wu9XouSh' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'\n"); fprintf(ofp, " ;123456789060535?\n"); fprintf(ofp, "\n"); fprintf(ofp, "Where 'wu9XouSh' is the public key, 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' is the private key and\n"); fprintf(ofp, "';123456789060535?' is the credential information to be encoded.\n"); fprintf(ofp, "\n"); fprintf(ofp, "\n"); fflush(ofp); } /* * * quick test/start: * * $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?' * @wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4= * * $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$' * ;123456789060535? * * $ fareqr dbdecode 'wu9XouSh' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$' * ;123456789060535? * */ int main(int argc, char **argv) { int i, r; char *tok_public = NULL, *tok_secret = NULL, *tok_cred = NULL, *fareqr_str = NULL; uint8_t x,y,z; uint8_t *src_data = NULL, *dst_data = NULL; int src_data_n = 0, dst_data_n = 0; char *fn = NULL; if (argc <= 1) { show_help(stderr); exit(1); } if (strcmp(argv[1], "encode")==0) { if (argc>2) { tok_public = strdup(argv[2]); if (argc>3) { tok_secret = strdup(argv[3]); if (argc>4) { tok_cred = strdup(argv[4]); } } } if ((!tok_public) || (!tok_secret) || (!tok_cred)) { show_help(stderr); if (tok_public) { free(tok_public); } if (tok_secret) { free(tok_secret); } if (tok_cred) { free(tok_cred); } exit(2); } fareqr_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE); r = fareqr_encode(tok_public, tok_secret, tok_cred, fareqr_str); if (r==0) { printf("%s\n", fareqr_str); } } else if (strcmp(argv[1], "decode")==0) { if (argc>2) { tok_secret = strdup(argv[2]); if (argc>3) { fareqr_str = strdup(argv[3]); } } r = fareqr_decode(fareqr_str, tok_public, tok_secret, NULL); if (r<0) { fprintf(stderr, "error, failed to decode qr fare string (%i)\n", r); } } else if (strcmp(argv[1], "dbdecode")==0) { if (argc>2) { fn = strdup(argv[2]); if (argc>3) { tok_public = strdup(argv[3]); if (argc>4) { fareqr_str = strdup(argv[4]); } } } tok_secret = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE); tok_secret[0] = '\0'; r = fareqr_lookup_seed_secret(fn, tok_public, tok_secret); if (r<0) { fprintf(stderr, "could not find '%s' in db '%s', exiting (got %i)\n", tok_public, fn, r); } else { r = fareqr_decode(fareqr_str, tok_public, tok_secret, NULL); if (r<0) { fprintf(stderr, "error, failed to decode qr fare string (%i)\n", r); } } } else if (strcmp(argv[1], "help")==0) { show_help(stdout); exit(0); } else { fprintf(stderr, "unknown operation '%s'\n", argv[1]); show_help(stderr); exit(3); } if (tok_public) { free(tok_public); } if (tok_secret) { free(tok_secret); } if (tok_cred) { free(tok_cred); } if (fareqr_str) { free(fareqr_str); } if (src_data) { free(src_data); } if (dst_data) { free(dst_data); } if (fn) { free(fn); } } #endif