Skip to main content

IOTA On-Chain Signatures Verification in Move

Move contracts in IOTA support verifications for several signature schemes on-chain. Not all signatures supported in on-chain verification are supported as user signature verification. See IOTA Signatures for valid signature schemes for transaction authorization.

This topic covers:

  1. How to use fastcrypto's CLI tool to create a signature of a given scheme. For testing and debugging only, DO NOT use in production.
  2. Call the Move method on-chain to verification by submitting the signature, the message and the public key.

Signature schemes covered:

  • Ed25519 signature (64 bytes)
  • Secp256k1 non-recoverable signature (64 bytes)
  • Secp256k1 recoverable signature (65 bytes)
  • Secp256r1 non-recoverable signature (64 bytes)
  • Secp256r1 recoverable signature (65 bytes)
  • BLS G1 signature (minSig setting)
  • BLS G2 signature (minPk setting)

Usage

Set up fastcrypto CLI binary

git clone [email protected]:MystenLabs/fastcrypto.git
cd fastcrypto/
cargo build --bin sigs-cli

Sign with CLI and submit to on-chain Move method

Ed25519 signature (64 bytes)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme ed25519 --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme ed25519 --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the verify method in Move. All inputs are represented in bytes in hex format:
    use iota::ed25519;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
let verify = ed25519::ed25519_verify(&sig, &pk, &msg);
assert!(verify == true, 0);

Secp256k1 non-recoverable signature (64 bytes)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme secp256k1 --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme secp256k1 --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the verify method in Move.
    use iota::ecdsa_k1;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
// The last param 1 represents the hash function used is SHA256, the default hash function used when signing in CLI.
let verify = ecdsa_k1::secp256k1_verify(&sig, &pk, &msg, 1);
assert!(verify == true, 0);

Secp256k1 recoverable signature (65 bytes)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme secp256k1-rec --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme secp256k1-rec --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the ecrecover method in Move and check equality.
    use iota::ecdsa_k1;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
// The last param 1 represents the hash function used is SHA256, the default hash function used when signing in CLI.
let recovered = ecdsa_k1::secp256k1_ecrecover(&sig, &msg, 1);
assert!(pk == recovered, 0);

Secp256r1 non-recoverable signature (64 bytes)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme secp256r1 --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme secp256r1 --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the verify method in Move.
    use iota::ecdsa_r1;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
// The last param 1 represents the hash function used is SHA256, the default hash function used when signing in CLI.
let verify = ecdsa_r1::secp256r1_verify(&sig, &pk, &msg, 1);
assert!(verify == true, 0);

Secp256r1 recoverable signature (65 bytes)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme secp256r1-rec --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme secp256r1-rec --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the ecrecover method in Move and check equality.
    use iota::ecdsa_r1;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
// The last param 1 represents the hash function used is SHA256, the default hash function used when signing in CLI.
let recovered = ecdsa_r1::secp256r1_ecrecover(&sig, &msg, 1);
assert!(pk == recovered, 0);

BLS G1 signature (48 bytes, minSig setting)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme bls12381-minsig --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme bls12381-minsig --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the verify method in Move.
    use iota::bls12381;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
let verified = bls12381::bls12381_min_sig_verify(&sig, &pk, &msg);
assert!(verified == true, 0);

BLS G1 signature (96 bytes, minPk setting)

  1. Generate a key and sign a message.
target/debug/sigs-cli keygen --scheme bls12381-minpk --seed 0000000000000000000000000000000000000000000000000000000000000000                
Private key in hex: $SK
Public key in hex: $PK

target/debug/sigs-cli sign --scheme bls12381-minpk --msg $MSG --secret-key $SK

Signature in hex: $SIG
Public key in hex: $PK
  1. Call the verify method in Move.
    use iota::bls12381;

let msg = x"$MSG";
let pk = x"$PK";
let sig = x"$SIG";
let verified = bls12381::bls12381_min_pk_verify(&sig, &pk, &msg);
assert!(verified == true, 0);

Question 1/2

Which of the following signature schemes cannot be verified on-chain in IOTA's Move contracts?