ブロックの署名検証(NIS1)


前回のNIS1(今のNEM)版。

さくっと行きます。

署名されるデータ

NIS1は前回のcatapultとルールが少し違い、データの前にデータ長が付くようになっています。例えば、32byte の公開鍵の前に 0x20000000 がプレフィックスとして付きます。

また、それがプログラム上で オブジェクト と呼ばれるものであれば、オブジェクトデータ長 + データ長 + データ のようになる(別のフィールドが間に入ることもある)ので若干ややこしいところがあります。

この辺りのルールは昔、トランザクションのパターンですが別の場所に書いてあるのでそちらを見てみてください。

今回署名されるNIS1のブロックはこちら。

ブロック内に一つだけTransferTransactionが入ったブロックです。

NIS1の面白いところが、ブロックに入るトランザクションの全データをそのまま署名にかけるところだ。

catapultもそうだが、ブロックに格納されるトランザクションの証明は、それらを集約したハッシュ値を使うことが多い。しかし、NIS1では直接トランザクションに署名をかけにいく。

「SPVなんか許さねぇよ?」という強い意志を感じます。(恐らく違う)

電子署名は何を使うのか

電子署名はcatapultと同じく、 ed25519 です。但し、前回も書きましたが、内部で使用されるハッシュ関数が Keccak_512 であるという点でcatapultと異なります。(catapultでは SHA3_512

署名検証してみる

require "ed25519_keccak"

class Deterministic_Transfer_Transaction
  def initialize
    @tx_data_size = "BC000000";
    @entity_type = "01010000"
    @version = "02000098"
    @timestamp = "6E000200"
    @pubkey_of_signer_size = "20000000"
    @pubkey_of_signer = "F9BD190DD0C364261F5C8A74870CC7F7374E631352293C62ECC437657E5DE2CD"
    @signature_size = "40000000"
    @signature = "AC00BFBA8CF3B236567398DE63C3339BEE9975E94B000835445A0A19825DA262B9CDE6D6370D950F4C2DC278F304DF2EA8947852CC17B6B5791EF2D99AB62D06"
    @fee = "4054890000000000"
    @deadline = "7E0E0200"
    @recipient_address_size = "28000000"
    @recipient_address = "4E414E454D4F41424C4147523732415A3252563356345A48444358573235585137334F374F425435"
    @amount = "40420F0000000000"
    @message_data_size = "00000000"
    @mosaic_count = "00000000"
  end

  def get_data_buffer
    data_buffer = @tx_data_size \
                + @entity_type \
                + @version \
                + @timestamp \
                + @pubkey_of_signer_size \
                + @pubkey_of_signer \
                + @signature_size \
                + @signature \
                + @fee \
                + @deadline \
                + @recipient_address_size \
                + @recipient_address \
                + @amount \
                + @message_data_size \
                + @mosaic_count
    return data_buffer
  end
end

class Deterministic_block_nis1
  attr_reader :signature,:pubkey_of_signer

  def initialize()
    @entity_type = "01000000"
    @version = "01000098"
    @timestamp = "96000200"
    @pubkey_of_signer_size = "20000000"
    @pubkey_of_signer = "F6F8E0F08CCE7401D59FF4C20114899104C2FE5E8D471BCB41A7536CEB7ADA8D"
    @prev_block_hash_datasize = "24000000"
    @prev_block_hash_size     = "20000000"
    @prev_block_hash = "659BD1647228D19276673EF1676C21F91455BE0799E0716CA0B7058367498946"
    @height = "A701000000000000"
    @tx_count = "01000000"

    @signature = "61FDA17A1B612CE61F43858C881B7BE3377C26DFCE64DB66CA25D2023807344294AFC451ABCEFFDA96823C07CD3708331BA7621DFC92684D5676863D5EEB2706"
  end

  def get_data_buffer()
    tx = Deterministic_Transfer_Transaction.new

    data_buffer = @entity_type \
                + @version \
                + @timestamp \
                + @pubkey_of_signer_size \
                + @pubkey_of_signer \
                + @prev_block_hash_datasize \
                + @prev_block_hash_size \
                + @prev_block_hash \
                + @height \
                + @tx_count

      data_buffer = data_buffer + tx.get_data_buffer
    return data_buffer
  end
end

nis1_block = Deterministic_block_nis1.new

signature = nis1_block.signature
message = nis1_block.get_data_buffer
pubkey_of_signer = nis1_block.pubkey_of_signer

ed25519 = Ed25519Keccak::Keccak512.new

is_verify = ed25519.verify( pubkey_of_signer , message , signature, :hex )

puts( "is verify ? : " + is_verify.to_s )

実行すれば、true の結果を確認することができるはずです。

さいごに

Don't trust verify!!!!!!!!