rb_mumble_protocol 0.1.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 +385 -0
- data/Cargo.toml +7 -0
- data/ext/rb_mumble_protocol/Cargo.toml +14 -0
- data/ext/rb_mumble_protocol/src/crypt_state.rs +456 -0
- data/ext/rb_mumble_protocol/src/lib.rs +113 -0
- data/lib/rb_mumble_protocol/crypt_state.rb +6 -0
- data/lib/rb_mumble_protocol/version.rb +5 -0
- data/lib/rb_mumble_protocol.rb +10 -0
- metadata +54 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3e1daa7a8599ad332f998313a54453e096eb3cdb0a2e091028bc33e179945168
|
|
4
|
+
data.tar.gz: 24859982a247cdf5f3d9bfc03d163db347995aa9b7642650043737749ba0d43e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d7f2032dd233a3714bca92ca14f2918b65bd89e1891f68881c720dcd741ea16764e589a72ab4fc293257424a6482420f252460cb0ae4092408f02eccc5def763
|
|
7
|
+
data.tar.gz: 31c1e2b93dbb4834023c98272090248b4633486e5a8fe7eeb48e6a6c2d09a207d5ad95cb4bf16588370d1d7da1581b31ffe182b03049b3761c4538881fff30d3
|
data/Cargo.lock
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "aho-corasick"
|
|
7
|
+
version = "1.0.2"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"memchr",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "bindgen"
|
|
16
|
+
version = "0.62.0"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "c6720a8b7b2d39dd533285ed438d458f65b31b5c257e6ac7bb3d7e82844dd722"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"bitflags",
|
|
21
|
+
"cexpr",
|
|
22
|
+
"clang-sys",
|
|
23
|
+
"lazy_static",
|
|
24
|
+
"lazycell",
|
|
25
|
+
"peeking_take_while",
|
|
26
|
+
"proc-macro2",
|
|
27
|
+
"quote",
|
|
28
|
+
"regex",
|
|
29
|
+
"rustc-hash",
|
|
30
|
+
"shlex",
|
|
31
|
+
"syn 1.0.109",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[[package]]
|
|
35
|
+
name = "bitflags"
|
|
36
|
+
version = "1.3.2"
|
|
37
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
38
|
+
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
39
|
+
|
|
40
|
+
[[package]]
|
|
41
|
+
name = "bytes"
|
|
42
|
+
version = "1.4.0"
|
|
43
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
44
|
+
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
|
45
|
+
|
|
46
|
+
[[package]]
|
|
47
|
+
name = "cc"
|
|
48
|
+
version = "1.0.79"
|
|
49
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
50
|
+
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
|
51
|
+
|
|
52
|
+
[[package]]
|
|
53
|
+
name = "cexpr"
|
|
54
|
+
version = "0.6.0"
|
|
55
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
56
|
+
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
|
57
|
+
dependencies = [
|
|
58
|
+
"nom",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[[package]]
|
|
62
|
+
name = "cfg-if"
|
|
63
|
+
version = "1.0.0"
|
|
64
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
65
|
+
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
66
|
+
|
|
67
|
+
[[package]]
|
|
68
|
+
name = "clang-sys"
|
|
69
|
+
version = "1.6.1"
|
|
70
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
71
|
+
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
|
|
72
|
+
dependencies = [
|
|
73
|
+
"glob",
|
|
74
|
+
"libc",
|
|
75
|
+
"libloading",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[[package]]
|
|
79
|
+
name = "foreign-types"
|
|
80
|
+
version = "0.3.2"
|
|
81
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
82
|
+
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
|
83
|
+
dependencies = [
|
|
84
|
+
"foreign-types-shared",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[[package]]
|
|
88
|
+
name = "foreign-types-shared"
|
|
89
|
+
version = "0.1.1"
|
|
90
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
91
|
+
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
|
92
|
+
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "glob"
|
|
95
|
+
version = "0.3.1"
|
|
96
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
97
|
+
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|
98
|
+
|
|
99
|
+
[[package]]
|
|
100
|
+
name = "lazy_static"
|
|
101
|
+
version = "1.4.0"
|
|
102
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
103
|
+
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
104
|
+
|
|
105
|
+
[[package]]
|
|
106
|
+
name = "lazycell"
|
|
107
|
+
version = "1.3.0"
|
|
108
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
109
|
+
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
110
|
+
|
|
111
|
+
[[package]]
|
|
112
|
+
name = "libc"
|
|
113
|
+
version = "0.2.147"
|
|
114
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
115
|
+
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
|
116
|
+
|
|
117
|
+
[[package]]
|
|
118
|
+
name = "libloading"
|
|
119
|
+
version = "0.7.4"
|
|
120
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
121
|
+
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
|
122
|
+
dependencies = [
|
|
123
|
+
"cfg-if",
|
|
124
|
+
"winapi",
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "magnus"
|
|
129
|
+
version = "0.4.4"
|
|
130
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
131
|
+
checksum = "fc87660cd7daa49fddbfd524c836de54d5c927d520cd163f43700c5087c57d6c"
|
|
132
|
+
dependencies = [
|
|
133
|
+
"magnus-macros",
|
|
134
|
+
"rb-sys",
|
|
135
|
+
"rb-sys-env",
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "magnus-macros"
|
|
140
|
+
version = "0.3.0"
|
|
141
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
142
|
+
checksum = "206cb23bfeea05180c97522ef6a3e52a4eb17b0ed2f30ee3ca9c4f994d2378ae"
|
|
143
|
+
dependencies = [
|
|
144
|
+
"proc-macro2",
|
|
145
|
+
"quote",
|
|
146
|
+
"syn 1.0.109",
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
[[package]]
|
|
150
|
+
name = "memchr"
|
|
151
|
+
version = "2.5.0"
|
|
152
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
153
|
+
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
154
|
+
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "minimal-lexical"
|
|
157
|
+
version = "0.2.1"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
160
|
+
|
|
161
|
+
[[package]]
|
|
162
|
+
name = "nom"
|
|
163
|
+
version = "7.1.3"
|
|
164
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
165
|
+
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
|
166
|
+
dependencies = [
|
|
167
|
+
"memchr",
|
|
168
|
+
"minimal-lexical",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "once_cell"
|
|
173
|
+
version = "1.18.0"
|
|
174
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
175
|
+
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
|
176
|
+
|
|
177
|
+
[[package]]
|
|
178
|
+
name = "openssl"
|
|
179
|
+
version = "0.10.55"
|
|
180
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
181
|
+
checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
|
|
182
|
+
dependencies = [
|
|
183
|
+
"bitflags",
|
|
184
|
+
"cfg-if",
|
|
185
|
+
"foreign-types",
|
|
186
|
+
"libc",
|
|
187
|
+
"once_cell",
|
|
188
|
+
"openssl-macros",
|
|
189
|
+
"openssl-sys",
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
[[package]]
|
|
193
|
+
name = "openssl-macros"
|
|
194
|
+
version = "0.1.1"
|
|
195
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
196
|
+
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|
197
|
+
dependencies = [
|
|
198
|
+
"proc-macro2",
|
|
199
|
+
"quote",
|
|
200
|
+
"syn 2.0.27",
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[[package]]
|
|
204
|
+
name = "openssl-sys"
|
|
205
|
+
version = "0.9.90"
|
|
206
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
207
|
+
checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
|
|
208
|
+
dependencies = [
|
|
209
|
+
"cc",
|
|
210
|
+
"libc",
|
|
211
|
+
"pkg-config",
|
|
212
|
+
"vcpkg",
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
[[package]]
|
|
216
|
+
name = "peeking_take_while"
|
|
217
|
+
version = "0.1.2"
|
|
218
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
219
|
+
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
|
220
|
+
|
|
221
|
+
[[package]]
|
|
222
|
+
name = "pkg-config"
|
|
223
|
+
version = "0.3.27"
|
|
224
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
225
|
+
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
|
226
|
+
|
|
227
|
+
[[package]]
|
|
228
|
+
name = "proc-macro2"
|
|
229
|
+
version = "1.0.66"
|
|
230
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
231
|
+
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
|
232
|
+
dependencies = [
|
|
233
|
+
"unicode-ident",
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
[[package]]
|
|
237
|
+
name = "quote"
|
|
238
|
+
version = "1.0.31"
|
|
239
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
240
|
+
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
|
|
241
|
+
dependencies = [
|
|
242
|
+
"proc-macro2",
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
[[package]]
|
|
246
|
+
name = "rb-sys"
|
|
247
|
+
version = "0.9.79"
|
|
248
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
249
|
+
checksum = "939fb78db3e4f26665c1d4c7b91ca66d3578335a19aba552d4a6445811d07072"
|
|
250
|
+
dependencies = [
|
|
251
|
+
"rb-sys-build",
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
[[package]]
|
|
255
|
+
name = "rb-sys-build"
|
|
256
|
+
version = "0.9.79"
|
|
257
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
258
|
+
checksum = "335a95eb0420d52fa94ef12019df3c2c250c6b19cbb3c60bd05cb7e9c362072c"
|
|
259
|
+
dependencies = [
|
|
260
|
+
"bindgen",
|
|
261
|
+
"lazy_static",
|
|
262
|
+
"proc-macro2",
|
|
263
|
+
"quote",
|
|
264
|
+
"regex",
|
|
265
|
+
"shell-words",
|
|
266
|
+
"syn 1.0.109",
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
[[package]]
|
|
270
|
+
name = "rb-sys-env"
|
|
271
|
+
version = "0.1.2"
|
|
272
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
273
|
+
checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb"
|
|
274
|
+
|
|
275
|
+
[[package]]
|
|
276
|
+
name = "rb_mumble_protocol"
|
|
277
|
+
version = "0.1.0"
|
|
278
|
+
dependencies = [
|
|
279
|
+
"bytes",
|
|
280
|
+
"magnus",
|
|
281
|
+
"openssl",
|
|
282
|
+
]
|
|
283
|
+
|
|
284
|
+
[[package]]
|
|
285
|
+
name = "regex"
|
|
286
|
+
version = "1.9.1"
|
|
287
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
288
|
+
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
|
289
|
+
dependencies = [
|
|
290
|
+
"aho-corasick",
|
|
291
|
+
"memchr",
|
|
292
|
+
"regex-automata",
|
|
293
|
+
"regex-syntax",
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
[[package]]
|
|
297
|
+
name = "regex-automata"
|
|
298
|
+
version = "0.3.3"
|
|
299
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
300
|
+
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
|
301
|
+
dependencies = [
|
|
302
|
+
"aho-corasick",
|
|
303
|
+
"memchr",
|
|
304
|
+
"regex-syntax",
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
[[package]]
|
|
308
|
+
name = "regex-syntax"
|
|
309
|
+
version = "0.7.4"
|
|
310
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
311
|
+
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
|
312
|
+
|
|
313
|
+
[[package]]
|
|
314
|
+
name = "rustc-hash"
|
|
315
|
+
version = "1.1.0"
|
|
316
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
317
|
+
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
318
|
+
|
|
319
|
+
[[package]]
|
|
320
|
+
name = "shell-words"
|
|
321
|
+
version = "1.1.0"
|
|
322
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
323
|
+
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
|
324
|
+
|
|
325
|
+
[[package]]
|
|
326
|
+
name = "shlex"
|
|
327
|
+
version = "1.1.0"
|
|
328
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
329
|
+
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
|
330
|
+
|
|
331
|
+
[[package]]
|
|
332
|
+
name = "syn"
|
|
333
|
+
version = "1.0.109"
|
|
334
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
335
|
+
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
|
336
|
+
dependencies = [
|
|
337
|
+
"proc-macro2",
|
|
338
|
+
"quote",
|
|
339
|
+
"unicode-ident",
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
[[package]]
|
|
343
|
+
name = "syn"
|
|
344
|
+
version = "2.0.27"
|
|
345
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
346
|
+
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
|
|
347
|
+
dependencies = [
|
|
348
|
+
"proc-macro2",
|
|
349
|
+
"quote",
|
|
350
|
+
"unicode-ident",
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
[[package]]
|
|
354
|
+
name = "unicode-ident"
|
|
355
|
+
version = "1.0.11"
|
|
356
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
357
|
+
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
|
358
|
+
|
|
359
|
+
[[package]]
|
|
360
|
+
name = "vcpkg"
|
|
361
|
+
version = "0.2.15"
|
|
362
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
363
|
+
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|
364
|
+
|
|
365
|
+
[[package]]
|
|
366
|
+
name = "winapi"
|
|
367
|
+
version = "0.3.9"
|
|
368
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
369
|
+
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
370
|
+
dependencies = [
|
|
371
|
+
"winapi-i686-pc-windows-gnu",
|
|
372
|
+
"winapi-x86_64-pc-windows-gnu",
|
|
373
|
+
]
|
|
374
|
+
|
|
375
|
+
[[package]]
|
|
376
|
+
name = "winapi-i686-pc-windows-gnu"
|
|
377
|
+
version = "0.4.0"
|
|
378
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
379
|
+
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
380
|
+
|
|
381
|
+
[[package]]
|
|
382
|
+
name = "winapi-x86_64-pc-windows-gnu"
|
|
383
|
+
version = "0.4.0"
|
|
384
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
385
|
+
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
data/Cargo.toml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "rb_mumble_protocol"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
authors = ["Mikhail Odebe <derpiranha@gmail.com>"]
|
|
6
|
+
publish = false
|
|
7
|
+
|
|
8
|
+
[lib]
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
magnus = { version = "0.4" }
|
|
13
|
+
bytes = "1.0"
|
|
14
|
+
openssl = { version = "0.10" }
|
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
//! Implementation of the cryptography used for Mumble's voice channel
|
|
2
|
+
|
|
3
|
+
use bytes::BytesMut;
|
|
4
|
+
use openssl::memcmp;
|
|
5
|
+
use openssl::rand::rand_bytes;
|
|
6
|
+
|
|
7
|
+
/// Maximum size of an encrypted Mumble packet.
|
|
8
|
+
/// Note that larger packets can be produced if there is sufficient voice data in one packet but
|
|
9
|
+
/// there's no guarantee that the remote end will not just drop it.
|
|
10
|
+
pub const MAX_PACKET_SIZE: usize = 1024;
|
|
11
|
+
/// Size in bytes of the AES key used in `CryptState`.
|
|
12
|
+
pub const KEY_SIZE: usize = 16;
|
|
13
|
+
/// Size in bytes of blocks for the AES primitive.
|
|
14
|
+
pub const BLOCK_SIZE: usize = std::mem::size_of::<u128>();
|
|
15
|
+
|
|
16
|
+
/// Implements OCB2-AES128 for encryption and authentication of the voice packets
|
|
17
|
+
/// when transmitted over UDP.
|
|
18
|
+
/// Also provides statistics about good, late and lost packets.
|
|
19
|
+
///
|
|
20
|
+
/// Note that OCB is covered by patents, however a license has been granted for use in "most"
|
|
21
|
+
/// software. See: http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm
|
|
22
|
+
///
|
|
23
|
+
/// Based on https://github.com/mumble-voip/mumble/blob/e31d267a11b4ed0597ad41309a7f6b715837141f/src/CryptState.cpp
|
|
24
|
+
#[derive(Debug)]
|
|
25
|
+
pub struct CryptState {
|
|
26
|
+
key: [u8; KEY_SIZE],
|
|
27
|
+
|
|
28
|
+
// internally as native endianness, externally as little endian and during ocb_* as big endian
|
|
29
|
+
encrypt_nonce: u128,
|
|
30
|
+
decrypt_nonce: u128,
|
|
31
|
+
decrypt_history: [u8; 0x100],
|
|
32
|
+
|
|
33
|
+
good: u32,
|
|
34
|
+
late: u32,
|
|
35
|
+
lost: u32,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// The reason a decrypt operation failed.
|
|
39
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
40
|
+
pub enum DecryptError {
|
|
41
|
+
/// The packet is too short to be decrypted
|
|
42
|
+
Eof,
|
|
43
|
+
/// The packet has already been decrypted previously.
|
|
44
|
+
Repeat,
|
|
45
|
+
/// The packet was far too late.
|
|
46
|
+
Late,
|
|
47
|
+
/// The MAC of the decrypted packet did not match.
|
|
48
|
+
///
|
|
49
|
+
/// This may also indicate a substantial de-sync of the decryption nonce.
|
|
50
|
+
Mac,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl CryptState {
|
|
54
|
+
/// Creates a new CryptState with randomly generated key and initial encrypt- and decrypt-nonce.
|
|
55
|
+
pub fn generate_new() -> Self {
|
|
56
|
+
let mut key = [0; KEY_SIZE];
|
|
57
|
+
rand_bytes(&mut key).unwrap();
|
|
58
|
+
|
|
59
|
+
CryptState {
|
|
60
|
+
key,
|
|
61
|
+
|
|
62
|
+
encrypt_nonce: 0,
|
|
63
|
+
decrypt_nonce: 1 << 127,
|
|
64
|
+
decrypt_history: [0; 0x100],
|
|
65
|
+
|
|
66
|
+
good: 0,
|
|
67
|
+
late: 0,
|
|
68
|
+
lost: 0,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
pub fn make_new(&self) -> Self {
|
|
73
|
+
CryptState {
|
|
74
|
+
key: self.key.clone(),
|
|
75
|
+
|
|
76
|
+
encrypt_nonce: self.encrypt_nonce.clone(),
|
|
77
|
+
decrypt_nonce: self.decrypt_nonce.clone(),
|
|
78
|
+
decrypt_history: [0; 0x100],
|
|
79
|
+
|
|
80
|
+
good: 0,
|
|
81
|
+
late: 0,
|
|
82
|
+
lost: 0,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Creates a new CryptState from previously generated key, encrypt- and decrypt-nonce.
|
|
87
|
+
pub fn new_from(
|
|
88
|
+
key: [u8; KEY_SIZE],
|
|
89
|
+
encrypt_nonce: [u8; BLOCK_SIZE],
|
|
90
|
+
decrypt_nonce: [u8; BLOCK_SIZE],
|
|
91
|
+
) -> Self {
|
|
92
|
+
CryptState {
|
|
93
|
+
key,
|
|
94
|
+
|
|
95
|
+
encrypt_nonce: u128::from_le_bytes(encrypt_nonce),
|
|
96
|
+
decrypt_nonce: u128::from_le_bytes(decrypt_nonce),
|
|
97
|
+
decrypt_history: [0; 0x100],
|
|
98
|
+
|
|
99
|
+
good: 0,
|
|
100
|
+
late: 0,
|
|
101
|
+
lost: 0,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Returns the amount of packets transmitted without issues.
|
|
106
|
+
pub fn get_good(&self) -> u32 {
|
|
107
|
+
self.good
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Returns the amount of packets which were transmitted successfully but arrived late.
|
|
111
|
+
pub fn get_late(&self) -> u32 {
|
|
112
|
+
self.late
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Returns the amount of packets which were lost.
|
|
116
|
+
pub fn get_lost(&self) -> u32 {
|
|
117
|
+
self.lost
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Returns the shared, **private** key.
|
|
121
|
+
pub fn get_key(&self) -> &[u8; KEY_SIZE] {
|
|
122
|
+
&self.key
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// Returns the nonce used for encrypting.
|
|
126
|
+
pub fn get_encrypt_nonce(&self) -> [u8; BLOCK_SIZE] {
|
|
127
|
+
self.encrypt_nonce.to_le_bytes()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Returns the nonce used for decrypting.
|
|
131
|
+
pub fn get_decrypt_nonce(&self) -> [u8; BLOCK_SIZE] {
|
|
132
|
+
self.decrypt_nonce.to_le_bytes()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// Updates the nonce used for decrypting.
|
|
136
|
+
pub fn set_decrypt_nonce(&mut self, nonce: &[u8; BLOCK_SIZE]) {
|
|
137
|
+
self.decrypt_nonce = u128::from_le_bytes(*nonce);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/// Encrypts an encoded voice packet and returns the resulting bytes.
|
|
141
|
+
pub fn encrypt(&mut self, src: Vec<u8>, dst: &mut BytesMut) {
|
|
142
|
+
self.encrypt_nonce = self.encrypt_nonce.wrapping_add(1);
|
|
143
|
+
|
|
144
|
+
// Leave four bytes for header
|
|
145
|
+
dst.resize(4, 0);
|
|
146
|
+
let mut inner = dst.split_off(4);
|
|
147
|
+
|
|
148
|
+
// Copy source bytes
|
|
149
|
+
inner.extend_from_slice(&src);
|
|
150
|
+
|
|
151
|
+
// Encryption
|
|
152
|
+
let tag = self.ocb_encrypt(inner.as_mut());
|
|
153
|
+
|
|
154
|
+
// Build result
|
|
155
|
+
dst.unsplit(inner);
|
|
156
|
+
dst[0] = self.encrypt_nonce as u8;
|
|
157
|
+
dst[1..4].copy_from_slice(&tag.to_be_bytes()[0..3]);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Decrypts a voice packet and (if successful) returns the resulting bytes.
|
|
161
|
+
pub fn decrypt(&mut self, buf: &mut BytesMut) -> Result<(), DecryptError> {
|
|
162
|
+
if buf.len() < 4 {
|
|
163
|
+
return Err(DecryptError::Eof);
|
|
164
|
+
}
|
|
165
|
+
let header = buf.split_to(4);
|
|
166
|
+
let nonce_0 = header[0];
|
|
167
|
+
|
|
168
|
+
// If we update our decrypt_nonce and the tag check fails or we've been processing late
|
|
169
|
+
// packets, we need to revert it
|
|
170
|
+
let saved_nonce = self.decrypt_nonce;
|
|
171
|
+
let mut late = false; // will always restore nonce if this is the case
|
|
172
|
+
let mut lost = 0; // for stats only
|
|
173
|
+
|
|
174
|
+
if self.decrypt_nonce.wrapping_add(1) as u8 == nonce_0 {
|
|
175
|
+
// in order
|
|
176
|
+
self.decrypt_nonce = self.decrypt_nonce.wrapping_add(1);
|
|
177
|
+
} else {
|
|
178
|
+
// packet is late or repeated, or we lost a few packets in between
|
|
179
|
+
let diff = nonce_0.wrapping_sub(self.decrypt_nonce as u8) as i8;
|
|
180
|
+
|
|
181
|
+
self.decrypt_nonce = self.decrypt_nonce.wrapping_add(diff as u128);
|
|
182
|
+
if diff > 0 {
|
|
183
|
+
lost = i32::from(diff - 1); // lost a few packets in between this and the last one
|
|
184
|
+
} else if diff > -30 {
|
|
185
|
+
if self.decrypt_history[nonce_0 as usize] == (self.decrypt_nonce >> 8) as u8 {
|
|
186
|
+
self.decrypt_nonce = saved_nonce;
|
|
187
|
+
return Err(DecryptError::Repeat);
|
|
188
|
+
}
|
|
189
|
+
// just late
|
|
190
|
+
late = true;
|
|
191
|
+
lost = -1;
|
|
192
|
+
} else {
|
|
193
|
+
return Err(DecryptError::Late); // late by more than 30 packets
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let tag = self.ocb_decrypt(buf.as_mut());
|
|
198
|
+
|
|
199
|
+
if !memcmp::eq(&tag.to_be_bytes()[0..3], &header[1..4]) {
|
|
200
|
+
self.decrypt_nonce = saved_nonce;
|
|
201
|
+
return Err(DecryptError::Mac);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
self.decrypt_history[nonce_0 as usize] = (self.decrypt_nonce >> 8) as u8;
|
|
205
|
+
|
|
206
|
+
self.good += 1;
|
|
207
|
+
if late {
|
|
208
|
+
self.late += 1;
|
|
209
|
+
self.decrypt_nonce = saved_nonce;
|
|
210
|
+
}
|
|
211
|
+
self.lost = (self.lost as i32 + lost as i32) as u32;
|
|
212
|
+
|
|
213
|
+
Ok(())
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// Encrypt the provided buffer using AES-OCB, returning the tag.
|
|
217
|
+
fn ocb_encrypt(&self, mut buf: &mut [u8]) -> u128 {
|
|
218
|
+
let mut offset = self.aes_encrypt(self.encrypt_nonce.to_be());
|
|
219
|
+
let mut checksum = 0u128;
|
|
220
|
+
|
|
221
|
+
while buf.len() > BLOCK_SIZE {
|
|
222
|
+
let (chunk, remainder) = buf.split_at_mut(BLOCK_SIZE);
|
|
223
|
+
buf = remainder;
|
|
224
|
+
let chunk: &mut [u8; BLOCK_SIZE] = chunk.try_into().expect("split_at works");
|
|
225
|
+
|
|
226
|
+
offset = s2(offset);
|
|
227
|
+
|
|
228
|
+
let plain = u128::from_be_bytes(*chunk);
|
|
229
|
+
let encrypted = self.aes_encrypt(offset ^ plain) ^ offset;
|
|
230
|
+
chunk.copy_from_slice(&encrypted.to_be_bytes());
|
|
231
|
+
|
|
232
|
+
checksum ^= plain;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
offset = s2(offset);
|
|
236
|
+
|
|
237
|
+
let len = buf.len();
|
|
238
|
+
assert!(len <= BLOCK_SIZE);
|
|
239
|
+
let pad = self.aes_encrypt((len * 8) as u128 ^ offset);
|
|
240
|
+
let mut block = pad.to_be_bytes();
|
|
241
|
+
block[..len].copy_from_slice(buf);
|
|
242
|
+
let plain = u128::from_be_bytes(block);
|
|
243
|
+
let encrypted = pad ^ plain;
|
|
244
|
+
buf.copy_from_slice(&encrypted.to_be_bytes()[..len]);
|
|
245
|
+
|
|
246
|
+
checksum ^= plain;
|
|
247
|
+
|
|
248
|
+
self.aes_encrypt(offset ^ s2(offset) ^ checksum)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/// Decrypt the provided buffer using AES-OCB, returning the tag.
|
|
252
|
+
/// **Make sure to verify that the tag matches!**
|
|
253
|
+
fn ocb_decrypt(&self, mut buf: &mut [u8]) -> u128 {
|
|
254
|
+
let mut offset = self.aes_encrypt(self.decrypt_nonce.to_be());
|
|
255
|
+
let mut checksum = 0u128;
|
|
256
|
+
|
|
257
|
+
while buf.len() > BLOCK_SIZE {
|
|
258
|
+
let (chunk, remainder) = buf.split_at_mut(BLOCK_SIZE);
|
|
259
|
+
buf = remainder;
|
|
260
|
+
let chunk: &mut [u8; BLOCK_SIZE] = chunk.try_into().expect("split_at works");
|
|
261
|
+
|
|
262
|
+
offset = s2(offset);
|
|
263
|
+
|
|
264
|
+
let encrypted = u128::from_be_bytes(*chunk);
|
|
265
|
+
let plain = self.aes_decrypt(offset ^ encrypted) ^ offset;
|
|
266
|
+
chunk.copy_from_slice(&plain.to_be_bytes());
|
|
267
|
+
|
|
268
|
+
checksum ^= plain;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
offset = s2(offset);
|
|
272
|
+
|
|
273
|
+
let len = buf.len();
|
|
274
|
+
assert!(len <= BLOCK_SIZE);
|
|
275
|
+
let pad = self.aes_encrypt((len * 8) as u128 ^ offset);
|
|
276
|
+
let mut block = [0; BLOCK_SIZE];
|
|
277
|
+
block[..len].copy_from_slice(buf);
|
|
278
|
+
let plain = u128::from_be_bytes(block) ^ pad;
|
|
279
|
+
buf.copy_from_slice(&plain.to_be_bytes()[..len]);
|
|
280
|
+
|
|
281
|
+
checksum ^= plain;
|
|
282
|
+
|
|
283
|
+
self.aes_encrypt(offset ^ s2(offset) ^ checksum)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// AES-128 encryption primitive.
|
|
287
|
+
fn aes_encrypt(&self, block: u128) -> u128 {
|
|
288
|
+
// TODO is there no better way to do this (and aes_decrypt)?
|
|
289
|
+
let mut result = [0u8; BLOCK_SIZE * 2];
|
|
290
|
+
let mut crypter = openssl::symm::Crypter::new(
|
|
291
|
+
openssl::symm::Cipher::aes_128_ecb(),
|
|
292
|
+
openssl::symm::Mode::Encrypt,
|
|
293
|
+
&self.key,
|
|
294
|
+
None,
|
|
295
|
+
)
|
|
296
|
+
.unwrap();
|
|
297
|
+
crypter.pad(false);
|
|
298
|
+
crypter.update(&block.to_be_bytes(), &mut result).unwrap();
|
|
299
|
+
crypter.finalize(&mut result).unwrap();
|
|
300
|
+
u128::from_be_bytes((&result[..BLOCK_SIZE]).try_into().unwrap())
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/// AES-128 decryption primitive.
|
|
304
|
+
fn aes_decrypt(&self, block: u128) -> u128 {
|
|
305
|
+
let mut result = [0u8; BLOCK_SIZE * 2];
|
|
306
|
+
let mut crypter = openssl::symm::Crypter::new(
|
|
307
|
+
openssl::symm::Cipher::aes_128_ecb(),
|
|
308
|
+
openssl::symm::Mode::Decrypt,
|
|
309
|
+
&self.key,
|
|
310
|
+
None,
|
|
311
|
+
)
|
|
312
|
+
.unwrap();
|
|
313
|
+
crypter.pad(false);
|
|
314
|
+
crypter.update(&block.to_be_bytes(), &mut result).unwrap();
|
|
315
|
+
crypter.finalize(&mut result).unwrap();
|
|
316
|
+
u128::from_be_bytes((&result[..BLOCK_SIZE]).try_into().unwrap())
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
fn s2(block: u128) -> u128 {
|
|
321
|
+
let rot = block.rotate_left(1);
|
|
322
|
+
let carry = rot & 1;
|
|
323
|
+
rot ^ (carry * 0x86)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
#[cfg(test)]
|
|
327
|
+
mod test {
|
|
328
|
+
use bytes::BufMut;
|
|
329
|
+
|
|
330
|
+
use super::*;
|
|
331
|
+
|
|
332
|
+
fn u128hex(src: &str) -> u128 {
|
|
333
|
+
u128::from_str_radix(src, 16).unwrap()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
fn bytes_from_hex(src: &str) -> BytesMut {
|
|
337
|
+
let mut buf = BytesMut::new();
|
|
338
|
+
hex_to_bytes(src, &mut buf);
|
|
339
|
+
buf
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
fn hex_to_bytes(src: &str, dst: &mut BytesMut) {
|
|
343
|
+
dst.clear();
|
|
344
|
+
dst.reserve(src.len() / 2);
|
|
345
|
+
let mut iter = src.chars();
|
|
346
|
+
while !iter.as_str().is_empty() {
|
|
347
|
+
dst.put_u8(u8::from_str_radix(&iter.as_str()[..2], 16).unwrap());
|
|
348
|
+
iter.next();
|
|
349
|
+
iter.next();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
#[test]
|
|
354
|
+
fn encrypt_and_decrypt_are_inverse() {
|
|
355
|
+
let mut server_state = CryptState::generate_new();
|
|
356
|
+
// swap nonce vectors side to side
|
|
357
|
+
let mut client_state =
|
|
358
|
+
CryptState::new_from(
|
|
359
|
+
*server_state.get_key(),
|
|
360
|
+
server_state.get_decrypt_nonce(),
|
|
361
|
+
server_state.get_encrypt_nonce(),
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
let mut buffer = BytesMut::new();
|
|
365
|
+
let src = "test".as_bytes().to_vec();
|
|
366
|
+
server_state.encrypt(src.clone(), &mut buffer);
|
|
367
|
+
|
|
368
|
+
let mut buffer2 = BytesMut::new();
|
|
369
|
+
buffer2.extend_from_slice(&(buffer.to_vec()));
|
|
370
|
+
|
|
371
|
+
client_state.decrypt(&mut buffer2).unwrap();
|
|
372
|
+
|
|
373
|
+
assert_eq!(src, buffer2.to_vec());
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#[test]
|
|
377
|
+
fn aes_test_vectors() {
|
|
378
|
+
let key = u128hex("E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA");
|
|
379
|
+
let state =
|
|
380
|
+
CryptState::new_from(key.to_be_bytes(), Default::default(), Default::default());
|
|
381
|
+
assert_eq!(
|
|
382
|
+
u128hex("6743C3D1519AB4F2CD9A78AB09A511BD"),
|
|
383
|
+
state.aes_encrypt(u128hex("014BAF2278A69D331D5180103643E99A"))
|
|
384
|
+
);
|
|
385
|
+
assert_eq!(
|
|
386
|
+
u128hex("014BAF2278A69D331D5180103643E99A"),
|
|
387
|
+
state.aes_decrypt(u128hex("6743C3D1519AB4F2CD9A78AB09A511BD"))
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Test vectors from http://web.cs.ucdavis.edu/~rogaway/papers/draft-krovetz-ocb-00.txt
|
|
392
|
+
// (excluding ones with headers since those aren't implemented here)
|
|
393
|
+
#[test]
|
|
394
|
+
#[allow(clippy::cognitive_complexity)] // all macro-generated
|
|
395
|
+
fn ocb_test_vectors() {
|
|
396
|
+
macro_rules! test_cases {
|
|
397
|
+
($(
|
|
398
|
+
T : $name:expr,
|
|
399
|
+
M : $plain:expr,
|
|
400
|
+
C : $cipher:expr,
|
|
401
|
+
T : $tag:expr,
|
|
402
|
+
)*) => {$(
|
|
403
|
+
let key = u128hex("000102030405060708090a0b0c0d0e0f");
|
|
404
|
+
let nonce = u128hex("000102030405060708090a0b0c0d0e0f");
|
|
405
|
+
let state = CryptState::new_from(
|
|
406
|
+
key.to_be_bytes(),
|
|
407
|
+
nonce.to_be_bytes(),
|
|
408
|
+
nonce.to_be_bytes(),
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
let mut result = BytesMut::new();
|
|
412
|
+
hex_to_bytes($plain.as_ref(), &mut result);
|
|
413
|
+
let tag = state.ocb_encrypt(&mut result);
|
|
414
|
+
assert_eq!(bytes_from_hex($cipher), result, concat!("ENCRYPT-RESULT-", $name));
|
|
415
|
+
assert_eq!(u128hex($tag), tag, concat!("ENCRYPT-TAG-", $name));
|
|
416
|
+
|
|
417
|
+
hex_to_bytes($cipher.as_ref(), &mut result);
|
|
418
|
+
let tag = state.ocb_decrypt(&mut result);
|
|
419
|
+
assert_eq!(bytes_from_hex($plain), result, concat!("DECRYPT-RESULT-", $name));
|
|
420
|
+
assert_eq!(u128hex($tag), tag, concat!("DECRYPT-TAG-", $name));
|
|
421
|
+
)*};
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
test_cases! {
|
|
425
|
+
T : "OCB-AES-128-0B",
|
|
426
|
+
M : "",
|
|
427
|
+
C : "",
|
|
428
|
+
T : "BF3108130773AD5EC70EC69E7875A7B0",
|
|
429
|
+
|
|
430
|
+
T : "OCB-AES-128-8B",
|
|
431
|
+
M : "0001020304050607",
|
|
432
|
+
C : "C636B3A868F429BB",
|
|
433
|
+
T : "A45F5FDEA5C088D1D7C8BE37CABC8C5C",
|
|
434
|
+
|
|
435
|
+
T : "OCB-AES-128-16B",
|
|
436
|
+
M : "000102030405060708090A0B0C0D0E0F",
|
|
437
|
+
C : "52E48F5D19FE2D9869F0C4A4B3D2BE57",
|
|
438
|
+
T : "F7EE49AE7AA5B5E6645DB6B3966136F9",
|
|
439
|
+
|
|
440
|
+
T : "OCB-AES-128-24B",
|
|
441
|
+
M : "000102030405060708090A0B0C0D0E0F1011121314151617",
|
|
442
|
+
C : "F75D6BC8B4DC8D66B836A2B08B32A636CC579E145D323BEB",
|
|
443
|
+
T : "A1A50F822819D6E0A216784AC24AC84C",
|
|
444
|
+
|
|
445
|
+
T : "OCB-AES-128-32B",
|
|
446
|
+
M : "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
|
|
447
|
+
C : "F75D6BC8B4DC8D66B836A2B08B32A636CEC3C555037571709DA25E1BB0421A27",
|
|
448
|
+
T : "09CA6C73F0B5C6C5FD587122D75F2AA3",
|
|
449
|
+
|
|
450
|
+
T : "OCB-AES-128-40B",
|
|
451
|
+
M : "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
|
452
|
+
C : "F75D6BC8B4DC8D66B836A2B08B32A6369F1CD3C5228D79FD6C267F5F6AA7B231C7DFB9D59951AE9C",
|
|
453
|
+
T : "9DB0CDF880F73E3E10D4EB3217766688",
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
use std::cell::RefCell;
|
|
2
|
+
|
|
3
|
+
use magnus::{class, define_module, method, function, prelude::*, Error, RHash};
|
|
4
|
+
|
|
5
|
+
use bytes::BytesMut;
|
|
6
|
+
|
|
7
|
+
pub mod crypt_state;
|
|
8
|
+
|
|
9
|
+
#[magnus::wrap(class = "RbMumbleProtocol::CryptState", free_immediatly, size)]
|
|
10
|
+
struct CryptStateRef(RefCell<crypt_state::CryptState>);
|
|
11
|
+
|
|
12
|
+
impl CryptStateRef {
|
|
13
|
+
pub fn new() -> Self {
|
|
14
|
+
Self(RefCell::new(crypt_state::CryptState::generate_new()))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub fn new_from(
|
|
18
|
+
key: Vec<u8>,
|
|
19
|
+
encrypt_nonce: Vec<u8>,
|
|
20
|
+
decrypt_nonce: Vec<u8>,
|
|
21
|
+
) -> Self {
|
|
22
|
+
let new_key =
|
|
23
|
+
key
|
|
24
|
+
.try_into()
|
|
25
|
+
.unwrap_or_else(|v: Vec<u8>| panic!("Expected a Key of length {} but it was {}", 16, v.len()));
|
|
26
|
+
|
|
27
|
+
let new_encrypt_nonce =
|
|
28
|
+
encrypt_nonce
|
|
29
|
+
.try_into()
|
|
30
|
+
.unwrap_or_else(|v: Vec<u8>| panic!("Expected a Encrypt nonce of length {} but it was {}", 16, v.len()));
|
|
31
|
+
|
|
32
|
+
let new_decrypt_nonce =
|
|
33
|
+
decrypt_nonce
|
|
34
|
+
.try_into()
|
|
35
|
+
.unwrap_or_else(|v: Vec<u8>| panic!("Expected a Decrypt nonce of length {} but it was {}", 16, v.len()));
|
|
36
|
+
|
|
37
|
+
let new_state = crypt_state::CryptState::new_from(
|
|
38
|
+
new_key,
|
|
39
|
+
new_encrypt_nonce,
|
|
40
|
+
new_decrypt_nonce
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
Self(RefCell::new(new_state))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pub fn key(&self) -> Vec<u8> { self.0.try_borrow_mut().unwrap().get_key().to_vec() }
|
|
47
|
+
pub fn encrypt_nonce(&self) -> Vec<u8> { self.0.try_borrow_mut().unwrap().get_encrypt_nonce().to_vec() }
|
|
48
|
+
pub fn decrypt_nonce(&self) -> Vec<u8> { self.0.try_borrow_mut().unwrap().get_decrypt_nonce().to_vec() }
|
|
49
|
+
|
|
50
|
+
pub fn stats(&self) -> RHash {
|
|
51
|
+
let hash = RHash::new();
|
|
52
|
+
let state = self.0.try_borrow_mut().unwrap();
|
|
53
|
+
|
|
54
|
+
let _ = hash.aset("good", state.get_good());
|
|
55
|
+
let _ = hash.aset("late", state.get_late());
|
|
56
|
+
let _ = hash.aset("lost", state.get_lost());
|
|
57
|
+
|
|
58
|
+
hash
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub fn encrypt(&self, src: Vec<u8>) -> Vec<u8> {
|
|
62
|
+
let mut buffer = BytesMut::new();
|
|
63
|
+
|
|
64
|
+
self.0.try_borrow_mut().unwrap().encrypt(src, &mut buffer);
|
|
65
|
+
|
|
66
|
+
buffer.to_vec()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
pub fn decrypt(&self, encrypted: Vec<u8>) -> Vec<u8> {
|
|
70
|
+
let mut buffer = BytesMut::new();
|
|
71
|
+
buffer.extend_from_slice(&encrypted);
|
|
72
|
+
|
|
73
|
+
self.0.try_borrow_mut().unwrap().decrypt(&mut buffer).unwrap();
|
|
74
|
+
|
|
75
|
+
buffer.to_vec()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[magnus::init]
|
|
80
|
+
fn init() -> Result<(), Error> {
|
|
81
|
+
let module = define_module("RbMumbleProtocol")?;
|
|
82
|
+
let class = module.define_class("CryptState", class::object())?;
|
|
83
|
+
|
|
84
|
+
class.define_singleton_method("new", function!(CryptStateRef::new, 0))?;
|
|
85
|
+
class.define_singleton_method("new_from", function!(CryptStateRef::new_from, 3))?;
|
|
86
|
+
|
|
87
|
+
class.define_method("key", method!(CryptStateRef::key, 0))?;
|
|
88
|
+
class.define_method("encrypt_nonce", method!(CryptStateRef::encrypt_nonce, 0))?;
|
|
89
|
+
class.define_method("decrypt_nonce", method!(CryptStateRef::decrypt_nonce, 0))?;
|
|
90
|
+
class.define_method("stats", method!(CryptStateRef::stats, 0))?;
|
|
91
|
+
|
|
92
|
+
class.define_method("encrypt", method!(CryptStateRef::encrypt, 1))?;
|
|
93
|
+
class.define_method("decrypt", method!(CryptStateRef::decrypt, 1))?;
|
|
94
|
+
|
|
95
|
+
Ok(())
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#[test]
|
|
99
|
+
fn encrypt_and_decrypt_are_inverse() {
|
|
100
|
+
let server_state = CryptStateRef::new();
|
|
101
|
+
// swap nonce vectors side to side
|
|
102
|
+
let client_state = CryptStateRef::new_from(
|
|
103
|
+
server_state.key(),
|
|
104
|
+
server_state.decrypt_nonce(),
|
|
105
|
+
server_state.encrypt_nonce()
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
let src= "test".as_bytes().to_vec();
|
|
109
|
+
let encrypted= server_state.encrypt(src.clone());
|
|
110
|
+
let result= client_state.decrypt(encrypted.clone());
|
|
111
|
+
|
|
112
|
+
assert_eq!(src, result);
|
|
113
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "rb_mumble_protocol/version"
|
|
4
|
+
require_relative "rb_mumble_protocol/crypt_state"
|
|
5
|
+
require_relative "rb_mumble_protocol/rb_mumble_protocol"
|
|
6
|
+
|
|
7
|
+
module RbMumbleProtocol
|
|
8
|
+
class Error < StandardError; end
|
|
9
|
+
# Your code goes here...
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rb_mumble_protocol
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mikhail Odebe
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-07-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Gem that providing classes for implementing Mumble-related projects.
|
|
14
|
+
email:
|
|
15
|
+
- derpiranha@gmail.com
|
|
16
|
+
executables: []
|
|
17
|
+
extensions:
|
|
18
|
+
- ext/rb_mumble_protocol/Cargo.toml
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- Cargo.lock
|
|
22
|
+
- Cargo.toml
|
|
23
|
+
- ext/rb_mumble_protocol/Cargo.toml
|
|
24
|
+
- ext/rb_mumble_protocol/src/crypt_state.rs
|
|
25
|
+
- ext/rb_mumble_protocol/src/lib.rs
|
|
26
|
+
- lib/rb_mumble_protocol.rb
|
|
27
|
+
- lib/rb_mumble_protocol/crypt_state.rb
|
|
28
|
+
- lib/rb_mumble_protocol/version.rb
|
|
29
|
+
homepage: https://github.com/Odebe/rb_mumble_protocol
|
|
30
|
+
licenses: []
|
|
31
|
+
metadata:
|
|
32
|
+
homepage_uri: https://github.com/Odebe/rb_mumble_protocol
|
|
33
|
+
source_code_uri: https://github.com/Odebe/rb_mumble_protocol
|
|
34
|
+
changelog_uri: https://github.com/Odebe/rb_mumble_protocol
|
|
35
|
+
post_install_message:
|
|
36
|
+
rdoc_options: []
|
|
37
|
+
require_paths:
|
|
38
|
+
- lib
|
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 2.6.0
|
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: 3.3.11
|
|
49
|
+
requirements: []
|
|
50
|
+
rubygems_version: 3.4.10
|
|
51
|
+
signing_key:
|
|
52
|
+
specification_version: 4
|
|
53
|
+
summary: Gem that providing classes for implementing Mumble-related projects.
|
|
54
|
+
test_files: []
|