Ed25519verify_bare Implementation - General - Algorand
Ed25519verify_bare Implementation
post by pheathwa on Sep 16, 2022
Have implemented a smart signature contract account where funds in the escrow can be pulled by the receiver only if the receiver’s address has been signed by a secret key, yielding a signature, which is then verified against the related public key (embedded in the contract).
Following are the relevant snippets - I’m missing something in the interplay between calling the contract and the ed25519verify_bare TEAL code - any suggestions appreciated
— Public/Secret Key Setup —
const keys = nacl.sign.keyPair();
const publicKeyBytes = keys.publicKey;
const secretKeyBytes = keys.secretKey;
const recipientAddress = "OKKGIO…"; // Valid Account Address
const signature = nacl.sign.detached(Buffer.from(recipientAddress), secretKeyBytes);
const verify = nacl.sign.detached.verify(Buffer.from(recipientAddress), signature, publicKeyBytes);
console.log('verify', verify); // Verified!
– SDK –
const pubKey = Buffer.from(publicKeyBytes).toString("base64");
// NOTE pubKey gets injected into the TEAL as below, pre-compilation
let smartSigArgs = ;
smartSigArgs.push(Buffer.from("rcv"));
smartSigArgs.push(signature); // arg 1 below
const smartSig = new algosdk.LogicSigAccount(compiledCodeBytes, smartSigArgs);
— TEAL —
gtxn 1 AssetReceiver // same as recipientAddress above
arg 1 // Signature
pushbytes b64 ${pubKey}
ed25519verify_bare
bz handle_fail // Always fails
post by fabrice on Sep 16, 2022
Most likely the issue is that OKKGIO… is an encoded address with checksum.
The address stored in AssetReceiver is a 32-byte public key.
To debug smart contracts, I strongly recommend using tealdbg or goal clear dryrun and check that each field matches what you are expecting. Doing so you would see that the message you are signing in the JS is different from the one you are verifying in TEAL.
post by pheathwa on Sep 16, 2022
Yes - that appears to be it. The TEAL is unchanged, but it worked after replacing:
const signature = nacl.sign.detached(Buffer.from(recipientAddress), secretKeyBytes);
with:
const signature = nacl.sign.detached(algosdk.decodeAddress(recipientAddress).publicKey, secretKeyBytes);
So, the lesson is understanding the difference between what is presented as the address vs. what is being processed behind the scenes.
Thanks for the insights!
Paul