Class: BSV::Wallet::ProtoWallet::KeyDeriver
- Inherits:
-
Object
- Object
- BSV::Wallet::ProtoWallet::KeyDeriver
- Includes:
- Validators
- Defined in:
- lib/bsv/wallet/proto_wallet/key_deriver.rb
Overview
BRC-42/43 key derivation.
Derives child keys from a root private key using BKDS (BSV Key Derivation Scheme). Supports protocol IDs, key IDs, counterparties, and security levels as defined in BRC-43.
Constant Summary collapse
- ANYONE_BN =
OpenSSL::BN.new(1)
Instance Attribute Summary collapse
-
#root_key ⇒ Object
readonly
Returns the value of attribute root_key.
Instance Method Summary collapse
-
#derive_private_key(protocol_id, key_id, counterparty) ⇒ BSV::Primitives::PrivateKey
Derives a private key using BRC-42 key derivation.
-
#derive_public_key(protocol_id, key_id, counterparty, for_self: false) ⇒ BSV::Primitives::PublicKey
Derives a public key using BRC-42 key derivation.
-
#derive_symmetric_key(protocol_id, key_id, counterparty) ⇒ BSV::Primitives::SymmetricKey
Derives a symmetric key for encryption/HMAC operations.
-
#identity_key ⇒ String
Returns the identity public key as a hex string.
-
#identity_key_bytes ⇒ String
Returns the identity public key as a 33-byte compressed binary string.
-
#initialize(root_key) ⇒ KeyDeriver
constructor
A new instance of KeyDeriver.
-
#reveal_counterparty_secret(counterparty) ⇒ String
Reveals the ECDH shared secret between this wallet and a counterparty.
-
#reveal_specific_secret(counterparty, protocol_id, key_id) ⇒ String
Reveals the specific key offset for a particular derived key.
Methods included from Validators
validate_counterparty!, validate_key_id!, validate_protocol_id!, validate_pub_key_hex!
Constructor Details
#initialize(root_key) ⇒ KeyDeriver
Returns a new instance of KeyDeriver.
21 22 23 24 25 26 27 28 29 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 21 def initialize(root_key) @root_key = if root_key == 'anyone' BSV::Primitives::PrivateKey.new(ANYONE_BN) elsif root_key.is_a?(BSV::Primitives::PrivateKey) root_key else raise ArgumentError, "expected a BSV::Primitives::PrivateKey or 'anyone', got #{root_key.class}" end end |
Instance Attribute Details
#root_key ⇒ Object (readonly)
Returns the value of attribute root_key.
18 19 20 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 18 def root_key @root_key end |
Instance Method Details
#derive_private_key(protocol_id, key_id, counterparty) ⇒ BSV::Primitives::PrivateKey
Derives a private key using BRC-42 key derivation.
77 78 79 80 81 82 83 84 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 77 def derive_private_key(protocol_id, key_id, counterparty) Validators.validate_protocol_id!(protocol_id) Validators.validate_key_id!(key_id) invoice = compute_invoice_number(protocol_id, key_id) BSV.logger&.debug { "[KeyDeriver] derive_private_key: invoice=#{invoice.inspect}" } counterparty_pub = resolve_counterparty(counterparty) @root_key.derive_child(counterparty_pub, invoice) end |
#derive_public_key(protocol_id, key_id, counterparty, for_self: false) ⇒ BSV::Primitives::PublicKey
Derives a public key using BRC-42 key derivation.
57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 57 def derive_public_key(protocol_id, key_id, counterparty, for_self: false) Validators.validate_protocol_id!(protocol_id) Validators.validate_key_id!(key_id) invoice = compute_invoice_number(protocol_id, key_id) BSV.logger&.debug { "[KeyDeriver] derive_public_key: invoice=#{invoice.inspect} for_self=#{for_self}" } counterparty_pub = resolve_counterparty(counterparty) if for_self @root_key.derive_child(counterparty_pub, invoice).public_key else counterparty_pub.derive_child(@root_key, invoice) end end |
#derive_symmetric_key(protocol_id, key_id, counterparty) ⇒ BSV::Primitives::SymmetricKey
Derives a symmetric key for encryption/HMAC operations.
Uses ECDH between the derived private and public child keys to produce a shared secret, then uses the X-coordinate as the key.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 95 def derive_symmetric_key(protocol_id, key_id, counterparty) Validators.validate_protocol_id!(protocol_id) Validators.validate_key_id!(key_id) invoice = compute_invoice_number(protocol_id, key_id) counterparty_pub = resolve_counterparty(counterparty) derived_private = @root_key.derive_child(counterparty_pub, invoice) derived_public = counterparty_pub.derive_child(@root_key, invoice) BSV::Primitives::SymmetricKey.from_ecdh(derived_private, derived_public) end |
#identity_key ⇒ String
Returns the identity public key as a hex string.
33 34 35 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 33 def identity_key @identity_key ||= @root_key.public_key.to_hex end |
#identity_key_bytes ⇒ String
Returns the identity public key as a 33-byte compressed binary string.
Pubkeys are hex-canonical in this SDK (see ADR-001 — the documented exception to binary-internal), so #identity_key (hex) is the default. This binary accessor exists for the rare sites that need raw bytes (e.g. feeding BSV::Primitives::Hash#hash160) without round-tripping hex → binary at each call.
46 47 48 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 46 def identity_key_bytes @identity_key_bytes ||= @root_key.public_key.compressed end |
#reveal_counterparty_secret(counterparty) ⇒ String
Reveals the ECDH shared secret between this wallet and a counterparty. Used for BRC-69 Method 1 (counterparty key linkage).
112 113 114 115 116 117 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 112 def reveal_counterparty_secret(counterparty) raise InvalidParameterError.new('counterparty', 'not "self" for key linkage revelation') if counterparty == 'self' counterparty_pub = resolve_counterparty(counterparty) @root_key.derive_shared_secret(counterparty_pub).compressed end |
#reveal_specific_secret(counterparty, protocol_id, key_id) ⇒ String
Reveals the specific key offset for a particular derived key. Used for BRC-69 Method 2 (specific key linkage).
126 127 128 129 130 131 132 133 |
# File 'lib/bsv/wallet/proto_wallet/key_deriver.rb', line 126 def reveal_specific_secret(counterparty, protocol_id, key_id) Validators.validate_protocol_id!(protocol_id) Validators.validate_key_id!(key_id) counterparty_pub = resolve_counterparty(counterparty) shared = @root_key.derive_shared_secret(counterparty_pub) invoice = compute_invoice_number(protocol_id, key_id) BSV::Primitives::Digest.hmac_sha256(shared.compressed, invoice.encode('UTF-8')) end |