0


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

引言

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

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

// 这里一下没找到前端代码,从别人哪里拿过的-见谅
import {ethers,providers} from 'ethers';classWalletHolder{
    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 defaultclassWalletUtils{publicstaticasyncmetamask(): Promise<Array<any>>{try{var provider =newethers.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[newWalletHolder(provider,signer,accounts),null];}static holder:WalletHolder;publicstaticgetsigner(): providers.JsonRpcSigner {return WalletUtils.holder.signer;}publicstaticgetprovider(): providers.Provider {return WalletUtils.holder.provider;}publicstaticgetaccounts(): Array<string>{return WalletUtils.holder.accounts;}publicstaticasyncinit(){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签名验签
 */publicclassECRecoverUtil{publicstaticvoidmain(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 私钥
     */publicstaticStringsignPrefixedMessage(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 结果
     */publicstaticBooleanvalidate(String signature,String content,String walletAddress)throws SignatureException {if(content ==null){returnfalse;}// 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 =newSign.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);}}
标签: java 开发语言 maven

本文转载自: https://blog.csdn.net/qq_38420688/article/details/137518700
版权归原作者 终有链响 所有, 如有侵权,请联系我们删除。

“前端和Java验签以太坊钱包签名实现中心化登录”的评论:

还没有评论