nkeys-rb 0.4.5.0-arm-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6f780464183e5852119c9a266f95ff9f5997e6f4946f4b2772aaf98219f9a49a
4
+ data.tar.gz: e490e1a316931b12938dda7c981cab573a952ad240578430e5bf96106d4f2eaa
5
+ SHA512:
6
+ metadata.gz: 788180ecd8fdd6e907661148f20264a9efe987a457ddce2a4a63054df406fb62bbe55d05be3c17101e1782f495815722b8f7b6794cae61faa2c7fbd0c06a2f54
7
+ data.tar.gz: bd54abf9d2ac2f0fdc098176f527ea70582cdb9c94354b511831325f772fb02237864e4b3a97e0ffea4bbbb3cb51bac4d8e8faa36d2bb700469f40e5300effee
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # nkeys-rb
2
+
3
+ Ruby bindings for the Rust [`nkeys`](https://crates.io/crates/nkeys) crate.
4
+
5
+ NKeys is the NATS key format: an Ed25519 keypair whose public half is
6
+ base32-encoded behind a prefix byte naming its role (`A...` account, `U...`
7
+ user, `N...` server), with a CRC-16 check — plus a separate x25519 "xkey"
8
+ (`X...`) used for encryption rather than signing.
9
+
10
+ ## Why this exists
11
+
12
+ There is already an `nkeys` gem on rubygems.org. It stopped at 0.1.0 and is
13
+ incomplete in two ways that matter to anything implementing NATS
14
+ [auth callout](https://docs.nats.io/learn/security/auth-callout):
15
+
16
+ 1. Its `public_key` hardcodes the **user** prefix byte, so an account keypair
17
+ reports a `U...` key rather than the `A...` a server config names in
18
+ `auth_callout.issuer`. A verdict signed by a key the server cannot name is
19
+ refused.
20
+ 2. It has no concept of **xkeys** at all — no prefix, no key type, no
21
+ seal/open — so the encrypted form of auth callout cannot be spoken.
22
+
23
+ Hence the name: `nkeys-rb`, because `nkeys` is taken.
24
+
25
+ This gem is only the key primitives. Building the NATS JWTs an auth callout
26
+ answers with is ordinary Ruby work (JSON, base64url, `SHA512-256`, base32) and
27
+ deliberately lives in the caller.
28
+
29
+ ## Usage
30
+
31
+ ```ruby
32
+ require "nkeys"
33
+
34
+ account = NKeys::KeyPair.generate("account")
35
+ account.public_key # => "A..." — goes in the server config
36
+ account.seed # => "SA..." — goes in a secret
37
+
38
+ signature = account.sign("payload")
39
+ account.verify("payload", signature) # => true
40
+
41
+ # Verify-only, from a public key alone.
42
+ NKeys::KeyPair.from_public_key(account.public_key).verify("payload", signature)
43
+
44
+ # xkeys encrypt rather than sign.
45
+ service = NKeys::XKey.generate
46
+ server = NKeys::XKey.generate
47
+
48
+ sealed = server.seal("credentials", service.public_key)
49
+ service.open(sealed, server.public_key) # => "credentials"
50
+ ```
51
+
52
+ Roles accepted by `KeyPair.generate`: `account`, `user`, `server`, `operator`,
53
+ `cluster`.
54
+
55
+ ## Development
56
+
57
+ The repository ships a `flake.nix` with Ruby, the Rust toolchain and the
58
+ libclang that `rb_sys`' bindgen needs:
59
+
60
+ ```bash
61
+ direnv allow # or: nix develop
62
+ bundle install
63
+ bundle exec rake compile
64
+ bin/test
65
+ ```
66
+
67
+ ## Versioning
68
+
69
+ The gem version is `<nkeys crate version>.<our release>`:
70
+
71
+ ```
72
+ nkeys-rb 0.4.5.0
73
+ └─┬─┘ └ our release against that crate
74
+ └ the Rust nkeys crate this wraps
75
+ ```
76
+
77
+ So `nkeys-rb 0.4.5.2` is the third build of this gem against `nkeys 0.4.5`. The
78
+ crate is pinned exactly in `ext/nkeys/Cargo.toml` (`version = "=0.4.5"`) so the
79
+ claim cannot quietly become false — `bin/increment-version` moves both together.
80
+
81
+ Depend on it pessimistically to the fourth segment (`~> 0.4.5.0`) and you track
82
+ our fixes without silently moving to a new crate.
83
+
84
+ ## Releasing
85
+
86
+ Consumers must never need Rust. That is the whole point: `bundle install` should
87
+ find a gem for its platform with the `.so` already inside, rather than a source
88
+ gem that shells out to `cargo`.
89
+
90
+ A release is TWO kinds of gem for the same version — the source gem (the
91
+ fallback for any platform not precompiled) and one precompiled gem per platform.
92
+ CI builds the second kind; `bin/release-gem` builds the first and pushes both.
93
+
94
+ ```bash
95
+ bin/increment-version # bump our segment: 0.4.5.0 -> 0.4.5.1
96
+ # ...or, to track a new crate release (also repins ext/nkeys/Cargo.toml):
97
+ # bin/increment-version 0.4.6 # -> 0.4.6.0
98
+ git commit -am "Bump to $(ruby -Ilib -rnkeys/version -e 'print NKeys::VERSION')"
99
+ git push origin main # cross-compile.yml builds the platform gems
100
+ # ...wait for that run to go green...
101
+ bin/release-gem # downloads them, builds the source gem, pushes all
102
+ ```
103
+
104
+ `bin/release-gem` refuses to run if the local version is not ahead of what is
105
+ already on RubyGems, and if the latest green CI run built a different version it
106
+ says so rather than publishing a mismatched set. It tolerates gems that are
107
+ already published, so a release that dies partway through can simply be re-run.
108
+
109
+ It needs the [GitHub CLI](https://cli.github.com) to fetch the CI artifacts.
110
+
111
+ ## Testing
112
+
113
+ Specs are co-located with the code they cover, in `__END__` blocks, and run with
114
+ [scampi](https://github.com/general-intelligence-systems/scampi):
115
+
116
+ ```bash
117
+ bin/test
118
+ ```
119
+
120
+ `bundle exec lefthook install` wires that plus a trufflehog secret scan into a
121
+ pre-commit hook.
Binary file
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NKeys
4
+ # <nkeys crate version>.<our release>. The first three segments say which
5
+ # version of the Rust crate this gem wraps; the fourth is ours, bumped for
6
+ # changes on the Ruby side against that same crate. Managed by
7
+ # bin/increment-version -- edit that, not this.
8
+ VERSION = "0.4.5.0"
9
+ end
data/lib/nkeys.rb ADDED
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NATS NKeys for Ruby, over the Rust `nkeys` crate.
4
+ #
5
+ # The classes (NKeys::KeyPair, NKeys::XKey) are defined by the native
6
+ # extension's #[magnus::init]; this file only locates and requires the compiled
7
+ # object. See ext/nkeys/src/lib.rs for what each method does and why this is a
8
+ # binding rather than a pure-Ruby implementation.
9
+ #
10
+ # account = NKeys::KeyPair.generate("account")
11
+ # account.public_key # => "A..."
12
+ # account.seed # => "SA..."
13
+ # account.sign("payload") # => raw Ed25519 signature bytes
14
+ #
15
+ # xkey = NKeys::XKey.generate
16
+ # xkey.public_key # => "X..."
17
+ # sealed = xkey.seal("secret", recipient_public_key)
18
+ # xkey.open(sealed, sender_public_key)
19
+
20
+ require_relative "nkeys/version"
21
+
22
+ module NKeys
23
+ end
24
+
25
+ # Precompiled ("fat") gems ship one .so per Ruby minor version under a versioned
26
+ # subdir (lib/nkeys/3.3/nkeys_rb.so). A locally source-compiled build lands flat,
27
+ # in lib/nkeys/. Try the versioned path first, then fall back to the flat one.
28
+ begin
29
+ RUBY_VERSION =~ /(\d+\.\d+)/
30
+ require_relative "nkeys/#{Regexp.last_match(1)}/nkeys_rb"
31
+ rescue LoadError
32
+ require_relative "nkeys/nkeys_rb"
33
+ end
34
+
35
+ __END__
36
+ describe "NKeys::KeyPair" do
37
+ it "prefixes the public key by role" do
38
+ # The whole reason this binding exists: the pure-Ruby nkeys gem reports a
39
+ # U... key for every role, so an account key could not be named in a
40
+ # server's auth_callout.issuer.
41
+ NKeys::KeyPair.generate("account").public_key.should.start_with "A"
42
+ NKeys::KeyPair.generate("user").public_key.should.start_with "U"
43
+ NKeys::KeyPair.generate("server").public_key.should.start_with "N"
44
+ end
45
+
46
+ it "rejects an unknown role" do
47
+ lambda { NKeys::KeyPair.generate("wombat") }.should.raise(ArgumentError)
48
+ end
49
+
50
+ it "round-trips through its seed" do
51
+ original = NKeys::KeyPair.generate("account")
52
+ restored = NKeys::KeyPair.from_seed(original.seed)
53
+
54
+ # A seed carries its own role, so the restored key keeps the A... prefix
55
+ # without being told which role it was.
56
+ restored.public_key.should == original.public_key
57
+ end
58
+
59
+ it "signs and verifies" do
60
+ key = NKeys::KeyPair.generate("account")
61
+ signature = key.sign("payload")
62
+
63
+ key.verify("payload", signature).should == true
64
+ key.verify("tampered", signature).should == false
65
+ end
66
+
67
+ it "verifies with a public-key-only keypair" do
68
+ key = NKeys::KeyPair.generate("account")
69
+ signature = key.sign("payload")
70
+
71
+ NKeys::KeyPair.from_public_key(key.public_key).verify("payload", signature).should == true
72
+ end
73
+
74
+ it "cannot sign with a public-key-only keypair" do
75
+ key = NKeys::KeyPair.from_public_key(NKeys::KeyPair.generate("account").public_key)
76
+
77
+ lambda { key.sign("payload") }.should.raise(RuntimeError)
78
+ end
79
+ end
80
+
81
+ describe "NKeys::XKey" do
82
+ it "prefixes the public key with X" do
83
+ NKeys::XKey.generate.public_key.should.start_with "X"
84
+ end
85
+
86
+ it "round-trips a sealed message between two xkeys" do
87
+ # The shape auth callout uses: the server seals a request to the service's
88
+ # xkey, and the service seals its response back to the server's.
89
+ server = NKeys::XKey.generate
90
+ service = NKeys::XKey.generate
91
+
92
+ sealed = server.seal("credentials", service.public_key)
93
+ service.open(sealed, server.public_key).should == "credentials"
94
+ end
95
+
96
+ it "refuses to open a message sealed for someone else" do
97
+ server = NKeys::XKey.generate
98
+ service = NKeys::XKey.generate
99
+ stranger = NKeys::XKey.generate
100
+
101
+ sealed = server.seal("credentials", service.public_key)
102
+
103
+ lambda { stranger.open(sealed, server.public_key) }.should.raise(RuntimeError)
104
+ end
105
+
106
+ it "round-trips through its seed" do
107
+ original = NKeys::XKey.generate
108
+ restored = NKeys::XKey.from_seed(original.seed)
109
+
110
+ restored.public_key.should == original.public_key
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nkeys-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.5.0
5
+ platform: arm-linux
6
+ authors:
7
+ - Nathan Kidd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake-compiler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: scampi
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: lefthook
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ description: 'NATS NKeys for Ruby, as a native extension over the Rust `nkeys` crate:
70
+ Ed25519 keypairs across every key role, and the x25519 XKey sealing used by NATS
71
+ auth callout. Named nkeys-rb because the plain `nkeys` gem name is taken by an unrelated
72
+ pure-Ruby implementation.'
73
+ email:
74
+ - nathankidd@hey.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - README.md
80
+ - lib/nkeys.rb
81
+ - lib/nkeys/3.3/nkeys_rb.so
82
+ - lib/nkeys/3.4/nkeys_rb.so
83
+ - lib/nkeys/4.0/nkeys_rb.so
84
+ - lib/nkeys/version.rb
85
+ homepage: https://github.com/n-at-han-k/nkeys-rb
86
+ licenses:
87
+ - Apache-2.0
88
+ metadata:
89
+ homepage_uri: https://github.com/n-at-han-k/nkeys-rb
90
+ source_code_uri: https://github.com/n-at-han-k/nkeys-rb
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '3.3'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: 4.1.dev
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.5.23
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Ruby bindings for the Rust nkeys crate.
113
+ test_files: []