Class: KeyPairs::KeyPairs
- Inherits:
-
Object
- Object
- KeyPairs::KeyPairs
- Defined in:
- lib/key-pairs/key_pairs.rb
Overview
Main entry point for XRPL key pair operations.
Instance Method Summary collapse
-
#derive_address(public_key) ⇒ String
Derives an XRP address from a public key.
-
#derive_key_pair(seed, options = {}) ⇒ Hash
Derives a key pair from an encoded seed.
-
#generate_seed(entropy = nil, type = 'secp256k1') ⇒ String
Generates a new seed.
-
#initialize ⇒ KeyPairs
constructor
A new instance of KeyPairs.
-
#sign(message, private_key, algorithm = nil) ⇒ String
Signs a message with a private key.
-
#verify(message, signature, public_key) ⇒ Boolean
Verifies a signature.
Constructor Details
#initialize ⇒ KeyPairs
Returns a new instance of KeyPairs.
8 9 10 |
# File 'lib/key-pairs/key_pairs.rb', line 8 def initialize @address_codec = AddressCodec::AddressCodec.new end |
Instance Method Details
#derive_address(public_key) ⇒ String
Derives an XRP address from a public key.
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/key-pairs/key_pairs.rb', line 81 def derive_address(public_key) public_key_bytes = [public_key].pack('H*') # Account ID is RIPEMD160(SHA256(public_key)) sha256 = Digest::SHA256.digest(public_key_bytes) # Ruby doesn't have RIPEMD160 in Digest by default sometimes, # but OpenSSL has it. ripemd160 = OpenSSL::Digest.new('RIPEMD160').digest(sha256) @address_codec.encode_account_id(ripemd160.unpack('C*')) end |
#derive_key_pair(seed, options = {}) ⇒ Hash
Derives a key pair from an encoded seed.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/key-pairs/key_pairs.rb', line 25 def derive_key_pair(seed, = {}) decoded = @address_codec.decode_seed(seed) type = decoded[:type] entropy = decoded[:bytes] if type == 'ed25519' Ed25519.derive_key_pair(entropy) else # For secp256k1, we use the entropy as seed Secp256k1.derive_key_pair(entropy) end end |
#generate_seed(entropy = nil, type = 'secp256k1') ⇒ String
Generates a new seed.
16 17 18 19 |
# File 'lib/key-pairs/key_pairs.rb', line 16 def generate_seed(entropy = nil, type = 'secp256k1') entropy ||= SecureRandom.random_bytes(16).bytes @address_codec.encode_seed(entropy, type) end |
#sign(message, private_key, algorithm = nil) ⇒ String
Signs a message with a private key.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/key-pairs/key_pairs.rb', line 43 def sign(, private_key, algorithm = nil) if algorithm == 'ed25519' || (algorithm.nil? && private_key.length == 64) # Heuristic: Ed25519 private keys in our lib are 32 bytes (64 hex chars). # Secp256k1 are also 32 bytes, but Ed25519 is often explicitly requested. # Actually, let's look at the prefix of the public key if we had it. # Since we don't have the public key here, we rely on the caller or length. # In XRPL-Ruby, Ed25519 private keys are 64 hex chars (32 bytes). # Secp256k1 are also 64 hex chars. This is ambiguous! # Let's try to see if it's explicitly 'ed25519'. begin return Ed25519.sign(, private_key) if algorithm == 'ed25519' return Secp256k1.sign(, private_key) rescue => e # If secp fails and we didn't specify, maybe it was ed? # But that's dangerous. raise e end else Secp256k1.sign(, private_key) end end |
#verify(message, signature, public_key) ⇒ Boolean
Verifies a signature.
70 71 72 73 74 75 76 |
# File 'lib/key-pairs/key_pairs.rb', line 70 def verify(, signature, public_key) if public_key.start_with?('ED') Ed25519.verify(, signature, public_key) else Secp256k1.verify(, signature, public_key) end end |