Skip to content

Instantly share code, notes, and snippets.

@azuchi
Last active August 28, 2018 06:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azuchi/f8258f3fef2c1cb11b88ce7a6d541e77 to your computer and use it in GitHub Desktop.
Save azuchi/f8258f3fef2c1cb11b88ce7a6d541e77 to your computer and use it in GitHub Desktop.
スクリプトレスなマルチシグを構成するスクリプト
# 効率的なECDSAの2-of-2のマルチシグ
require 'bitcoin'
require 'paillier'
# アリスが鍵ペアを生成
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
# ボブはランダムなnonceを生成
bob_r = Bitcoin::Key.generate
bob_R = bob_r.to_point
# アリスはボブのナンスの点と自分のrを使ってRを計算
aR = bob_R.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))
point_field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
# 共通の点の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)
# アリスは復号したデータから署名に必要なsを計算する。
s = point_field.mod(s_dash * point_field.inverse(alice_r.priv_key.to_i(16))).to_i
# 署名データとしてエンコード
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment