commit d52819b4b31d3143890b8b80f5a36ebd4e4455be Author: 鲁树人 Date: Mon Sep 2 21:01:19 2024 +0100 init: it builds diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/lib_um_crypto.iml b/.idea/lib_um_crypto.iml new file mode 100644 index 0000000..b096c45 --- /dev/null +++ b/.idea/lib_um_crypto.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..dc37cdd --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..72d5bed --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3ff2f66 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,383 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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", + "wasm-bindgen", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "minicov" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "um_wasm" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "umc_kuwo", + "wasm-bindgen", + "wasm-bindgen-test", +] + +[[package]] +name = "umc_kuwo" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64", + "itertools", + "thiserror", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "minicov", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f7c94cb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +resolver = "2" +members = ["um_crypto/*", "um_wasm"] diff --git a/LICENSE_APACHE b/LICENSE_APACHE new file mode 100644 index 0000000..d5ac8cc --- /dev/null +++ b/LICENSE_APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2024 Project Unlock Music + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE_MIT b/LICENSE_MIT new file mode 100644 index 0000000..7f84c5b --- /dev/null +++ b/LICENSE_MIT @@ -0,0 +1,25 @@ +Copyright (c) 2024 Project Unlock Music + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..003dd14 --- /dev/null +++ b/README.MD @@ -0,0 +1,7 @@ +# um_crypto + +加解密算法实现 (Rust)。 + +## 授权协议 + +Apache License 2.0 + MIT 双协议 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..678f9ef --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +wasm-pack build --target bundler um_wasm/ diff --git a/um_crypto/kuwo/Cargo.toml b/um_crypto/kuwo/Cargo.toml new file mode 100644 index 0000000..24ec27d --- /dev/null +++ b/um_crypto/kuwo/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "umc_kuwo" +version = "0.1.0" +edition = "2021" + +[dependencies] +base64 = "0.22.1" +itertools = "0.13.0" +anyhow = "1.0.86" +thiserror = "1.0.63" diff --git a/um_crypto/kuwo/src/des/constants.rs b/um_crypto/kuwo/src/des/constants.rs new file mode 100644 index 0000000..96977f8 --- /dev/null +++ b/um_crypto/kuwo/src/des/constants.rs @@ -0,0 +1,108 @@ +pub const KEY_RND_SHIFTS: [u8; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]; +pub const KEY_SHIFT_MASKS: [u64; 3] = [0, 0x100001, 0x300003]; +pub const KEY_SHIFT_LEFT_MASKS: [u64; 16] = { + let mut result = [0u64; 16]; + let mut i = 0usize; + while i < 16 { + result[i] = KEY_SHIFT_MASKS[KEY_RND_SHIFTS[i] as usize]; + i += 1; + } + result +}; +pub const SBOXES: [[u8; 64]; 8] = [ + [ + 13, 7, 10, 0, 6, 9, 5, 15, 8, 4, 3, 10, 11, 14, 12, 5, 2, 11, 9, 6, 15, 12, 0, 3, 4, 1, 14, + 13, 1, 2, 7, 8, 1, 2, 12, 15, 10, 4, 0, 3, 13, 14, 6, 9, 7, 8, 9, 6, 15, 1, 5, 12, 3, 10, + 14, 5, 8, 7, 11, 0, 4, 13, 2, 11, + ], + [ + 4, 1, 3, 10, 15, 12, 5, 0, 2, 11, 9, 6, 8, 7, 6, 9, 11, 4, 12, 15, 0, 3, 10, 5, 14, 13, 7, + 8, 13, 14, 1, 2, 13, 6, 14, 9, 4, 1, 2, 14, 11, 13, 5, 0, 1, 10, 8, 3, 0, 11, 3, 5, 9, 4, + 15, 2, 7, 8, 12, 15, 10, 7, 6, 12, + ], + [ + 12, 9, 0, 7, 9, 2, 14, 1, 10, 15, 3, 4, 6, 12, 5, 11, 1, 14, 13, 0, 2, 8, 7, 13, 15, 5, 4, + 10, 8, 3, 11, 6, 10, 4, 6, 11, 7, 9, 0, 6, 4, 2, 13, 1, 9, 15, 3, 8, 15, 3, 1, 14, 12, 5, + 11, 0, 2, 12, 14, 7, 5, 10, 8, 13, + ], + [ + 2, 4, 8, 15, 7, 10, 13, 6, 4, 1, 3, 12, 11, 7, 14, 0, 12, 2, 5, 9, 10, 13, 0, 3, 1, 11, 15, + 5, 6, 8, 9, 14, 14, 11, 5, 6, 4, 1, 3, 10, 2, 12, 15, 0, 13, 2, 8, 5, 11, 8, 0, 15, 7, 14, + 9, 4, 12, 7, 10, 9, 1, 13, 6, 3, + ], + [ + 7, 10, 1, 15, 0, 12, 11, 5, 14, 9, 8, 3, 9, 7, 4, 8, 13, 6, 2, 1, 6, 11, 12, 2, 3, 0, 5, + 14, 10, 13, 15, 4, 13, 3, 4, 9, 6, 10, 1, 12, 11, 0, 2, 5, 0, 13, 14, 2, 8, 15, 7, 4, 15, + 1, 10, 7, 5, 6, 12, 11, 3, 8, 9, 14, + ], + [ + 10, 13, 1, 11, 6, 8, 11, 5, 9, 4, 12, 2, 15, 3, 2, 14, 0, 6, 13, 1, 3, 15, 4, 10, 14, 9, 7, + 12, 5, 0, 8, 7, 13, 1, 2, 4, 3, 6, 12, 11, 0, 13, 5, 14, 6, 8, 15, 2, 7, 10, 8, 15, 4, 9, + 11, 5, 9, 0, 14, 3, 10, 7, 1, 12, + ], + [ + 15, 0, 9, 5, 6, 10, 12, 9, 8, 7, 2, 12, 3, 13, 5, 2, 1, 14, 7, 8, 11, 4, 0, 3, 14, 11, 13, + 6, 4, 1, 10, 15, 3, 13, 12, 11, 15, 3, 6, 0, 4, 10, 1, 7, 8, 4, 11, 14, 13, 8, 0, 6, 2, 15, + 9, 5, 7, 1, 10, 12, 14, 2, 5, 9, + ], + [ + 14, 4, 3, 15, 2, 13, 5, 3, 13, 14, 6, 9, 11, 2, 0, 5, 4, 1, 10, 12, 15, 6, 9, 10, 1, 8, 12, + 7, 8, 11, 7, 0, 0, 15, 10, 5, 14, 4, 9, 10, 7, 8, 12, 3, 13, 1, 3, 6, 15, 12, 6, 11, 2, 9, + 5, 0, 4, 2, 11, 14, 1, 7, 8, 13, + ], +]; + +// custom +pub const PBOX: [u8; 32] = [ + 15, 6, 19, 20, 28, 11, 27, 16, 0, 14, 22, 25, 4, 17, 30, 9, 1, 7, 23, 13, 31, 26, 2, 8, 18, 12, + 29, 5, 21, 10, 3, 24, +]; + +// custom +pub const IP: [u8; 64] = [ + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, + 55, 47, 39, 31, 23, 15, 7, 56, 48, 40, 32, 24, 16, 8, 0, 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, + 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, +]; + +// custom +pub const IP_INV: [u8; 64] = [ + 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25, 32, 0, 40, 8, 48, 16, 56, 24, +]; + +// custom +pub const KEY_PERMUTATION_TABLE: [u8; 56] = [ + //key_param_c + key_param_d + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, + 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, + 20, 12, 4, 27, 19, 11, 3, +]; + +// custom +pub const KEY_COMPRESSION: [u8; 64] = [ + 13, 16, 10, 23, 0, 4, 255, 255, 2, 27, 14, 5, 20, 9, 255, 255, 22, 18, 11, 3, 25, 7, 255, 255, + 15, 6, 26, 19, 12, 1, 255, 255, 40, 51, 30, 36, 46, 54, 255, 255, 29, 39, 50, 44, 32, 47, 255, + 255, 43, 48, 38, 55, 33, 52, 255, 255, 45, 41, 49, 35, 28, 31, 255, 255, +]; + +// custom +pub const KEY_EXPANSION: [u8; 64] = [ + 31, 0, 1, 2, 3, 4, 255, 255, 3, 4, 5, 6, 7, 8, 255, 255, 7, 8, 9, 10, 11, 12, 255, 255, 11, 12, + 13, 14, 15, 16, 255, 255, 15, 16, 17, 18, 19, 20, 255, 255, 19, 20, 21, 22, 23, 24, 255, 255, + 23, 24, 25, 26, 27, 28, 255, 255, 27, 28, 29, 30, 31, 30, 255, 255, +]; + +pub const U64_SHIFT_TABLE_CACHE: [u64; 64] = { + let mut data = [0u64; 64]; + + let mut i = 0; + while i < 32 { + data[i] = 1u64 << i; + data[i + 32] = 1u64 << (i + 32); + i += 1; + } + + data +}; diff --git a/um_crypto/kuwo/src/des/des_impl.rs b/um_crypto/kuwo/src/des/des_impl.rs new file mode 100644 index 0000000..1a60323 --- /dev/null +++ b/um_crypto/kuwo/src/des/des_impl.rs @@ -0,0 +1,109 @@ +use super::{constants, helper}; +use crate::KuwoCryptoError; +use anyhow::Result; +use itertools::Either; + +/// Encrypt or Decrypt? +pub enum Mode { + Encrypt, + Decrypt, +} + +#[derive(Debug, Clone, Copy)] +pub struct KuwoDes { + subkeys: [u64; 16], +} + +fn des_subkey_expansion(key: &[u8; 8], mode: Mode) -> [u64; 16] { + let key = u64::from_le_bytes(*key); + + let mut param = helper::map_u64(key, &constants::KEY_PERMUTATION_TABLE); + + let mut subkeys = [0u64; 16]; + let subkey_iter = match mode { + Mode::Decrypt => Either::Left(subkeys.iter_mut().rev()), + Mode::Encrypt => Either::Right(subkeys.iter_mut()), + }; + + for ((subkey, shl), shl_mask) in subkey_iter + .zip(constants::KEY_RND_SHIFTS) + .zip(constants::KEY_SHIFT_LEFT_MASKS) + { + param = ((param & shl_mask) << (28 - shl)) | ((param & !shl_mask) >> (shl)); + *subkey = helper::map_u64(param, &constants::KEY_COMPRESSION); + } + + subkeys +} + +fn des_subkey_round(state: u64, subkey: u64) -> u64 { + let old_left = helper::u64_get_hi32(state); + let old_right = helper::u64_get_lo32(state); + + // Key expansion + let state = helper::map_u64(old_left as u64, &constants::KEY_EXPANSION); + let state = state ^ subkey; + + // SBox transformation + let right = constants::SBOXES + .iter() + .zip(state.to_be_bytes()) + .fold(0u32, |next, (sbox, b)| { + (next << 4) | (sbox[b as usize] as u32) + }); + + let right = helper::map_u32(right, &constants::PBOX); + let right = right ^ old_right; + + helper::make_u64(right, old_left) +} + +impl KuwoDes { + pub fn new(key: &[u8; 8], mode: Mode) -> Self { + Self { + subkeys: des_subkey_expansion(key, mode), + } + } + + pub fn transform_block(&self, data: u64) -> u64 { + let mut state = helper::map_u64(data, &constants::IP); + + state = self + .subkeys + .iter() + .fold(state, |state, &subkey| des_subkey_round(state, subkey)); + + // Swap data hi32/lo32 + state = helper::swap_u64_side(state); + + // Final permutation + state = helper::map_u64(state, &constants::IP_INV); + + state + } + + pub fn transform(&self, data: &mut [u8]) -> Result<()> { + if data.len() % 8 != 0 { + Err(KuwoCryptoError::InvalidDesDataSize(data.len()))? + } + + for block in data.chunks_exact_mut(8) { + let value = u64::from_le_bytes(block.try_into()?); + let value = self.transform_block(value); + block.copy_from_slice(&value.to_le_bytes()); + } + Ok(()) + } +} + +#[test] +fn test_des_decrypt() { + let mut input = [ + 0x36, 0x3C, 0x3E, 0x0D, 0x30, 0x31, 0xA4, 0x6C, 0xA0, 0xF0, 0x3A, 0xEC, 0x7F, 0x26, 0xF6, + 0xF4, + ]; + + let des = KuwoDes::new(b"ylzsxkwm", Mode::Decrypt); + des.transform(&mut input).unwrap(); + assert_eq!(&input, b"12345678ABCDEFGH"); +} diff --git a/um_crypto/kuwo/src/des/helper.rs b/um_crypto/kuwo/src/des/helper.rs new file mode 100644 index 0000000..2125a77 --- /dev/null +++ b/um_crypto/kuwo/src/des/helper.rs @@ -0,0 +1,49 @@ +pub(super) const fn make_u64(hi32: u32, lo32: u32) -> u64 { + ((hi32 as u64) << 32) | (lo32 as u64) +} + +pub(super) const fn swap_u64_side(value: u64) -> u64 { + (value.wrapping_shr(32)) | (value.wrapping_shl(32)) +} + +pub(super) const fn u64_get_lo32(value: u64) -> u32 { + value as u32 +} + +pub(super) const fn u64_get_hi32(value: u64) -> u32 { + value.wrapping_shr(32) as u32 +} + +pub(super) fn get_u64_by_shift_idx(value: u8) -> u64 { + if value == 255 { + return 0; + } + + if cfg!(target_pointer_width = "64") { + 1u64.wrapping_shl(value as u32) + } else { + super::constants::U64_SHIFT_TABLE_CACHE + .get(value as usize) + .copied() + .unwrap_or_default() + } +} + +#[test] +fn test_get_u64_by_shift_idx() { + assert_eq!(get_u64_by_shift_idx(0), 1); + assert_eq!(get_u64_by_shift_idx(63), 0x8000000000000000); +} + +pub(super) fn map_u64(src_value: u64, table: &[u8]) -> u64 { + table.iter().enumerate().fold(0u64, |acc, (i, &idx)| { + match get_u64_by_shift_idx(idx) & src_value { + 0 => acc, + _ => acc | get_u64_by_shift_idx(i as u8), + } + }) +} + +pub(super) fn map_u32(src_value: u32, table: &[u8]) -> u32 { + map_u64(src_value as u64, table) as u32 +} diff --git a/um_crypto/kuwo/src/des/mod.rs b/um_crypto/kuwo/src/des/mod.rs new file mode 100644 index 0000000..8c03b5b --- /dev/null +++ b/um_crypto/kuwo/src/des/mod.rs @@ -0,0 +1,52 @@ +use anyhow::Result; +use base64::alphabet; +use base64::engine::{DecodePaddingMode, GeneralPurpose as Base64Engine, GeneralPurposeConfig}; +use base64::prelude::*; + +mod constants; +mod des_impl; +mod helper; +pub use des_impl::{KuwoDes, Mode}; + +/// Don't add padding when encoding, and require no padding when decoding. +const B64: Base64Engine = Base64Engine::new( + &alphabet::STANDARD, + GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent), +); + +/// Decrypt string content +pub fn decrypt_ksing(data: &str, key: &[u8; 8]) -> Result { + let mut decoded = B64.decode(data)?; + + let des = KuwoDes::new(key, Mode::Decrypt); + des.transform(&mut decoded[..])?; + + let result = String::from_utf8_lossy(&decoded[..]) + .trim_end_matches('\x00') + .to_string(); + + Ok(result) +} + +pub fn encrypt_ksing>(data: T, key: &[u8; 8]) -> Result { + let mut data = Vec::from(data.as_ref()); + let padded_len = ((data.len() + 7) / 8) * 8; + data.resize(padded_len, 0u8); + + let des = KuwoDes::new(key, Mode::Encrypt); + des.transform(&mut data[..])?; + Ok(B64.encode(data)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_decode() { + let expected = "hello world"; + let decoded = + decrypt_ksing("tx5ct5ilzeLs7pN1C4RI6w==", b"12345678").expect("decrypt failed"); + assert_eq!(decoded, expected); + } +} diff --git a/um_crypto/kuwo/src/lib.rs b/um_crypto/kuwo/src/lib.rs new file mode 100644 index 0000000..61f99a4 --- /dev/null +++ b/um_crypto/kuwo/src/lib.rs @@ -0,0 +1,11 @@ +pub mod des; +use thiserror::Error; + +/// Commonly used secret key for Kuwo services. +pub const SECRET_KEY: [u8; 8] = *b"ylzsxkwm"; + +#[derive(Error, Debug)] +pub enum KuwoCryptoError { + #[error("Invalid DES data size (expected: {0} mod 8 == 0)")] + InvalidDesDataSize(usize), +} diff --git a/um_wasm/.gitignore b/um_wasm/.gitignore new file mode 100644 index 0000000..4e30131 --- /dev/null +++ b/um_wasm/.gitignore @@ -0,0 +1,6 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ +pkg/ +wasm-pack.log diff --git a/um_wasm/Cargo.toml b/um_wasm/Cargo.toml new file mode 100644 index 0000000..88a390d --- /dev/null +++ b/um_wasm/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "um_wasm" +version = "0.1.0" +authors = ["鲁树人 "] +edition = "2018" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasm-bindgen = "0.2.84" + +# 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.7", optional = true } +umc_kuwo = { path = "../um_crypto/kuwo" } + +[dev-dependencies] +wasm-bindgen-test = "0.3.34" + +[profile.release] +# Tell `rustc` to optimize for small code size. +opt-level = "s" diff --git a/um_wasm/README.md b/um_wasm/README.md new file mode 100644 index 0000000..9d7ceb8 --- /dev/null +++ b/um_wasm/README.md @@ -0,0 +1,3 @@ +# um_wasm + +加解密算法 Rust ❤️ WebAssembly 计划。 diff --git a/um_wasm/src/lib.rs b/um_wasm/src/lib.rs new file mode 100644 index 0000000..5a1262d --- /dev/null +++ b/um_wasm/src/lib.rs @@ -0,0 +1,19 @@ +mod utils; + +use utils::set_panic_hook; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + fn alert(s: &str); +} + +#[wasm_bindgen] +pub fn init() { + set_panic_hook(); +} + +#[wasm_bindgen] +pub fn greet() { + alert("hello world!"); +} diff --git a/um_wasm/src/utils.rs b/um_wasm/src/utils.rs new file mode 100644 index 0000000..b1d7929 --- /dev/null +++ b/um_wasm/src/utils.rs @@ -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(); +} diff --git a/um_wasm/tests/web.rs b/um_wasm/tests/web.rs new file mode 100644 index 0000000..de5c1da --- /dev/null +++ b/um_wasm/tests/web.rs @@ -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); +}