Created
May 3, 2018 05:51
-
-
Save azuchi/e8fcfaf6e84263bdfefe583f0644cfc2 to your computer and use it in GitHub Desktop.
ECDSA版Adaptor Signatureの作成
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ECDSAを使ったAdaptor Signature | |
require 'bitcoin' | |
require 'paillier' | |
point_field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order) | |
# アリスが鍵ペアを生成 | |
alice_key = Bitcoin::Key.generate | |
alice_pub = alice_key.to_point | |
# ボブが鍵ペアを生成 | |
bob_key = Bitcoin::Key.generate | |
bob_pub = bob_key.to_point | |
# ロック先のマルチシグ用の公開鍵 | |
new_key = bob_pub.multiply_by_scalar(alice_key.priv_key.to_i(16)) | |
# アリスはランダムなnonceを生成 | |
alice_r = Bitcoin::Key.generate | |
alice_R = alice_r.to_point | |
# ボブは秘密の値αを作成 | |
alpha = Bitcoin::Key.generate | |
alpha_R = alpha.to_point | |
# ボブはランダムなnonceを生成 | |
bob_r = Bitcoin::Key.generate | |
bob_R = bob_r.to_point | |
# ボブのnonceとαの点から新しい点を計算 | |
R3 = alpha_R.multiply_by_scalar(bob_r.priv_key.to_i(16)) | |
# アリスはR3と自分のrを使ってRを計算 | |
aR = R3.multiply_by_scalar(alice_r.priv_key.to_i(16)) | |
# ボブはアリスのナンスの点と自分のr*αを使ってRを計算 | |
bR = alice_R.multiply_by_scalar(bob_r.priv_key.to_i(16) * alpha.priv_key.to_i(16)) | |
# 共通の点のx座標 | |
r = point_field.mod(aR.x) | |
# メッセージ(実際にはマルチシグにロックされたコインを使用するトランザクションのsighashになる) | |
m = Bitcoin.sha256('message'.htb) | |
e = ECDSA.normalize_digest(m, ECDSA::Group::Secp256k1.bit_length) | |
# アリスはPaillier暗号の鍵ペアを生成する | |
privkey, pubkey = Paillier.generateKeypair(2048) | |
# アリスはckeyを生成してボブに渡す | |
ckey = Paillier.encrypt(pubkey, alice_key.priv_key.to_i(16)) | |
# ボブはc1,c2を計算する。 | |
pq = Paillier::Primes.generatePrime(1024) * ECDSA::Group::Secp256k1.order | |
c1 = Paillier.encrypt(pubkey, point_field.mod(point_field.inverse(bob_r.priv_key.to_i(16)) * (e)) + pq) | |
c2 = Paillier.eMulConst(pubkey, ckey, point_field.mod(bob_key.priv_key.to_i(16) * r * point_field.inverse(bob_r.priv_key.to_i(16)))) | |
c3 = Paillier.eAdd(pubkey, c1, c2) | |
# アリスはc3を復号する。 | |
s_dash = Paillier.decrypt(privkey, pubkey, c3) | |
# アリスは復号したデータに自分のr^-1をしたs''を計算してボブに送る。 | |
s_2dash = point_field.mod(s_dash * point_field.inverse(alice_r.priv_key.to_i(16))).to_i | |
# ボブはアリスから受け取ったs''にαを乗算して署名に必要なsを計算する。 | |
s = point_field.mod(s_2dash * point_field.inverse(alpha.priv_key.to_i(16))) | |
# 署名データとしてエンコード | |
signature = ECDSA::Format::SignatureDerString.encode(ECDSA::Signature.new(r, s)) | |
# 実際にアリスとボブのマルチシグ用の公開鍵で検証 | |
multisig_pubkey = Bitcoin::Key.new(pubkey: ECDSA::Format::PointOctetString.encode(new_key, compression: true).bth) | |
puts multisig_pubkey.verify(signature, m) | |
# アリスはボブが公開した署名(r, s)と自分がボブに送ったs''からαの値を知る。 | |
calculate_alpha = point_field.mod(point_field.inverse(s * point_field.inverse(s_2dash))) | |
# これはボブが作成したαと一致する。 | |
puts alpha.priv_key.to_i(16) == calculate_alpha |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment