Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web3/schnorrkel failed to verify ext_sr_sign generated signatures #256

Closed
EclesioMeloJunior opened this issue Dec 29, 2021 · 6 comments
Closed

Comments

@EclesioMeloJunior
Copy link

Description

Hello! I'm trying to use the repository https://github.com/w3f/schnorrkel, more specifically the function verify_simple to verify signatures generated by polkadot-js using thesignRaw function and unforunately it's not working. However the function signatureVerify from @polkadot/util-crypto verify correctly the same signature.

Steps to reproduce

  1. I've used the polkadot extension and the polkadot-js to generate the signature
scren-record.mov
output at console.log 

Public Key (hex) 0xf84d048da2ddae2d9d8fd6763f469566e8817a26114f39408de15547f6d47805
Message => message to sign
Signature (hex) 0x48ce2c90e08651adfc8ecef84e916f6d1bb51ebebd16150ee12df247841a5437951ea0f9d632ca165e6ab391532e75e701be6a1caa88c8a6bcca3511f55b4183
  1. With the https://github.com/w3f/schnorrkel cloned at my machine I created the following test case (which fails) at src/sign.rs file:
#[test]
fn verify_polkadot_js_signature() {
      use hex_literal::hex;
      const CTX : &'static [u8] = b"substrate";
        
      let message = b"message to sign";
      let public = hex!("f84d048da2ddae2d9d8fd6763f469566e8817a26114f39408de15547f6d47805");
      let public = PublicKey::from_bytes(&public[..]).unwrap();
        
      let signature = hex!("48ce2c90e08651adfc8ecef84e916f6d1bb51ebebd16150ee12df247841a5437951ea0f9d632ca165e6ab391532e75e701be6a1caa88c8a6bcca3511f55b4183");
      let signature = Signature::from_bytes(&signature).unwrap();
        
      let ok = public.verify_simple(CTX, message, &signature).is_ok();
      assert!(ok)
}

Debugging the polkadot-js signatureVerify function I noticed that this function calls the rust function ext_sr_verify under the hoods by a WASM biding (very interestingly 😄 ) and the rust function uses the same w3f/schnorrkel repository, then I assumed the function ext_sr_sign is used to generate the signature so I decided to create the following test case that uses these 2 functions to generate and verify a signature:

    #[test]
fn sign_and_verify() {
        const CTX : &'static [u8] = b"substrate";
        let sec = SecretKey::generate();
        let pub_bytes = sec.to_public().to_bytes();
        
        // ext_sr_sign function
        let sig = match (SecretKey::from_ed25519_bytes(&sec.to_bytes()), PublicKey::from_bytes(&pub_bytes)) {
            (Ok(s), Ok(k)) => s
                .sign_simple(CTX, message, &k)
                .to_bytes()
                .to_vec(),
            _ => panic!("Invalid secret or pubkey provided.")
        };

        // ext_sr_verify function
        let res =   match (Signature::from_bytes(&sig), PublicKey::from_bytes(&pub_bytes)) {
            (Ok(s), Ok(k)) => k
                .verify_simple(CTX, message, &s)
                .is_ok(),
            _ => false
        };

        assert!(res)
}

And unfortunately, this test case fails. The same thing happens with the https://github.com/ChainSafe/go-schnorrkel package, the original issue was reported into Gossamer discord channel.

Thanks in advance!

@EclesioMeloJunior
Copy link
Author

Moving the issue to w3f/schnorrkel#77

@jacogr
Copy link
Member

jacogr commented Dec 29, 2021

From the extension the data is actually wrapped in a wrapper before signing. It is not signed as-is passed in. (This is to ensure users cannot be duped I to signing transactions with the raw sign functionality)

The data is passed to wrapBytes before being signed - https://github.com/polkadot-js/common/blob/master/packages/util/src/u8a/wrap.ts

@burdges
Copy link

burdges commented Dec 29, 2021

Also derivation path maybe?

@jacogr
Copy link
Member

jacogr commented Dec 29, 2021

Here is your test data adapted to use the signature supplied by the extension -

https://github.com/polkadot-js/wasm/pull/257/files#diff-adf4dccb86867d4d556199a23c9457df917d84c5dc1d9a9f12dc3a5f31ea4289R251-R259

It is your first test above (same public, same signature), the only change is to adapt the message to b"<Bytes>message to sign</Bytes>" since the signRaw adds that exact wrapping - and obviously, since it is added in this repo, it adapts the wasm-interface-isms exposed, aka the ext_sr_verify handles the signature & public conversions.

It passes -

test sr25519::tests::can_verify_known_wrapped_message ... ok

@EclesioMeloJunior
Copy link
Author

EclesioMeloJunior commented Dec 29, 2021

@jacogr now works using the wrapper! Example using the go-schnorrkel pkg! https://gist.github.com/EclesioMeloJunior/bb1a65e22aa2a4e27263206b42e34c43

@polkadot-js-bot
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue if you think you have a related problem or query.

@polkadot-js polkadot-js locked as resolved and limited conversation to collaborators Jan 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants