DAPP开发中Web3唤醒MetaMask签名数据+Java校验签名实现去中心化和中心化用户数据的鉴权

  • Chain哥
  • 更新于 2022-11-24 16:47
  • 阅读 5571

使用场景大多数用在DAPP中调用中心化数据或者操作某些中心化功能的时候通过DAPP调用MetaMask钱包对数据进行签名传递给后台,后台验证签名数据是否是否当前用户钱包地址签名的数据实现鉴权。

        使用场景大多数用在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

image.png

二、Java端使用Web3J校验数据

1、正常校验 true

image.png 2、改变下钱包地址在次校验 false

image.png

三、后端源码-来源于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;
    }
}

image.png 学如逆水行舟,不进则退。心似平原跑马,易放难收。全栈工程师是指掌握多种技能,并能利用多种技能独立完成产品的人。 也叫全端工程师(同时具备前端和后台能力),英文Full Stack engineer。【人工智能】【区块链】【系统/网络/运维】【云计算/大数据】【数据库】【移动开发】【后端开发】【游戏开发】【UI设计】【微服务】【爬虫】【Java】【Go】【C++】【PHP】【Python】【Android/IOS】【HTML/CSS】【JavaScript】【Node】。。。

欢迎各位大神萌新一起专研分享各行各业技术!

Chain区块链开发社区:593674370

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Chain哥
Chain哥
个人简介:学如逆水行舟,不进则退。心似平原跑马,易放难收!