前回の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!!!!!!!!