Jak uzyskać klucz publiczny ECDSA z podpisu Bitcoin? … SEC1 4.1.6 odzyskiwanie kluczy dla krzywych (mod p) -fields
Aktualizacja: Częściowe rozwiązanie dostępne w Git
EDYCJA: Skompilowana wersja jest dostępna pod adresemhttps://github.com/makerofthings7/Bitcoin-MessageSignerVerifier
Pamiętaj, że wiadomość do zweryfikowania musi miećBitcoin Signed Message:\n
jako prefiks.Źródło1 Source2
Coś jest nie tak w implementacji C #, że prawdopodobnie mogę to poprawićta implementacja Pythona
Wydaje się, że ma problem z wymyśleniem poprawnego adresu Base 58.
Mam następujący komunikat, podpis i adres Base58 poniżej. Zamierzam wyodrębnić klucz z podpisu, skrótu tego klucza i porównać skróty Base58.
Mój problem to: Jak wyodrębnić klucz z podpisu? (EdytowaćZnalazłem kod c ++ na dole tego posta, potrzebujesz go w Bouncy Castle / lub C #)
Wiadomość
StackOverflow test 123
Podpis
IB7XjSi9TdBbB3dVUK4+Uzqf2Pqk71XkZ5PUsVUN+2gnb3TaZWJwWW2jt0OjhHc4B++yYYRy1Lg2kl+WaiF+Xsc=
Adres Base58 Bitcoin „hash”
1Kb76YK9a4mhrif766m321AMocNvzeQxqV
Ponieważ adres Base58 Bitcoin jest tylko hashem, nie mogę go użyć do walidacji komunikatu Bitcoin. Możliwe jest jednak wyodrębnienie klucza publicznego z apodpis.
Edytować: Podkreślam, że czerpię klucz publiczny z samego podpisu, a nie z skrótu klucza publicznego Base58. Jeśli chcę (i rzeczywiście chcę), powinienem być w stanie przekonwertować te bity klucza publicznego do skrótu Base58. Nie potrzebuję pomocy w tym, po prostu potrzebuję pomocy w wyodrębnieniu bitów klucza publicznego i weryfikacji podpisu.
Pytanie
W jakim podpisie znajduje się ten podpis? PKCS10? (Odpowiedź: nie, to zastrzeżonejak opisano tutaj)
jak wyodrębnić klucz publiczny w Bouncy Castle?
Jaki jest właściwy sposób weryfikacji podpisu? (załóżmy, że już wiem, jak przekonwertować bity klucza publicznego na hash równy powyższemu hashowi Bitcoin)
Wcześniejsze badania
Ten link opisuje sposób korzystania z krzywych ECDSA, a poniższy kod pozwoli mi przekonwertować klucz publiczny na obiekt BC, ale nie jestem pewien, w jaki sposób uzyskać punktQ
z podpisu.
W poniższej próbce Q jest wartością zakodowaną na stałe
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);
Dodatkowe badania:
TO jest źródłem Bitcoin, które weryfikuje wiadomość.
Po zdekodowaniu Base64 podpisuRecoverCompact (hash wiadomości, podpis) jest nazywany. Nie jestem programistą C ++, więc zakładam, że muszę się dowiedzieć, jak to zrobićkey.Recover
Prace. To lubkey.GetPubKey
To jest kod C ++, którego potrzebuję w C #, najlepiej w nadmuchiwanym zamku ... ale wezmę wszystko, co działa.
// 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;
}
... kod dlaECDSA_SIG_recover_key_GFp jest tutaj
Niestandardowy format podpisu w Bitcoin
Ta odpowiedź mówi, że są 4 możliwe klucze publiczne, które mogą tworzyć sygnaturę, a to jest kodowane w nowszych sygnaturach.