dstu_core 0.1.0-aarch64-linux → 0.5.0-aarch64-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 +4 -4
- data/README.md +19 -8
- data/lib/dstu_core/3.1/dstu_core_rb.so +0 -0
- data/lib/dstu_core/3.2/dstu_core_rb.so +0 -0
- data/lib/dstu_core/3.3/dstu_core_rb.so +0 -0
- data/lib/dstu_core/3.4/dstu_core_rb.so +0 -0
- data/lib/dstu_core/secretstream.rb +149 -64
- data/lib/dstu_core/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d25697754c4bacdf34799f7f30030d32452ebb98dad7b51be4936ce50fd49b75
|
|
4
|
+
data.tar.gz: d0d537156e83fb2e88a7fe01667de9a3ba35c54f1c70149f9b5f8c59b97b787d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7048b087b76cfbba8fc78c64f3e1680125671d59ba840fa6caafddaba1ba970a8f194a7ac11366bf485935ccc7e058d98663871d1ffe531792f583724bbfe340
|
|
7
|
+
data.tar.gz: 38d44e88e422e45e008b2281d16b7523b2cd0a4446e3c6c303ccf5ca32e69b5dda4fe47063a7bf2653a71a2ae0d5d7dd957975105b940b0906338e0bcfceb8d8
|
data/README.md
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
# dstu-core (Ruby bindings)
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
`docs/
|
|
5
|
-
|
|
6
|
-
install from source as shown below.
|
|
3
|
+
**Pre-1.0. Not independently audited.** See the root project's `docs/SECURITY.md` and
|
|
4
|
+
`docs/DECISIONS.md` for the full threat model and per-construction status. This binding wraps the
|
|
5
|
+
full `dstu_core::crypto_*` surface (`docs/bindings-strategy.md` T-160).
|
|
7
6
|
|
|
8
|
-
## Installing
|
|
7
|
+
## Installing
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
gem install dstu_core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
require "dstu_core"
|
|
15
|
+
DstuCore.self_test
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Building from source (contributors)
|
|
9
19
|
|
|
10
20
|
```sh
|
|
11
21
|
gem install bundler
|
|
@@ -64,12 +74,13 @@ raise unless DstuCore.secretbox_open(key, sealed) == "a message worth protecting
|
|
|
64
74
|
| Module | Methods/classes | Notes |
|
|
65
75
|
|---|---|---|
|
|
66
76
|
| `crypto_secretbox` | `secretbox_keygen`, `secretbox_seal`, `secretbox_open` | Single-message authenticated encryption. `examples/secretbox.rb`. |
|
|
67
|
-
| `crypto_box` | `box_keygen`, `box_public_key`, `box_seal`, `box_open` | Public-key encryption (hybrid via KDF over `hazmat::dstu9041`, `l(p)=256`, D-169). `box_seal`/`box_open`
|
|
68
|
-
| `
|
|
77
|
+
| `crypto_box` | `box_keygen`, `box_public_key`, `box_seal`, `box_open`, `BoxWriter`, `BoxReader` | Public-key encryption (hybrid via KDF over `hazmat::dstu9041`, `l(p)=256`, D-169). `box_seal`/`box_open` hold the whole message in memory; `BoxWriter`/`BoxReader` write and read the same bytes (format v3) chunk by chunk, as `uacrypt box-seal`/`box-open` do. `examples/box.rb`. |
|
|
78
|
+
| `crypto_box384` | `box384_keygen`, `box384_public_key`, `box384_seal`, `box384_open`, `Box384Writer`, `Box384Reader` | `l(p)=384`/E384/1 sibling of `crypto_box` (T-297). `examples/box384.rb`. |
|
|
79
|
+
| `crypto_box512` | `box512_keygen`, `box512_public_key`, `box512_seal`, `box512_open`, `Box512Writer`, `Box512Reader` | `l(p)=512`/E512/1 sibling of `crypto_box` (T-193/T-204). `examples/box512.rb`. |
|
|
69
80
|
| `crypto_secretstream` | `secretstream_keygen`, `SecretStreamPushState`, `SecretStreamPullState`, `SecretStreamWriter`, `SecretStreamReader` | Chunked streaming AEAD. `SecretStreamWriter`/`Reader` (modeled on stdlib's own `Zlib::GzipWriter`/`GzipReader`) wire format matches `uacrypt encrypt`/`decrypt` exactly (D-118). `examples/secretstream_file.rb`. |
|
|
70
81
|
| `crypto_sign` | `sign_keygen`, `sign_verifying_key`, `sign_message`, `sign_verify` | DSTU 4145 `m=163` digital signatures, deterministic nonce (no RNG dependency). `examples/sign.rb`. |
|
|
71
82
|
| `crypto_sign257` | `sign257_keygen`, `sign257_verifying_key`, `sign257_message`, `sign257_verify` | `m=257` sibling of `crypto_sign` (T-199/T-204) — the curve real Diia-issued qualified signatures use. `examples/sign257.rb`. |
|
|
72
|
-
| `crypto_pwhash` | `pwhash_hash_password`, `pwhash_verify_password`, `PWHASH_INTERACTIVE`/`PWHASH_MODERATE`/`PWHASH_SENSITIVE` | Argon2id (the one deliberately non-DSTU component, D-49/D-50). `examples/password_hashing.rb`. |
|
|
83
|
+
| `crypto_pwhash` | `pwhash_hash_password`, `pwhash_verify_password`, `pwhash_derive_key`, `PWHASH_INTERACTIVE`/`PWHASH_MODERATE`/`PWHASH_SENSITIVE`, `PassphraseWriter`, `PassphraseReader` | Argon2id (the one deliberately non-DSTU component, D-49/D-50). `pwhash_derive_key` equals libsodium's `crypto_pwhash`. `PassphraseWriter`/`PassphraseReader` write and read the files `uacrypt encrypt --passphrase` makes (D-219/D-240); each runs Argon2id at 256 MiB once. `examples/password_hashing.rb`. |
|
|
73
84
|
| `crypto_auth` | `auth_keygen`, `auth`, `auth_verify` | Keyed message authentication (Kupyna-KMAC). `examples/misc.rb`. |
|
|
74
85
|
| `crypto_kdf` | `kdf_keygen`, `kdf_derive_subkey` | Deterministic subkey derivation. `examples/misc.rb`. |
|
|
75
86
|
| `crypto_generichash` | `kupyna256`, `kupyna512`, `Kupyna256Hasher`, `Kupyna512Hasher` | One-shot and streaming Kupyna hashing. `examples/misc.rb`. |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# `crypto_secretstream` idiomatic wrapper (docs/DECISIONS.md D-118, docs/bindings-strategy.md
|
|
4
|
-
# T-160 step 3) - hides chunk/tag/header bookkeeping behind `write`/`each
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# T-160 step 3) - hides chunk/tag/header bookkeeping behind `write`/`each`. The framing itself
|
|
5
|
+
# (record layout, length rules, Final, trailing data) is dstu-core's stream-file codec, exposed as
|
|
6
|
+
# SecretStreamFileEncryptor/SecretStreamFileDecryptor (T-284); this file does only I/O. Modeled on
|
|
7
|
+
# stdlib's own
|
|
7
8
|
# Zlib::GzipWriter/Zlib::GzipReader - the same "wraps an IO, transforms chunks transparently"
|
|
8
9
|
# shape, the closest Ruby-native precedent for this problem (matching Python's file-like object,
|
|
9
10
|
# Node's stream.Transform).
|
|
10
11
|
#
|
|
11
12
|
# **Wire format matches `uacrypt encrypt`/`decrypt` exactly**
|
|
12
13
|
# (crates/uacrypt/src/lib.rs's `run_secretstream_encrypt`/`run_secretstream_decrypt`, D-68):
|
|
13
|
-
# `header (32 bytes)` followed by one record per chunk, `tag_byte (1) ||
|
|
14
|
-
# ciphertext (chunk_len) || auth_tag (16)
|
|
15
|
-
# `SECRETSTREAM_CHUNK_BYTES`,
|
|
16
|
-
# decryptable by `uacrypt decrypt` and vice versa.
|
|
14
|
+
# `version (1) || header (32 bytes)` followed by one record per chunk, `tag_byte (1) ||
|
|
15
|
+
# chunk_len_u32_le (4) || ciphertext (chunk_len) || auth_tag (16)`. Every record but the Final one is
|
|
16
|
+
# exactly 8 KiB (`SECRETSTREAM_CHUNK_BYTES`, part of the format since D-208, not an independent
|
|
17
|
+
# choice) - a file `SecretStreamWriter` writes is decryptable by `uacrypt decrypt` and vice versa.
|
|
18
|
+
# The shared vectors in crates/dstu-core/tests/vectors/secretstream-file/ pin this.
|
|
17
19
|
#
|
|
18
20
|
# **Every `String` this wrapper touches is binary (`ASCII-8BIT`/`BINARY`)**, both what it writes
|
|
19
21
|
# to `out`/`inp` and what `#read_all`/`#each` yield - matching every underlying `crypto_*` wrapper
|
|
@@ -22,10 +24,12 @@
|
|
|
22
24
|
# differing encodings and fails even when the bytes match (`"привіт".b == "привіт"` is `false` in
|
|
23
25
|
# Ruby) - this is a caller-side encoding-compare gotcha, not a bug in this wrapper.
|
|
24
26
|
module DstuCore
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
+
# dstu-core's crypto_secretstream::CHUNK_BYTES and wire constants (D-208); the codec enforces
|
|
28
|
+
# them, these stay as public constants.
|
|
27
29
|
SECRETSTREAM_CHUNK_BYTES = 8 * 1024
|
|
28
30
|
SECRETSTREAM_AUTH_TAG_BYTES = 16
|
|
31
|
+
# Matches dstu-core's crypto_secretstream::FORMAT_VERSION (D-208); the shared vectors pin it.
|
|
32
|
+
SECRETSTREAM_FORMAT_VERSION = 2
|
|
29
33
|
|
|
30
34
|
# Write-only wrapper: buffers input and pushes each full 8 KiB chunk to `out` as it fills, hiding
|
|
31
35
|
# the header/tag/framing bookkeeping entirely.
|
|
@@ -35,12 +39,7 @@ module DstuCore
|
|
|
35
39
|
# end
|
|
36
40
|
class SecretStreamWriter
|
|
37
41
|
def initialize(key, out)
|
|
38
|
-
|
|
39
|
-
@out.binmode if @out.respond_to?(:binmode)
|
|
40
|
-
@push = SecretStreamPushState.new(key)
|
|
41
|
-
@out.write(@push.header)
|
|
42
|
-
@buf = +""
|
|
43
|
-
@closed = false
|
|
42
|
+
start(SecretStreamFileEncryptor.new(key), out)
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
# Block form: yields a writer, then closes it - **only on the success path**. The D-118
|
|
@@ -61,18 +60,21 @@ module DstuCore
|
|
|
61
60
|
@closed
|
|
62
61
|
end
|
|
63
62
|
|
|
64
|
-
# Buffers `data`,
|
|
65
|
-
# exactly-8-KiB) chunk is
|
|
66
|
-
# data is coming -
|
|
67
|
-
#
|
|
63
|
+
# Buffers `data`, sealing every full 8 KiB chunk that is certain not to be the last one. The
|
|
64
|
+
# trailing partial (or exactly-8-KiB) chunk is held back until `close`, since only `close`
|
|
65
|
+
# knows no more data is coming - an exact multiple of 8 KiB must end in a full Final record
|
|
66
|
+
# (D-208). Full chunks are cut from `data` by offset, so one large write costs linear time
|
|
67
|
+
# (T-276).
|
|
68
68
|
def write(data)
|
|
69
69
|
raise IOError, "closed stream" if @closed
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@
|
|
71
|
+
data = data.b
|
|
72
|
+
pos = top_up_buffer(data)
|
|
73
|
+
while data.bytesize - pos > SECRETSTREAM_CHUNK_BYTES
|
|
74
|
+
@out.write(@enc.seal_chunk(data.byteslice(pos, SECRETSTREAM_CHUNK_BYTES)))
|
|
75
|
+
pos += SECRETSTREAM_CHUNK_BYTES
|
|
75
76
|
end
|
|
77
|
+
@buf << data.byteslice(pos..)
|
|
76
78
|
data.bytesize
|
|
77
79
|
end
|
|
78
80
|
|
|
@@ -83,19 +85,36 @@ module DstuCore
|
|
|
83
85
|
def close
|
|
84
86
|
return if @closed
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
@out.write(@enc.seal_final(@buf))
|
|
87
89
|
@buf = +""
|
|
88
90
|
@closed = true
|
|
89
91
|
end
|
|
90
92
|
|
|
91
93
|
private
|
|
92
94
|
|
|
93
|
-
def
|
|
94
|
-
|
|
95
|
-
@out.
|
|
96
|
-
@
|
|
97
|
-
@
|
|
98
|
-
@
|
|
95
|
+
def start(enc, out)
|
|
96
|
+
@out = out
|
|
97
|
+
@out.binmode if @out.respond_to?(:binmode)
|
|
98
|
+
@enc = enc
|
|
99
|
+
@buf = +""
|
|
100
|
+
@closed = false
|
|
101
|
+
@out.write(@enc.prefix)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Adds `data` to the held-back chunk if it all fits; otherwise tops that chunk up to a full one
|
|
105
|
+
# and seals it, since more data follows. Returns how many bytes of `data` it consumed.
|
|
106
|
+
def top_up_buffer(data)
|
|
107
|
+
return 0 if @buf.empty?
|
|
108
|
+
|
|
109
|
+
if @buf.bytesize + data.bytesize <= SECRETSTREAM_CHUNK_BYTES
|
|
110
|
+
@buf << data
|
|
111
|
+
return data.bytesize
|
|
112
|
+
end
|
|
113
|
+
taken = SECRETSTREAM_CHUNK_BYTES - @buf.bytesize
|
|
114
|
+
@buf << data.byteslice(0, taken)
|
|
115
|
+
@out.write(@enc.seal_chunk(@buf))
|
|
116
|
+
@buf = +""
|
|
117
|
+
taken
|
|
99
118
|
end
|
|
100
119
|
end
|
|
101
120
|
|
|
@@ -113,11 +132,8 @@ module DstuCore
|
|
|
113
132
|
include Enumerable
|
|
114
133
|
|
|
115
134
|
def initialize(key, inp)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
header = read_exact(32, "header")
|
|
119
|
-
@pull = SecretStreamPullState.new(key, header)
|
|
120
|
-
@done = false
|
|
135
|
+
bind(inp)
|
|
136
|
+
start(SecretStreamFileDecryptor.new(key))
|
|
121
137
|
end
|
|
122
138
|
|
|
123
139
|
def self.open(key, inp)
|
|
@@ -128,7 +144,10 @@ module DstuCore
|
|
|
128
144
|
def each
|
|
129
145
|
return enum_for(:each) unless block_given?
|
|
130
146
|
|
|
131
|
-
|
|
147
|
+
until @done
|
|
148
|
+
plaintext = step
|
|
149
|
+
yield plaintext unless plaintext.empty?
|
|
150
|
+
end
|
|
132
151
|
end
|
|
133
152
|
|
|
134
153
|
def read_all
|
|
@@ -140,34 +159,41 @@ module DstuCore
|
|
|
140
159
|
|
|
141
160
|
private
|
|
142
161
|
|
|
143
|
-
def
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# bytes remaining after `Final` rather than silently ignoring them. Checked before
|
|
161
|
-
# `plaintext` is returned, so a trailing-data stream never yields this last chunk either
|
|
162
|
-
# via `each` or `read_all`.
|
|
163
|
-
raise DstuCore::Error, "trailing data after the secretstream's Final chunk" if @inp.read(1)
|
|
162
|
+
def bind(inp)
|
|
163
|
+
@inp = inp
|
|
164
|
+
@inp.binmode if @inp.respond_to?(:binmode)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def start(dec)
|
|
168
|
+
@dec = dec
|
|
169
|
+
@done = false
|
|
170
|
+
# The version byte and header, read now so a wrong version fails at construction.
|
|
171
|
+
2.times { step }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# The bytes in front of the stream file (a box prefix, a passphrase-file header); a shorter
|
|
175
|
+
# input cannot be opened at all.
|
|
176
|
+
def read_prefix(size, what)
|
|
177
|
+
prefix = read_up_to(size)
|
|
178
|
+
raise Error, "input too short to contain a #{what}" if prefix.bytesize < size
|
|
164
179
|
|
|
180
|
+
prefix
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Feeds the codec one `next_len` read: the plaintext that read released (possibly empty), or
|
|
184
|
+
# at end of input the Final chunk's (after which the stream is done).
|
|
185
|
+
def step
|
|
186
|
+
want = @dec.next_len
|
|
187
|
+
data = read_up_to(want)
|
|
188
|
+
if data.bytesize < want
|
|
165
189
|
@done = true
|
|
190
|
+
return @dec.finish
|
|
166
191
|
end
|
|
167
|
-
|
|
192
|
+
@dec.feed(data)
|
|
168
193
|
end
|
|
169
194
|
|
|
170
|
-
|
|
195
|
+
# Reads until `size` bytes arrived or `inp` ended; a short result means end of input.
|
|
196
|
+
def read_up_to(size)
|
|
171
197
|
pieces = []
|
|
172
198
|
remaining = size
|
|
173
199
|
while remaining.positive?
|
|
@@ -177,12 +203,71 @@ module DstuCore
|
|
|
177
203
|
pieces << piece
|
|
178
204
|
remaining -= piece.bytesize
|
|
179
205
|
end
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
206
|
+
pieces.join.b
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# crypto_box sealed to `public_key` as a stream (format v3, T-265/T-269): the same bytes
|
|
211
|
+
# `box_seal` returns, written chunk by chunk; `box_open`/BoxReader read them.
|
|
212
|
+
class BoxWriter < SecretStreamWriter
|
|
213
|
+
def initialize(public_key, out) # rubocop:disable Lint/MissingSuper
|
|
214
|
+
start(SecretStreamFileEncryptor.box_seal(public_key), out)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Reads a crypto_box stream (or a `box_seal` blob) with bounded memory.
|
|
219
|
+
class BoxReader < SecretStreamReader
|
|
220
|
+
def initialize(secret_key, inp) # rubocop:disable Lint/MissingSuper
|
|
221
|
+
bind(inp)
|
|
222
|
+
start(SecretStreamFileDecryptor.box_open(secret_key, read_prefix(BOX_OPEN_STREAM_PREFIX_BYTES, "sealed message")))
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# crypto_box384 counterpart of BoxWriter.
|
|
227
|
+
class Box384Writer < SecretStreamWriter
|
|
228
|
+
def initialize(public_key, out) # rubocop:disable Lint/MissingSuper
|
|
229
|
+
start(SecretStreamFileEncryptor.box384_seal(public_key), out)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# crypto_box384 counterpart of BoxReader.
|
|
234
|
+
class Box384Reader < SecretStreamReader
|
|
235
|
+
def initialize(secret_key, inp) # rubocop:disable Lint/MissingSuper
|
|
236
|
+
bind(inp)
|
|
237
|
+
start(SecretStreamFileDecryptor.box384_open(secret_key, read_prefix(BOX384_OPEN_STREAM_PREFIX_BYTES, "sealed message")))
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# crypto_box512 counterpart of BoxWriter.
|
|
242
|
+
class Box512Writer < SecretStreamWriter
|
|
243
|
+
def initialize(public_key, out) # rubocop:disable Lint/MissingSuper
|
|
244
|
+
start(SecretStreamFileEncryptor.box512_seal(public_key), out)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# crypto_box512 counterpart of BoxReader.
|
|
249
|
+
class Box512Reader < SecretStreamReader
|
|
250
|
+
def initialize(secret_key, inp) # rubocop:disable Lint/MissingSuper
|
|
251
|
+
bind(inp)
|
|
252
|
+
start(SecretStreamFileDecryptor.box512_open(secret_key, read_prefix(BOX512_OPEN_STREAM_PREFIX_BYTES, "sealed message")))
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# A passphrase file (D-219/D-240) - the bytes `uacrypt encrypt --passphrase` writes. `new` runs
|
|
257
|
+
# Argon2id (256 MiB, t=3, about a second) before writing anything.
|
|
258
|
+
class PassphraseWriter < SecretStreamWriter
|
|
259
|
+
def initialize(passphrase, out) # rubocop:disable Lint/MissingSuper
|
|
260
|
+
start(SecretStreamFileEncryptor.passphrase_seal(passphrase), out)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
184
263
|
|
|
185
|
-
|
|
264
|
+
# Reads a passphrase file. The header is checked before Argon2 runs; a wrong passphrase raises
|
|
265
|
+
# DstuCore::Error at the first record.
|
|
266
|
+
class PassphraseReader < SecretStreamReader
|
|
267
|
+
def initialize(passphrase, inp) # rubocop:disable Lint/MissingSuper
|
|
268
|
+
bind(inp)
|
|
269
|
+
header = read_prefix(PASSPHRASE_FILE_HEADER_BYTES, "passphrase file header")
|
|
270
|
+
start(SecretStreamFileDecryptor.passphrase_open(header, passphrase))
|
|
186
271
|
end
|
|
187
272
|
end
|
|
188
273
|
end
|
data/lib/dstu_core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dstu_core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- dstu-core contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Ruby bindings for dstu-core (Ukrainian DSTU cryptographic standards)
|
|
14
|
-
-
|
|
14
|
+
- not independently audited.
|
|
15
15
|
email:
|
|
16
16
|
executables: []
|
|
17
17
|
extensions: []
|