自作の公開鍵復元が動かないので、先生を動かすことにした。
https://github.com/bitcoinjs/bitcoinjs-lib/tree/v2.1.4
recoverPubKeyを持つのがv2なので、この辺りを使った。
こんな感じで書くと、動くことが分かった。
var ecdsa = require('./src/ecdsa') var BigInteger = require('bigi') var ECSignature = require('./src/ecsignature') //pubkey= 03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459 //hash=b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad // r=047c1b1111bbe0fc09cf2ed28dd1abd613c02b747af8edd1274886654259bbfb // s=1d00ca3fc10a111a5a3ea0669992e4ad9a2f1c402ec5fd29d9e1348ab0584fa2 var e = BigInteger.fromHex('b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad') var r = BigInteger.fromHex('047c1b1111bbe0fc09cf2ed28dd1abd613c02b747af8edd1274886654259bbfb') var s = BigInteger.fromHex('1d00ca3fc10a111a5a3ea0669992e4ad9a2f1c402ec5fd29d9e1348ab0584fa2') var signature = new ECSignature(r, s) var i = 0 var Qprime = ecdsa.recoverPubKey(e, signature, i) var QprimeHex = Qprime.getEncoded().toString('hex') console.log('Qprime=', QprimeHex)
$ node recover_pub.js
Qprime= 03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459
さすが先生ですわ・・・。
自分の結果と比較するために、データを残しておこう。
i=0
03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459i=1
0383a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4i=2
03ccb2ec2eca77c75955cd5334e9f0248adf51dcb37744fef36a9152dd468cbe37i=3
02082151f0695b3b98128e4326e7ddd1f44264448d39723b10ba56976c44fe5dbai=4
例外発生
うちの子はこうだ。
i=0
0283a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4i=1
02becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459i=2
03f23664e578b9cc1f8eb81e47ce3eb037043a5a92f0a3fc09ebd2ca121f862e05i=3
03b06c50b0579e2142f56756c29445d7762539368be48918db2d6bd4f2f562b51d
i=0とi=1の結果が逆のような形になっている。
i=2と3は共通点がない。
この辺りに突破口がないだろうか。
うーん、-eの値が違う。
先生
e = b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad
eNeg= 477e54c3b8f46c67524a15934c9f2eb8db3ead45f33e343a9db863f8e92c9394
私
e = B881AB3C470B9398ADB5EA6CB360D145DF702FA0BC0A6C012219FA93E709ADAD
eNeg = 477E54C3B8F46C67524A15934C9F2EBA208FD05F43F593FEDDE6056B18F64E82
実は、前回まで私は (0 - e) % Pを計算していたのだが、ログに出してみるとeと同じ値だったのだ。。。
Y座標の符号を逆にするときの反省を生かして(P - e) % Pにしたのが今回。
それでも、微妙に値が違っている。
先生は、e.negate().mod(n)で計算している。
だいたい、一番最後の桁を足しても、0xD + 0x4は0じゃないやん。。。
やけになって、PではなくNでやってみた。
私
e = B881AB3C470B9398ADB5EA6CB360D145DF702FA0BC0A6C012219FA93E709ADAD
eNeg = 477E54C3B8F46C67524A15934C9F2EB8DB3EAD45F33E343A9DB863F8E92C9394
理屈はわからんが、値が一致してしまったではないか。
i=0
03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459i=1
0383a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4i=2
02b06c50b0579e2142f56756c29445d7762539368be48918db2d6bd4f2f562b51di=3
02f23664e578b9cc1f8eb81e47ce3eb037043a5a92f0a3fc09ebd2ca121f862e05
うーん、i=2と3がまだ不一致だ。
これは、Rが不一致なためのようだ。
先生(i=2)
x= 01047c1b1111bbe0fc09cf2ed28dd1abd4ce6f085b2a418e0ce71ae4f2128ffd3c
R= 02047c1b1111bbe0fc09cf2ed28dd1abd4ce6f085b2a418e0ce71ae4f31290010d私
x = 01047C1B1111BBE0FC09CF2ED28DD1ABD4CE6F085B2A418E0CE71AE4F2128FFD3C
R.x = 01047C1B1111BBE0FC09CF2ED28DD1ABD4CE6F085B2A418E0CE71AE4F2128FFD
R.y = 7F6ACBA2D227DCA73DDC17A895454F00A97F34A87967BECB6535287E0E5C436C
xは同じ値で、Rはxの先頭に0x02を付けたもののはずだが、先生はそうしていない。
そして、私もそうなっていないのだが、なんでだ??
あ、表示桁が足りてない・・・。
xにNを足したとき、33byteになってしまったのだ。
単純なバグだな。
i=2
03ccb2ec2eca77c75955cd5334e9f0248adf51dcb37744fef36a9152dd468cbe37i=3
02082151f0695b3b98128e4326e7ddd1f44264448d39723b10ba56976c44fe5dba
一致した。
で、だ。
ハッシュ値eに対する-eを求めるとき、N - eして値が一致したけど、それでよいのだろうか?
secp256k1の法に従うことにはなるのだろうけど、そこが感覚的に分かっていない。
(sR - eG)を求めるとき、APIとしては (a * P + b * Q)しかないためにbをマイナスにしようとしただけなのだ。
だから、単純に(0 - e)を求めたのだが、これは当然負の数で、それは0~N-1の世界にいないからダメなのか?
「module 負」で検索すると、そういう計算自体が微妙なところらしい。
言語間で違うということは、ライブラリだと言語に関係なく違いが生じるということか。
うーん、難しいことはやらずにAPIだけ使い回して完了させる予定だったのに、最後に悩みが残る結果になってしまった。
楕円曲線の簡単な説明をしてくれるサイトでも読むか。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。