当前位置:首页 » 《我的小黑屋》 » 正文

前端和Java验签以太坊钱包签名实现中心化登录

25 人参与  2024年05月01日 13:00  分类 : 《我的小黑屋》  评论

点击全文阅读


引言

相信做过一些dapp项目的小伙伴都知道,当dapp需要和中心化的业务系统交互时,怎么验证登录成了一个问题。要dapp输入登录账户密码就很奇怪,违背了设计初衷,不登录吧,中心化系统又没有安全可言。
故此需要一个特定的动作。只有当钱包持有人授权登录(连接钱包),前端js通过调用特定api加密得到算法,从而传到后台验证签名,从而达到登录效果。

前端js 加密代码(web.js)

// 这里一下没找到前端代码,从别人哪里拿过的-见谅import {ethers,providers} from 'ethers';class WalletHolder{    provider:providers.Provider;    signer:providers.JsonRpcSigner;    accounts:Array<string>;    constructor(_provider:providers.Provider,_signer:providers.JsonRpcSigner,_accounts:Array<string>) {        this.provider = _provider;        this.signer = _signer;        this.accounts = _accounts;    }}export default class WalletUtils{    public static async metamask() : Promise<Array<any>> {        try {            var provider = new ethers.providers.Web3Provider(window['ethereum']);            var accounts = await provider.send("eth_requestAccounts", []);            var signer = await provider.getSigner();            console.log("Account:", await signer.getAddress());        } catch (error) {          return [null,error]           }        return [new WalletHolder(provider,signer,accounts),null];    }    static holder:WalletHolder;        public static get signer() : providers.JsonRpcSigner {        return WalletUtils.holder.signer;    }    public static get provider() : providers.Provider {        return WalletUtils.holder.provider;    }            public static get accounts() : Array<string> {        return WalletUtils.holder.accounts;    }            public static async init(){        const[holder,error] = await WalletUtils.metamask();        if(error){            console.error('init metamask error',error)            return;        }        if(holder instanceof WalletHolder){            WalletUtils.holder = holder;            console.log('init success')        }    }}  if(!WalletUtils.holder){   await WalletUtils.init();  }  const defaultSinger  = WalletUtils.signer;       //使用签名及逆行   const message = await defaultSinger.signMessage("areyouok!")           //content = "hgqZgU7IuZM8y1rWUQOaMCbbb2QS39EtNWvLGu9FyDvTTQD/cOiLkgYNy+xGl/oEh/idTY2xNh9Kdpmg+ljgfFnd8R8bOEZ2JH38c4Jlhhm6ypntKdVKgrm9dquk8En4sZw1R/mEh8O7sSQ7kLOBv6Epzme0ZGyXJVWA4accjBo=";          // sing= "0xcb0a1688018b8cd8f0f5dd66647de8bb251772bc4aa64c9ac8ffc37af29299462f0ee7715646b8172e381bdf44ac5970180bbc10d31de1b6ec59a09d620fa8e21b";          //walletAddress = "0x37949e80Aedc7d72CFB3667d092161EA8729Ba49";

java验签

引入pom

  <!--web3j-->        <dependency>            <groupId>org.web3j</groupId>            <artifactId>core</artifactId>            <version>5.0.0</version>        </dependency>        <dependency>            <groupId>org.web3j</groupId>            <artifactId>geth</artifactId>            <version>5.0.0</version>            <exclusions>                <exclusion>                    <groupId>com.squareup.okhttp3</groupId>                    <artifactId>okhttp</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.web3j</groupId>            <artifactId>abi</artifactId>            <version>5.0.0</version>        </dependency>

为了方便java同学测试,我这里附上 验签代码加密代码,线上只需要验签代码,因为加密代码由前端同学完成了。

import org.web3j.crypto.Credentials;import org.web3j.crypto.Keys;import org.web3j.crypto.Sign;import org.web3j.utils.Numeric;import java.math.BigInteger;import java.security.SignatureException;import java.util.Arrays;/** * @Description: Web3j签名验签 */public class ECRecoverUtil {     public static void main(String[] args) throws SignatureException {        String content = "hgqZgU7IuZM8y1rWUQOaMCbbb2QS39EtNWvLGu9FyDvTTQD/cOiLkgYNy+xGl/oEh/idTY2xNh9Kdpmg+ljgfFnd8R8bOEZ2JH38c4Jlhhm6ypntKdVKgrm9dquk8En4sZw1R/mEh8O7sSQ7kLOBv6Epzme0ZGyXJVWA4accjBo=";        String     sing= "0xcb0a1688018b8cd8f0f5dd66647de8bb251772bc4aa64c9ac8ffc37af29299462f0ee7715646b8172e381bdf44ac5970180bbc10d31de1b6ec59a09d620fa8e21b";        String walletAddress = "0x37949e80Aedc7d72CFB3667d092161EA8729Ba49";        boolean mark = validate(sing,content,walletAddress);        System.out.println(sing);        System.out.println(mark);    }    /**     * 签名     *     * @param content    原文信息     * @param privateKey 私钥     */    public static String signPrefixedMessage(String content, String privateKey) {        // todo 如果验签不成功,就不需要Hash.sha3 直接content.getBytes()就可以了        // 原文信息字节数组//        byte[] contentHashBytes = Hash.sha3(content.getBytes());        byte[] contentHashBytes = content.getBytes();        // 根据私钥获取凭证对象        Credentials credentials = Credentials.create(privateKey);        //        Sign.SignatureData signMessage = Sign.signPrefixedMessage(contentHashBytes, credentials.getEcKeyPair());        byte[] r = signMessage.getR();        byte[] s = signMessage.getS();        byte[] v = signMessage.getV();        byte[] signByte = Arrays.copyOf(r, v.length + r.length + s.length);        System.arraycopy(s, 0, signByte, r.length, s.length);        System.arraycopy(v, 0, signByte, r.length + s.length, v.length);        return Numeric.toHexString(signByte);    }    /**     * 验证签名     *     * @param signature     验签数据     * @param content       原文数据     * @param walletAddress 钱包地址     * @return 结果     */    public static Boolean validate(String signature, String content, String walletAddress) throws SignatureException {        if (content == null) {            return false;        }        // todo 如果验签不成功,就不需要Hash.sha3 直接content.getBytes()就可以了        // 原文字节数组//        byte[] msgHash = Hash.sha3(content.getBytes());        byte[] msgHash = content.getBytes();        // 签名数据        byte[] signatureBytes = Numeric.hexStringToByteArray(signature);        byte v = signatureBytes[64];        if (v < 27) {            v += 27;        }        //通过摘要和签名后的数据,还原公钥        Sign.SignatureData signatureData = new Sign.SignatureData(                v,                Arrays.copyOfRange(signatureBytes, 0, 32),                Arrays.copyOfRange(signatureBytes, 32, 64));        // 签名的前缀消息到密钥        BigInteger publicKey = Sign.signedPrefixedMessageToKey(msgHash, signatureData);        // 得到公钥(私钥对应的钱包地址)        String parseAddress = "0x" + Keys.getAddress(publicKey);        // 将钱包地址进行比对        return parseAddress.equalsIgnoreCase(walletAddress);    }}

点击全文阅读


本文链接:http://zhangshiyu.com/post/102623.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 她的记忆停留在了最爱初恋的那年许欣柔楚临川完本_她的记忆停留在了最爱初恋的那年(许欣柔楚临川)
  • 全书浏览假千金的实习生男友霸占我办公室,我反手让他们倾家荡产(顾家明)_假千金的实习生男友霸占我办公室,我反手让他们倾家荡产(顾家明)全书结局
  • 童养夫让我给他的新欢出修复费(林嘉芝林思雅)_童养夫让我给他的新欢出修复费林嘉芝林思雅
  • 全文资助生女婿让我给他白月光付三千万月子中心钱(宋清玉宋雅)列表_全文资助生女婿让我给他白月光付三千万月子中心钱
  • 碎在时光里的谎言喻景宴秦明月完本_碎在时光里的谎言(喻景宴秦明月)
  • 旧爱剜心吻成灰席鄢之岑秋全书免费旧爱剜心吻成灰席鄢之岑秋全书免费
  • 结婚六年丈夫不碰我谁知儿子亲爹是寡头(纪清言傅司砚),结婚六年丈夫不碰我谁知儿子亲爹是寡头
  • 老公想换掉我的男胎,我笑他自不量力(宋薇于继业)_老公想换掉我的男胎,我笑他自不量力宋薇于继业
  • 给太子下了噬心蛊后,皇后找上门(小夭赵劼)全书浏览_给太子下了噬心蛊后,皇后找上门全书浏览
  • 豪门绝嗣!带球跑的夫人回来了!(谢长宴慕清杳)_豪门绝嗣!带球跑的夫人回来了!谢长宴慕清杳
  • 完美身材(李朵林之晴)_完美身材李朵林之晴
  • 离婚后,我和快穿系统绑定(白意秋陈荣周立慧)_离婚后,我和快穿系统绑定(白意秋陈荣周立慧)

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1