Skip to content

Instantly share code, notes, and snippets.

@azuchi
Created May 3, 2018 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azuchi/e8fcfaf6e84263bdfefe583f0644cfc2 to your computer and use it in GitHub Desktop.
Save azuchi/e8fcfaf6e84263bdfefe583f0644cfc2 to your computer and use it in GitHub Desktop.
ECDSA版Adaptor Signatureの作成
# 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