Feat: encrypted mqtt sending
This commit is contained in:
parent
c2c62d8a64
commit
33b24a70a7
15 changed files with 1396 additions and 118 deletions
5
crypto_helper/.gitignore
vendored
Normal file
5
crypto_helper/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
bin/
|
||||
pkg/
|
||||
wasm-pack.log
|
534
crypto_helper/Cargo.lock
generated
Normal file
534
crypto_helper/Cargo.lock
generated
Normal file
|
@ -0,0 +1,534 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto_helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64",
|
||||
"console_error_panic_hook",
|
||||
"generic-array",
|
||||
"hex",
|
||||
"pbkdf2",
|
||||
"sha256",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"wee_alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.3",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
|
||||
dependencies = [
|
||||
"digest 0.10.6",
|
||||
"hmac",
|
||||
"password-hash",
|
||||
"sha2 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha256"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e334db67871c14c18fc066ad14af13f9fdf5f9a91c61af432d1e3a39c8c6a141"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"sha2 0.9.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"memory_units",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
38
crypto_helper/Cargo.toml
Normal file
38
crypto_helper/Cargo.toml
Normal file
|
@ -0,0 +1,38 @@
|
|||
[package]
|
||||
name = "crypto_helper"
|
||||
version = "0.1.0"
|
||||
authors = ["Dorian Zedler <dorian@itsblue.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.63"
|
||||
|
||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||
# logging them with `console.error`. This is great for development, but requires
|
||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||
# code size when deploying.
|
||||
console_error_panic_hook = { version = "0.1.6", optional = true }
|
||||
|
||||
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
|
||||
# compared to the default allocator's ~10K. It is slower than the default
|
||||
# allocator, however.
|
||||
wee_alloc = { version = "0.4.5", optional = true }
|
||||
base64 = "0.21.0"
|
||||
pbkdf2 = "0.11.0"
|
||||
hex = "0.4.3"
|
||||
aes-gcm = { version="0.10.1", features = ["aes", "alloc"], default-features = false }
|
||||
generic-array = "0.14.6"
|
||||
sha256 = "1.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.13"
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
86
crypto_helper/README.md
Normal file
86
crypto_helper/README.md
Normal file
|
@ -0,0 +1,86 @@
|
|||
<div align="center">
|
||||
|
||||
<h1><code>wasm-pack-template</code></h1>
|
||||
|
||||
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
|
||||
|
||||
<p>
|
||||
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
|
||||
<span> | </span>
|
||||
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
|
||||
</h3>
|
||||
|
||||
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
[**📚 Read this template tutorial! 📚**][template-docs]
|
||||
|
||||
This template is designed for compiling Rust libraries into WebAssembly and
|
||||
publishing the resulting package to NPM.
|
||||
|
||||
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
|
||||
templates and usages of `wasm-pack`.
|
||||
|
||||
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
|
||||
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
|
||||
|
||||
## 🚴 Usage
|
||||
|
||||
### 🐑 Use `cargo generate` to Clone this Template
|
||||
|
||||
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
|
||||
|
||||
```
|
||||
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
|
||||
cd my-project
|
||||
```
|
||||
|
||||
### 🛠️ Build with `wasm-pack build`
|
||||
|
||||
```
|
||||
wasm-pack build
|
||||
```
|
||||
|
||||
### 🔬 Test in Headless Browsers with `wasm-pack test`
|
||||
|
||||
```
|
||||
wasm-pack test --headless --firefox
|
||||
```
|
||||
|
||||
### 🎁 Publish to NPM with `wasm-pack publish`
|
||||
|
||||
```
|
||||
wasm-pack publish
|
||||
```
|
||||
|
||||
## 🔋 Batteries Included
|
||||
|
||||
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
|
||||
between WebAssembly and JavaScript.
|
||||
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
|
||||
for logging panic messages to the developer console.
|
||||
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
|
||||
for small code size.
|
||||
* `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally
|
||||
submitted for inclusion in the work by you, as defined in the Apache-2.0
|
||||
license, shall be dual licensed as above, without any additional terms or
|
||||
conditions.
|
60
crypto_helper/src/crypto.rs
Normal file
60
crypto_helper/src/crypto.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use pbkdf2::{self, password_hash::PasswordHasher};
|
||||
use base64::{Engine as _};
|
||||
use generic_array::typenum::{UInt, B1, B0, UTerm, U32};
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use aes_gcm::{
|
||||
aead::{Aead, KeyInit, generic_array::GenericArray},
|
||||
Aes256Gcm
|
||||
};
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Crypto {
|
||||
iv: IV,
|
||||
c: Aes256Gcm
|
||||
}
|
||||
|
||||
type Key = GenericArray<u8, U32>;
|
||||
type IV = GenericArray<u8, UInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>, B0>>;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Crypto {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(password: &str, salt: &str) -> Self {
|
||||
let key = Self::_pbkdf2(password, salt, 1000, 32);
|
||||
let iv = Self::_pbkdf2(password, salt, 5000, 12);
|
||||
|
||||
println!("Key {}\nIV {}", hex::encode(&key), hex::encode(&iv));
|
||||
|
||||
|
||||
let iv: IV = GenericArray::clone_from_slice(&iv);
|
||||
let key: &Key = GenericArray::from_slice(&key);
|
||||
let c = Aes256Gcm::new(key);
|
||||
|
||||
Crypto { iv: iv, c:c }
|
||||
}
|
||||
|
||||
pub fn sha256(input: &str) -> String {
|
||||
sha256::digest(input)
|
||||
}
|
||||
|
||||
fn _pbkdf2(password: &str, salt: &str, rounds: u32, output_length: usize) -> Vec<u8> {
|
||||
let params = pbkdf2::Params { rounds: rounds, output_length: output_length };
|
||||
let salt = base64::engine::general_purpose::STANDARD_NO_PAD.encode(salt);
|
||||
let salt = pbkdf2::password_hash::Salt::new(&salt).unwrap();
|
||||
|
||||
let res = pbkdf2::Pbkdf2.hash_password_customized(password.as_bytes(), None, None, params, salt).unwrap();
|
||||
|
||||
res.hash.unwrap().as_bytes().to_owned()
|
||||
}
|
||||
|
||||
pub fn encrypt(&self, plaintext: &str) -> String {
|
||||
base64::engine::general_purpose::STANDARD_NO_PAD.encode(self.c.encrypt(&self.iv, plaintext.as_bytes()).unwrap())
|
||||
}
|
||||
|
||||
pub fn decrypt(&self, ciphertext: &str) -> String {
|
||||
let ciphertext = base64::engine::general_purpose::STANDARD_NO_PAD.decode(ciphertext).unwrap();
|
||||
String::from_utf8(self.c.decrypt(&self.iv, &*ciphertext).unwrap()).unwrap()
|
||||
}
|
||||
}
|
20
crypto_helper/src/lib.rs
Normal file
20
crypto_helper/src/lib.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
mod utils;
|
||||
pub mod crypto;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||
// allocator.
|
||||
#[cfg(feature = "wee_alloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
fn alert(s: &str);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn greet() {
|
||||
alert("Hello, crypto!");
|
||||
}
|
10
crypto_helper/src/utils.rs
Normal file
10
crypto_helper/src/utils.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
#[cfg(feature = "console_error_panic_hook")]
|
||||
console_error_panic_hook::set_once();
|
||||
}
|
13
crypto_helper/tests/web.rs
Normal file
13
crypto_helper/tests/web.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
//! Test suite for the Web and headless browsers.
|
||||
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
extern crate wasm_bindgen_test;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn pass() {
|
||||
assert_eq!(1 + 1, 2);
|
||||
}
|
31
index.css
31
index.css
|
@ -4,6 +4,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.timer {
|
||||
font-size: 8em;
|
||||
font-weight: bold;
|
||||
|
@ -16,13 +23,31 @@
|
|||
animation: blinker 2s ease infinite;
|
||||
}
|
||||
|
||||
.timer.sending {
|
||||
color: #ff0;
|
||||
animation: blinker 2s ease infinite;
|
||||
}
|
||||
|
||||
main {
|
||||
height: 100vh;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
main > div {
|
||||
height: 100%;
|
||||
.timer-container-div {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.timer-div {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tap-area {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: pointer;
|
||||
}
|
61
index.html
61
index.html
|
@ -6,13 +6,15 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
|
||||
<script src="https://unpkg.com/crypto-js@4.1.1/crypto-js.js"></script>
|
||||
|
||||
|
||||
<script src="lib/crypto_helper.js"></script>
|
||||
<script src="js/index.js"></script>
|
||||
|
||||
<script src="js/localState.js"></script>
|
||||
<script src="js/mqtt.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css" />
|
||||
<link rel="stylesheet" href="index.css" />
|
||||
|
||||
|
||||
<audio id="sound-0" src="sound/0.mp3" preload="auto"></audio>
|
||||
<audio id="sound-1" src="sound/1.mp3" preload="auto"></audio>
|
||||
<audio id="sound-2" src="sound/2.mp3" preload="auto"></audio>
|
||||
|
@ -28,21 +30,50 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<main class="container">
|
||||
<div x-data>
|
||||
<div @click="$store.localState.next()">
|
||||
|
||||
|
||||
<hgroup>
|
||||
<h1>OK! .. READY! ... GO!</h1>
|
||||
<h2 x-text="$store.localState.stateHint"></h2>
|
||||
</hgroup>
|
||||
<script>
|
||||
const event = new Event('wasm-loaded');
|
||||
wasm_bindgen('lib/crypto_helper_bg.wasm').then(() => {
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
</script>
|
||||
<main class="container" x-data>
|
||||
<div class="timer-container-div" x-show="$store.localState._state !== 5">
|
||||
<div @click="$store.localState.next()" class="tap-area" x-show="$store.localState._state === 2"></div>
|
||||
<div @click="$store.localState.next()" class="timer-div">
|
||||
<hgroup>
|
||||
<h1>OK! .. READY! ... GO!</h1>
|
||||
<h2 x-text="$store.localState.stateHint"></h2>
|
||||
</hgroup>
|
||||
|
||||
<div x-data="Timer">
|
||||
<p :class="'timer' + (over ? ' over':'')"
|
||||
x-text="time + 's'"></p>
|
||||
<p :class="'timer' + (over ? ($store.localState._state === 3 ? ' sending':' over'):'')" x-text="time + 's'"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="$store.localState._state === 0">
|
||||
<details>
|
||||
<summary>Remote connection</summary>
|
||||
|
||||
<div x-show="!$store.mqtt.connected">
|
||||
<p>To send the times to a computer, please enter a password here:</p>
|
||||
<form x-data="PasswordForm()" @submit.prevent="submitForm">
|
||||
<label for="passwordForm_password">Password:</label>
|
||||
<input id="passwordForm_password" type="text" x-model="formData.password" placeholder="Password" />
|
||||
<small>Make sure, this is exactly the same on your computer!</small>
|
||||
<button type="submit">Connect</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div x-show="$store.mqtt.connected">
|
||||
<p>Connected</p>
|
||||
<button @click="$store.localState.password = ''">Disconnect</button>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="timer-container-div" x-show="$store.localState._state === 5">
|
||||
<h1 class="loading" aria-busy="true">Connecting...</h1>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
154
js/index.js
154
js/index.js
|
@ -1,108 +1,62 @@
|
|||
async function play() {
|
||||
const number = document.getElementById("number").value;
|
||||
sayNumber(number);
|
||||
}
|
||||
|
||||
async function sayNumber(number) {
|
||||
console.log(number)
|
||||
number = number.toString();
|
||||
number = number.replace(/[^0-9]/, "");
|
||||
for(let i = 0; i < number.length; i++) {
|
||||
await playAudio(document.getElementById(`sound-${number[i]}`));
|
||||
}
|
||||
console.log(number);
|
||||
number = number.toString();
|
||||
number = number.replace(/[^0-9]/, "");
|
||||
for (let i = 0; i < number.length; i++) {
|
||||
await playAudio(document.getElementById(`sound-${number[i]}`));
|
||||
}
|
||||
}
|
||||
|
||||
function playAudio(audio){
|
||||
return new Promise(res=>{
|
||||
audio.play()
|
||||
audio.onended = res
|
||||
})
|
||||
function playAudio(audio) {
|
||||
return new Promise((res) => {
|
||||
audio.play();
|
||||
audio.onended = res;
|
||||
});
|
||||
}
|
||||
|
||||
function uuidv4() {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(
|
||||
c ^
|
||||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
|
||||
).toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
function PasswordForm() {
|
||||
return {
|
||||
formData: {
|
||||
password: "",
|
||||
},
|
||||
submitForm() {
|
||||
Alpine.store("localState").password = this.formData.password;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function Timer() {
|
||||
return {
|
||||
time: 0,
|
||||
over: false,
|
||||
init() {
|
||||
setInterval(() => {
|
||||
const startedAt = Alpine.store("localState").startedAt;
|
||||
const resultTime = Alpine.store("localState").time;
|
||||
return {
|
||||
time: 0,
|
||||
over: false,
|
||||
init() {
|
||||
setInterval(() => {
|
||||
const startedAt = Alpine.store("localState").startedAt;
|
||||
const resultTime = Alpine.store("localState").time;
|
||||
|
||||
let time;
|
||||
if (!startedAt && !resultTime) {
|
||||
time = 0;
|
||||
this.over = false;
|
||||
} else if (resultTime) {
|
||||
time = (resultTime / 1000);
|
||||
this.over = true;
|
||||
} else {
|
||||
this.over = false;
|
||||
time =
|
||||
((new Date().getTime() - startedAt) / 1000)
|
||||
;
|
||||
}
|
||||
let time;
|
||||
if (!startedAt && !resultTime) {
|
||||
time = 0;
|
||||
this.over = false;
|
||||
} else if (resultTime) {
|
||||
time = resultTime / 1000;
|
||||
this.over = true;
|
||||
} else {
|
||||
this.over = false;
|
||||
time = (new Date().getTime() - startedAt) / 1000;
|
||||
}
|
||||
|
||||
this.time = time.toFixed(2)
|
||||
}, 10);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
|
||||
Alpine.store("localState", {
|
||||
_state: 0,
|
||||
// 0: idle
|
||||
// 1: starting
|
||||
// 2: running
|
||||
// 3: stopped
|
||||
|
||||
startedAt: null,
|
||||
time: null,
|
||||
stateHint: "",
|
||||
|
||||
init() {
|
||||
Alpine.effect(() => {
|
||||
switch(this._state) {
|
||||
case 0: {
|
||||
this.startedAt = null;
|
||||
this.time = null;
|
||||
this.stateHint = "Tap to start";
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
this.stateHint = "Get ready..."
|
||||
playAudio(document.getElementById("sound-ok-ready-go")).then(() => {
|
||||
Alpine.store("localState")._state = 2;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
this.stateHint = "Tap to stop"
|
||||
this.startedAt = new Date().getTime() - 200;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
this.stateHint = "Tap to reset"
|
||||
this.time = new Date().getTime() - this.startedAt;
|
||||
sayNumber((this.time / 1000).toFixed(2));
|
||||
this.startedAt = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
next() {
|
||||
console.log("next");
|
||||
playAudio(document.getElementById("sound-silence"))
|
||||
|
||||
if(this._state == 1) return;
|
||||
|
||||
this._state = (this._state + 1) % 4
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
this.time = time.toFixed(2);
|
||||
}, 10);
|
||||
},
|
||||
};
|
||||
}
|
105
js/localState.js
Normal file
105
js/localState.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.store("localState", {
|
||||
_state: 0,
|
||||
// 0: idle
|
||||
// 1: starting
|
||||
// 2: running
|
||||
// 3: sending time to mqtt
|
||||
// 4: stopped
|
||||
// 5: connecting to mqtt
|
||||
|
||||
startedAt: null,
|
||||
time: null,
|
||||
stateHint: "",
|
||||
password: null,
|
||||
|
||||
init() {
|
||||
Alpine.effect(() => {
|
||||
if (this.password == null) {
|
||||
this.password = localStorage.getItem("password");
|
||||
} else {
|
||||
localStorage.setItem("password", this.password);
|
||||
}
|
||||
|
||||
const mqtt = Alpine.store("mqtt");
|
||||
if (!mqtt) return;
|
||||
if (this.password == null || this.password == "") {
|
||||
mqtt.disconnect();
|
||||
} else {
|
||||
mqtt.connect();
|
||||
}
|
||||
});
|
||||
|
||||
Alpine.effect(() => {
|
||||
switch (this._state) {
|
||||
case 0:
|
||||
this.stateHint = "Tap here to start";
|
||||
break;
|
||||
case 1:
|
||||
this.stateHint = "Get ready...";
|
||||
break;
|
||||
case 2:
|
||||
this.stateHint = "Tap anywhere to stop";
|
||||
break;
|
||||
case 3:
|
||||
this.stateHint = "Sending time to MQTT...";
|
||||
break;
|
||||
|
||||
case 4:
|
||||
this.stateHint = "Tap here to reset";
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
next() {
|
||||
playAudio(document.getElementById("sound-silence"));
|
||||
|
||||
if (this._state == 1 || this._state == 3) return;
|
||||
|
||||
this._setState((this._state + 1) % 5);
|
||||
},
|
||||
|
||||
_setState(state) {
|
||||
switch (state) {
|
||||
case 0: {
|
||||
this.startedAt = null;
|
||||
this.time = null;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
playAudio(document.getElementById("sound-ok-ready-go")).then(() => {
|
||||
Alpine.store("localState")._setState(2);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
this.startedAt = new Date().getTime() - 200;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
this.time =
|
||||
((new Date().getTime() - this.startedAt) / 1000).toFixed(2) * 1000;
|
||||
this.startedAt = null;
|
||||
sayNumber(this.time / 10);
|
||||
|
||||
if (Alpine.store("mqtt").connected) {
|
||||
Alpine.store("mqtt")
|
||||
.sendTime(this.time)
|
||||
.then(() => {
|
||||
Alpine.store("localState")._setState(4);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
state = 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this._state = state;
|
||||
},
|
||||
});
|
||||
});
|
117
js/mqtt.js
Normal file
117
js/mqtt.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
let wasm_inited_resolve;
|
||||
const wasm_inited = new Promise((resolve) => {wasm_inited_resolve = resolve;});
|
||||
|
||||
document.addEventListener("wasm-loaded", () => {
|
||||
wasm_inited_resolve(wasm_bindgen)
|
||||
});
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.store("mqtt", {
|
||||
connected: false,
|
||||
_client: null,
|
||||
_topic: null,
|
||||
_c: null,
|
||||
|
||||
_pendingPromises: {},
|
||||
|
||||
sendTime(time) {
|
||||
if (!this.connected) return null;
|
||||
|
||||
const id = uuidv4();
|
||||
const promise = new Promise((resolve, reject) => {this._pendingPromises[id] = [resolve, reject]});
|
||||
this._publish({
|
||||
id: id, // used to prevent replay attacks and to identify confirm messages
|
||||
kind: "Time", // can be "time" or "confirm"
|
||||
time: time, // only used for "time"
|
||||
});
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
async connect() {
|
||||
if (this.connected) return;
|
||||
|
||||
const password = Alpine.store("localState").password;
|
||||
const that = this;
|
||||
const brokerDomain = "broker.emqx.io";
|
||||
const url = `wss://${brokerDomain}:8084/mqtt`;
|
||||
|
||||
if (!password) return false;
|
||||
|
||||
const {Crypto} = await wasm_inited;
|
||||
|
||||
Alpine.store("localState")._state = 5;
|
||||
|
||||
// derive key from password
|
||||
this._c = new Crypto(password, brokerDomain);
|
||||
|
||||
console.log("Test", this._encrypt("test"));
|
||||
|
||||
this._topic = Crypto.sha256(
|
||||
this._encrypt(`org.speedclimbing.ok-ready-go.${password}`)
|
||||
).toString();
|
||||
|
||||
console.log("Connecting to MQTT broker...");
|
||||
console.log("topic:", this._topic);
|
||||
|
||||
const options = {
|
||||
// Clean session
|
||||
clean: true,
|
||||
connectTimeout: 4000,
|
||||
};
|
||||
|
||||
this._client = mqtt.connect(url, options);
|
||||
|
||||
this._client.on("connect", () => {
|
||||
Alpine.store("localState")._state = 0;
|
||||
|
||||
that._client.subscribe(that._topic);
|
||||
this.connected = true;
|
||||
});
|
||||
|
||||
this._client.on("message", (topic, message) => {
|
||||
// message is Buffer
|
||||
message = that._decrypt(message.toString());
|
||||
const data = JSON.parse(message);
|
||||
|
||||
if (topic !== that._topic || data.kind !== "Confirm" || Object.keys(this._pendingPromises).indexOf(data.id) === -1) return;
|
||||
|
||||
console.log("<<< ", data);
|
||||
this._pendingPromises[data.id][0]();
|
||||
});
|
||||
},
|
||||
|
||||
disconnect() {
|
||||
if(!this.connected) return;
|
||||
|
||||
this._client.end(true);
|
||||
|
||||
this._client = null;
|
||||
this.connected = false;
|
||||
this._topic = null;
|
||||
|
||||
for (const promiseId in this._pendingPromises) {
|
||||
this._pendingPromises[promiseId][1]();
|
||||
}
|
||||
|
||||
this._pendingPromises = {};
|
||||
},
|
||||
|
||||
_publish(data) {
|
||||
const encryptedData = this._encrypt(JSON.stringify(data));
|
||||
console.log(">>> ", data);
|
||||
this._client.publish(this._topic, encryptedData, {
|
||||
qos: 1,
|
||||
retain: false,
|
||||
});
|
||||
},
|
||||
|
||||
_encrypt(data) {
|
||||
return this._c.encrypt(data);
|
||||
},
|
||||
|
||||
_decrypt(data) {
|
||||
return this._c.decrypt(data);
|
||||
},
|
||||
});
|
||||
});
|
280
lib/crypto_helper.js
Normal file
280
lib/crypto_helper.js
Normal file
|
@ -0,0 +1,280 @@
|
|||
let wasm_bindgen;
|
||||
(function() {
|
||||
const __exports = {};
|
||||
let script_src;
|
||||
if (typeof document === 'undefined') {
|
||||
script_src = location.href;
|
||||
} else {
|
||||
script_src = new URL(document.currentScript.src, location.href).toString();
|
||||
}
|
||||
let wasm;
|
||||
|
||||
const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
|
||||
cachedTextDecoder.decode();
|
||||
|
||||
let cachedUint8Memory0 = null;
|
||||
|
||||
function getUint8Memory0() {
|
||||
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
|
||||
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8Memory0;
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
const cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length);
|
||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len);
|
||||
|
||||
const mem = getUint8Memory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let cachedInt32Memory0 = null;
|
||||
|
||||
function getInt32Memory0() {
|
||||
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
|
||||
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedInt32Memory0;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
__exports.greet = function() {
|
||||
wasm.greet();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Crypto {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(Crypto.prototype);
|
||||
obj.ptr = ptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
__destroy_into_raw() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.__destroy_into_raw();
|
||||
wasm.__wbg_crypto_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @param {string} password
|
||||
* @param {string} salt
|
||||
*/
|
||||
constructor(password, salt) {
|
||||
const ptr0 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(salt, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.crypto_new(ptr0, len0, ptr1, len1);
|
||||
return Crypto.__wrap(ret);
|
||||
}
|
||||
/**
|
||||
* @param {string} input
|
||||
* @returns {string}
|
||||
*/
|
||||
static sha256(input) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.crypto_sha256(retptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(r0, r1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {string} plaintext
|
||||
* @returns {string}
|
||||
*/
|
||||
encrypt(plaintext) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(plaintext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.crypto_encrypt(retptr, this.ptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(r0, r1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {string} ciphertext
|
||||
* @returns {string}
|
||||
*/
|
||||
decrypt(ciphertext) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(ciphertext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.crypto_decrypt(retptr, this.ptr, ptr0, len0);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(r0, r1);
|
||||
}
|
||||
}
|
||||
}
|
||||
__exports.Crypto = Crypto;
|
||||
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getImports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbg_alert_0cc0cb8b17d72dde = function(arg0, arg1) {
|
||||
alert(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
function initMemory(imports, maybe_memory) {
|
||||
|
||||
}
|
||||
|
||||
function finalizeInit(instance, module) {
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
cachedInt32Memory0 = null;
|
||||
cachedUint8Memory0 = null;
|
||||
|
||||
|
||||
return wasm;
|
||||
}
|
||||
|
||||
function initSync(module) {
|
||||
const imports = getImports();
|
||||
|
||||
initMemory(imports);
|
||||
|
||||
if (!(module instanceof WebAssembly.Module)) {
|
||||
module = new WebAssembly.Module(module);
|
||||
}
|
||||
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
|
||||
return finalizeInit(instance, module);
|
||||
}
|
||||
|
||||
async function init(input) {
|
||||
if (typeof input === 'undefined') {
|
||||
input = script_src.replace(/\.js$/, '_bg.wasm');
|
||||
}
|
||||
const imports = getImports();
|
||||
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
initMemory(imports);
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
return finalizeInit(instance, module);
|
||||
}
|
||||
|
||||
wasm_bindgen = Object.assign(init, { initSync }, __exports);
|
||||
|
||||
})();
|
BIN
lib/crypto_helper_bg.wasm
Normal file
BIN
lib/crypto_helper_bg.wasm
Normal file
Binary file not shown.
Loading…
Reference in a new issue