From 556767ad1d958ce0edc06599c230f0556145b6e8 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 13 Feb 2025 11:42:52 +0000 Subject: [PATCH] feat: add signature validity checks --- src/app/components/transaction.tsx | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/app/components/transaction.tsx b/src/app/components/transaction.tsx index c59e72b..b56d285 100644 --- a/src/app/components/transaction.tsx +++ b/src/app/components/transaction.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from "react"; import { useWallet } from "@meshsdk/react"; -import { deserializeAddress } from "@meshsdk/core"; +import { deserializeAddress, checkSignature } from "@meshsdk/core"; import { Button, TextField, Box, Typography, Container, Table, TableBody, TableCell, TableContainer, TableRow, Paper, Link } from "@mui/material"; import * as CLS from "@emurgo/cardano-serialization-lib-browser"; import ReactJsonPretty from 'react-json-pretty'; @@ -11,7 +11,6 @@ import { TransactionChecks } from "./validationChecks"; import { decodeHextoTx,convertGAToBech,getCardanoScanURL,getDataHashFromURI} from "../utils/txUtils"; import { VotingDetails } from "./votingDetails"; - export const TransactionButton = () => { const [message, setMessage] = useState(""); const [unsignedTransactionHex, setUnsignedTransactionHex] = useState(""); @@ -134,14 +133,37 @@ export const TransactionButton = () => { }; const signTransaction = async () => { - console.log("isPartOfSigners:", validationState.isPartOfSigners); try { if (validationState.isPartOfSigners) { + // Pass transaction to wallet for signing const signedTx = await wallet.signTx(unsignedTransactionHex, true); - console.log("Transaction signed successfully"); - const signedTransactionObj = decodeHextoTx(signedTx); + const witnessHex = signedTransactionObj?.witness_set().vkeys()?.get(0)?.to_hex() || ''; + const signature = signedTransactionObj?.witness_set().vkeys()?.get(0).signature().to_hex() || ''; + let providedVkey = signedTransactionObj?.witness_set().vkeys()?.get(0).vkey().to_hex() || ''; + + // Remove the (confusing) CBOR header, not sure why mesh adds this + providedVkey = providedVkey.substring(4); + const providedVKeyObj = CLS.PublicKey.from_hex(providedVkey); + + // Check to make sure the wallet produced a signature as expected + + // compare the desired credential with the vKey returned from wallet + const expectedVKeyHash = deserializeAddress(await wallet.getChangeAddress()).stakeCredentialHash; + const providedVKeyHash = providedVKeyObj.hash().to_hex(); + + if (providedVKeyHash != expectedVKeyHash) { + throw new Error("Wallet returned unexpected VKey."); + } + + // Check the produced signature if valid + const txHash = CLS.FixedTransaction.from_hex(unsignedTransactionHex).transaction_hash().to_bytes(); + const validSignature = providedVKeyObj.verify(txHash, CLS.Ed25519Signature.from_hex(signature)); + + if (!validSignature){ + throw new Error("Wallet created an invalid signature."); + } setSignature(witnessHex || ''); console.log("Witness (hex): ", witnessHex);