Contract内のエンドユーザサイン確認

本サービスでは、エンドユーザ側でエンドユーザ自身の KeyPair でサインを行い、APIサーバではそのサインを含めた形でトランザクションを発行し、そのサインを Contract 内で確認します。

Contract Sign Check

まず、エンドユーザのクライアントサイドでのサイン方法の確認をします。

エンドユーザ側のサインは AltExecCnsContract の中で行われているため、実装時に意識する必要はありませんが、Contract内でのサインの確認内容を理解するために解説します。

  • エンドユーザのサイン方法

    エンドユーザ側での本サービスの呼び出し方法の例は下記になります。

    • 呼び出し部分
      var contract = new AltExecCnsContract(account, '__CNS_ADDRESS__');
      contract.sendTransaction('__PASSWORD__', 'SomeContract', 'someMethod', ['p0', 1, 'p2'], abi, function(err, res) {
          if (err) console.error(err);
          else console.log(res.join(','));
      }
      

    実際のサインは AltExecCnsContract#sendTransaction 内で行われます。

    • ソースコード抜粋
      AltExecCnsContract.prototype.sendTransaction = function(password, contractName, functionName, params, abi, callback) {
          ...
          var altParams = new AltExecCnsParams(cnsAddress, contractName, functionName, params);
          altParams.setTypesFromAbi(abi);
          const hash = altParams.getHashedParams();
          ...
          this.account.sign(password, hash).then(function(sign) {
              ...
          };
      };
      

    ここでは、エンドユーザが呼出に使用する『全ての』パラメータからhash値を導出し、そのハッシュ値に対してサインを作成します。

    AltExecCnsContractのソースコード全体はこちら

  • Contract内でチェック

    エンドユーザのサインをコントラクト内でチェックする方法は下記になります。

    • Contract内の実装

      contract SomeContract is VersionContract {
          function SomeContract(ContractNameService _cns)     VersionContract(_cns, "SomeContract") {}
          function someMethod(bytes _sign, bytes32 _p0, uint _p1, bytes32 _p2) constant returns (string) {
              // create all parameters hash
              bytes32 hash = calcEnvHash('someMethod');
              hash = sha3(hash, _p0);
              hash = sha3(hash, _p1);
              hash = sha3(hash, _p2);
              // get end user's addresss
              address endUserAddr = Utils.recoverAddress(hash, _sign);
              ...
          }
      }
      

    コントラクト内でのサインのチェックは、エンドユーザのクライアントで行ったチェックと同様の処理を行います。

    上記サンプルで最初に処理している「VersionContract#calcEnvHash」にて次の項目のhashを生成します。

    • ContractNameServiceのアドレス
    • コントラクト名
    • 関数名

    残りの処理で全パラメータのハッシュ値を計算します。

    最後に、生成されたハッシュ値からエンドユーザのアドレスを取得します。

    address endUserAddr = Utils.recoverAddress(hash, _sign);
    

    エンドユーザがサインした値に、1bitでも偽装があれば、hash値が変わり、取得されるアドレスも代わってしまうため、エンドユーザ(のアドレス)に成りすますこともできないですし、エンドユーザが指定したパラメータを変更することもできません。

    取得された endUserAddr に対して処理権限があるかのチェックを実装すれば、確実に特定のエンドユーザだけが処理できる仕組みが出来上がります。

  • サインの厳密化

    今までの処理で、エンドユーザのサインを元にContractの処理を実行することができましたが、さらにサインを厳密にチェックすることができます。

    それについては別の項としていますので、サインのチェック厳密化 の項を参照ください。

results matching ""

    No results matching ""