? ? ? ? 使用场景大多数用在DAPP中调用中心化数据或者操作某些中心化功能的时候通过DAPP调用MetaMask钱包对数据进行签名传递给后台,后台验证签名数据是否是否当前用户钱包地址签名的数据实现鉴权。
一、DAPP端用Web3签名数据
注:不同的web3版本签名代码有点差异
1、0.26版本签名?web3.personal.sign
//参数1:要签名的数据
//参数2:签名的钱包地址
web3.personal.sign(web3.fromUtf8("Hello Dapp"), "0x40141cF4756A72DF8D8f81c1E0c2ad403C127b9E",(err, res) => {
console.log("签名后的数据:",res)
//0x53ea88d24f4ef8cdcc4bcc843912510b065cd6014c453ff61316c4cd75162f0a38f83a2103da028fb8e5181292ba194b0c8aa21a9ddacdf6783ebfa608889d121c
})
//web3.eth.sign此签名方法MetaMask会提示未来版本会被移除
2、1.0版本签名??web3.eth.personal.sign
3、唤醒MetaMask钱包签名数据
签名后数据为:0x53ea88d24f4ef8cdcc4bcc843912510b065cd6014c453ff61316c4cd75162f0a38f83a2103da028fb8e5181292ba194b0c8aa21a9ddacdf6783ebfa608889d121c
二、Java端使用Web3J校验数据
1、正常校验 true
?2、改变下钱包地址在次校验 false
?三、后端源码-来源于github上的源码
1、web3j包
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>3.6.0</version>
</dependency>
2、校验源码?
package zh.block.manage.common.utils;
import org.web3j.crypto.*;
import org.web3j.utils.Numeric;
import org.web3j.crypto.Sign.SignatureData;
import java.math.BigInteger;
import java.util.Arrays;
/**
* 以太坊签名消息校验工具
*/
public class MetaMaskUtil {
/**
* 以太坊自定义的签名消息都以以下字符开头
* 参考 eth_sign in https://github.com/ethereum/wiki/wiki/JSON-RPC
*/
public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n";
public static void main(String[] args) {
//签名后的数据
String signature="0x53ea88d24f4ef8cdcc4bcc843912510b065cd6014c453ff61316c4cd75162f0a38f83a2103da028fb8e5181292ba194b0c8aa21a9ddacdf6783ebfa608889d121c";
//签名原文
String message="Hello Dapp";
//签名的钱包地址
String address="0xc290436b3da897115493a1547B52783c50f0Bef3";
Boolean result = validate(signature,message,address);
System.out.println(result);
}
/**
* 对签名消息,原始消息,账号地址三项信息进行认证,判断签名是否有效
* @param signature
* @param message
* @param address
* @return
*/
public static boolean validate(String signature, String message, String address) {
//参考 eth_sign in https://github.com/ethereum/wiki/wiki/JSON-RPC
// eth_sign
// The sign method calculates an Ethereum specific signature with:
// sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).
//
// By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature.
// This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to
// impersonate the victim.
String prefix = PERSONAL_MESSAGE_PREFIX + message.length();
byte[] msgHash = Hash.sha3((prefix + message).getBytes());
byte[] signatureBytes = Numeric.hexStringToByteArray(signature);
byte v = signatureBytes[64];
if (v < 27) {
v += 27;
}
SignatureData sd = new SignatureData(
v,
Arrays.copyOfRange(signatureBytes, 0, 32),
Arrays.copyOfRange(signatureBytes, 32, 64));
String addressRecovered = null;
boolean match = false;
// Iterate for each possible key to recover
for (int i = 0; i < 4; i++) {
BigInteger publicKey = Sign.recoverFromSignature(
(byte) i,
new ECDSASignature(new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())),
msgHash);
if (publicKey != null) {
addressRecovered = "0x" + Keys.getAddress(publicKey);
if (addressRecovered.equals(address)) {
match = true;
break;
}
}
}
return match;
}
}
多链钱包充提系统
学如逆水行舟,不进则退。心似平原跑马,易放难收。【区块链】【系统/网络/运维】【云计算/大数据】【数据库】【移动开发】【后端开发】【游戏开发】【UI设计】【微服务】【爬虫】【Java】【Go】【C++】【PHP】【Python】【Android/IOS】【HTML/CSS】【JavaScript】【Node】【VUE】【ReactNaive】。。。
欢迎各位大神萌新一起专研分享各行各业技术!
Chain区块链开发社区:593674370
?
|