密码学
Muta 使用 secp256k1 参数以实现椭圆曲线数字签名算法(ECDSA) 的功能
如何生成生成地址
记私钥 pr, 对应地址函数 A(pr),则有:
A(pr) = Bit[12..32)(Keccak(ECDSAPUBKEY(pr)))
Muta 的地址对应成一个 bech32 的地址,生成的过程详细描述为:
- 私钥 -> 公钥:私钥通过 ECDSA 公钥生成算法转换为公钥
- 公钥 -> 哈希:公钥通过 Keccak 函数转换哈希值
- 哈希 -> 地址:截取前 160bit 哈希值
- 椭圆曲线地址 -> bech32 地址: 将椭圆曲线地址按 bech32 中的 base32 重新编码,随后配合 HRP,生成校验位和完整 bech32 地址
如何签名交易
记私钥 pr,待签名消息 x,对应有签名函数 S(x),则有:
S(x) = ECDSASIGN(Keccak(RLP(x)), pr)
由于使用 spec256k1,因此签名对应成一个 512bit 的值,签名过程消息描述为:
- 消息 -> 序列化消息:消息通过 RLP 序列化,消息序列为
- chainID
- cyclesLimit
- cyclesPrice
- nonce
- method
- service
- payload
- timeout
- 序列化消息 -> 哈希:序列化消息通过 Keccak 函数转换哈希值
- 哈希 -> 签名:哈希值通过 ECDSA 签名算法生成签名
下面的例子,将使用伪代码描述签名的过程
import { encode as RLPEncode } from 'rlp';import createKeccakHash from 'keccak'import { sign as ECDSASign } from 'scep256k1';const tx = [chainId, // '0xb6a4d7da21443f5e816e8700eea87610e6d769657d6b8ec73028457bf2ca4036'cyclesLimit, // '0xffff'cyclesPrice, // '0xffff'nonce, // '0x0000000000000000000000000000000000000000000000000000000000000000'method, // 'a_service_method'service, // 'a_service_name'payload, // 'a_method_payload'timeout, // '0xffff' // => current_block_height + timeout_gap - 1];const encodedMessage = RLPEncode(tx);const hash = createKeccakHash('keccak256').update(encodedMessage).digest();const signature = ECDSASign(hash, privateKey);