说一下我的尝试经历,想实现的朋友可以参考:
1. PWCore.provider.sign(message);
pw-core可以访问的方法。
可惜,它应该是provider本身的签名。比如,如果是连接的MetaMask钱包,那就是Eth的personal_sign
签名。
2. Eth的personal_sign
的签名逻辑
实现逻辑,涉及下面3个js:
-
ethers.js/message.ts L35:对message进行哈希摘要
export function hashMessage(message: Uint8Array | string): string {
if (typeof(message) === "string") { message = toUtf8Bytes(message); }
return keccak256(concat([
toUtf8Bytes(MessagePrefix),
toUtf8Bytes(String(message.length)),
message
]));
}
-
ethers.js/signing-key.ts L64:实现了私钥的具体签名逻辑
sign(digest: BytesLike): Signature {
assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
const [ sigDer, recid ] = secp256k1.signSync(getBytesCopy(digest), getBytesCopy(this.#privateKey), {
recovered: true,
canonical: true
});
const sig = secp256k1.Signature.fromHex(sigDer);
return Signature.from({
r: toBeHex("0x" + sig.r.toString(16), 32),
s: toBeHex("0x" + sig.s.toString(16), 32),
v: (recid ? 0x1c: 0x1b)
});
}
-
ethers.js/base-wallet.ts L104:
return this.signingKey.sign(hashMessage(message)).serialized;
3. CKB 的签名逻辑
都在 neuron/sign-message.ts 中。
// L86
private static signatureHash(message: string) {
const buffer = Buffer.from(SignMessage.magicString + message, 'utf-8')
const blake2b = new Blake2b()
blake2b.updateBuffer(buffer)
return blake2b.digest()
}
// L41
private static signByPrivateKey(privateKey: string, message: string): string {
const digest = SignMessage.signatureHash(message)
const ecPair = new ECPair(privateKey)
const signature = ecPair.signRecoverable(digest)
return signature
}
4. 测试数据
Eth地址:0x309ddffb87f07afba6b69cfed4bdfaea774f6abb
对应的CKB地址:ckb1qzl58smqy32hnrq6vxjedcxe2fugvnz497h7yvwqvwel40uh4rltcqfsnh0lhpls0ta6dd5ulm2tm7h2wa8k4wcq0va7g
message:hello, world
Eth环境下的MetaMask签名结果:
0x63ca73e288a03befb6cb01a932bd08ff8da621c3365f5daee95abdeebe5258fc67c2d04986c426c305b5d66de3140b47dd3f7785c2fe8f93fb0f315b064d7af91c
pw-core的PWCore.provider.sign(message);结果:
0x63ca73e288a03befb6cb01a932bd08ff8da621c3365f5daee95abdeebe5258fc67c2d04986c426c305b5d66de3140b47dd3f7785c2fe8f93fb0f315b064d7af901
可以看出,eth和pw-core结果基本一样,区别就是最后一个byte。
5. 总结
我暂时没有思路。。。搞不定啊。。。 /(ㄒoㄒ)/~~
借此机会重构了一个工具出来:各个链的签名——就差Nervos了:Wallet Functions - RuneBox
我重新开放了PW的签名,感兴趣的可以自行测试。