kee

Offline IOU signer with QR as transport
git clone https://holbrook.no/src/kee
Info | Log | Files | Refs | README | LICENSE

commit 2cfcda3e0c4556a11918997d81d6ead71adc7aa4
parent 8fd4617d0ee6399ca30e97bc1a73244c87137af4
Author: lash <dev@holbrook.no>
Date:   Wed, 24 Apr 2024 08:46:44 +0100

Complete sign/verify test for ledger and ledger item

Diffstat:
Msrc/gpg.c | 37++++++++++++++++++++++++++++++++-----
Msrc/gpg.h | 1+
Msrc/ledger.c | 14+++++++-------
Msrc/tests/sign.c | 163++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 193 insertions(+), 22 deletions(-)

diff --git a/src/gpg.c b/src/gpg.c @@ -14,6 +14,7 @@ const char *gpgVersion = NULL; +const char sign_test[64]; size_t get_padsize(size_t insize, size_t blocksize) { @@ -275,7 +276,7 @@ static int key_create_file(gcry_sexp_t *key, const char *p, const char *passphra int gpg_key_create(gcry_sexp_t *key) { - const char *sexp_quick = "(genkey(ecc(curve Ed25519)))"; + const char *sexp_quick = "(genkey(ecc(flags eddsa)(curve Ed25519)))"; //char *pv; gcry_sexp_t in; gcry_error_t e; @@ -293,22 +294,48 @@ int gpg_key_create(gcry_sexp_t *key) { return 0; } -static int sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) { +int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) { gcry_error_t e; gcry_sexp_t data; + size_t err_offset; char in[BUFLEN]; - sprintf(in, "(data(flags eddsa(hash-algo sha512(value %s))))", v); - gcry_sexp_new(&data, in, strlen(in), 0); + e = gcry_sexp_build(&data, &err_offset, "(data(flags eddsa)(hash-algo sha512)(value %b))", 64, v); + if (e) { + sprintf(in, "error sign sexp data build: %s\n", gcry_strerror(e)); + debug_log(DEBUG_ERROR, in); + return ERR_KEYFAIL; + } e = gcry_pk_sign(out, data, *key); if (e) { sprintf(in, "error sign: %s\n", gcry_strerror(e)); debug_log(DEBUG_ERROR, in); return ERR_KEYFAIL; } + return 0; } +int gpg_verify(gcry_sexp_t *sig, gcry_sexp_t *key, const char *v) { + gcry_error_t e; + gcry_sexp_t data; + size_t err_offset; + char in[BUFLEN]; + + e = gcry_sexp_build(&data, &err_offset, "(data(flags eddsa)(hash-algo sha512)(value %b))", 64, v); + if (e) { + sprintf(in, "error sign sexp data build: %s\n", gcry_strerror(e)); + debug_log(DEBUG_ERROR, in); + return ERR_KEYFAIL; + } + e = gcry_pk_verify(*sig, data, *key); + if (e != GPG_ERR_NO_ERROR) { + sprintf(in, "error verify: %s\n", gcry_strerror(e)); + debug_log(DEBUG_ERROR, in); + return 1; + } +} + char *gpg_store_get_fingerprint(struct gpg_store *gpg) { return gpg->fingerprint; } @@ -392,6 +419,6 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase) { sprintf(pp, "found key %s in %s", (unsigned char*)gpg->fingerprint, p); debug_log(DEBUG_INFO, pp); } - r = sign(&o, &k, "foo"); + r = gpg_sign(&o, &k, sign_test); return r; } diff --git a/src/gpg.h b/src/gpg.h @@ -88,5 +88,6 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase); int gpg_store_digest(struct gpg_store *gpg, char *out, const char *in); char *gpg_store_get_fingerprint(struct gpg_store *gpg); int gpg_key_create(gcry_sexp_t *key); +int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v); #endif diff --git a/src/ledger.c b/src/ledger.c @@ -78,13 +78,13 @@ static char *get_message(asn1_node item, char *out_digest, char *out_data, size_ printf("%d (%s) %s\n", r, err, asn1_strerror(r)); return NULL; } - - c = 64; - r = asn1_read_value(item, "signatureResponse", sig, (int*)&c); - if (r != ASN1_SUCCESS) { - printf("%d (%s) %s\n", r, err, asn1_strerror(r)); - return NULL; - } +// +// c = 64; +// r = asn1_read_value(item, "signatureResponse", sig, (int*)&c); +// if (r != ASN1_SUCCESS) { +// printf("%d (%s) %s\n", r, err, asn1_strerror(r)); +// return NULL; +// } buf[0] = 0; c = 0; diff --git a/src/tests/sign.c b/src/tests/sign.c @@ -6,24 +6,39 @@ const char *content_test = "Subject: foo\n\nsome content\n"; const char *content_test_item = "Subject: bar\n\nsome other content\n"; -const char *content_test_item_two = "Subject: baz\n\nmore more more content\n"; int main() { int r; + size_t c; gcry_sexp_t alice; + gcry_sexp_t alice_pub; gcry_sexp_t bob; + gcry_sexp_t bob_pub; gcry_sexp_t tmp; + gcry_sexp_t sig; + gcry_sexp_t msg; + gcry_mpi_t sr; + gcry_mpi_t ss; + gcry_error_t err; + char *p; char *out; size_t out_len; char *out_item; size_t out_item_len; struct kee_ledger_t ledger; struct kee_ledger_item_t item; - struct kee_ledger_item_t item_two; + struct kee_ledger_item_t *item_parsed; struct kee_content_t content; struct kee_content_t content_item; - struct kee_content_t content_item_two; char item_sum[64]; + const char *version; + + version = gcry_check_version(NULL); + if (version == 0x0) { + return 1; + } + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); r = gpg_key_create(&alice); if (r) { @@ -83,7 +98,7 @@ int main() { return 1; } - out_len = 4096; + out_len = 1024*1024; out = malloc(out_len); r = kee_ledger_serialize(&ledger, out, &out_len); if (r) { @@ -116,22 +131,150 @@ int main() { return 1; } - free(out); - kee_content_free(&content_item); - kee_content_free(&content); - kee_ledger_free(&ledger); - out_item_len = 4096; - out_item = malloc(out_len); + out_item = malloc(out_item_len); r = kee_ledger_item_serialize(&item, out_item, &out_item_len, KEE_LEDGER_ITEM_SERIALIZE_REQUEST); if (r) { return 1; } + r = calculate_digest_algo(out_item, out_item_len, item_sum, GCRY_MD_SHA512); + if (r) { + return 1; + } + r = gpg_sign(&sig, &bob, item_sum); + if (r) { + return 1; + } + c = 0; + bob_pub = gcry_sexp_find_token(bob, "public-key", 10); + if (bob_pub == NULL) { + return 1; + } + err = gcry_sexp_build(&bob_pub, &c, "(key-data%S)", bob_pub); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + r = gpg_verify(&sig, &bob, item_sum); + if (r) { + return 1; + } + tmp = gcry_sexp_find_token(sig, "r", 1); + if (tmp == NULL) { + return 1; + } + sr = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD); + if (sr == NULL) { + return 1; + } + tmp = gcry_sexp_find_token(sig, "s", 1); + if (tmp == NULL) { + return 1; + } + ss = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD); + if (ss == NULL) { + return 1; + } + c = 0; + err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, sr); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + if (c != 32) { + return 1; + } + memcpy(item.bob_signature, item_sum, 32); + c = 0; + err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, ss); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + if (c != 32) { + return 1; + } + memcpy(item.bob_signature+32, item_sum, 32); + + out_item_len = 4096; + r = kee_ledger_item_serialize(&item, out_item, &out_item_len, KEE_LEDGER_ITEM_SERIALIZE_RESPONSE); + if (r) { + return 1; + } r = calculate_digest_algo(out_item, out_item_len, item_sum, GCRY_MD_SHA512); if (r) { return 1; } + r = gpg_sign(&sig, &alice, item_sum); + if (r) { + return 1; + } + c = 0; + alice_pub = gcry_sexp_find_token(alice, "public-key", 10); + if (alice_pub == NULL) { + return 1; + } + err = gcry_sexp_build(&alice_pub, &c, "(key-data%S)", alice_pub); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + r = gpg_verify(&sig, &alice, item_sum); + if (r) { + return 1; + } + tmp = NULL; + tmp = gcry_sexp_find_token(sig, "r", 1); + if (tmp == NULL) { + return 1; + } + sr = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD); + if (sr == NULL) { + return 1; + } + tmp = NULL; + tmp = gcry_sexp_find_token(sig, "s", 1); + if (tmp == NULL) { + return 1; + } + ss = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD); + if (ss == NULL) { + return 1; + } + c = 0; + err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, sr); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + if (c != 32) { + return 1; + } + memcpy(item.alice_signature, item_sum, 32); + c = 0; + err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, ss); + if (err != GPG_ERR_NO_ERROR) { + return 1; + } + if (c != 32) { + return 1; + } + memcpy(item.alice_signature+32, item_sum, 32); + + out_item_len = 4096; + r = kee_ledger_item_serialize(&item, out_item, &out_item_len, KEE_LEDGER_ITEM_SERIALIZE_FINAL); + if (r) { + return 1; + } + *(out_item+out_item_len) = 1; + + item_parsed = kee_ledger_parse_item(&ledger, out_item, out_item_len + 1); + if (item_parsed == NULL) { + return 1; + } + tmp = NULL; + + free(out_item); + free(out); + kee_content_free(&content_item); + kee_content_free(&content); + kee_ledger_free(&ledger); return 0; }