HTML+JS+Rails 정면 서명 → 뒷면 서명 검증 [초보자용]

백엔드에서 메타마스크 등의 지갑 주소를 이용하려고 할 때 안내 데스크에서 보내는 값이 정말 정확하지 않다고 생각했습니다.
따라서 서명을 통해 정확한 지갑 주소를 얻을 수 있으며, 다음은 방법을 설명한다.
프론트 데스크톱에서 서명→백엔드에서 서명을 검증하면 정확한 주소임을 증명할 수 있다.
이번에는 HTML+Javascript+Rails로 진행됩니다.

HTML


먼저 프런트의 HTML입니다.
프로그램 라이브러리와 js 실행 단추를 불러왔을 뿐입니다!
axios를 사용하고 있는데, 다른 것도 괜찮을까요?
블록체인에 대한 라이브러리, 웹3.js를 사용하고 있습니다.
ethers.다음에 js판을 주고 싶어요!
index.rb
<html>

<head>
  <meta charset="UTF-8" />
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/ethereum/[email protected]/dist/web3.min.js"></script>
</head>

<body>
  <button class="enableEthereumButton">Enable Ethereum</button>

  <script src="./register.js">
  </script>
</body>

</html>

Javascript


다음은 js 파일입니다.
register.js
const registerUserButton = document.querySelector('.registerUserButton');

registerUserButton.addEventListener('click', () => {
  unlockWallet();
});

async function unlockWallet() {
  //web3がない、もしくはメタマスクのない状況(window.ethereumがない状況)ならその注意文を出してreturn
  if (typeof web3 == 'undefined' && typeof window.ethereum == 'undefined') {
    console.log('Wallet is not installed!');
    return
  }

  // web3をnewする metamaskであろうがその他であろうが、同じバージョンのweb3を使う(ethers.jsでもいいかも)
  window.web3 = new Web3(window.ethereum);

  ethereum.request({ method: 'eth_requestAccounts' })
  .then(function(result){
    signAndRegister(result[0]);
  })
}

function signAndRegister(wallet_address){
  web3.eth.personal.sign("Agree", wallet_address)
  .then(function(result){
    const params = {
      signed_data: result,
      address: wallet_address,
    }
    axios.post(apiUrl, params)
    .then(function(res) {
      console.log(res)
    })
    .catch(function(error) {
      console.log(error)
    })
  })
}
↓ 이 방법은 메타마스크와 연결된 지갑의 주소를 되돌려줍니다.
ethereum.request({ method: "eth_requestAccounts" });
https://docs.metamask.io/guide/ethereum-provider.html
↓ 실행 후 Metamask를 팝업하여 서명합니다.
web3.eth.personal.sign("Agree", wallet_address);
이 방법에서 나온 반환값 서명 데이터를 백엔드에 전달합니다.
https://docs.metamask.io/guide/signing-data.html#signing-data-with-metamask

Rails


그런 다음 Rails로 서명을 확인합니다.
프론트에서 보낸 서명 데이터에서 주소를 복원하여 함께 보낸 주소와 일치하는지 확인합니다.
ruby-eth Gem을 사용하여 서명에서 주소를 복구할 수 있습니다.
gem 'eth', '~> 0.4.10'
signatures_controller.rb
class Api::V1::SignaturesController < Api::ApplicationController
   def create
    address = recover_address(params[:signed_data], "Agree")

    #復元したアドレスと、投げられてきたアドレスが異なる場合はErrorを返す(不正)
    if address.downcase != params[:address].downcase
      @error_message = "Error"
      return
    end

    #ここで何かしら行いたい動作をする。
  end

  private
    #署名からpublic keyを復元し、そのpublic_keyからaddressを復元する
    def recover_address(signature, message)
      public_key = Eth::Key.personal_recover(message, signature)
      address = Eth::Utils.public_key_to_address(public_key)
      return address
    end
end
서명 데이터와 서명 정보에서 공개 키를 복원하고 주소를 추출합니다.
public_key = Eth::Key.personal_recover(message, signature)
address = Eth::Utils.public_key_to_address(public_key)
이후 함께 보낸 주소와 복원된 주소가 일치하면 서명 검증이 완료됩니다!!
이렇게 하면 백엔드에서 정확한 지갑 주소를 사용할 수 있다.

총결산


백엔드에서 메타마스크 등 지갑 주소를 활용하고 싶을 때의 검증 방법에 대한 해설이다.

좋은 웹페이지 즐겨찾기