nkeys-rb 0.4.5.0
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 +7 -0
- data/Cargo.lock +710 -0
- data/Cargo.toml +7 -0
- data/README.md +121 -0
- data/ext/nkeys/Cargo.toml +31 -0
- data/ext/nkeys/extconf.rb +8 -0
- data/ext/nkeys/src/lib.rs +217 -0
- data/lib/nkeys/version.rb +9 -0
- data/lib/nkeys.rb +112 -0
- metadata +124 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1de6543d9e7a964389eba74589dbee086974c9f177e439cceda3f9ef752ae132
|
|
4
|
+
data.tar.gz: 87d70ee4132991fc0a986dc2947217e6ef05ad067b1c140f02c7daf427a7d133
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4d138de4e710dbf2241232c0417f6ca16a3ef8c900dd1c487b29ac1289e47c7305d445b309cf6bcd4f050f16abeda4754b5b166df0d50e0d5ffea89f815580c8
|
|
7
|
+
data.tar.gz: e89a81dea9e9c77ec51cd9d7c1df3fd76a99a74864391c736e132732da51636bc07a5f0c218c74c88bcbae0f19ce4e05a8faecf87bb21c705784658aeb7568ef
|
data/Cargo.lock
ADDED
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "aead"
|
|
7
|
+
version = "0.5.2"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"crypto-common",
|
|
12
|
+
"generic-array",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[[package]]
|
|
16
|
+
name = "aho-corasick"
|
|
17
|
+
version = "1.1.5"
|
|
18
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
19
|
+
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"memchr",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[package]]
|
|
25
|
+
name = "base64ct"
|
|
26
|
+
version = "1.8.3"
|
|
27
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
28
|
+
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
|
29
|
+
|
|
30
|
+
[[package]]
|
|
31
|
+
name = "bindgen"
|
|
32
|
+
version = "0.72.1"
|
|
33
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
34
|
+
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
|
35
|
+
dependencies = [
|
|
36
|
+
"bitflags",
|
|
37
|
+
"cexpr",
|
|
38
|
+
"clang-sys",
|
|
39
|
+
"itertools",
|
|
40
|
+
"proc-macro2",
|
|
41
|
+
"quote",
|
|
42
|
+
"regex",
|
|
43
|
+
"rustc-hash",
|
|
44
|
+
"shlex",
|
|
45
|
+
"syn",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "bitflags"
|
|
50
|
+
version = "2.13.1"
|
|
51
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
|
+
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
|
53
|
+
|
|
54
|
+
[[package]]
|
|
55
|
+
name = "block-buffer"
|
|
56
|
+
version = "0.10.4"
|
|
57
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
|
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
|
59
|
+
dependencies = [
|
|
60
|
+
"generic-array",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[[package]]
|
|
64
|
+
name = "cexpr"
|
|
65
|
+
version = "0.6.0"
|
|
66
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
67
|
+
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
|
68
|
+
dependencies = [
|
|
69
|
+
"nom",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[[package]]
|
|
73
|
+
name = "cfg-if"
|
|
74
|
+
version = "1.0.4"
|
|
75
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
76
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
77
|
+
|
|
78
|
+
[[package]]
|
|
79
|
+
name = "cipher"
|
|
80
|
+
version = "0.4.4"
|
|
81
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
82
|
+
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
|
83
|
+
dependencies = [
|
|
84
|
+
"crypto-common",
|
|
85
|
+
"inout",
|
|
86
|
+
"zeroize",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[[package]]
|
|
90
|
+
name = "clang-sys"
|
|
91
|
+
version = "1.9.1"
|
|
92
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
93
|
+
checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a"
|
|
94
|
+
dependencies = [
|
|
95
|
+
"glob",
|
|
96
|
+
"libc",
|
|
97
|
+
"libloading",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[[package]]
|
|
101
|
+
name = "const-oid"
|
|
102
|
+
version = "0.9.6"
|
|
103
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
104
|
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
|
105
|
+
|
|
106
|
+
[[package]]
|
|
107
|
+
name = "cpufeatures"
|
|
108
|
+
version = "0.2.17"
|
|
109
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
110
|
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
|
111
|
+
dependencies = [
|
|
112
|
+
"libc",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
[[package]]
|
|
116
|
+
name = "crypto-common"
|
|
117
|
+
version = "0.1.7"
|
|
118
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
119
|
+
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
|
120
|
+
dependencies = [
|
|
121
|
+
"generic-array",
|
|
122
|
+
"rand_core",
|
|
123
|
+
"typenum",
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
[[package]]
|
|
127
|
+
name = "crypto_box"
|
|
128
|
+
version = "0.9.1"
|
|
129
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
130
|
+
checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009"
|
|
131
|
+
dependencies = [
|
|
132
|
+
"aead",
|
|
133
|
+
"crypto_secretbox",
|
|
134
|
+
"curve25519-dalek",
|
|
135
|
+
"salsa20",
|
|
136
|
+
"subtle",
|
|
137
|
+
"zeroize",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
[[package]]
|
|
141
|
+
name = "crypto_secretbox"
|
|
142
|
+
version = "0.1.1"
|
|
143
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
144
|
+
checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1"
|
|
145
|
+
dependencies = [
|
|
146
|
+
"aead",
|
|
147
|
+
"cipher",
|
|
148
|
+
"generic-array",
|
|
149
|
+
"poly1305",
|
|
150
|
+
"salsa20",
|
|
151
|
+
"subtle",
|
|
152
|
+
"zeroize",
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "curve25519-dalek"
|
|
157
|
+
version = "4.1.3"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
|
160
|
+
dependencies = [
|
|
161
|
+
"cfg-if",
|
|
162
|
+
"cpufeatures",
|
|
163
|
+
"curve25519-dalek-derive",
|
|
164
|
+
"digest",
|
|
165
|
+
"fiat-crypto",
|
|
166
|
+
"rustc_version",
|
|
167
|
+
"subtle",
|
|
168
|
+
"zeroize",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "curve25519-dalek-derive"
|
|
173
|
+
version = "0.1.1"
|
|
174
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
175
|
+
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
|
176
|
+
dependencies = [
|
|
177
|
+
"proc-macro2",
|
|
178
|
+
"quote",
|
|
179
|
+
"syn",
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
[[package]]
|
|
183
|
+
name = "data-encoding"
|
|
184
|
+
version = "2.11.1"
|
|
185
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
186
|
+
checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
|
|
187
|
+
|
|
188
|
+
[[package]]
|
|
189
|
+
name = "der"
|
|
190
|
+
version = "0.7.10"
|
|
191
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
192
|
+
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
|
193
|
+
dependencies = [
|
|
194
|
+
"const-oid",
|
|
195
|
+
"pem-rfc7468",
|
|
196
|
+
"zeroize",
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
[[package]]
|
|
200
|
+
name = "digest"
|
|
201
|
+
version = "0.10.7"
|
|
202
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
203
|
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|
204
|
+
dependencies = [
|
|
205
|
+
"block-buffer",
|
|
206
|
+
"crypto-common",
|
|
207
|
+
]
|
|
208
|
+
|
|
209
|
+
[[package]]
|
|
210
|
+
name = "ed25519"
|
|
211
|
+
version = "2.2.3"
|
|
212
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
213
|
+
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
|
214
|
+
dependencies = [
|
|
215
|
+
"signature",
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
[[package]]
|
|
219
|
+
name = "ed25519-dalek"
|
|
220
|
+
version = "2.2.0"
|
|
221
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
222
|
+
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
|
223
|
+
dependencies = [
|
|
224
|
+
"curve25519-dalek",
|
|
225
|
+
"ed25519",
|
|
226
|
+
"sha2",
|
|
227
|
+
"signature",
|
|
228
|
+
"subtle",
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
[[package]]
|
|
232
|
+
name = "either"
|
|
233
|
+
version = "1.17.0"
|
|
234
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
235
|
+
checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
|
|
236
|
+
|
|
237
|
+
[[package]]
|
|
238
|
+
name = "fiat-crypto"
|
|
239
|
+
version = "0.2.9"
|
|
240
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
241
|
+
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
|
242
|
+
|
|
243
|
+
[[package]]
|
|
244
|
+
name = "generic-array"
|
|
245
|
+
version = "0.14.7"
|
|
246
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
247
|
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
248
|
+
dependencies = [
|
|
249
|
+
"typenum",
|
|
250
|
+
"version_check",
|
|
251
|
+
"zeroize",
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
[[package]]
|
|
255
|
+
name = "getrandom"
|
|
256
|
+
version = "0.2.17"
|
|
257
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
258
|
+
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
|
259
|
+
dependencies = [
|
|
260
|
+
"cfg-if",
|
|
261
|
+
"libc",
|
|
262
|
+
"wasi",
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
[[package]]
|
|
266
|
+
name = "glob"
|
|
267
|
+
version = "0.3.4"
|
|
268
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
269
|
+
checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
|
|
270
|
+
|
|
271
|
+
[[package]]
|
|
272
|
+
name = "inout"
|
|
273
|
+
version = "0.1.4"
|
|
274
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
275
|
+
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
|
276
|
+
dependencies = [
|
|
277
|
+
"generic-array",
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
[[package]]
|
|
281
|
+
name = "itertools"
|
|
282
|
+
version = "0.13.0"
|
|
283
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
284
|
+
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|
285
|
+
dependencies = [
|
|
286
|
+
"either",
|
|
287
|
+
]
|
|
288
|
+
|
|
289
|
+
[[package]]
|
|
290
|
+
name = "lazy_static"
|
|
291
|
+
version = "1.5.0"
|
|
292
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
293
|
+
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
294
|
+
|
|
295
|
+
[[package]]
|
|
296
|
+
name = "libc"
|
|
297
|
+
version = "0.2.189"
|
|
298
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
299
|
+
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|
300
|
+
|
|
301
|
+
[[package]]
|
|
302
|
+
name = "libloading"
|
|
303
|
+
version = "0.8.9"
|
|
304
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
305
|
+
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
|
306
|
+
dependencies = [
|
|
307
|
+
"cfg-if",
|
|
308
|
+
"windows-link",
|
|
309
|
+
]
|
|
310
|
+
|
|
311
|
+
[[package]]
|
|
312
|
+
name = "log"
|
|
313
|
+
version = "0.4.33"
|
|
314
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
315
|
+
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
|
316
|
+
|
|
317
|
+
[[package]]
|
|
318
|
+
name = "magnus"
|
|
319
|
+
version = "0.8.2"
|
|
320
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
321
|
+
checksum = "3b36a5b126bbe97eb0d02d07acfeb327036c6319fd816139a49824a83b7f9012"
|
|
322
|
+
dependencies = [
|
|
323
|
+
"magnus-macros",
|
|
324
|
+
"rb-sys",
|
|
325
|
+
"rb-sys-env",
|
|
326
|
+
"seq-macro",
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
[[package]]
|
|
330
|
+
name = "magnus-macros"
|
|
331
|
+
version = "0.8.0"
|
|
332
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
333
|
+
checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
|
|
334
|
+
dependencies = [
|
|
335
|
+
"proc-macro2",
|
|
336
|
+
"quote",
|
|
337
|
+
"syn",
|
|
338
|
+
]
|
|
339
|
+
|
|
340
|
+
[[package]]
|
|
341
|
+
name = "memchr"
|
|
342
|
+
version = "2.8.3"
|
|
343
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
344
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
345
|
+
|
|
346
|
+
[[package]]
|
|
347
|
+
name = "minimal-lexical"
|
|
348
|
+
version = "0.2.1"
|
|
349
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
350
|
+
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
351
|
+
|
|
352
|
+
[[package]]
|
|
353
|
+
name = "nkeys"
|
|
354
|
+
version = "0.4.5"
|
|
355
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
356
|
+
checksum = "879011babc47a1c7fdf5a935ae3cfe94f34645ca0cac1c7f6424b36fc743d1bf"
|
|
357
|
+
dependencies = [
|
|
358
|
+
"crypto_box",
|
|
359
|
+
"data-encoding",
|
|
360
|
+
"ed25519",
|
|
361
|
+
"ed25519-dalek",
|
|
362
|
+
"getrandom",
|
|
363
|
+
"log",
|
|
364
|
+
"rand",
|
|
365
|
+
"signatory",
|
|
366
|
+
]
|
|
367
|
+
|
|
368
|
+
[[package]]
|
|
369
|
+
name = "nkeys_rb"
|
|
370
|
+
version = "0.1.0"
|
|
371
|
+
dependencies = [
|
|
372
|
+
"magnus",
|
|
373
|
+
"nkeys",
|
|
374
|
+
]
|
|
375
|
+
|
|
376
|
+
[[package]]
|
|
377
|
+
name = "nom"
|
|
378
|
+
version = "7.1.3"
|
|
379
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
380
|
+
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
|
381
|
+
dependencies = [
|
|
382
|
+
"memchr",
|
|
383
|
+
"minimal-lexical",
|
|
384
|
+
]
|
|
385
|
+
|
|
386
|
+
[[package]]
|
|
387
|
+
name = "opaque-debug"
|
|
388
|
+
version = "0.3.1"
|
|
389
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
390
|
+
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
|
391
|
+
|
|
392
|
+
[[package]]
|
|
393
|
+
name = "pem-rfc7468"
|
|
394
|
+
version = "0.7.0"
|
|
395
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
396
|
+
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
|
|
397
|
+
dependencies = [
|
|
398
|
+
"base64ct",
|
|
399
|
+
]
|
|
400
|
+
|
|
401
|
+
[[package]]
|
|
402
|
+
name = "pkcs8"
|
|
403
|
+
version = "0.10.2"
|
|
404
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
405
|
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
|
406
|
+
dependencies = [
|
|
407
|
+
"der",
|
|
408
|
+
"spki",
|
|
409
|
+
]
|
|
410
|
+
|
|
411
|
+
[[package]]
|
|
412
|
+
name = "poly1305"
|
|
413
|
+
version = "0.8.0"
|
|
414
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
415
|
+
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
|
416
|
+
dependencies = [
|
|
417
|
+
"cpufeatures",
|
|
418
|
+
"opaque-debug",
|
|
419
|
+
"universal-hash",
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
[[package]]
|
|
423
|
+
name = "ppv-lite86"
|
|
424
|
+
version = "0.2.21"
|
|
425
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
426
|
+
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
|
427
|
+
dependencies = [
|
|
428
|
+
"zerocopy",
|
|
429
|
+
]
|
|
430
|
+
|
|
431
|
+
[[package]]
|
|
432
|
+
name = "proc-macro2"
|
|
433
|
+
version = "1.0.107"
|
|
434
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
435
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
436
|
+
dependencies = [
|
|
437
|
+
"unicode-ident",
|
|
438
|
+
]
|
|
439
|
+
|
|
440
|
+
[[package]]
|
|
441
|
+
name = "quote"
|
|
442
|
+
version = "1.0.47"
|
|
443
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
444
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
445
|
+
dependencies = [
|
|
446
|
+
"proc-macro2",
|
|
447
|
+
]
|
|
448
|
+
|
|
449
|
+
[[package]]
|
|
450
|
+
name = "rand"
|
|
451
|
+
version = "0.8.7"
|
|
452
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
453
|
+
checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
|
|
454
|
+
dependencies = [
|
|
455
|
+
"libc",
|
|
456
|
+
"rand_chacha",
|
|
457
|
+
"rand_core",
|
|
458
|
+
]
|
|
459
|
+
|
|
460
|
+
[[package]]
|
|
461
|
+
name = "rand_chacha"
|
|
462
|
+
version = "0.3.1"
|
|
463
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
464
|
+
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
|
465
|
+
dependencies = [
|
|
466
|
+
"ppv-lite86",
|
|
467
|
+
"rand_core",
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
[[package]]
|
|
471
|
+
name = "rand_core"
|
|
472
|
+
version = "0.6.4"
|
|
473
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
474
|
+
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
475
|
+
dependencies = [
|
|
476
|
+
"getrandom",
|
|
477
|
+
]
|
|
478
|
+
|
|
479
|
+
[[package]]
|
|
480
|
+
name = "rb-sys"
|
|
481
|
+
version = "0.9.128"
|
|
482
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
483
|
+
checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a"
|
|
484
|
+
dependencies = [
|
|
485
|
+
"rb-sys-build",
|
|
486
|
+
]
|
|
487
|
+
|
|
488
|
+
[[package]]
|
|
489
|
+
name = "rb-sys-build"
|
|
490
|
+
version = "0.9.128"
|
|
491
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
492
|
+
checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a"
|
|
493
|
+
dependencies = [
|
|
494
|
+
"bindgen",
|
|
495
|
+
"lazy_static",
|
|
496
|
+
"proc-macro2",
|
|
497
|
+
"quote",
|
|
498
|
+
"regex",
|
|
499
|
+
"shell-words",
|
|
500
|
+
"syn",
|
|
501
|
+
]
|
|
502
|
+
|
|
503
|
+
[[package]]
|
|
504
|
+
name = "rb-sys-env"
|
|
505
|
+
version = "0.2.3"
|
|
506
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
507
|
+
checksum = "cca7ad6a7e21e72151d56fe2495a259b5670e204c3adac41ee7ef676ea08117a"
|
|
508
|
+
|
|
509
|
+
[[package]]
|
|
510
|
+
name = "regex"
|
|
511
|
+
version = "1.13.1"
|
|
512
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
513
|
+
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
|
|
514
|
+
dependencies = [
|
|
515
|
+
"aho-corasick",
|
|
516
|
+
"memchr",
|
|
517
|
+
"regex-automata",
|
|
518
|
+
"regex-syntax",
|
|
519
|
+
]
|
|
520
|
+
|
|
521
|
+
[[package]]
|
|
522
|
+
name = "regex-automata"
|
|
523
|
+
version = "0.4.18"
|
|
524
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
525
|
+
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
|
|
526
|
+
dependencies = [
|
|
527
|
+
"aho-corasick",
|
|
528
|
+
"memchr",
|
|
529
|
+
"regex-syntax",
|
|
530
|
+
]
|
|
531
|
+
|
|
532
|
+
[[package]]
|
|
533
|
+
name = "regex-syntax"
|
|
534
|
+
version = "0.8.11"
|
|
535
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
536
|
+
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
537
|
+
|
|
538
|
+
[[package]]
|
|
539
|
+
name = "rustc-hash"
|
|
540
|
+
version = "2.1.3"
|
|
541
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
542
|
+
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
|
|
543
|
+
|
|
544
|
+
[[package]]
|
|
545
|
+
name = "rustc_version"
|
|
546
|
+
version = "0.4.1"
|
|
547
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
548
|
+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
|
549
|
+
dependencies = [
|
|
550
|
+
"semver",
|
|
551
|
+
]
|
|
552
|
+
|
|
553
|
+
[[package]]
|
|
554
|
+
name = "salsa20"
|
|
555
|
+
version = "0.10.2"
|
|
556
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
557
|
+
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
|
|
558
|
+
dependencies = [
|
|
559
|
+
"cipher",
|
|
560
|
+
]
|
|
561
|
+
|
|
562
|
+
[[package]]
|
|
563
|
+
name = "semver"
|
|
564
|
+
version = "1.0.28"
|
|
565
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
566
|
+
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
|
567
|
+
|
|
568
|
+
[[package]]
|
|
569
|
+
name = "seq-macro"
|
|
570
|
+
version = "0.3.6"
|
|
571
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
572
|
+
checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
|
|
573
|
+
|
|
574
|
+
[[package]]
|
|
575
|
+
name = "sha2"
|
|
576
|
+
version = "0.10.9"
|
|
577
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
578
|
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
|
579
|
+
dependencies = [
|
|
580
|
+
"cfg-if",
|
|
581
|
+
"cpufeatures",
|
|
582
|
+
"digest",
|
|
583
|
+
]
|
|
584
|
+
|
|
585
|
+
[[package]]
|
|
586
|
+
name = "shell-words"
|
|
587
|
+
version = "1.1.1"
|
|
588
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
589
|
+
checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
|
|
590
|
+
|
|
591
|
+
[[package]]
|
|
592
|
+
name = "shlex"
|
|
593
|
+
version = "1.3.0"
|
|
594
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
595
|
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
596
|
+
|
|
597
|
+
[[package]]
|
|
598
|
+
name = "signatory"
|
|
599
|
+
version = "0.27.1"
|
|
600
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
601
|
+
checksum = "c1e303f8205714074f6068773f0e29527e0453937fe837c9717d066635b65f31"
|
|
602
|
+
dependencies = [
|
|
603
|
+
"pkcs8",
|
|
604
|
+
"rand_core",
|
|
605
|
+
"signature",
|
|
606
|
+
"zeroize",
|
|
607
|
+
]
|
|
608
|
+
|
|
609
|
+
[[package]]
|
|
610
|
+
name = "signature"
|
|
611
|
+
version = "2.2.0"
|
|
612
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
613
|
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
|
614
|
+
dependencies = [
|
|
615
|
+
"digest",
|
|
616
|
+
"rand_core",
|
|
617
|
+
]
|
|
618
|
+
|
|
619
|
+
[[package]]
|
|
620
|
+
name = "spki"
|
|
621
|
+
version = "0.7.3"
|
|
622
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
623
|
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
|
624
|
+
dependencies = [
|
|
625
|
+
"base64ct",
|
|
626
|
+
"der",
|
|
627
|
+
]
|
|
628
|
+
|
|
629
|
+
[[package]]
|
|
630
|
+
name = "subtle"
|
|
631
|
+
version = "2.6.1"
|
|
632
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
633
|
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
634
|
+
|
|
635
|
+
[[package]]
|
|
636
|
+
name = "syn"
|
|
637
|
+
version = "2.0.119"
|
|
638
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
639
|
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
640
|
+
dependencies = [
|
|
641
|
+
"proc-macro2",
|
|
642
|
+
"quote",
|
|
643
|
+
"unicode-ident",
|
|
644
|
+
]
|
|
645
|
+
|
|
646
|
+
[[package]]
|
|
647
|
+
name = "typenum"
|
|
648
|
+
version = "1.20.1"
|
|
649
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
650
|
+
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
|
651
|
+
|
|
652
|
+
[[package]]
|
|
653
|
+
name = "unicode-ident"
|
|
654
|
+
version = "1.0.24"
|
|
655
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
656
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
657
|
+
|
|
658
|
+
[[package]]
|
|
659
|
+
name = "universal-hash"
|
|
660
|
+
version = "0.5.1"
|
|
661
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
662
|
+
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
|
663
|
+
dependencies = [
|
|
664
|
+
"crypto-common",
|
|
665
|
+
"subtle",
|
|
666
|
+
]
|
|
667
|
+
|
|
668
|
+
[[package]]
|
|
669
|
+
name = "version_check"
|
|
670
|
+
version = "0.9.5"
|
|
671
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
672
|
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
673
|
+
|
|
674
|
+
[[package]]
|
|
675
|
+
name = "wasi"
|
|
676
|
+
version = "0.11.1+wasi-snapshot-preview1"
|
|
677
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
678
|
+
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
679
|
+
|
|
680
|
+
[[package]]
|
|
681
|
+
name = "windows-link"
|
|
682
|
+
version = "0.2.1"
|
|
683
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
684
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
685
|
+
|
|
686
|
+
[[package]]
|
|
687
|
+
name = "zerocopy"
|
|
688
|
+
version = "0.8.56"
|
|
689
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
690
|
+
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
|
|
691
|
+
dependencies = [
|
|
692
|
+
"zerocopy-derive",
|
|
693
|
+
]
|
|
694
|
+
|
|
695
|
+
[[package]]
|
|
696
|
+
name = "zerocopy-derive"
|
|
697
|
+
version = "0.8.56"
|
|
698
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
699
|
+
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
|
|
700
|
+
dependencies = [
|
|
701
|
+
"proc-macro2",
|
|
702
|
+
"quote",
|
|
703
|
+
"syn",
|
|
704
|
+
]
|
|
705
|
+
|
|
706
|
+
[[package]]
|
|
707
|
+
name = "zeroize"
|
|
708
|
+
version = "1.9.0"
|
|
709
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
710
|
+
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
data/Cargo.toml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Workspace root. rb_sys / rake-compiler (and rb-sys-dock during
|
|
2
|
+
# cross-compilation) run `cargo metadata` from the repository root, so the native
|
|
3
|
+
# extension crate under ext/ must be declared here as a workspace member. The
|
|
4
|
+
# resolved Cargo.lock also lives at the root for reproducible cross builds.
|
|
5
|
+
[workspace]
|
|
6
|
+
members = ["ext/nkeys"]
|
|
7
|
+
resolver = "2"
|
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.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# The crate is `nkeys_rb`, not `nkeys`, so it can depend on the crates.io
|
|
2
|
+
# `nkeys` it wraps without the two names colliding.
|
|
3
|
+
[package]
|
|
4
|
+
name = "nkeys_rb"
|
|
5
|
+
version = "0.1.0"
|
|
6
|
+
edition = "2021"
|
|
7
|
+
publish = false
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
name = "nkeys_rb"
|
|
11
|
+
crate-type = ["cdylib"]
|
|
12
|
+
|
|
13
|
+
[dependencies]
|
|
14
|
+
# magnus 0.8 is required for Ruby 4.0 C-API compatibility (0.7 fails to compile
|
|
15
|
+
# against Ruby 4.0: rb_fiber_raise pointer mutability + RTypedData.typed_flag).
|
|
16
|
+
magnus = "0.8"
|
|
17
|
+
|
|
18
|
+
# The library this gem exists to expose: the NATS key format (base32 + CRC-16
|
|
19
|
+
# seed/public encoding, one prefix byte per role), Ed25519 signing, and x25519
|
|
20
|
+
# XKey sealing.
|
|
21
|
+
#
|
|
22
|
+
# `xkeys` IS NOT A DEFAULT FEATURE. Without it the crate has no XKey type at
|
|
23
|
+
# all, and half the reason this gem exists (sealing an auth callout request)
|
|
24
|
+
# does not compile.
|
|
25
|
+
#
|
|
26
|
+
# PINNED EXACTLY, because the gem's version encodes it: nkeys-rb 0.4.5.N wraps
|
|
27
|
+
# nkeys 0.4.5. A caret range could resolve to 0.4.6 and make that claim false.
|
|
28
|
+
# bin/increment-version rewrites this line when moving to a new crate release.
|
|
29
|
+
[dependencies.nkeys]
|
|
30
|
+
version = "=0.4.5"
|
|
31
|
+
features = ["xkeys"]
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
//! Ruby bindings for the Rust `nkeys` crate, via magnus.
|
|
2
|
+
//!
|
|
3
|
+
//! NKeys is the NATS key format: an Ed25519 keypair whose public half is
|
|
4
|
+
//! base32-encoded behind a prefix byte naming its role (`A...` account,
|
|
5
|
+
//! `U...` user, `N...` server), with a CRC-16 check, plus a separate x25519
|
|
6
|
+
//! "xkey" (`X...`) used for encryption rather than signing.
|
|
7
|
+
//!
|
|
8
|
+
//! WHY BIND THE RUST CRATE rather than use the pure-Ruby `nkeys` gem: that gem
|
|
9
|
+
//! stopped at 0.1.0 and is incomplete in two ways that matter to anything doing
|
|
10
|
+
//! NATS auth callout.
|
|
11
|
+
//!
|
|
12
|
+
//! 1. Its `public_key` hardcodes the USER prefix byte, so an account keypair
|
|
13
|
+
//! reports a `U...` key rather than the `A...` a server config names in
|
|
14
|
+
//! `auth_callout.issuer`. A verdict signed by a key the server cannot name
|
|
15
|
+
//! is refused.
|
|
16
|
+
//!
|
|
17
|
+
//! 2. It has no concept of xkeys at all -- no prefix, no key type, no
|
|
18
|
+
//! seal/open -- so the encrypted form of auth callout cannot be spoken.
|
|
19
|
+
//!
|
|
20
|
+
//! The API is string-centric (seeds and public keys in, base32 strings out)
|
|
21
|
+
//! because that is how NATS moves keys around: in config files, in credentials
|
|
22
|
+
//! files and in JWT claims.
|
|
23
|
+
|
|
24
|
+
use magnus::{function, method, prelude::*, Error, RString, Ruby};
|
|
25
|
+
|
|
26
|
+
use nkeys::{KeyPair, KeyPairType, XKey as NKeysXKey};
|
|
27
|
+
|
|
28
|
+
// --- helpers ---------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
fn rt_err<E: std::fmt::Display>(e: E) -> Error {
|
|
31
|
+
// Safe: every caller runs inside a Ruby method invocation (GVL held).
|
|
32
|
+
let ruby = Ruby::get().expect("rt_err called outside the Ruby VM");
|
|
33
|
+
Error::new(ruby.exception_runtime_error(), e.to_string())
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fn arg_err<S: Into<String>>(message: S) -> Error {
|
|
37
|
+
let ruby = Ruby::get().expect("arg_err called outside the Ruby VM");
|
|
38
|
+
Error::new(ruby.exception_arg_error(), message.into())
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Ruby bytes in.
|
|
42
|
+
///
|
|
43
|
+
/// TAKE `RString`, NOT `Vec<u8>`: magnus maps `Vec<u8>` to a Ruby ARRAY of
|
|
44
|
+
/// integers, so a `Vec<u8>` parameter rejects the Ruby String every caller
|
|
45
|
+
/// actually passes with "no implicit conversion of String into Array".
|
|
46
|
+
///
|
|
47
|
+
/// Copied out immediately. `as_slice` is unsafe because the borrow does not
|
|
48
|
+
/// stop Ruby moving or collecting the string underneath it; taking a `Vec` here
|
|
49
|
+
/// means nothing downstream holds a reference into the Ruby heap.
|
|
50
|
+
fn bytes_in(string: RString) -> Vec<u8> {
|
|
51
|
+
unsafe { string.as_slice() }.to_vec()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// Ruby bytes out, as a String rather than an Array -- for the same reason.
|
|
55
|
+
/// These are keys, signatures and ciphertext: binary, and what callers want to
|
|
56
|
+
/// base64 or hand back to NATS.
|
|
57
|
+
fn bytes_out(bytes: &[u8]) -> RString {
|
|
58
|
+
let ruby = Ruby::get().expect("bytes_out called outside the Ruby VM");
|
|
59
|
+
|
|
60
|
+
ruby.str_from_slice(bytes)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Map a role name to its prefix byte. Accepts the same spellings NATS uses in
|
|
64
|
+
/// its own tooling, so a caller can pass what `nsc` would print.
|
|
65
|
+
fn key_pair_type(role: &str) -> Result<KeyPairType, Error> {
|
|
66
|
+
match role {
|
|
67
|
+
"account" => Ok(KeyPairType::Account),
|
|
68
|
+
"user" => Ok(KeyPairType::User),
|
|
69
|
+
"server" => Ok(KeyPairType::Server),
|
|
70
|
+
"operator" => Ok(KeyPairType::Operator),
|
|
71
|
+
"cluster" => Ok(KeyPairType::Cluster),
|
|
72
|
+
other => Err(arg_err(format!(
|
|
73
|
+
"unknown key role {other:?}: expected account, user, server, operator or cluster"
|
|
74
|
+
))),
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// --- KeyPair ---------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
/// An Ed25519 NATS keypair, of any role.
|
|
81
|
+
#[magnus::wrap(class = "NKeys::KeyPair", free_immediately, size)]
|
|
82
|
+
struct RKeyPair(KeyPair);
|
|
83
|
+
|
|
84
|
+
impl RKeyPair {
|
|
85
|
+
/// A fresh keypair. `role` picks the prefix byte, and so what the public key
|
|
86
|
+
/// looks like: "account" -> `A...`, "user" -> `U...`, "server" -> `N...`.
|
|
87
|
+
fn generate(role: String) -> Result<Self, Error> {
|
|
88
|
+
Ok(RKeyPair(KeyPair::new(key_pair_type(&role)?)))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Restore from an `S...` seed. A seed encodes its own role, so the public
|
|
92
|
+
/// key comes back with the right prefix without being told which it is.
|
|
93
|
+
fn from_seed(seed: String) -> Result<Self, Error> {
|
|
94
|
+
KeyPair::from_seed(&seed).map(RKeyPair).map_err(rt_err)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// A VERIFY-ONLY keypair from a public key. `sign` and `seed` on one of
|
|
98
|
+
/// these raise, because there is no private half to use.
|
|
99
|
+
fn from_public_key(public_key: String) -> Result<Self, Error> {
|
|
100
|
+
KeyPair::from_public_key(&public_key)
|
|
101
|
+
.map(RKeyPair)
|
|
102
|
+
.map_err(rt_err)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// The public half, prefixed by role.
|
|
106
|
+
fn public_key(&self) -> String {
|
|
107
|
+
self.0.public_key()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// The seed -- the whole private key, and the thing that belongs in a
|
|
111
|
+
/// secret rather than a config file. Raises for a verify-only keypair.
|
|
112
|
+
fn seed(&self) -> Result<String, Error> {
|
|
113
|
+
self.0.seed().map_err(rt_err)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Raw Ed25519 signature over `input`, as a binary String.
|
|
117
|
+
///
|
|
118
|
+
/// Deliberately NOT base64: callers need different encodings of the same
|
|
119
|
+
/// signature (a JWT wants base64url without padding, a CONNECT nonce wants
|
|
120
|
+
/// standard base64), so the encoding is theirs to choose.
|
|
121
|
+
fn sign(&self, input: RString) -> Result<RString, Error> {
|
|
122
|
+
self.0
|
|
123
|
+
.sign(&bytes_in(input))
|
|
124
|
+
.map(|signature| bytes_out(&signature))
|
|
125
|
+
.map_err(rt_err)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Whether `sig` is a valid signature over `input`. A bad signature is
|
|
129
|
+
/// `false` rather than an exception -- it is an expected answer, not a fault.
|
|
130
|
+
fn verify(&self, input: RString, sig: RString) -> bool {
|
|
131
|
+
self.0.verify(&bytes_in(input), &bytes_in(sig)).is_ok()
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- XKey ------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
/// An x25519 NATS xkey: the curve keypair used to ENCRYPT rather than sign.
|
|
138
|
+
#[magnus::wrap(class = "NKeys::XKey", free_immediately, size)]
|
|
139
|
+
struct RXKey(NKeysXKey);
|
|
140
|
+
|
|
141
|
+
impl RXKey {
|
|
142
|
+
fn generate() -> Self {
|
|
143
|
+
RXKey(NKeysXKey::new())
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fn from_seed(seed: String) -> Result<Self, Error> {
|
|
147
|
+
NKeysXKey::from_seed(&seed).map(RXKey).map_err(rt_err)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// A seal-only xkey from a public key, for encrypting to someone else.
|
|
151
|
+
fn from_public_key(public_key: String) -> Result<Self, Error> {
|
|
152
|
+
NKeysXKey::from_public_key(&public_key)
|
|
153
|
+
.map(RXKey)
|
|
154
|
+
.map_err(rt_err)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/// The public half -- an `X...` key.
|
|
158
|
+
fn public_key(&self) -> String {
|
|
159
|
+
self.0.public_key()
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
fn seed(&self) -> Result<String, Error> {
|
|
163
|
+
self.0.seed().map_err(rt_err)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/// Encrypt `input` to `recipient` (an `X...` public key).
|
|
167
|
+
///
|
|
168
|
+
/// The crate wants an `XKey` for the counterparty; the Ruby side passes the
|
|
169
|
+
/// public key as a STRING, because that is the form NATS moves keys in --
|
|
170
|
+
/// out of a config file, or off the `xkey` field of an auth callout
|
|
171
|
+
/// request. Parsing it here keeps that conversion out of every caller.
|
|
172
|
+
fn seal(&self, input: RString, recipient: String) -> Result<RString, Error> {
|
|
173
|
+
let recipient = NKeysXKey::from_public_key(&recipient).map_err(rt_err)?;
|
|
174
|
+
|
|
175
|
+
self.0
|
|
176
|
+
.seal(&bytes_in(input), &recipient)
|
|
177
|
+
.map(|sealed| bytes_out(&sealed))
|
|
178
|
+
.map_err(rt_err)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/// Decrypt `input` from `sender` (an `X...` public key).
|
|
182
|
+
fn open(&self, input: RString, sender: String) -> Result<RString, Error> {
|
|
183
|
+
let sender = NKeysXKey::from_public_key(&sender).map_err(rt_err)?;
|
|
184
|
+
|
|
185
|
+
self.0
|
|
186
|
+
.open(&bytes_in(input), &sender)
|
|
187
|
+
.map(|opened| bytes_out(&opened))
|
|
188
|
+
.map_err(rt_err)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// --- init ------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
#[magnus::init]
|
|
195
|
+
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
196
|
+
let namespace = ruby.define_module("NKeys")?;
|
|
197
|
+
|
|
198
|
+
let keypair = namespace.define_class("KeyPair", ruby.class_object())?;
|
|
199
|
+
keypair.define_singleton_method("generate", function!(RKeyPair::generate, 1))?;
|
|
200
|
+
keypair.define_singleton_method("from_seed", function!(RKeyPair::from_seed, 1))?;
|
|
201
|
+
keypair.define_singleton_method("from_public_key", function!(RKeyPair::from_public_key, 1))?;
|
|
202
|
+
keypair.define_method("public_key", method!(RKeyPair::public_key, 0))?;
|
|
203
|
+
keypair.define_method("seed", method!(RKeyPair::seed, 0))?;
|
|
204
|
+
keypair.define_method("sign", method!(RKeyPair::sign, 1))?;
|
|
205
|
+
keypair.define_method("verify", method!(RKeyPair::verify, 2))?;
|
|
206
|
+
|
|
207
|
+
let xkey = namespace.define_class("XKey", ruby.class_object())?;
|
|
208
|
+
xkey.define_singleton_method("generate", function!(RXKey::generate, 0))?;
|
|
209
|
+
xkey.define_singleton_method("from_seed", function!(RXKey::from_seed, 1))?;
|
|
210
|
+
xkey.define_singleton_method("from_public_key", function!(RXKey::from_public_key, 1))?;
|
|
211
|
+
xkey.define_method("public_key", method!(RXKey::public_key, 0))?;
|
|
212
|
+
xkey.define_method("seed", method!(RXKey::seed, 0))?;
|
|
213
|
+
xkey.define_method("seal", method!(RXKey::seal, 2))?;
|
|
214
|
+
xkey.define_method("open", method!(RXKey::open, 2))?;
|
|
215
|
+
|
|
216
|
+
Ok(())
|
|
217
|
+
}
|
|
@@ -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,124 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: nkeys-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.4.5.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nathan Kidd
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rb_sys
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.9'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.9'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake-compiler
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.2'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: scampi
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '1.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '1.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: lefthook
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2.1'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.1'
|
|
82
|
+
description: 'NATS NKeys for Ruby, as a native extension over the Rust `nkeys` crate:
|
|
83
|
+
Ed25519 keypairs across every key role, and the x25519 XKey sealing used by NATS
|
|
84
|
+
auth callout. Named nkeys-rb because the plain `nkeys` gem name is taken by an unrelated
|
|
85
|
+
pure-Ruby implementation.'
|
|
86
|
+
email:
|
|
87
|
+
- nathankidd@hey.com
|
|
88
|
+
executables: []
|
|
89
|
+
extensions:
|
|
90
|
+
- ext/nkeys/extconf.rb
|
|
91
|
+
extra_rdoc_files: []
|
|
92
|
+
files:
|
|
93
|
+
- Cargo.lock
|
|
94
|
+
- Cargo.toml
|
|
95
|
+
- README.md
|
|
96
|
+
- ext/nkeys/Cargo.toml
|
|
97
|
+
- ext/nkeys/extconf.rb
|
|
98
|
+
- ext/nkeys/src/lib.rs
|
|
99
|
+
- lib/nkeys.rb
|
|
100
|
+
- lib/nkeys/version.rb
|
|
101
|
+
homepage: https://github.com/n-at-han-k/nkeys-rb
|
|
102
|
+
licenses:
|
|
103
|
+
- Apache-2.0
|
|
104
|
+
metadata:
|
|
105
|
+
homepage_uri: https://github.com/n-at-han-k/nkeys-rb
|
|
106
|
+
source_code_uri: https://github.com/n-at-han-k/nkeys-rb
|
|
107
|
+
rdoc_options: []
|
|
108
|
+
require_paths:
|
|
109
|
+
- lib
|
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
|
+
requirements:
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '3.3'
|
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
|
+
requirements:
|
|
117
|
+
- - ">="
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: '0'
|
|
120
|
+
requirements: []
|
|
121
|
+
rubygems_version: 3.7.2
|
|
122
|
+
specification_version: 4
|
|
123
|
+
summary: Ruby bindings for the Rust nkeys crate.
|
|
124
|
+
test_files: []
|