How to verify signed data?

I’m having some trouble to understand how am I supposed to verify if a signed data was really signed by a specific address.

Checking this CBOR

845846A201276761646472657373583900E922E8166852073D6C1C9BE0736530404C9C26D9BA1773E11D32D11C0F7B2C7F8924528D797A8F86D8210D6276E09F47B82ECD53A24900E7A166686173686564F44B68656C6C6F20776F726C645840D1FCCD8B340A46FD9573FE6A0F6BFC8373562019E9FCD8BDFD7A7D08A89FE98BF28E6736BAE823C024C7B20081C6D30FC4676D2A314299F22CB0264EE7E6AB04

That I got from signing a “hello world” message payload:

[h'A201276761646472657373583900E922E8166852073D6C1C9BE0736530404C9C26D9BA1773E11D32D11C0F7B2C7F8924528D797A8F86D8210D6276E09F47B82ECD53A24900E7', {"hashed": false}, h'68656C6C6F20776F726C64', h'D1FCCD8B340A46FD9573FE6A0F6BFC8373562019E9FCD8BDFD7A7D08A89FE98BF28E6736BAE823C024C7B20081C6D30FC4676D2A314299F22CB0264EE7E6AB04']

I see that I have the address in the headers and I also have the ed25519 signature, but I’m not sure how am I supposed to determine the public key for this and I obviously don’t have access to the secret at that point. I was trying something like:

import { eddsa } from "elliptic";

const EdDSA = new eddsa("ed25519");

const key = EdDSA.keyFromPublic(
    ? // what do I put here? Is there a way I can get the public key from the address hex?
);

const verifies = key.verify(
  "hello world",
  "D1FCCD8B340A46FD9573FE6A0F6BFC8373562019E9FCD8BDFD7A7D08A89FE98BF28E6736BAE823C024C7B20081C6D30FC4676D2A314299F22CB0264EE7E6AB04"
);

console.log("Valid:", verifies);

Thanks in advance for your time!

I don’t think you can get the public key from the address. The address just contains a hash of the public key, not the key itself. For transactions, the key is sent in the witness set, not in the transaction body itself.

I don’t know what the design rationale is for that, but it is that way. So, you’d request the public key from whoever signed it and not only verify the signature, but also check that the hash of that public key fits with the public key hash in the address.

Also: If I read the CDDL at https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl correctly, messages in transactions are not signed directly, but rather a hash of all the auxiliary data is put in the transaction body, which is then signed by the witnesses.

Have you tried cardano-cli transaction view?

Note: this won’t help you with JavaScript but the output will aid debugging and looking at the implementation will show pretty printing and decoding not only of CBOR but also BECH32 etc

I think I wasn’t that clear and I may have put the wrong category in this topic. This is not related to transactions, but more related to CIP-0008

I’m not looking into submitting or verifying transactions, I just want to check if a message was really signed by a specific user.

For example, in Nami wallet, you would use the signData function from the dApp connector. After you do that, you get the signed message with the signature and I send that to my back end. But after it gets there, how can I verify that the message was really signed by the address X? If I don’t verify that I would allow any user to send a message in name of any wallet address they want

Still the same applies:

Awfully written CIP, but I think the relevant part is:
https://github.com/cardano-foundation/CIPs/blob/master/CIP-0008/README.md#signing-and-verification-process
“to specify which public key was used to sign, use the cwt protected header.”

Is someone really using this CIP? Can you look at examples, how they put the public keys into real-world uses of that?