Module: Solana::Ruby::Kit::Keys

Extended by:
T::Sig
Defined in:
lib/solana/ruby/kit/keys/key_pair.rb,
lib/solana/ruby/kit/keys/public_key.rb,
lib/solana/ruby/kit/keys/signatures.rb,
lib/solana/ruby/kit/keys/private_key.rb

Defined Under Namespace

Classes: KeyPair, Signature, SignatureBytes

Constant Summary collapse

SIGNATURE_MIN_STR_LEN =

Length bounds for a base58-encoded 64-byte signature string.

64
SIGNATURE_MAX_STR_LEN =
88

Class Method Summary collapse

Class Method Details

.assert_signature!(putative) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 80

def assert_signature!(putative)
  unless putative.length.between?(SIGNATURE_MIN_STR_LEN, SIGNATURE_MAX_STR_LEN)
    Kernel.raise SolanaError.new(
      SolanaError::KEYS__SIGNATURE_STRING_LENGTH_OUT_OF_RANGE,
      actual_length: putative.length
    )
  end

  bytes = Encoding::Base58.decode(putative)
  assert_signature_bytes!(bytes)
rescue ArgumentError
  Kernel.raise SolanaError.new(SolanaError::KEYS__SIGNATURE_STRING_LENGTH_OUT_OF_RANGE, actual_length: putative.length)
end

.assert_signature_bytes!(putative) ⇒ Object



112
113
114
115
116
117
118
119
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 112

def assert_signature_bytes!(putative)
  unless putative.bytesize == SignatureBytes::BYTE_LENGTH
    Kernel.raise SolanaError.new(
      SolanaError::KEYS__INVALID_SIGNATURE_BYTE_LENGTH,
      actual_length: putative.bytesize
    )
  end
end

.create_key_pair_from_bytes(bytes) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/solana/ruby/kit/keys/key_pair.rb', line 45

def create_key_pair_from_bytes(bytes)
  if bytes.bytesize != 64
    Kernel.raise SolanaError.new(
      SolanaError::KEYS__INVALID_KEY_PAIR_BYTE_LENGTH,
      byte_length: bytes.bytesize
    )
  end

  private_seed = bytes.byteslice(0, 32) || Kernel.raise(SolanaError.new(SolanaError::KEYS__INVALID_KEY_PAIR_BYTE_LENGTH, byte_length: bytes.bytesize))
  public_bytes = bytes.byteslice(32, 32) || Kernel.raise(SolanaError.new(SolanaError::KEYS__INVALID_KEY_PAIR_BYTE_LENGTH, byte_length: bytes.bytesize))

  signing_key = RbNaCl::SigningKey.new(private_seed.b)
  verify_key  = signing_key.verify_key

  # Verify that the embedded public key matches the derived one.
  unless verify_key.to_bytes == public_bytes.b
    Kernel.raise SolanaError.new(SolanaError::KEYS__PUBLIC_KEY_MUST_MATCH_PRIVATE_KEY)
  end

  # Round-trip sign-and-verify with random data (mirrors the TypeScript check).
  random_data = RbNaCl::Random.random_bytes(32)
  signed_data = sign_bytes(signing_key, random_data)
  unless verify_signature(verify_key, signed_data, random_data)
    Kernel.raise SolanaError.new(SolanaError::KEYS__PUBLIC_KEY_MUST_MATCH_PRIVATE_KEY)
  end

  KeyPair.new(signing_key: signing_key, verify_key: verify_key)
end

.create_key_pair_from_private_key_bytes(bytes) ⇒ Object



79
80
81
82
# File 'lib/solana/ruby/kit/keys/key_pair.rb', line 79

def create_key_pair_from_private_key_bytes(bytes)
  signing_key = RbNaCl::SigningKey.new(bytes.b)
  KeyPair.new(signing_key: signing_key, verify_key: signing_key.verify_key)
end

.create_private_key_from_bytes(bytes, extractable: false) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/solana/ruby/kit/keys/private_key.rb', line 28

def create_private_key_from_bytes(bytes, extractable: false)
  if bytes.bytesize != 32
    Kernel.raise SolanaError.new(
      SolanaError::KEYS__INVALID_KEY_PAIR_BYTE_LENGTH,
      byte_length: bytes.bytesize
    )
  end

  RbNaCl::SigningKey.new(bytes.b)
end

.decode_signature(sig) ⇒ Object



166
167
168
169
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 166

def decode_signature(sig)
  bytes = Encoding::Base58.decode(sig.value)
  signature_bytes(bytes)
end

.encode_signature(sig_bytes) ⇒ Object



160
161
162
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 160

def encode_signature(sig_bytes)
  Signature.new(Encoding::Base58.encode(sig_bytes.value))
end

.generate_key_pairObject



32
33
34
35
# File 'lib/solana/ruby/kit/keys/key_pair.rb', line 32

def generate_key_pair
  signing_key = RbNaCl::SigningKey.generate
  KeyPair.new(signing_key: signing_key, verify_key: signing_key.verify_key)
end

.get_public_key_from_private_key(signing_key, extractable: false) ⇒ Object



23
24
25
26
27
28
29
# File 'lib/solana/ruby/kit/keys/public_key.rb', line 23

def get_public_key_from_private_key(signing_key, extractable: false)
  unless signing_key.respond_to?(:verify_key)
    Kernel.raise SolanaError.new(SolanaError::ADDRESSES__INVALID_ED25519_PUBLIC_KEY)
  end

  signing_key.verify_key
end

.sign_bytes(signing_key, data) ⇒ Object



137
138
139
140
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 137

def sign_bytes(signing_key, data)
  raw = signing_key.sign(data.b)
  SignatureBytes.new(raw)
end

.signature(putative) ⇒ Object



97
98
99
100
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 97

def signature(putative)
  assert_signature!(putative)
  Signature.new(putative)
end

.signature?(putative) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
74
75
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 68

def signature?(putative)
  return false unless putative.length.between?(SIGNATURE_MIN_STR_LEN, SIGNATURE_MAX_STR_LEN)

  bytes = Encoding::Base58.decode(putative)
  bytes.bytesize == SignatureBytes::BYTE_LENGTH
rescue ArgumentError
  false
end

.signature_bytes(putative) ⇒ Object



124
125
126
127
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 124

def signature_bytes(putative)
  assert_signature_bytes!(putative)
  SignatureBytes.new(putative.b)
end

.signature_bytes?(putative) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 105

def signature_bytes?(putative)
  putative.bytesize == SignatureBytes::BYTE_LENGTH
end

.verify_signature(verify_key, sig_bytes, data) ⇒ Object



151
152
153
154
155
156
# File 'lib/solana/ruby/kit/keys/signatures.rb', line 151

def verify_signature(verify_key, sig_bytes, data)
  verify_key.verify(sig_bytes.value, data.b)
  true
rescue RbNaCl::BadSignatureError
  false
end