diff --git a/coins/monero/src/wallet/send/mod.rs b/coins/monero/src/wallet/send/mod.rs
index 531ea529..45f57123 100644
--- a/coins/monero/src/wallet/send/mod.rs
+++ b/coins/monero/src/wallet/send/mod.rs
@@ -87,6 +87,8 @@ pub enum TransactionError {
   NotEnoughFunds(u64, u64),
   #[error("invalid address")]
   InvalidAddress,
+  #[error("wrong spend private key")]
+  WrongPrivateKey,
   #[error("rpc error ({0})")]
   RpcError(RpcError),
   #[error("clsag error ({0})")]
@@ -282,7 +284,12 @@ impl SignableTransaction {
   ) -> Result<Transaction, TransactionError> {
     let mut images = Vec::with_capacity(self.inputs.len());
     for input in &self.inputs {
-      images.push(generate_key_image(&(spend + input.key_offset)));
+      let offset = spend + input.key_offset;
+      if (&offset * &ED25519_BASEPOINT_TABLE) != input.key {
+        Err(TransactionError::WrongPrivateKey)?;
+      }
+
+      images.push(generate_key_image(&offset));
     }
     images.sort_by(key_image_sort);
 
diff --git a/coins/monero/src/wallet/send/multisig.rs b/coins/monero/src/wallet/send/multisig.rs
index 02c3e4ff..18dba94b 100644
--- a/coins/monero/src/wallet/send/multisig.rs
+++ b/coins/monero/src/wallet/send/multisig.rs
@@ -83,6 +83,31 @@ impl SignableTransaction {
     }
     transcript.append_message(b"change", &self.change.as_bytes());
 
+    // Sort included before cloning it around
+    included.sort_unstable();
+
+    for (i, input) in self.inputs.iter().enumerate() {
+      // Check this the right set of keys
+      let offset = keys.offset(dalek_ff_group::Scalar(input.key_offset));
+      if offset.group_key().0 != input.key {
+        Err(TransactionError::WrongPrivateKey)?;
+      }
+
+      clsags.push(
+        AlgorithmMachine::new(
+          ClsagMultisig::new(
+            transcript.clone(),
+            inputs[i].clone()
+          ).map_err(|e| TransactionError::MultisigError(e))?,
+          Arc::new(offset),
+          &included
+        ).map_err(|e| TransactionError::FrostError(e))?
+      );
+    }
+
+    // Verify these outputs by a dummy prep
+    self.prepare_outputs(rng, [0; 32])?;
+
     // Select decoys
     // Ideally, this would be done post entropy, instead of now, yet doing so would require sign
     // to be async which isn't preferable. This should be suitably competent though
@@ -97,25 +122,6 @@ impl SignableTransaction {
       &self.inputs
     ).await.map_err(|e| TransactionError::RpcError(e))?;
 
-    // Sort included before cloning it around
-    included.sort_unstable();
-
-    for (i, input) in self.inputs.iter().enumerate() {
-      clsags.push(
-        AlgorithmMachine::new(
-          ClsagMultisig::new(
-            transcript.clone(),
-            inputs[i].clone()
-          ).map_err(|e| TransactionError::MultisigError(e))?,
-          Arc::new(keys.offset(dalek_ff_group::Scalar(input.key_offset))),
-          &included
-        ).map_err(|e| TransactionError::FrostError(e))?
-      );
-    }
-
-    // Verify these outputs by a dummy prep
-    self.prepare_outputs(rng, [0; 32])?;
-
     Ok(TransactionMachine {
       signable: self,
       i: keys.params().i(),