Last active
August 28, 2018 06:11
-
-
Save azuchi/f8258f3fef2c1cb11b88ce7a6d541e77 to your computer and use it in GitHub Desktop.
スクリプトレスなマルチシグを構成するスクリプト
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の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