서버에서 메세지에 서명 후 컨트랙트에서 검사하기

현재 구현하고자 하는 기능은

  • 파라미터 : 배포된 특정 컨트랙트 주소(deplyedContract), 금액
  • 메세지 : 위 파라미터를 하나의 hash로 만들고 해당 hash에 A 유저의 주소로 서명한 메세지

배포해놓은 컨트랙트(deplyedContract)에 기록되어있는 유저의 주소와 메세지에 서명한 A가 일치하는 지 확인하는 함수를 만들려고 하는데 일치검사에서 계속 실패하고 있습니다.

https://docs.soliditylang.org/en/v0.8.17/solidity-by-example.html#id3
이 문서의 예제를 참고해서 klaytn 함수로 대체하여 사용하는 중입니다.

특이사항은 privateKey를 관리하지 않으려고 KAS를 활용하고자 합니다.

현재 여러 함수를 테스트해봤고 마지막 버전은

암호화 및 서명하는 코드

var dataToSign = caverjs.utils.soliditySha3(
{ t: ‘address’, v: contractAddress },
{ t: ‘uint256’, v: amount }).toString(“hex”);

var request = require(‘request’);

    var auth = {
        "username": "{accessKeyId}",
        "password": "{secretAccessKey}"
    }
    var jsonDataObj = {
        "data": dataToSign 
    }
    console.log(jsonDataObj)
    request.post({
        auth: auth,
        headers: { 'Content-Type': 'application/json', 'x-chain-id': '1001' },
        url: ' https://wallet-api.klaytnapi.com/v2/key/{키 아이디}/sign',
        body: jsonDataObj,
        json: true
    }, function (error, response, body) {
        console.log(body)
    })

스마트 컨트랙트 내부 코드

function isValidSignature(uint256 amount, bytes memory signature)
internal
view
returns (bool)
{
bytes32 message = prefixed(keccak256(abi.encodePacked(address(this), amount)));

    // sender의 서명인지 확인 
    return recoverSigner(message, signature) == recipient; 
}


function splitSignature(bytes memory sig)
    internal
    pure
    returns (uint8 v, bytes32 r, bytes32 s)
{
    require(sig.length == 65);

    assembly {
        // first 32 bytes, after the length prefix
        r := mload(add(sig, 32))
        // second 32 bytes
        s := mload(add(sig, 64))
        // final byte (first byte of the next 32 bytes)
        v := byte(0, mload(add(sig, 96)))
    }

    return (v, r, s);
}

function whatIsThis()
    external
    view
    returns (address)
{
    return address(this);
}

function recoverSigner(bytes32 message, bytes memory sig)
    internal
    pure
    returns (address)
{
    (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);

    return ecrecover(message, v, r, s);
}

/// builds a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 hash) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked("\x19Klaytn Signed Message:\n32", hash));
}

를 사용중입니다.

결론적으로 궁금한건 위의 작업을 위해 사용할 수 있는 클레이튼 코드나 함수입니다.