| 286 | } |
| 287 | |
| 288 | bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const |
| 289 | { |
| 290 | assert(sig.size() == 64); |
| 291 | secp256k1_keypair keypair; |
| 292 | if (!secp256k1_keypair_create(secp256k1_context_sign, &keypair, begin())) return false; |
| 293 | if (merkle_root) { |
| 294 | secp256k1_xonly_pubkey pubkey; |
| 295 | if (!secp256k1_keypair_xonly_pub(secp256k1_context_sign, &pubkey, nullptr, &keypair)) return false; |
| 296 | unsigned char pubkey_bytes[32]; |
| 297 | if (!secp256k1_xonly_pubkey_serialize(secp256k1_context_sign, pubkey_bytes, &pubkey)) return false; |
| 298 | uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root); |
| 299 | if (!secp256k1_keypair_xonly_tweak_add(GetVerifyContext(), &keypair, tweak.data())) return false; |
| 300 | } |
| 301 | bool ret = secp256k1_schnorrsig_sign32(secp256k1_context_sign, sig.data(), hash.data(), &keypair, aux.data()); |
| 302 | if (ret) { |
| 303 | // Additional verification step to prevent using a potentially corrupted signature |
| 304 | secp256k1_xonly_pubkey pubkey_verify; |
| 305 | ret = secp256k1_keypair_xonly_pub(GetVerifyContext(), &pubkey_verify, nullptr, &keypair); |
| 306 | ret &= secp256k1_schnorrsig_verify(GetVerifyContext(), sig.data(), hash.begin(), 32, &pubkey_verify); |
| 307 | } |
| 308 | if (!ret) memory_cleanse(sig.data(), sig.size()); |
| 309 | memory_cleanse(&keypair, sizeof(keypair)); |
| 310 | return ret; |
| 311 | } |
| 312 | |
| 313 | bool CKey::Load(const CPrivKey &seckey, const CPubKey &vchPubKey, bool fSkipCheck=false) { |
| 314 | if (!ec_seckey_import_der(secp256k1_context_sign, (unsigned char*)begin(), seckey.data(), seckey.size())) |