Created
May 6, 2018 06:51
-
-
Save azuchi/20317f760a9b07e4cd73ec1e79999aa5 to your computer and use it in GitHub Desktop.
ECDSAでTaprootを構成した際のPの署名を生成するコード
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でTaprootを構成した際のPの署名を生成するコード | |
require 'bitcoin' | |
require 'paillier' | |
include Bitcoin::Opcodes | |
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 | |
alternative = (Bitcoin::Script.new << 1000 << OP_CHECKSEQUENCEVERIFY << OP_DROP << bob_key.pubkey << OP_CHECKSIG).to_payload | |
# ロック先のマルチシグ用の公開鍵 | |
c = bob_pub.multiply_by_scalar(alice_key.priv_key.to_i(16)) | |
hash = point_field.mod(Bitcoin.sha256(ECDSA::Format::PointOctetString.encode(c, compression: true).bth + alternative.bth).bth.to_i(16)) | |
P = c + ECDSA::Group::Secp256k1.new_point(hash) | |
# アリスはランダムな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)) | |
# 共通の点の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)))) | |
c2 = Paillier.eAddConst(pubkey, c2, hash * 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)) | |
# 実際にPで検証 | |
multisig_pubkey = Bitcoin::Key.new(pubkey: ECDSA::Format::PointOctetString.encode(P, 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