-
Notifications
You must be signed in to change notification settings - Fork 1k
Adds message signing to wallet #4286
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
base: master
Are you sure you want to change the base?
Changes from all commits
6297300
642cc9e
3bca0e3
599ce81
7ccfbbf
211b2b1
bdc9a28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |
|
|
||
| using Akka.Actor; | ||
| using Neo.ConsoleService; | ||
| using Neo.Cryptography; | ||
| using Neo.Extensions; | ||
| using Neo.Json; | ||
| using Neo.Network.P2P.Payloads; | ||
|
|
@@ -27,9 +28,11 @@ | |
| using System.Linq; | ||
| using System.Numerics; | ||
| using System.Security.Cryptography; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
| using static Neo.SmartContract.Helper; | ||
| using ECPoint = Neo.Cryptography.ECC.ECPoint; | ||
| using ECCurve = Neo.Cryptography.ECC.ECCurve; | ||
|
|
||
| namespace Neo.CLI | ||
| { | ||
|
|
@@ -475,8 +478,8 @@ private void OnListKeyCommand() | |
| /// <summary> | ||
| /// Process "sign" command | ||
| /// </summary> | ||
| /// <param name="jsonObjectToSign">Json object to sign</param> | ||
| [ConsoleCommand("sign", Category = "Wallet Commands")] | ||
| /// <param name="jsonObjectToSign">The json string that records the transaction information</param> | ||
| [ConsoleCommand("sign tx", Category = "Wallet Commands")] | ||
| private void OnSignCommand(JObject jsonObjectToSign) | ||
| { | ||
| if (NoWallet()) return; | ||
|
|
@@ -508,6 +511,73 @@ private void OnSignCommand(JObject jsonObjectToSign) | |
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Process "sign message" command | ||
| /// </summary> | ||
| /// <param name="message">Message to sign</param> | ||
| [ConsoleCommand("sign message", Category = "Wallet Commands")] | ||
| private void OnSignMessageCommand(string message) | ||
| { | ||
| if (NoWallet()) return; | ||
|
|
||
| string password = ConsoleHelper.ReadUserInput("password", true); | ||
| if (password.Length == 0) | ||
| { | ||
| ConsoleHelper.Info("Cancelled"); | ||
| return; | ||
| } | ||
| if (!CurrentWallet!.VerifyPassword(password)) | ||
| { | ||
| ConsoleHelper.Error("Incorrect password"); | ||
| return; | ||
| } | ||
|
|
||
| var saltBytes = new byte[16]; | ||
| RandomNumberGenerator.Fill(saltBytes); | ||
| var saltHex = saltBytes.ToHexString().ToLowerInvariant(); | ||
|
|
||
| var paramBytes = Encoding.UTF8.GetBytes(saltHex + message); | ||
|
|
||
| byte[] payload; | ||
| using (var ms = new MemoryStream()) | ||
| using (var w = new BinaryWriter(ms, Encoding.UTF8, true)) | ||
| { | ||
| // We add these 4 bytes to prevent the signature from being a valid transaction | ||
| w.Write((byte)0x01); | ||
| w.Write((byte)0x00); | ||
| w.Write((byte)0x01); | ||
| w.Write((byte)0xF0); | ||
| // Write the actual message to sign | ||
| w.WriteVarBytes(paramBytes); | ||
| // We add these 2 bytes to prevent the signature from being a valid transaction | ||
| w.Write((ushort)0); | ||
| w.Flush(); | ||
| payload = ms.ToArray(); | ||
| } | ||
|
|
||
| ConsoleHelper.Info("Signed Payload: ", $"{Environment.NewLine}{payload.ToHexString()}"); | ||
| Console.WriteLine(); | ||
| ConsoleHelper.Info(" Curve: ", "secp256r1"); | ||
| ConsoleHelper.Info("Algorithm: ", "010001f0 + VarBytes(Salt + Message) + 0000"); | ||
| ConsoleHelper.Info(" ", "See the online documentation for details on how to verify this signature."); | ||
| ConsoleHelper.Info(" ", "https://developers.neo.org/docs/n3/node/cli/cli#sign_message"); | ||
| Console.WriteLine(); | ||
| ConsoleHelper.Info("Generated signatures:"); | ||
| Console.WriteLine(); | ||
|
|
||
| foreach (WalletAccount account in CurrentWallet.GetAccounts().Where(p => p.HasKey)) | ||
| { | ||
| var key = account.GetKey(); | ||
| var signature = Crypto.Sign(payload, key.PrivateKey, ECCurve.Secp256r1); | ||
|
|
||
| ConsoleHelper.Info(" Address: ", account.Address); | ||
| ConsoleHelper.Info(" PublicKey: ", key.PublicKey.EncodePoint(true).ToHexString()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we dont really support secp256k1, the key you get is still p-256 pubkey.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I think I saw in the code for Do you want me tor remove the option to select curve and only use
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a structured format that specifies the address, public key, and algorithm for signing. This also facilitates verification.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some questions:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean we need to define an output format including address, public key, and algorithm of the signature.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Latest commit includes the algorithm and curve used + some helpful text and link to documentation on how to verify the generated signatures. @erikzhang, is this what you wanted? Or did you want a stuctured format in terms of JSON or YAML? Or did you want us to define a standard for the padding and salting?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want a standard with json format please.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @erikzhang I made a draft: neo-project/proposals#210 |
||
| ConsoleHelper.Info(" Signature: ", signature.ToHexString()); | ||
| ConsoleHelper.Info(" Salt: ", saltHex); | ||
| Console.WriteLine(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Process "send" command | ||
| /// </summary> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to follow something like the https://www.cyfrin.io/blog/understanding-ethereum-signature-standards-eip-191-eip-712, domain separator it's important to avoid signature replays between different chains, like testnet and mainnet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neo/src/Neo/Network/P2P/Helper.cs
Lines 71 to 88 in ac7ebab
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adrian-fjellberg we should call this method, let me add some changes. Also this PR should be moved now to https://github.com/neo-project/neo-node