使用MetAmask的授权 - 签名和验证 - 您可以在这种方法中找到任何弱点吗?
我想开发一个WebApp(FrontEnd:reactJ,后端:Spring Boot),在该WebApp中,用户可以在无需登录单词的含义(用户名 +密码)的情况下进行交互,而是使用MetAmask来证明其身份。
你们能否在以下方法中找到任何弱点:
- 客户端请求服务器
/nonce?publicAddress = {metAmaskAddress}
- 服务器为特定的metAmask地址生成一个UUID,并使用简短的ttl和ttl和将其返回到客户端
- 客户端通过metAmask客户端符号符号,
- 提出了一个请求,将签名的nonce和MetAmask地址放在标题
- 服务器 中签署nonce的metAmask地址与标题中发送的一个相同,并且nonce不是过期的
客户端代码(使用ethers库)
if (!window.ethereum) {
throw new Error("No crypto wallet found. Please install it.");
}
await window.ethereum.send("eth_requestAccounts");
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const address = await signer.getAddress();
const nonceResponse = await fetch(`/nonce?userId=${address}`, {
method: "get",
headers: {
"Content-Type": "application/json",
},
});
const nonce = await nonceResponse.text();
const signature = await signer.signMessage(nonce);
await fetch("/doSomething", {
method: "post",
headers: {
"Content-Type": "application/json",
"Authorization": signature,
"Public-Address": address,
},
body: JSON.stringify("data"),
});
@PostMapping("/doSomething")
public void doSomething(
@RequestHeader(value = HttpHeaders.AUTHORIZATION) String signedNonce,
@RequestHeader(value = "Public-Address") String publicAddress,
@RequestBody String body) {
String originalNonce = nonceService.getNonceForAddress(publicAddress)
.orElseThrow(() -> new HttpClientErrorException(HttpStatus.UNAUTHORIZED));
boolean verified = verifySignature(
publicAddress,
signedNonce,
originalNonce
);
if (verified) {
// do something with the body
} else {
throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED);
}
}
public static boolean verifySignature(String address, String signedMessage, String originalMessage) {
String decryptedAddress = getAddressUsedToSignHashedPrefixedMessage(signedMessage, originalMessage);
decryptedAddress = "0x" + decryptedAddress;
return address.equalsIgnoreCase(decryptedAddress);
}
@SneakyThrows
private static String getAddressUsedToSignHashedPrefixedMessage(String signedHash, String originalMessage) {
String r = signedHash.substring(0, 66);
String s = "0x" + signedHash.substring(66, 130);
String v = "0x" + signedHash.substring(130, 132);
String publicKey = Sign.signedPrefixedMessageToKey(
originalMessage.getBytes(),
new Sign.SignatureData(
Numeric.hexStringToByteArray(v)[0],
Numeric.hexStringToByteArray(r),
Numeric.hexStringToByteArray(s))
)
.toString(16);
return Keys.getAddress(publicKey);
}
(请忽略Sneakythrows)
感谢您阅读这篇文章 - 任何评论/建议/批评都将受到赞赏:)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论