Verifying Schnorr Signatures in ErgoScript

The problem with verifying signatures on-chain is that there is only 256-bits big integer data type.

Thus better to reduce number of bigints used by using simpler textbook version of Schnorr validation (message details missed):

{
    val message = ...
    // Computing challenge
    // a of signature in (a, z)
    val a = getVar[GroupElement](1).get
    val aBytes = a.getEncoded

    val holderBytes = holder.getEncoded

    val e: Coll[Byte] = blake2b256(aBytes ++ message ++ holderBytes) // strong Fiat-Shamir
    val eInt = byteArrayToBigInt(e) // challenge as big integer
         

     // z of signature in (a, z)
     val zBytes = getVar[Coll[Byte]](2).get
     val z = byteArrayToBigInt(zBytes)

     // Signature is valid if g^z = a * x^e
     val properSignature = g.exp(z) == a.multiply(holder.exp(eInt))
    
     sigmaProp(properSignature)
}

and then in offchain code we need to be sure that z big integer fits into 255 bits. The following code is simply iterating over signatures while one which can be provided used on the blockchain

  def randBigInt: BigInt = {
    val random = new SecureRandom()
    val values = new Array[Byte](32)
    random.nextBytes(values)
    BigInt(values).mod(SecP256K1.q)
  }

  @tailrec
  def sign(msg: Array[Byte], secretKey: BigInt): (GroupElement, BigInt) = {
    val g: GroupElement = CryptoConstants.dlogGroup.generator

    val pk = g.exp(secretKey.bigInteger)

    val r = randBigInt
    val a: GroupElement = g.exp(r.bigInteger)
    val e = scorex.crypto.hash.Blake2b256(a.getEncoded.toArray ++ msg ++ pk.getEncoded.toArray)
    val z = (r + secretKey * BigInt(e)) % CryptoConstants.groupOrder

    if(z.bitLength <= 255) {
      (a, z)
    } else {
      sign(msg,secretKey)
    }
  }

Examples on building transactions can be found in ChainCash repository, e.g. this test https://github.com/kushti/chaincash/blob/master/src/test/scala/kiosk/ChainCashSpec.scala

**Note, that previously insecure variant was published! Fixed now. Thanks dusek for reporting! **

3 Likes