Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

keccak256

简介

非对称加密在通讯领域里面有比较普遍的应用场景。这里是个例子做验签的流程。

验签:

私钥持有者将大段文本做摘要,对摘要用私钥签名,生成验签字符串。将大段文本广播给其他人。并且将公钥公布。

其他人拿到大段文本先做摘要,将摘要、验签字符串作为参数调用恢复函数能获得一份公钥信息,将公钥信息和对方的公钥信息对比,就能知道大段文本是否出自私钥持有者。

加密解密:

甲方拿到乙方的公钥对大段文本做加密,并且发送给乙方。

乙方拿到加密后的文本使用自己的私钥对齐解密。

常见的非对称加密算法有两种:RSA、Keccak256。这里就是从调用API级别来说明如何用非对称加密。

web3.0

1
2
3
const sign = this.web3.eth.accounts.sign(message, signInfo.privateKey); // 将消息hash,并且签名出来
const address = this.web3.eth.accounts.recover(message, appAuth.signature); // 将消息hash,并且反解出公钥地址
const hashStr = this.web3.eth.accounts.hashMessage(message); // 将消息hash出来

ethers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Create a new SigningKey for privateKey.
new ethers.utils.SigningKey(privateKey)
// 将明文hash并且签名成
signingKey.signDigest( digest ) ⇒ Signature
// 返回签名消息产生签名的地址。
ethers.utils.verifyMessage( message , signature ) ⇒ string< Address >
// 返回用于对给出签名的摘要进行签名的私钥的未压缩公钥(即第一个字节将是 0x04)。
ethers.utils.recoverPublicKey( digest , signature ) ⇒ string< DataHexString< 65 > >

const hashedTransaction = ethers.utils.keccak256(rawTransaction); // 将交易keccake256 hash
const hashedTransactionBytes = ethers.utils.arrayify(hashedTransaction);
const publicKey: string = ethers.utils.recoverPublicKey(hashedTransactionBytes, signature)

// 这个例子是随机生成地址,私钥,公钥,以及签名,并将签名信息打印出来
const wallet = ethers.Wallet.createRandom();
// // 替换成metadata链接;
// const provider = new ethers.providers.Web3Provider(window.ethereum);
// const signer = provider.getSigner();
// signer.signMessage(message);
const message = 'Hello, world!';
const signature = await wallet.signMessage(message)
const recovered = await ethers.utils.verifyMessage(message, signature);
console.log('address:', wallet.address);
console.log('recovered:', recovered);

golang

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)

func testSignature() {
privateKey, err := crypto.HexToECDSA(myPrivateKey) // 从私钥字串构造对象
if err != nil {
log.Fatal(err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("error casting public key to ECDSA")
}
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) // 从私钥通过ECDSA产生公钥

rawMessage := "hello, this is text."
hash := crypto.Keccak256Hash([]byte(rawMessage)) // 将原文生成hash。
signature, err := crypto.Sign(hash.Bytes(), privateKey) // 将hash签名成signature
if err != nil {
log.Fatal(err)
}
finalSignature := hexutil.Encode(signature) // 生成最终签名

sigPublicKey, err := crypto.Ecrecover(hash.Bytes(), signature) // 使用hash和签名数据反解出公钥地址
if err != nil {
log.Fatal(err)
}

if (bytes.Equal(sigPublicKey, publicKeyBytes)) { // 检查公钥是否匹配
fmt.Println("is match!!!!")
}
}

参考