25

更新: Git で利用可能な部分的なソリューション

編集: これのコンパイル済みバージョンは、https://github.com/makerofthings7/Bitcoin-MessageSignerVerifierで入手できます。

Bitcoin Signed Message:\n検証するメッセージにはプレフィックスとして が 必要であることに注意してください。ソース1 ソース2

C# の実装に何か問題がありますが、この Python の実装から修正できる可能性があります。


実際に正しい Base 58 アドレスを割り出すのに問題があるようです。

以下のメッセージ、署名、Base58 アドレスがあります。署名からキーを抽出し、そのキーをハッシュして、Base58 ハッシュを比較するつもりです。

私の問題は次のとおりです。署名からキーを抽出するにはどうすればよいですか? (この投稿の下部にある C++ コードを編集してください。Bouncy Castle / または C# で必要です)

メッセージ

StackOverflow test 123

サイン

IB7XjSi9TdBbB3dVUK4+Uzqf2Pqk71XkZ5PUsVUN+2gnb3TaZWJwWW2jt0OjhHc4B++yYYRy1Lg2kl+WaiF+Xsc=

Base58 ビットコイン アドレス「ハッシュ」

1Kb76YK9a4mhrif766m321AMocNvzeQxqV

Base58 ビットコイン アドレスは単なるハッシュであるため、ビットコイン メッセージの検証には使用できません。ただし、署名から公開鍵を抽出することは可能です。

編集: Base58 公開鍵ハッシュからではなく、署名自体から公開鍵を導出していることを強調しています。私が望むなら (実際にそうしたいのですが)、これらの公開鍵ビットを Base58 ハッシュに変換できるはずです。これを行うのに支援は必要ありません。公開鍵のビットを抽出して署名を検証する際に支援が必要なだけです。

質問

  1. 上記の署名では、この署名の形式は何ですか? PKCS10? (回答: いいえ、こちらで説明されているように独自仕様です)

  2. Bouncy Castle で公開鍵を抽出するにはどうすればよいですか?

  3. 署名を検証する正しい方法は何ですか? (公開鍵ビットを上記のビットコイン ハッシュと等しいハッシュに変換する方法を既に知っていると仮定します)

先行研究

このリンクQでは、ECDSA 曲線の使用方法について説明しています。次のコードを使用すると、公開鍵を BC オブジェクトに変換できますが、署名から ポイントを取得する方法がわかりません。

以下のサンプルでは、​​Q はハードコードされた値です

  Org.BouncyCastle.Asn1.X9.X9ECParameters ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
  ECDomainParameters params = new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H);
  ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(
  ecp .curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
        params);
  PublicKey  pubKey = f.generatePublic(pubKeySpec);


 var signer = SignerUtilities.GetSigner("ECDSA"); // possibly similar to SHA-1withECDSA
 signer.Init(false, pubKey);
 signer.BlockUpdate(plainTextAsBytes, 0, plainTextAsBytes.Length);
 return signer.VerifySignature(signature);

追加の調査:

これは、メッセージを検証するビットコイン ソースです。

署名の Base64 をデコードした後、RecoverCompact(メッセージのハッシュ、署名)が呼び出されます。私は C++ プログラマーではないので、仕組みを理解する必要があると思いますkey.Recover。それかkey.GetPubKey

これは、C# で、理想的には弾む城で必要だと思う C++ コードですが、動作するものは何でも使用します。

// reconstruct public key from a compact signature
// This is only slightly more CPU intensive than just verifying it.
// If this function succeeds, the recovered public key is guaranteed to be valid
// (the signature is a valid signature of the given data for that key)
bool Recover(const uint256 &hash, const unsigned char *p64, int rec)
{
    if (rec<0 || rec>=3)
        return false;
    ECDSA_SIG *sig = ECDSA_SIG_new();
    BN_bin2bn(&p64[0],  32, sig->r);
    BN_bin2bn(&p64[32], 32, sig->s);
    bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1;
    ECDSA_SIG_free(sig);
    return ret;
}

... ECDSA_SIG_recover_key_GFp のコードはこちら

ビットコインのカスタム署名形式

この回答は、署名を生成できる公開鍵が 4 つあり、これが新しい署名でエンコードされていることを示しています。

4

2 に答える 2