usetech-llc / polkadot_api_dotnet

C# API for Polkadot
Apache License 2.0
33 stars 18 forks source link

Key Derivation for Public Keys #9

Open darkfriend77 opened 4 years ago

darkfriend77 commented 4 years ago

I was looking for way to derivate public keys from private keys.

Like the implementation .... in the sr25519 binding, GenerateKeypairFromSeed()

Is there something like that, I haven't found an functionality for derivation.

usetech-llc commented 4 years ago

That is correct, so far, there is no way to generate keys using this .NET library. We are using a modified version of subkey that will output the private key in 64-byte format. Here is how you can get the keys:

$ git clone github.com:usetech-llc/substrate.git
$ cd bin/utils/subkey
$ cargo build
$ cargo run -- generate
    Finished dev [unoptimized + debuginfo] target(s) in 0.78s
     Running `/home/greg/Development/src/polkadot/substrate_ut/target/debug/subkey generate`
Secret phrase `maple rather inject cage food unable enter economy adapt mandate novel start` is account:
  Network ID/version: substrate
  Secret seed:        0xce456c3f305bf2c31868b1f51eb297e8b304551f1e456758cfa555d0040b31f7
  64-byte secret:     0x1B04EA5667F6D63B7D405503651F56129B64ED148336F35EECCA53716B872B0B542E9D846415B636BB1741C22C8BCA827CEF9D170B9E671E36B60345D18B3894
  Public key (hex):   0xa805c199eaa3d4d3f0865691e94b3ce4a508ee68aef6d7b42642d0d5d389667d
  Account ID:         0xa805c199eaa3d4d3f0865691e94b3ce4a508ee68aef6d7b42642d0d5d389667d
  SS58 Address:       5Fs1cSCX2ZDvtfC6wvrWWFoQDRdcESLuoTyYofdE1AM7LVhD
stiiifff commented 4 years ago

I've stumbled on the issue that the Signer requires the 512-bit secret key, while most other libs and tools expose & use the 256-bit (aka MiniSecretKey) one. I've asked the question on Substrate Technical, and Jeff Burdges (from W3F) confirmed either can be used (the 512-bit secret key can be expanded from 256-bit one, see here).

Just for me to understand, what's the blocker for having an API equivalent to GenerateKeypairFromSeed ?

darkfriend77 commented 4 years ago

The Schnorrkel implementation is missing a few features to create keypairs.

  1. seed expanding to key & nonce
  2. create public key over the ristretto table and multiply
  3. compress ristretto to public key bytes

something like that should be enough to create the keypairs. It's not much missing, here is my first try https://github.com/darkfriend77/SubstrateNetApi/commit/ef7e066dc99463f1f7d0d17ed0d538e803cc34a9

stiiifff commented 4 years ago

Why not use the sr25519-dotnet lib ?

darkfriend77 commented 4 years ago

Hmm, I thought it will break the Unity3D compatibility, which is focused from our project, but I will give it a try to check this.

stiiifff commented 4 years ago

@darkfriend77 I just pushed some code over here : https://github.com/stiiifff/substrate-enterprise-sample-app/blob/de46e463335eb9fab22f32970e78da57bbeeb2f8/Parity.Substrate.EnterpriseSample/Services/AccountService.cs#L16

I can generate a mnemonic with the dotnetstandard-bip39 nuget, derive entropy & seed from the mnemonic, then create a keypair with the sr25519 dotnet lib. I will push a PR to the sr25519 dotnet lib to make it .net standard 2.1 compatible.

What you need to do manually for now is to build a native lib for https://github.com/Warchant/sr25519-crust. Just clone the repo, and build on your platform, then include the lib along the sr25519 dotnet lib (I've tested it on Mac, x86_64 & arm64 android).

I will try to find the time to package & publish a proper Nuget for sr25519 dotnet lib including the native libs for various platforms (/cc @gautamdhameja). That should be good enough for now.

darkfriend77 commented 4 years ago

I tested it in Unity3D and it seems to be fine, the only test that I need to do is that the signature can be verified by substrate to ... and of course we need more exposure, I added verify and sign byte[] message straight, currently only string is supported. mnemonic which match substrate would be super cool. Please use Standard 2.0 as 2.1 isn't supported in Unity3D so far. If 2.1 is need for Span and stuff like that I think ther eis a backported System.Memory package.

mnemonic image

I will try to replace Schnorrkel by sr25519 dotnet lib and see if it will break tests.

darkfriend77 commented 4 years ago

@stiiifff It seems that the implementation sr25519 dotnet lib doesn't match the implementation which currently substrate is using that's probablly why there is an individual Schnorrkel implementaition, it's the version v0.11 corresponding to https://github.com/usetech-llc/polkadot_api_dotnet/blob/master/Schnorrkel/Sr25519v011.cs which it can verify.

We would need the version https://github.com/usetech-llc/polkadot_api_dotnet/blob/master/Schnorrkel/Sr25519v091.cs which is currently what can verify and sign messages with substrate.

stiiifff commented 4 years ago

@darkfriend77 I opened a PR https://github.com/gautamdhameja/sr25519-dotnet/pull/1. Please try with one of the native lib, I've built them from the latest master branch of the C bindings (https://github.com/Warchant/sr25519-crust) which is compatible with Schnorrkel v0.9.1.

gregzaitsev commented 4 years ago

Yes, the API's sr25519 is a bit behind. BTW, we are planning to bring it up to date in about the middle of October. Does that change things for you?

darkfriend77 commented 4 years ago

@stiiifff I used your branch PR (https://github.com/stiiifff/sr25519-dotnet/tree/netstd-2_1) branch and now it doesn't verify any of the signatures ... sr25519-crust seems to be on 0.85 ??

negative outcome

            var simpleSign = Sr25519v011.SignSimple(pubKey, secKey, message);
            Assert.True(Sr25519v011.Verify(simpleSign, pubKey, message));
            Assert.True(sr25519_dotnet.lib.SR25519.Verify(message, simpleSign, pubKey)); <-- fails

negative outcome

            var signedByAlic3 = Utils.HexToByteArray("0xa63c26a956af0218f800f0f0cf119f56139c824967b4e9f84ee3aa1d0c206a3eff7572a036568f89d8406df259c2bb93875725d284fb76187c8bb5fe0246cb8f");
            Assert.True(Sr25519v091.Verify(signedByAlic3, publicKey, messag2));
            Assert.True(sr25519_dotnet.lib.SR25519.Verify(messag2, signedByAlic3, publicKey)); <-- fails

@gregzaitsev We currently have no dependency as we have implemented ed25519 keypair generation to workaround this issue. I started a chat with you on riot, maybe we can elaborate the next steps together?

darkfriend77 commented 4 years ago

marked test fails ... but is fine with substrate

image

stiiifff commented 4 years ago

@stiiifff I used your branch PR (https://github.com/stiiifff/sr25519-dotnet/tree/netstd-2_1) branch and now it doesn't verify any of the signatures ... sr25519-crust seems to be on 0.85 ??

As mentioned in the PR, I built the libs from the current master which references v0.9.1 of Schnorrkel. Everything looks OK to me on that front.

stiiifff commented 4 years ago

@darkfriend77 OK, I found an issue in the sr25519-dotnet lib: https://github.com/gautamdhameja/sr25519-dotnet/blob/259d403cee7d08b7da764246c49bcbbf1e9af9c4/sr25519-dotnet.lib/SR25519.cs#L119. If you pass a string with chars that are not valid UTF8 characters, this is gonna mess the whole thing. This is obviously not the case when signing extrinsic ... I will fix it to accept an hexadecimal string and process it differently.

farukterzioglu commented 3 years ago

I wrote an hd wallet for polkadot, but I am not sure about my approach. This issue is also related to that and can you kindly check it out at #11