PlatONnetwork/PlatON-Go

Support sha256 to verify ECDSA signature

Closed this issue · 6 comments

  1. A lot of platforms like intel SGX only support sha256 to sign messages.
  2. A lot of blockchain networks only support sha256 to sign messages, even ethereum is moving from Keccak to sha256 for ETH2.0.

The platon_ecrecover of chain_impl.hpp only supports Keccak-256. I think support sha256 is good for developers to build cross chain or cross platform applications.

Changing the underlying algorithm to sha256 is difficult to implement, it involves forking, data migration, etc.
So platon_ecrecover can not change to use sha256.
At the application level, the WASM virtual machine has implemented external function for the sha256 algorithm, code

After some tests, the platon_ecrecover of chain_impl.hpp is support sha256 to recover public key.

let's say we use secp256k1 private key to sign a message.

const Bytes = require("./bytes");
const elliptic = require("elliptic");
const secp256k1 = new elliptic.ec("secp256k1"); 

const encodeSignature = ([v, r, s]) => Bytes.flatten([r, s, v]);

const makeSigner = () => (hash, privateKey) => {
  const signature = secp256k1.keyFromPrivate(new Buffer(privateKey.slice(2), "hex")).sign(new Buffer(hash.slice(2), "hex"), { canonical: true });
  return encodeSignature([signature.recoveryParam == 0 ? "0x00" : "0x01", Bytes.pad(32, Bytes.fromNat("0x" + signature.r.toString(16))), Bytes.pad(32, Bytes.fromNat("0x" + signature.s.toString(16)))]);
};

const sign = makeSigner(); // v=0|1 instead of 27|28...

const text = "Hello World";
const privateKey = "0x4940cf212544505a0fad3e3932734220af101da915321489708f69bc908fda65"; // private key, Testnet only
const hash = "0x" + require("crypto").createHash("sha256").update(text).digest("hex");

var signature = sign(hash, privateKey);
console.log({ text, hash, signature });

Output:

{ text: 'Hello World',
  hash:
   '0xa591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e',
  signature:
  '0x6218ff2883e9ee97e29da6a3d6fe0f59081c2de9143b8dee336059c67fc249d965dbc3e5f6d3f0ae598d6be97c39a7a204d0636e50b0d56677eec7d84267c92801' }

Now, we just need submit text and signature to wasm contract to recover the public key.

byte hashed_value[32];
platon::platon_sha256(asBytes("Hello World"), hashed_value);
Address recovered_address;
auto ret = platon::platon_ecrecover(h256(hashed_value, sizeof(hashed_value)), fromHex("0x6218ff2883e9ee97e29da6a3d6fe0f59081c2de9143b8dee336059c67fc249d965dbc3e5f6d3f0ae598d6be97c39a7a204d0636e50b0d56677eec7d84267c92801"), recovered_address);
DEBUG(ret);
DEBUG(recovered_address.toString());

Output:

0
lat1qavfd7zwaknrxyx0drcmv0vr5zehgthhaqq6ul

The descriptions of platon_ecrecover needs to be updated, not only sha3, but also sha256.

Thank you for your suggestion, can you submit a PR to https://github.com/PlatONnetwork/PlatON-CDT/tree/feature/wasm

Cool! 👍 Thank you very much

close by done