Re: Help with hashing and signatures

"Schanzenbach, Martin" <[email protected]> Tue, 4 Aug 2020 16:21:54 +0200
Newsgroups gmane.network.gnunet.general
Message-ID <[email protected]>
Hi Alessio,

it is difficult helping without all of the code.
However, from what you posted is not clear at all where the error could be.
There is not necessarily anything wrong with your use of the crypto.

Questions I would ask are:

- Have you verified that the public key is still the same key in the verification step as it was in the signing step?
- If yes, is the signature the same string that you "sent"?

If any of the above is not true, your (de)serialization functions are buggy (extract_sig/key or the equivalend encoding functions).

BR

> On 4. Aug 2020, at 15:13, Alessio Vanni <[email protected]> wrote:
> 
> Hello,
> 
> I have a function used to sign some data and embed it in a larger
> structure, defined like so:
> 
>     int
>     sign_data(container, public_key, private_key) { ... }
> 
> (the type of the arguments are not included because they are not
> important; the keys are the GNUnet structs used by egos.)
> 
> The function hashes the data inside the container using GNUnet's hashing
> contexts and then signs the hash with the ECDSA signing functions.  The
> problem is that when I do the reverse, i.e. verifying the signature, I'm
> always getting a bad signature error.
> 
> The verify function is defined as:
> 
>     int
>     verify_signature(container) { ... }
> 
> in which `container' contains the signature and the public key of the
> signing entity.
> 
> Both functions hash the data using the following snippet (`msg' is the
> formal name of `container' in the actual function.)
> 
>     #define MAXBYTES 8192
>     struct SignatureData *sd = GNUNET_new(struct SignatureData);
> 
>     size_t segments = (msg->data_size / MAXBYTES) + 1;
>     struct GNUNET_HashContext *hc = GNUNET_CRYPTO_hash_context_start();
> 
>     if (1 == segments) {
> 	  GNUNET_CRYPTO_hash_context_read(hc, msg->data, msg->data_size);
>     } else {
> 	  size_t cursor = 0;
> 	  for (size_t i=0; i<segments; ++i) {
> 	       size_t mult = i * MAXBYTES;
> 	       size_t sz = (msg->data_size - mult > MAXBYTES) ?
> 		    MAXBYTES :
> 		    msg->data_size - mult;
> 
> 	       GNUNET_CRYPTO_hash_context_read(hc, msg->data+cursor, sz);
> 	       cursor += sz;
> 	  }
>     }
> 
>     GNUNET_CRYPTO_hash_context_finish(hc, &sd->hash);
> 
>     sd->purpose.size = htonl(sizeof(struct SignatureData));
>     sd->purpose.purpose = htonl(SIGN_PURPOSE);
> 
> where `struct SignatureData' is defined as such:
> 
>     struct SignatureData {
>          struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
>          struct GNUNET_HashCode hash;
>     };
> 
> After hashing the data, the signing function does this:
> 
>     struct GNUNET_CRYPTO_EcdsaSignature sig;
>     GNUNET_CRYPTO_ecdsa_sign(private_key, sd, &sig);
>     char *sstr = GNUNET_STRINGS_data_to_string_alloc(&sig, sizeof(sig));
> 
> `sstr' is then embedded in the container as explained earlier.
> 
> The verifying function first extracts the public key and the signature
> from the container, like so:
> 
>     struct GNUNET_CRYPTO_EcdsaPublicKey pk;
>     char *pkstr = extract_key(msg);
>     size_t pklen = strlen(pkstr);
>     GNUNET_CRYPTO_ecdsa_public_key_from_string(pkstr, pklen, &pk);
> 
>     struct GNUNET_CRYPTO_EcdsaSignature sig;
>     char *sigstr = extract_sig(msg);
>     size_t siglen = strlen(sigstr);
>     GNUNET_STRINGS_string_to_data(sigstr, siglen, &sig, sizeof(sig));
> 
> After that it hashes the data with the same code as above and then
> executes these statements:
> 
>     if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(SIGN_PURPOSE,
> 						 sd,
> 						 &sig,
> 						 &pk)) {
> 	  ERRLOG(_("Message not verified!\n"));
> 	  GNUNET_free(sd);
> 	  return GNUNET_NO;
>     }
> 
> The error happens here, as I'm always getting the error message and a
> return value of GNUNET_NO.
> 
> I don't really know what I'm doing wrong here and the documentation
> unfortunately isn't helpful at all, as the comments before the
> `GNUNET_CRYPTO_ecdsa_verify' function isn't even about that function
> (they list arguments that the function doesn't use.)  I'd really
> appreciate some guidance here.
> 
> Thank you,
> A.V.
>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEEPREGPBD5jRS9JNFHCwmY74b1m2oFAl8pbwIACgkQCwmY74b1
m2rGtg/+PfKosBGlq1zL4ZR32zTtFlBnykYlLYakSHc4eGzHbi5JfotkBqGq2ENx
U6QiwKWbvkklOPFptEYI1cYN1uOzf0PS8bK/l9IzubztEub1ANqC19AMWPqkvs/j
8cxLkMgP4AcFBceIqYSpOJ0hhr9kIItt6eRZMEiz89KGAI6QgXL8xfTkmtguNx9A
ohsEdMIWmzc+qW+AbeGNsqmsiuDCyuQsxRHZiXaqRLweV7eJFSN7KBMzsAbwzsmk
aDLymn/b0/r49GE3N3OwSEy1R7+sfv6iMGcqlsvwRxWU4vNaT6oE1v0p5mEMDOXd
cGArAR4j0G42bSh9X1dNV/u6+ho8R73c3Kxg2e7fEUAVw4ni+znh2Vakan0JoXoH
flVrOUWPPIFMHcExX3tROr1exWN5c2vD4sLQZAhEHKvmgeGqRVniK76aEDoer22C
6rOwwssgOJ7ZIC71K0rIbj8jagwzqlhuvdeLD8cwT+fkuc7uHtKH89Hh4Ztd/vcZ
XSs7GE8n0Rnb7QBI2fEeV3Kh9JksUeoB09gh3NdRBc60rRxmQI0J0A//ZUaGrKGW
WZI0XRMe7ua87OSSzzFwkX4NEn1osaVR1EcSJjutSadu2IWHreECaL2TJdSuAidt
kbZtSBzwlirPXhnXSe3xM8WAuh6FmrgMwu+2YJBvytD6wQzyfUU=
=tx5N
-----END PGP SIGNATURE-----