/*
* 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