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