From e4e8fadb0ffd7f9e8366382daacec64620a59f1a Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Mon, 30 Jun 2025 11:43:41 -0700 Subject: [PATCH] Update libsignal-client to 0.76.0 --- .github/workflows/ci.yml | 2 +- ACKNOWLEDGMENTS.md | 635 +----------------- app/attachment_channel.ts | 2 +- package.json | 2 +- pnpm-lock.yaml | 10 +- ts/Crypto.ts | 20 +- ts/Curve.ts | 22 +- ts/LibSignalStores.ts | 2 +- ts/SignalProtocolStore.ts | 43 +- ts/jobs/helpers/sendResendRequest.ts | 3 +- ts/jobs/helpers/sendSavedProto.ts | 3 +- ts/services/backups/credentials.ts | 17 +- ts/services/backups/crypto.ts | 8 +- ts/services/backups/import.ts | 12 +- ts/services/backups/index.ts | 2 +- ts/services/backups/validator.ts | 2 +- ts/services/calling.ts | 20 +- ts/services/groupCredentialFetcher.ts | 13 +- ts/services/username.ts | 15 +- ts/services/usernameIntegrity.ts | 3 +- ts/test-electron/backup/integration_test.ts | 2 +- ts/test-helpers/generateBackup.ts | 10 +- ts/textsecure/AccountManager.ts | 4 +- ts/textsecure/MessageReceiver.ts | 28 +- ts/textsecure/OutgoingMessage.ts | 11 +- ts/textsecure/ProvisioningCipher.ts | 2 +- ts/textsecure/SendMessage.ts | 4 +- ts/textsecure/WebAPI.ts | 27 +- ts/textsecure/cds/CDSISocket.ts | 18 +- ts/textsecure/cds/CDSSocketBase.ts | 19 +- ts/textsecure/getKeysForServiceId.ts | 19 +- ts/textsecure/processDataMessage.ts | 2 +- ts/updater/curve.ts | 10 +- ts/updater/signature.ts | 14 +- ts/util/ServiceId.ts | 8 +- ts/util/groupSendEndorsements.ts | 11 +- ts/util/handleMessageSend.ts | 2 +- ts/util/handleRetry.ts | 2 +- ts/util/lookupConversationWithoutServiceId.ts | 2 +- ts/util/pemToDer.ts | 6 +- ts/util/safetyNumber.ts | 8 +- ts/util/sendToGroup.ts | 17 +- ts/util/zkgroup.ts | 66 +- 43 files changed, 245 insertions(+), 883 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c290699f7b..a66b4686c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -234,7 +234,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: repository: 'signalapp/Signal-Message-Backup-Tests' - ref: '57807422c347f53cfa8d5a1423c382992a8fc199' + ref: '316c3d5eb15ffc923b5ce2925094fd49b34e8203' path: 'backup-integration-tests' - run: xvfb-run --auto-servernum pnpm run test-electron diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index 307e4a019f..1ec4a1e746 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -5961,7 +5961,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see ``` -## libsignal-account-keys, attest, libsignal-ffi, libsignal-jni, libsignal-jni-impl, libsignal-jni-testing, libsignal-node, signal-neon-futures, signal-neon-futures-tests, libsignal-bridge, libsignal-bridge-macros, libsignal-bridge-testing, libsignal-bridge-types, libsignal-cli-utils, libsignal-core, signal-crypto, device-transfer, libsignal-keytrans, signal-media, libsignal-message-backup, libsignal-message-backup-macros, libsignal-net, libsignal-net-chat, libsignal-net-infra, poksho, libsignal-protocol, usernames, zkcredential, zkgroup +## libsignal-account-keys, attest, libsignal-node, signal-neon-futures, libsignal-bridge, libsignal-bridge-macros, libsignal-bridge-testing, libsignal-bridge-types, libsignal-core, signal-crypto, device-transfer, libsignal-keytrans, signal-media, libsignal-message-backup, libsignal-message-backup-macros, libsignal-net, libsignal-net-chat, libsignal-net-infra, poksho, libsignal-protocol, usernames, zkcredential, zkgroup ``` GNU AFFERO GENERAL PUBLIC LICENSE @@ -8360,7 +8360,7 @@ THIS SOFTWARE. ``` -## rustls-webpki 0.102.8, rustls-webpki 0.103.1 +## rustls-webpki 0.103.1 ``` Except as otherwise noted, this project is licensed under the following @@ -8385,7 +8385,7 @@ third-party/chromium/LICENSE. ``` -## windows-core 0.61.0, windows-implement 0.60.0, windows-interface 0.59.1, windows-link 0.1.1, windows-result 0.3.2, windows-strings 0.4.0, windows-sys 0.45.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-targets 0.42.2, windows-targets 0.52.6, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.52.6, windows_x86_64_gnu 0.52.6, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.52.6 +## windows-core 0.61.0, windows-implement 0.60.0, windows-interface 0.59.1, windows-link 0.1.1, windows-result 0.3.2, windows-strings 0.4.0, windows-sys 0.52.0, windows-sys 0.59.0, windows-targets 0.52.6, windows_aarch64_msvc 0.52.6, windows_x86_64_gnu 0.52.6, windows_x86_64_msvc 0.52.6 ``` MIT License @@ -8626,7 +8626,7 @@ DEALINGS IN THE SOFTWARE. ``` -## backtrace 0.3.74, cc 1.2.18, cfg-if 1.0.0, cmake 0.1.48, openssl-probe 0.1.6, pkg-config 0.3.32, rustc-demangle 0.1.24, scoped-tls 1.0.1, socket2 0.5.9 +## backtrace 0.3.74, cc 1.2.18, cfg-if 1.0.0, cmake 0.1.48, openssl-probe 0.1.6, rustc-demangle 0.1.24, socket2 0.5.9 ``` Copyright (c) 2014 Alex Crichton @@ -8689,38 +8689,6 @@ DEALINGS IN THE SOFTWARE. ``` -## libz-sys 1.1.22 - -``` -Copyright (c) 2014 Alex Crichton -Copyright (c) 2020 Josh Triplett - -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. - -``` - ## mio 1.0.3 ``` @@ -8775,32 +8743,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` - -## mime 0.3.17 - -``` -Copyright (c) 2014 Sean McArthur - -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. - - ``` ## base64ct 1.6.0 @@ -8896,32 +8838,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` - -## unicase 2.8.1 - -``` -Copyright (c) 2014-2017 Sean McArthur - -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. - - ``` ## nom 7.1.3 @@ -8948,32 +8864,6 @@ 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. -``` - -## headers-core 0.2.0, headers 0.3.9 - -``` -Copyright (c) 2014-2019 Sean McArthur - -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. - - ``` ## libc 0.2.171 @@ -9007,31 +8897,6 @@ DEALINGS IN THE SOFTWARE. ``` -## hyper 0.14.32 - -``` -Copyright (c) 2014-2021 Sean McArthur - -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. - -``` - ## flate2 1.1.1 ``` @@ -9287,31 +9152,6 @@ SOFTWARE. ``` -## jni-sys 0.3.0 - -``` -Copyright (c) 2015 The rust-jni-sys Developers - -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. - -``` - ## which 4.4.2 ``` @@ -9615,37 +9455,6 @@ DEALINGS IN THE SOFTWARE. ``` -## serde_urlencoded 0.7.1 - -``` -Copyright (c) 2016 Anthony Ramine - -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. - -``` - ## intmap 3.1.0 ``` @@ -9720,7 +9529,7 @@ DEALINGS IN THE SOFTWARE. ``` -## rustls-native-certs 0.8.1, rustls-pemfile 2.2.0, rustls 0.22.4, rustls 0.23.25 +## rustls-native-certs 0.8.1, rustls 0.23.25 ``` Copyright (c) 2016 Joseph Birr-Pixton @@ -9782,31 +9591,6 @@ DEALINGS IN THE SOFTWARE. ``` -## httpdate 1.0.3 - -``` -Copyright (c) 2016 Pyfisch - -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. - -``` - ## rustc_version 0.4.1 ``` @@ -10081,7 +9865,7 @@ DEALINGS IN THE SOFTWARE. ``` -## tungstenite 0.21.0, tungstenite 0.26.2 +## tungstenite 0.26.2 ``` Copyright (c) 2017 Alexey Galakhov @@ -10200,7 +9984,7 @@ DEALINGS IN THE SOFTWARE. ``` -## tokio-tungstenite 0.21.0, tokio-tungstenite 0.26.2 +## tokio-tungstenite 0.26.2 ``` Copyright (c) 2017 Daniel Abramov @@ -10250,38 +10034,6 @@ 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. -``` - -## vcpkg 0.2.15 - -``` -Copyright (c) 2017 Jim McGrath - -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. - - ``` ## stable_deref_trait 1.2.0 @@ -10339,7 +10091,7 @@ SOFTWARE. ``` -## h2 0.3.26, h2 0.4.8 +## h2 0.4.8 ``` Copyright (c) 2017 h2 authors @@ -10370,7 +10122,7 @@ DEALINGS IN THE SOFTWARE. ``` -## http 0.2.12, http 1.3.1 +## http 1.3.1 ``` Copyright (c) 2017 http-rs authors @@ -10401,37 +10153,6 @@ DEALINGS IN THE SOFTWARE. ``` -## tokio-rustls 0.25.0 - -``` -Copyright (c) 2017 quininer kel - -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. - -``` - ## aes 0.8.4 ``` @@ -10642,32 +10363,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` - -## warp 0.3.7 - -``` -Copyright (c) 2018-2020 Sean McArthur - -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. - - ``` ## cbc 0.1.2, ctr 0.9.2 @@ -10886,37 +10581,6 @@ DEALINGS IN THE SOFTWARE. ``` -## http-body 0.4.6 - -``` -Copyright (c) 2019 Hyper Contributors - -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. - -``` - ## ghash 0.5.1 ``` @@ -11066,7 +10730,7 @@ DEALINGS IN THE SOFTWARE. ``` -## aes-gcm-siv 0.11.1, aes-gcm 0.10.3, chacha20poly1305 0.10.1 +## aes-gcm-siv 0.11.1, chacha20poly1305 0.10.1 ``` Copyright (c) 2019 The RustCrypto Project Developers @@ -11160,37 +10824,6 @@ DEALINGS IN THE SOFTWARE. ``` -## tower-service 0.3.3 - -``` -Copyright (c) 2019 Tower Contributors - -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. - -``` - ## universal-hash 0.5.1 ``` @@ -11971,7 +11604,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ``` -## rand 0.8.5, rand 0.9.0, rand_chacha 0.3.1, rand_chacha 0.9.0, rand_core 0.6.4, rand_core 0.9.3 +## rand 0.9.0, rand_chacha 0.9.0, rand_core 0.6.4, rand_core 0.9.3 ``` Copyright 2018 Developers of the Rand project @@ -12511,33 +12144,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## multer 2.1.0 - -``` -MIT License - -Copyright (c) 2020 Rousan Ali - -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. - -``` - ## snow 0.9.6 ``` @@ -12619,7 +12225,7 @@ SOFTWARE. ``` -## rustls-platform-verifier-android 0.1.1, rustls-platform-verifier 0.5.1 +## rustls-platform-verifier 0.5.1 ``` MIT License @@ -12673,30 +12279,6 @@ SOFTWARE. ``` -## cesu8 1.1.0 - -``` -MIT License - -Copyright (c) - -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. - -``` - ## tokio-stream 0.1.17, tokio-util 0.7.14, tokio 1.45.0 ``` @@ -12724,33 +12306,6 @@ SOFTWARE. ``` -## android-tzdata 0.1.1 - -``` -MIT License - -Copyright (c) [year] [fullname] - -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. - -``` - ## miniz_oxide 0.8.7 ``` @@ -12860,58 +12415,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## android_system_properties 0.1.5 - -``` -The MIT License (MIT) - -Copyright (c) 2013 Nicolas Silva - -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. - -``` - -## spin 0.9.8 - -``` -The MIT License (MIT) - -Copyright (c) 2014 Mathijs van de Nes - -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. -``` - ## typenum 1.18.0 ``` @@ -12965,7 +12468,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## base64 0.21.7, base64 0.22.1 +## base64 0.22.1 ``` The MIT License (MIT) @@ -12992,7 +12495,7 @@ THE SOFTWARE. ``` -## aho-corasick 1.1.3, byteorder 1.5.0, jiff 0.2.5, memchr 2.7.4, walkdir 2.5.0 +## aho-corasick 1.1.3, jiff 0.2.5, memchr 2.7.4 ``` The MIT License (MIT) @@ -13046,34 +12549,6 @@ 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. -``` - -## combine 4.6.7 - -``` -The MIT License (MIT) - -Copyright (c) 2015 Markus Westerlind - -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. - - ``` ## shlex 1.3.0 @@ -13211,33 +12686,6 @@ SOFTWARE. ``` -## jni 0.21.1 - -``` -The MIT License (MIT) - -Copyright (c) 2016 Prevoty, Inc. and jni-rs contributors - -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. - -``` - ## derive_builder 0.20.2, derive_builder_core 0.20.2, derive_builder_macro 0.20.2 ``` @@ -13265,33 +12713,6 @@ SOFTWARE. ``` -## same-file 1.0.6, winapi-util 0.1.9 - -``` -The MIT License (MIT) - -Copyright (c) 2017 Andrew Gallant - -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. - -``` - ## async-compression 0.4.22 ``` @@ -13490,34 +12911,6 @@ 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. -``` - -## mime_guess 2.0.5 - -``` -The MIT License (MIT) - -Copyright (c) 2015 Austin Bonander - -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. - - ``` ## generic-array 0.14.7 diff --git a/app/attachment_channel.ts b/app/attachment_channel.ts index b5fc8b2845..5b92f6ff2f 100644 --- a/app/attachment_channel.ts +++ b/app/attachment_channel.ts @@ -108,7 +108,7 @@ type RangeFinderContextType = Readonly< type DigestLRUEntryType = Readonly<{ key: Buffer; - digest: Buffer; + digest: Uint8Array; }>; const digestLRU = new LRUCache({ diff --git a/package.json b/package.json index c5e4c91f33..214072951f 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "@react-aria/utils": "3.25.3", "@react-spring/web": "9.7.5", "@react-types/shared": "3.27.0", - "@signalapp/libsignal-client": "0.74.1", + "@signalapp/libsignal-client": "0.76.0", "@signalapp/quill-cjs": "2.1.2", "@signalapp/ringrtc": "2.53.0", "@signalapp/sqlcipher": "2.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2a5d08082..0ab6cd11c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -129,8 +129,8 @@ importers: specifier: 3.27.0 version: 3.27.0(react@18.3.1) '@signalapp/libsignal-client': - specifier: 0.74.1 - version: 0.74.1 + specifier: 0.76.0 + version: 0.76.0 '@signalapp/quill-cjs': specifier: 2.1.2 version: 2.1.2 @@ -2767,8 +2767,8 @@ packages: '@signalapp/libsignal-client@0.60.2': resolution: {integrity: sha512-tU4kNP/yCwkFntb2ahXOSQJtzdy+YifAB2yv5hw0qyKSidRHLn6bYiz4Zo2tjxLDRoBLAUxCRsQramStiqNZdA==} - '@signalapp/libsignal-client@0.74.1': - resolution: {integrity: sha512-PEJou0yrBvxaAGg7JjONlRNM/t3PCBuY96wu7W6+57e38/7Mibo9kAMfE5B8DgVv+DUNMW9AgJhx5McCoIXYew==} + '@signalapp/libsignal-client@0.76.0': + resolution: {integrity: sha512-wQZFC79GAUeee8pf+aDK5Gii0HbQoCAv/oTn1Ht7d5mFq2pw/L0jRcv3j9DgVYodzCOlnanfto3apfA6eN/Whw==} '@signalapp/mock-server@13.0.1': resolution: {integrity: sha512-1rT0fYyqEad64GnZRrFVhNsgKpPS+pvyyk8iOGUHqnqnf818yLIYHblS/5m/cNcvHyC/BBqdtgRHAsfGNqkuZw==} @@ -12460,7 +12460,7 @@ snapshots: type-fest: 4.26.1 uuid: 8.3.2 - '@signalapp/libsignal-client@0.74.1': + '@signalapp/libsignal-client@0.76.0': dependencies: node-gyp-build: 4.8.4 type-fest: 4.26.1 diff --git a/ts/Crypto.ts b/ts/Crypto.ts index 7f41f2caef..7a0aeec605 100644 --- a/ts/Crypto.ts +++ b/ts/Crypto.ts @@ -1,7 +1,6 @@ // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import { Buffer } from 'buffer'; import Long from 'long'; import { sample } from 'lodash'; import { Aci, Pni, hkdf } from '@signalapp/libsignal-client'; @@ -58,12 +57,7 @@ export function deriveSecrets( salt: Uint8Array, info: Uint8Array ): [Uint8Array, Uint8Array, Uint8Array] { - const output = hkdf( - 3 * 32, - Buffer.from(input), - Buffer.from(info), - Buffer.from(salt) - ); + const output = hkdf(3 * 32, input, info, salt); return [ output.subarray(0, 32), output.subarray(32, 64), @@ -198,12 +192,12 @@ export function deriveStorageItemKey({ return hkdf( STORAGE_SERVICE_ITEM_KEY_LEN, - Buffer.from(recordIkm), - Buffer.concat([ - Buffer.from(STORAGE_SERVICE_ITEM_KEY_INFO_PREFIX), - Buffer.from(key), + recordIkm, + Bytes.concatenate([ + Bytes.fromString(STORAGE_SERVICE_ITEM_KEY_INFO_PREFIX), + key, ]), - Buffer.alloc(0) + new Uint8Array(0) ); } @@ -547,7 +541,7 @@ export function padAndEncryptAttachment({ // We generate the plaintext hash here for forwards-compatibility with streaming // attachment encryption, which may be the only place that the whole attachment flows // through memory - plaintextHash: Buffer.from(sha256(plaintext)).toString('hex'), + plaintextHash: Bytes.toHex(sha256(plaintext)), }; } diff --git a/ts/Curve.ts b/ts/Curve.ts index 3015a7c197..968c2a800b 100644 --- a/ts/Curve.ts +++ b/ts/Curve.ts @@ -69,12 +69,7 @@ export function generateKyberPreKey( identityKeyPair.privateKey, keyPair.getPublicKey().serialize() ); - return client.KyberPreKeyRecord.new( - keyId, - Date.now(), - keyPair, - Buffer.from(signature) - ); + return client.KyberPreKeyRecord.new(keyId, Date.now(), keyPair, signature); } export function generateKeyPair(): KeyPairType { @@ -91,13 +86,11 @@ export function createKeyPair(incomingKey: Uint8Array): KeyPairType { log.warn('createKeyPair: incoming private key was not clamped!'); } - const incomingKeyBuffer = Buffer.from(incomingKey); - - if (incomingKeyBuffer.length !== 32) { + if (incomingKey.length !== 32) { throw new Error('key must be 32 bytes long'); } - const privKey = client.PrivateKey.deserialize(incomingKeyBuffer); + const privKey = client.PrivateKey.deserialize(incomingKey); const pubKey = privKey.getPublicKey(); return new client.IdentityKeyPair(pubKey, privKey); @@ -122,19 +115,14 @@ export function verifySignature( message: Uint8Array, signature: Uint8Array ): boolean { - const messageBuffer = Buffer.from(message); - const signatureBuffer = Buffer.from(signature); - - return pubKey.verify(messageBuffer, signatureBuffer); + return pubKey.verify(message, signature); } export function calculateSignature( privKey: client.PrivateKey, plaintext: Uint8Array ): Uint8Array { - const plaintextBuffer = Buffer.from(plaintext); - - return privKey.sign(plaintextBuffer); + return privKey.sign(plaintext); } function validatePubKeyFormat(pubKey: Uint8Array): Uint8Array { diff --git a/ts/LibSignalStores.ts b/ts/LibSignalStores.ts index 8aac535521..c6c022de8a 100644 --- a/ts/LibSignalStores.ts +++ b/ts/LibSignalStores.ts @@ -143,7 +143,7 @@ export class IdentityKeys extends IdentityKeyStore { return null; } - return PublicKey.deserialize(Buffer.from(key)); + return PublicKey.deserialize(key); } async saveIdentity( diff --git a/ts/SignalProtocolStore.ts b/ts/SignalProtocolStore.ts index a36cf657b6..00ba1b491f 100644 --- a/ts/SignalProtocolStore.ts +++ b/ts/SignalProtocolStore.ts @@ -180,23 +180,23 @@ async function _fillCaches, HydratedType>( } export function hydrateSession(session: SessionType): SessionRecord { - return SessionRecord.deserialize(Buffer.from(session.record)); + return SessionRecord.deserialize(session.record); } export function hydratePublicKey(identityKey: IdentityKeyType): PublicKey { - return PublicKey.deserialize(Buffer.from(identityKey.publicKey)); + return PublicKey.deserialize(identityKey.publicKey); } export function hydratePreKey(preKey: PreKeyType): PreKeyRecord { - const publicKey = PublicKey.deserialize(Buffer.from(preKey.publicKey)); - const privateKey = PrivateKey.deserialize(Buffer.from(preKey.privateKey)); + const publicKey = PublicKey.deserialize(preKey.publicKey); + const privateKey = PrivateKey.deserialize(preKey.privateKey); return PreKeyRecord.new(preKey.keyId, publicKey, privateKey); } export function hydrateSignedPreKey( signedPreKey: SignedPreKeyType ): SignedPreKeyRecord { const createdAt = signedPreKey.created_at; - const pubKey = PublicKey.deserialize(Buffer.from(signedPreKey.publicKey)); - const privKey = PrivateKey.deserialize(Buffer.from(signedPreKey.privateKey)); - const signature = Buffer.from([]); + const pubKey = PublicKey.deserialize(signedPreKey.publicKey); + const privKey = PrivateKey.deserialize(signedPreKey.privateKey); + const signature = new Uint8Array(0); return SignedPreKeyRecord.new( signedPreKey.keyId, @@ -277,8 +277,8 @@ export class SignalProtocolStore extends EventEmitter { 'Invalid identity key serviceId' ); const { privKey, pubKey } = map.value[serviceId]; - const privateKey = PrivateKey.deserialize(Buffer.from(privKey)); - const publicKey = PublicKey.deserialize(Buffer.from(pubKey)); + const privateKey = PrivateKey.deserialize(privKey); + const publicKey = PublicKey.deserialize(pubKey); this.#ourIdentityKeys.set( serviceId, new IdentityKeyPair(publicKey, privateKey) @@ -374,7 +374,7 @@ export class SignalProtocolStore extends EventEmitter { return entry; } - const item = KyberPreKeyRecord.deserialize(Buffer.from(entry.fromDB.data)); + const item = KyberPreKeyRecord.deserialize(entry.fromDB.data); const newEntry = { hydrated: true as const, fromDB: entry.fromDB, @@ -932,9 +932,7 @@ export class SignalProtocolStore extends EventEmitter { return entry.item; } - const item = SenderKeyRecord.deserialize( - Buffer.from(entry.fromDB.data) - ); + const item = SenderKeyRecord.deserialize(entry.fromDB.data); this.senderKeys.set(id, { hydrated: true, item, @@ -2485,14 +2483,10 @@ export class SignalProtocolStore extends EventEmitter { const logId = `SignalProtocolStore.updateOurPniKeyMaterial(${pni})`; log.info(`${logId}: starting...`); - const identityKeyPair = IdentityKeyPair.deserialize( - Buffer.from(identityBytes) - ); - const signedPreKey = SignedPreKeyRecord.deserialize( - Buffer.from(signedPreKeyBytes) - ); + const identityKeyPair = IdentityKeyPair.deserialize(identityBytes); + const signedPreKey = SignedPreKeyRecord.deserialize(signedPreKeyBytes); const lastResortKyberPreKey = lastResortKyberPreKeyBytes - ? KyberPreKeyRecord.deserialize(Buffer.from(lastResortKyberPreKeyBytes)) + ? KyberPreKeyRecord.deserialize(lastResortKyberPreKeyBytes) : undefined; const { storage } = window; @@ -2636,13 +2630,10 @@ export class SignalProtocolStore extends EventEmitter { return false; } - const aciPublicKey = PublicKey.deserialize(Buffer.from(aciPublicKeyBytes)); - const pniPublicKey = PublicKey.deserialize(Buffer.from(pniPublicKeyBytes)); + const aciPublicKey = PublicKey.deserialize(aciPublicKeyBytes); + const pniPublicKey = PublicKey.deserialize(pniPublicKeyBytes); - return pniPublicKey.verifyAlternateIdentity( - aciPublicKey, - Buffer.from(signature) - ); + return pniPublicKey.verifyAlternateIdentity(aciPublicKey, signature); } #_getAllSessions(): Array { diff --git a/ts/jobs/helpers/sendResendRequest.ts b/ts/jobs/helpers/sendResendRequest.ts index 05c815d6bc..eb0ae39777 100644 --- a/ts/jobs/helpers/sendResendRequest.ts +++ b/ts/jobs/helpers/sendResendRequest.ts @@ -27,6 +27,7 @@ import { strictAssert } from '../../util/assert'; import type { DecryptionErrorEventData } from '../../textsecure/messageReceiverEvents'; import type { LoggerType } from '../../types/Logging'; import { startAutomaticSessionReset } from '../../util/handleRetry'; +import * as Bytes from '../../Bytes'; function failoverToLocalReset( logger: LoggerType, @@ -95,7 +96,7 @@ export async function sendResendRequest( } const plaintext = PlaintextContent.deserialize( - Buffer.from(plaintextBase64, 'base64') + Bytes.fromBase64(plaintextBase64) ); const { ContentHint } = Proto.UnidentifiedSenderMessage.Message; diff --git a/ts/jobs/helpers/sendSavedProto.ts b/ts/jobs/helpers/sendSavedProto.ts index 13ae726751..55043549ac 100644 --- a/ts/jobs/helpers/sendSavedProto.ts +++ b/ts/jobs/helpers/sendSavedProto.ts @@ -20,6 +20,7 @@ import { OutgoingIdentityKeyError, UnregisteredUserError, } from '../../textsecure/Errors'; +import * as Bytes from '../../Bytes'; export async function sendSavedProto( conversation: ConversationModel, @@ -77,7 +78,7 @@ export async function sendSavedProto( const sendType = 'resendFromLog'; try { - const proto = Proto.Content.decode(Buffer.from(protoBase64, 'base64')); + const proto = Proto.Content.decode(Bytes.fromBase64(protoBase64)); await handleMessageSend( messaging.sendMessageProtoAndWait({ contentHint, diff --git a/ts/services/backups/credentials.ts b/ts/services/backups/credentials.ts index fe395cc79a..3f5c66a40f 100644 --- a/ts/services/backups/credentials.ts +++ b/ts/services/backups/credentials.ts @@ -11,6 +11,7 @@ import { } from '@signalapp/libsignal-client/zkgroup'; import { type BackupKey } from '@signalapp/libsignal-client/dist/AccountKeys'; +import * as Bytes from '../../Bytes'; import { createLogger } from '../../logging/log'; import { strictAssert } from '../../util/assert'; import { drop } from '../../util/drop'; @@ -92,20 +93,18 @@ export class BackupCredentials { ); } - const cred = new BackupAuthCredential( - Buffer.from(result.credential, 'base64') - ); + const cred = new BackupAuthCredential(Bytes.fromBase64(result.credential)); const serverPublicParams = new GenericServerPublicParams( - Buffer.from(window.getBackupServerPublicParams(), 'base64') + Bytes.fromBase64(window.getBackupServerPublicParams()) ); const presentation = cred.present(serverPublicParams).serialize(); const signature = signatureKey.sign(presentation); const headers = { - 'X-Signal-ZK-Auth': presentation.toString('base64'), - 'X-Signal-ZK-Auth-Signature': signature.toString('base64'), + 'X-Signal-ZK-Auth': Bytes.toBase64(presentation), + 'X-Signal-ZK-Auth-Signature': Bytes.toBase64(signature), }; const info = { headers, level: result.level }; @@ -274,7 +273,7 @@ export class BackupCredentials { ); const serverPublicParams = new GenericServerPublicParams( - Buffer.from(window.getBackupServerPublicParams(), 'base64') + Bytes.fromBase64(window.getBackupServerPublicParams()) ); const result = new Array(); @@ -300,7 +299,7 @@ export class BackupCredentials { credential: buf, redemptionTime, } of allCredentials) { - const credentialRes = new BackupAuthCredentialResponse(Buffer.from(buf)); + const credentialRes = new BackupAuthCredentialResponse(buf); const redemptionTimeMs = DurationInSeconds.toMillis(redemptionTime); strictAssert( @@ -326,7 +325,7 @@ export class BackupCredentials { result.push({ type, - credential: credential.serialize().toString('base64'), + credential: Bytes.toBase64(credential.serialize()), level: credential.getBackupLevel(), redemptionTimeMs, }); diff --git a/ts/services/backups/crypto.ts b/ts/services/backups/crypto.ts index 2b77b39572..b0b79698c3 100644 --- a/ts/services/backups/crypto.ts +++ b/ts/services/backups/crypto.ts @@ -28,7 +28,7 @@ export function getBackupMediaRootKey(): BackupKey { const rootKey = window.storage.get('backupMediaRootKey'); strictAssert(rootKey, 'Media root key not available'); - return new BackupKey(Buffer.from(rootKey)); + return new BackupKey(rootKey); } const getMemoizedBackupSignatureKey = memoizee( @@ -94,7 +94,7 @@ export function deriveBackupMediaKeyMaterial( throw new Error('deriveBackupMediaKeyMaterial: mediaId missing'); } - const material = mediaRootKey.deriveMediaEncryptionKey(Buffer.from(mediaId)); + const material = mediaRootKey.deriveMediaEncryptionKey(mediaId); return { macKey: material.subarray(0, BACKUP_MEDIA_MAC_KEY_LEN), @@ -113,9 +113,7 @@ export function deriveBackupThumbnailTransitKeyMaterial( throw new Error('deriveBackupThumbnailTransitKeyMaterial: mediaId missing'); } - const material = mediaRootKey.deriveThumbnailTransitEncryptionKey( - Buffer.from(mediaId) - ); + const material = mediaRootKey.deriveThumbnailTransitEncryptionKey(mediaId); return { macKey: material.subarray(0, BACKUP_MEDIA_MAC_KEY_LEN), diff --git a/ts/services/backups/import.ts b/ts/services/backups/import.ts index f2266ac015..a27a394c4a 100644 --- a/ts/services/backups/import.ts +++ b/ts/services/backups/import.ts @@ -1130,7 +1130,7 @@ export class BackupImportStream extends Writable { strictAssert(Bytes.isNotEmpty(userId), 'Empty gv2 member userId'); const serviceId = fromServiceIdObject( - ServiceId.parseFromServiceIdBinary(Buffer.from(userId)) + ServiceId.parseFromServiceIdBinary(userId) ); return { @@ -1163,7 +1163,7 @@ export class BackupImportStream extends Writable { // in the Contact frame const serviceId = fromServiceIdObject( - ServiceId.parseFromServiceIdBinary(Buffer.from(userId)) + ServiceId.parseFromServiceIdBinary(userId) ); return { @@ -2164,9 +2164,7 @@ export class BackupImportStream extends Writable { bodyRanges.map(range => ({ ...range, mentionAci: range.mentionAci - ? Aci.parseFromServiceIdBinary( - Buffer.from(range.mentionAci) - ).getServiceIdString() + ? Aci.parseFromServiceIdBinary(range.mentionAci).getServiceIdString() : undefined, })) ); @@ -2422,7 +2420,7 @@ export class BackupImportStream extends Writable { } const receipt = new ReceiptCredentialPresentation( - Buffer.from(giftBadge.receiptCredentialPresentation) + giftBadge.receiptCredentialPresentation ); return { @@ -2901,7 +2899,7 @@ export class BackupImportStream extends Writable { details.push({ type: 'pending-add-one', serviceId: fromServiceIdObject( - ServiceId.parseFromServiceIdBinary(Buffer.from(inviteeServiceId)) + ServiceId.parseFromServiceIdBinary(inviteeServiceId) ), }); } diff --git a/ts/services/backups/index.ts b/ts/services/backups/index.ts index e73731e4a9..8aa3a49081 100644 --- a/ts/services/backups/index.ts +++ b/ts/services/backups/index.ts @@ -579,7 +579,7 @@ export class BackupsService { ); if (backupType === BackupType.Ciphertext) { const { aesKey, macKey } = getKeyMaterial( - ephemeralKey ? new BackupKey(Buffer.from(ephemeralKey)) : undefined + ephemeralKey ? new BackupKey(ephemeralKey) : undefined ); // First pass - don't decrypt, only verify mac diff --git a/ts/services/backups/validator.ts b/ts/services/backups/validator.ts index 51bba6a6e1..92d01be4ab 100644 --- a/ts/services/backups/validator.ts +++ b/ts/services/backups/validator.ts @@ -61,7 +61,7 @@ export async function validateBackupStream( frameCount += 1; const reader = new Reader(delimitedFrame); - const frame = Buffer.from(reader.bytes()); + const frame = reader.bytes(); // Info frame if (frameCount === 1) { diff --git a/ts/services/calling.ts b/ts/services/calling.ts index 283602984e..69c676df04 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -764,11 +764,11 @@ export class CallingClass { ); const response = new CreateCallLinkCredentialResponse( - Buffer.from(credentialBase64, 'base64') + Bytes.fromBase64(credentialBase64) ); const genericServerPublicParams = new GenericServerPublicParams( - Buffer.from(window.getGenericServerPublicParams(), 'base64') + Bytes.fromBase64(window.getGenericServerPublicParams()) ); const credential = context.receive( response, @@ -785,10 +785,10 @@ export class CallingClass { const result = await RingRTC.createCallLink( sfuUrl, - credentialPresentation, + Buffer.from(credentialPresentation), rootKey, adminKey, - serializedPublicParams, + Buffer.from(serializedPublicParams), CallLinkRestrictions.AdminApproval ); @@ -832,7 +832,7 @@ export class CallingClass { const result = await RingRTC.deleteCallLink( sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined, callLinkAdminKey @@ -869,7 +869,7 @@ export class CallingClass { await getCallLinkAuthCredentialPresentation(callLinkRootKey); const result = await RingRTC.updateCallLinkName( sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined, callLinkAdminKey, @@ -915,7 +915,7 @@ export class CallingClass { const result = await RingRTC.updateCallLinkRestrictions( sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined, callLinkAdminKey, @@ -950,7 +950,7 @@ export class CallingClass { const result = await RingRTC.readCallLink( this._sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined ); @@ -1246,7 +1246,7 @@ export class CallingClass { const result = await RingRTC.peekCallLinkCall( this._sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined ); @@ -1380,7 +1380,7 @@ export class CallingClass { const outerGroupCall = RingRTC.getCallLinkCall( this._sfuUrl, - authCredentialPresentation.serialize(), + Buffer.from(authCredentialPresentation.serialize()), callLinkRootKey, undefined, adminPasskey, diff --git a/ts/services/groupCredentialFetcher.ts b/ts/services/groupCredentialFetcher.ts index 37cda95393..c04069a09a 100644 --- a/ts/services/groupCredentialFetcher.ts +++ b/ts/services/groupCredentialFetcher.ts @@ -19,6 +19,7 @@ import { toDayMillis } from '../util/timestamp'; import { toTaggedPni } from '../types/ServiceId'; import { toPniObject, toAciObject } from '../util/ServiceId'; import { createLogger } from '../logging/log'; +import * as Bytes from '../Bytes'; const log = createLogger('groupCredentialFetcher'); @@ -221,11 +222,9 @@ export async function maybeFetchNewCredentials(): Promise { toAciObject(aci), toPniObject(pni), item.redemptionTime, - new AuthCredentialWithPniResponse( - Buffer.from(item.credential, 'base64') - ) + new AuthCredentialWithPniResponse(Bytes.fromBase64(item.credential)) ); - const credential = authCredential.serialize().toString('base64'); + const credential = Bytes.toBase64(authCredential.serialize()); return { redemptionTime: item.redemptionTime * durations.SECOND, @@ -237,21 +236,21 @@ export async function maybeFetchNewCredentials(): Promise { sortCredentials(rawCredentials).map(formatCredential); const genericServerPublicParamsBase64 = window.getGenericServerPublicParams(); const genericServerPublicParams = new GenericServerPublicParams( - Buffer.from(genericServerPublicParamsBase64, 'base64') + Bytes.fromBase64(genericServerPublicParamsBase64) ); function formatCallingCredential( item: GroupCredentialType ): GroupCredentialType { const response = new CallLinkAuthCredentialResponse( - Buffer.from(item.credential, 'base64') + Bytes.fromBase64(item.credential) ); const authCredential = response.receive( toAciObject(aci), item.redemptionTime, genericServerPublicParams ); - const credential = authCredential.serialize().toString('base64'); + const credential = Bytes.toBase64(authCredential.serialize()); return { redemptionTime: item.redemptionTime * durations.SECOND, diff --git a/ts/services/username.ts b/ts/services/username.ts index 807f810db2..511fdc78aa 100644 --- a/ts/services/username.ts +++ b/ts/services/username.ts @@ -119,7 +119,7 @@ export async function reserveUsername( abortSignal, }); - const index = hashes.findIndex(hash => hash.equals(usernameHash)); + const index = hashes.findIndex(hash => Bytes.areEqual(hash, usernameHash)); if (index === -1) { log.warn('reserveUsername: failed to find username hash in the response'); return { ok: false, error: ReserveUsernameError.Unprocessable }; @@ -244,7 +244,10 @@ export async function confirmUsername( } const { hash } = reservation; - strictAssert(usernames.hash(username).equals(hash), 'username hash mismatch'); + strictAssert( + Bytes.areEqual(usernames.hash(username), hash), + 'username hash mismatch' + ); const wasCorrupted = window.storage.get('usernameCorrupted'); @@ -252,13 +255,13 @@ export async function confirmUsername( await window.storage.remove('usernameLink'); let serverIdString: string; - let entropy: Buffer; + let entropy: Uint8Array; if (previousLink && isCaseChange(reservation)) { log.info('confirmUsername: updating link only'); const updatedLink = usernames.createUsernameLink( username, - Buffer.from(previousLink.entropy) + previousLink.entropy ); ({ entropy } = updatedLink); @@ -401,8 +404,8 @@ export async function resolveUsernameByLink({ await server.resolveUsernameLink(serverId); return usernames.decryptUsernameLink({ - entropy: Buffer.from(entropy), - encryptedUsername: Buffer.from(usernameLinkEncryptedValue), + entropy, + encryptedUsername: usernameLinkEncryptedValue, }); } catch (error) { if (error instanceof HTTPError && error.code === 404) { diff --git a/ts/services/usernameIntegrity.ts b/ts/services/usernameIntegrity.ts index 30012d46f0..8e20760539 100644 --- a/ts/services/usernameIntegrity.ts +++ b/ts/services/usernameIntegrity.ts @@ -17,6 +17,7 @@ import { getProfile } from '../util/getProfile'; import { isSharingPhoneNumberWithEverybody } from '../util/phoneNumberSharingMode'; import { bytesToUuid } from '../util/uuidToBytes'; import { createLogger } from '../logging/log'; +import * as Bytes from '../Bytes'; import { runStorageServiceSyncJob } from './storage'; import { writeProfile } from './writeProfile'; @@ -101,7 +102,7 @@ class UsernameIntegrityService { let failed = false; - if (remoteHash !== usernames.hash(username).toString('base64url')) { + if (remoteHash !== Bytes.toBase64url(usernames.hash(username))) { log.error('remote username mismatch'); await window.storage.put('usernameCorrupted', true); failed = true; diff --git a/ts/test-electron/backup/integration_test.ts b/ts/test-electron/backup/integration_test.ts index 8e3b3eb98d..72d83aa571 100644 --- a/ts/test-electron/backup/integration_test.ts +++ b/ts/test-electron/backup/integration_test.ts @@ -41,7 +41,7 @@ describe('backup/integration', () => { const files = readdirSync(BACKUP_INTEGRATION_DIR) .filter(file => file.endsWith('.binproto')) // TODO: DESKTOP-8906 - .filter(file => file !== 'chat_item_view_once_00.binproto') + .filter(file => file !== 'chat_item_view_once_07.binproto') .map(file => join(BACKUP_INTEGRATION_DIR, file)); if (files.length === 0) { diff --git a/ts/test-helpers/generateBackup.ts b/ts/test-helpers/generateBackup.ts index bb2beb7165..78ec2246c4 100644 --- a/ts/test-helpers/generateBackup.ts +++ b/ts/test-helpers/generateBackup.ts @@ -25,17 +25,17 @@ import { Backups } from '../protobuf'; export type BackupGeneratorConfigType = Readonly< { aci: AciString; - profileKey: Buffer; + profileKey: Uint8Array; conversations: number; conversationAcis?: ReadonlyArray; messages: number; - mediaRootBackupKey: Buffer; + mediaRootBackupKey: Uint8Array; } & ( | { accountEntropyPool: string; } | { - backupKey: Buffer; + backupKey: Uint8Array; } ) >; @@ -43,7 +43,7 @@ export type BackupGeneratorConfigType = Readonly< const IV_LENGTH = 16; export type GenerateBackupResultType = Readonly<{ - backupId: Buffer; + backupId: Uint8Array; stream: Readable; }>; @@ -145,7 +145,7 @@ function* createRecords({ const chats = new Array<{ id: Long; - aci: Buffer; + aci: Uint8Array; }>(); for (let i = 1; i <= conversations; i += 1) { diff --git a/ts/textsecure/AccountManager.ts b/ts/textsecure/AccountManager.ts index 7dd07406dc..c8b687c664 100644 --- a/ts/textsecure/AccountManager.ts +++ b/ts/textsecure/AccountManager.ts @@ -289,9 +289,7 @@ export default class AccountManager extends EventTarget { const name = decryptDeviceName( { - ephemeralPublic: PublicKey.deserialize( - Buffer.from(proto.ephemeralPublic) - ), + ephemeralPublic: PublicKey.deserialize(proto.ephemeralPublic), syntheticIv: proto.syntheticIv, ciphertext: proto.ciphertext, }, diff --git a/ts/textsecure/MessageReceiver.ts b/ts/textsecure/MessageReceiver.ts index 8409434845..7ab4864b6a 100644 --- a/ts/textsecure/MessageReceiver.ts +++ b/ts/textsecure/MessageReceiver.ts @@ -321,7 +321,7 @@ export default class MessageReceiver throw new Error('Server trust root is required!'); } this.#serverTrustRoot = PublicKey.deserialize( - Buffer.from(Bytes.fromBase64(serverTrustRoot)) + Bytes.fromBase64(serverTrustRoot) ); this.#incomingQueue = new PQueue({ @@ -1351,7 +1351,7 @@ export default class MessageReceiver log.info(`unsealEnvelope(${logId}): unidentified message`); const messageContent = await sealedSenderDecryptToUsmc( - Buffer.from(ciphertext), + ciphertext, stores.identityKeyStore ); @@ -1362,6 +1362,8 @@ export default class MessageReceiver const originalSource = envelope.source; const originalSourceUuid = envelope.sourceServiceId; + const groupId = messageContent.groupId(); + const newEnvelope: UnsealedEnvelope = { ...envelope, @@ -1379,7 +1381,7 @@ export default class MessageReceiver // UnsealedEnvelope-only fields unidentifiedDeliveryReceived: !(originalSource || originalSourceUuid), contentHint: messageContent.contentHint(), - groupId: messageContent.groupId()?.toString('base64'), + groupId: groupId ? Bytes.toBase64(groupId) : undefined, certificate, unsealedContent: messageContent, }; @@ -1845,8 +1847,7 @@ export default class MessageReceiver if (envelope.type === envelopeTypeEnum.PLAINTEXT_CONTENT) { log.info(`decrypt/${logId}: plaintext message`); - const buffer = Buffer.from(ciphertext); - const plaintextContent = PlaintextContent.deserialize(buffer); + const plaintextContent = PlaintextContent.deserialize(ciphertext); return { plaintext: this.#unpad(plaintextContent.body()), @@ -1865,7 +1866,7 @@ export default class MessageReceiver 'MessageReceiver.innerDecrypt: No sourceDevice for CIPHERTEXT message' ); } - const signalMessage = SignalMessage.deserialize(Buffer.from(ciphertext)); + const signalMessage = SignalMessage.deserialize(ciphertext); const plaintext = await this.#storage.protocol.enqueueSessionJob( address, @@ -1894,9 +1895,7 @@ export default class MessageReceiver 'MessageReceiver.innerDecrypt: No sourceDevice for PREKEY_BUNDLE message' ); } - const preKeySignalMessage = PreKeySignalMessage.deserialize( - Buffer.from(ciphertext) - ); + const preKeySignalMessage = PreKeySignalMessage.deserialize(ciphertext); const plaintext = await this.#storage.protocol.enqueueSessionJob( address, @@ -2619,8 +2618,7 @@ export default class MessageReceiver logUnexpectedUrgentValue(envelope, 'retryRequest'); - const buffer = Buffer.from(decryptionError); - const request = DecryptionErrorMessage.deserialize(buffer); + const request = DecryptionErrorMessage.deserialize(decryptionError); const { sourceServiceId: sourceAci, sourceDevice } = envelope; if (!sourceAci || !sourceDevice) { @@ -2672,9 +2670,7 @@ export default class MessageReceiver const sender = ProtocolAddress.new(sourceServiceId, sourceDevice); const senderKeyDistributionMessage = - SenderKeyDistributionMessage.deserialize( - Buffer.from(distributionMessage) - ); + SenderKeyDistributionMessage.deserialize(distributionMessage); const { destinationServiceId } = envelope; const address = new QualifiedAddress( destinationServiceId, @@ -2708,7 +2704,7 @@ export default class MessageReceiver const { pni: pniBytes, signature } = pniSignatureMessage; strictAssert(Bytes.isNotEmpty(pniBytes), `${logId}: missing PNI bytes`); - const pni = fromPniObject(Pni.fromUuidBytes(Buffer.from(pniBytes))); + const pni = fromPniObject(Pni.fromUuidBytes(pniBytes)); strictAssert(pni, `${logId}: missing PNI`); strictAssert(Bytes.isNotEmpty(signature), `${logId}: empty signature`); strictAssert(isAciString(aci), `${logId}: invalid ACI`); @@ -4153,7 +4149,7 @@ function processConversationIdentifier( if (threadGroupId) { return { type: 'group' as const, - groupId: Buffer.from(threadGroupId).toString('base64'), + groupId: Bytes.toBase64(threadGroupId), }; } if (threadE164) { diff --git a/ts/textsecure/OutgoingMessage.ts b/ts/textsecure/OutgoingMessage.ts index a90710806b..4dfbec35c9 100644 --- a/ts/textsecure/OutgoingMessage.ts +++ b/ts/textsecure/OutgoingMessage.ts @@ -44,6 +44,7 @@ import { SignalService as Proto } from '../protobuf'; import { createLogger } from '../logging/log'; import type { GroupSendToken } from '../types/GroupSendEndorsements'; import { isSignalServiceId } from '../util/isSignalConversation'; +import * as Bytes from '../Bytes'; const log = createLogger('OutgoingMessage'); @@ -388,7 +389,7 @@ export default class OutgoingMessage { if (message instanceof Proto.Content) { return signalEncrypt( - Buffer.from(this.getPlaintext()), + this.getPlaintext(), protocolAddress, sessionStore, identityKeyStore @@ -472,10 +473,10 @@ export default class OutgoingMessage { }); const certificate = SenderCertificate.deserialize( - Buffer.from(senderCertificate.serialized) + senderCertificate.serialized ); const groupIdBuffer = this.groupId - ? Buffer.from(this.groupId, 'base64') + ? Bytes.fromBase64(this.groupId) : null; const content = UnidentifiedSenderMessageContent.new( @@ -495,7 +496,7 @@ export default class OutgoingMessage { type: Proto.Envelope.Type.UNIDENTIFIED_SENDER, destinationDeviceId, destinationRegistrationId, - content: buffer.toString('base64'), + content: Bytes.toBase64(buffer), }; } @@ -508,7 +509,7 @@ export default class OutgoingMessage { ciphertextMessage.type() ); - const content = ciphertextMessage.serialize().toString('base64'); + const content = Bytes.toBase64(ciphertextMessage.serialize()); return { type, diff --git a/ts/textsecure/ProvisioningCipher.ts b/ts/textsecure/ProvisioningCipher.ts index f05426652d..a003b7867a 100644 --- a/ts/textsecure/ProvisioningCipher.ts +++ b/ts/textsecure/ProvisioningCipher.ts @@ -67,7 +67,7 @@ class ProvisioningCipherInner { } const ecRes = calculateAgreement( - PublicKey.deserialize(Buffer.from(masterEphemeral)), + PublicKey.deserialize(masterEphemeral), this.keyPair.privateKey ); const keys = deriveSecrets( diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index 7f90304703..f8937fd2c6 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -2176,7 +2176,7 @@ export default class MessageSender { }: Readonly<{ contentHint: number; messageId?: string; - proto: Buffer; + proto: Uint8Array; sendType: SendTypesType; timestamp: number; urgent: boolean; @@ -2402,7 +2402,7 @@ export default class MessageSender { serviceIds.length > 1 ? this.makeSendLogCallback({ contentHint: contentHint ?? ContentHint.IMPLICIT, - proto: Buffer.from(Proto.Content.encode(contentMessage).finish()), + proto: Proto.Content.encode(contentMessage).finish(), sendType: 'senderKeyDistributionMessage', timestamp, urgent, diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index e899c394d7..781e3bb477 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -3235,10 +3235,14 @@ export function initialize({ keyId: number; publicKey: K; signature: Uint8Array; - }): { id: () => number; publicKey: () => K; signature: () => Buffer } { + }): { + id: () => number; + publicKey: () => K; + signature: () => Uint8Array; + } { return { id: () => key.keyId, - signature: () => Buffer.from(key.signature), + signature: () => key.signature, publicKey: () => key.publicKey, }; } @@ -4093,22 +4097,21 @@ export function initialize({ ].join(CRLF); const end = `${CRLF}--${boundaryString}--${CRLF}`; - const startBuffer = Buffer.from(start, 'utf8'); - const attachmentBuffer = Buffer.from(encryptedBin); - const endBuffer = Buffer.from(end, 'utf8'); + const startBuffer = Bytes.fromString(start); + const attachmentBuffer = encryptedBin; + const endBuffer = Bytes.fromString(end); - const contentLength = - startBuffer.length + attachmentBuffer.length + endBuffer.length; - const data = Buffer.concat( - [startBuffer, attachmentBuffer, endBuffer], - contentLength - ); + const data = Bytes.concatenate([ + startBuffer, + attachmentBuffer, + endBuffer, + ]); return { data, contentType: `multipart/form-data; boundary=${boundaryString}`, headers: { - 'Content-Length': contentLength.toString(), + 'Content-Length': data.length.toString(), }, }; } diff --git a/ts/textsecure/cds/CDSISocket.ts b/ts/textsecure/cds/CDSISocket.ts index 90a9cfcbaa..d71b1e6217 100644 --- a/ts/textsecure/cds/CDSISocket.ts +++ b/ts/textsecure/cds/CDSISocket.ts @@ -9,7 +9,7 @@ import { CDSSocketBase, CDSSocketState } from './CDSSocketBase'; import type { CDSSocketBaseOptionsType } from './CDSSocketBase'; export type CDSISocketOptionsType = Readonly<{ - mrenclave: Buffer; + mrenclave: Uint8Array; }> & CDSSocketBaseOptionsType; @@ -41,7 +41,7 @@ export class CDSISocket extends CDSSocketBase { ); } - this.socket.sendBytes(this.#cdsClient.initialRequest()); + this.socket.sendBytes(Buffer.from(this.#cdsClient.initialRequest())); { const { done, value: message } = await this.socketIterator.next(); @@ -55,9 +55,11 @@ export class CDSISocket extends CDSSocketBase { protected override async sendRequest( _version: number, - request: Buffer + request: Uint8Array ): Promise { - this.socket.sendBytes(this.#cdsClient.establishedSend(request)); + this.socket.sendBytes( + Buffer.from(this.#cdsClient.establishedSend(request)) + ); const { done, value: ciphertext } = await this.socketIterator.next(); strictAssert(!done, 'CDSISocket.sendRequest(): expected token message'); @@ -70,8 +72,8 @@ export class CDSISocket extends CDSSocketBase { strictAssert(token, 'CDSISocket.sendRequest(): expected token'); this.socket.sendBytes( - this.#cdsClient.establishedSend( - Buffer.from( + Buffer.from( + this.#cdsClient.establishedSend( Proto.CDSClientRequest.encode({ tokenAck: true, }).finish() @@ -81,8 +83,8 @@ export class CDSISocket extends CDSSocketBase { } protected override async decryptResponse( - ciphertext: Buffer - ): Promise { + ciphertext: Uint8Array + ): Promise { return this.#cdsClient.establishedRecv(ciphertext); } diff --git a/ts/textsecure/cds/CDSSocketBase.ts b/ts/textsecure/cds/CDSSocketBase.ts index 28117c2bf8..8f085bd167 100644 --- a/ts/textsecure/cds/CDSSocketBase.ts +++ b/ts/textsecure/cds/CDSSocketBase.ts @@ -47,7 +47,7 @@ export abstract class CDSSocketBase< protected readonly logger: LoggerType; - protected readonly socketIterator: AsyncIterator; + protected readonly socketIterator: AsyncIterator; constructor(protected readonly options: Options) { super(); @@ -87,18 +87,18 @@ export abstract class CDSSocketBase< ); const request = Proto.CDSClientRequest.encode({ - newE164s: Buffer.concat( + newE164s: Bytes.concatenate( e164s.map(e164 => { // Long.fromString handles numbers with or without a leading '+' return new Uint8Array(Long.fromString(e164).toBytesBE()); }) ), - aciUakPairs: Buffer.concat(aciUakPairs), + aciUakPairs: Bytes.concatenate(aciUakPairs), returnAcisWithoutUaks, }).finish(); log.info(`CDSSocket.request(): sending version=${version} request`); - await this.sendRequest(version, Buffer.from(request)); + await this.sendRequest(version, request); const resultMap: Map = new Map(); @@ -129,9 +129,14 @@ export abstract class CDSSocketBase< public abstract handshake(): Promise; - protected abstract sendRequest(version: number, data: Buffer): Promise; + protected abstract sendRequest( + version: number, + data: Uint8Array + ): Promise; - protected abstract decryptResponse(ciphertext: Buffer): Promise; + protected abstract decryptResponse( + ciphertext: Uint8Array + ): Promise; // EventEmitter types @@ -161,7 +166,7 @@ export abstract class CDSSocketBase< // Private // - #iterateSocket(): AsyncIterator { + #iterateSocket(): AsyncIterator { const stream = new Readable({ read: noop, objectMode: true }); this.socket.on('message', ({ type, binaryData }) => { diff --git a/ts/textsecure/getKeysForServiceId.ts b/ts/textsecure/getKeysForServiceId.ts index d2366596a4..ee6eb65890 100644 --- a/ts/textsecure/getKeysForServiceId.ts +++ b/ts/textsecure/getKeysForServiceId.ts @@ -152,20 +152,13 @@ async function handleServerKeys( const protocolAddress = ProtocolAddress.new(serviceId, deviceId); const preKeyId = preKey?.keyId || null; const preKeyObject = preKey - ? PublicKey.deserialize(Buffer.from(preKey.publicKey)) + ? PublicKey.deserialize(preKey.publicKey) : null; - const signedPreKeyObject = PublicKey.deserialize( - Buffer.from(signedPreKey.publicKey) - ); - const identityKey = PublicKey.deserialize( - Buffer.from(response.identityKey) - ); + const signedPreKeyObject = PublicKey.deserialize(signedPreKey.publicKey); + const identityKey = PublicKey.deserialize(response.identityKey); - const pqPreKeyId = pqPreKey.keyId; - const pqPreKeyPublic = KEMPublicKey.deserialize( - Buffer.from(pqPreKey.publicKey) - ); - const pqPreKeySignature = Buffer.from(pqPreKey.signature); + const { keyId: pqPreKeyId, signature: pqPreKeySignature } = pqPreKey; + const pqPreKeyPublic = KEMPublicKey.deserialize(pqPreKey.publicKey); const preKeyBundle = PreKeyBundle.new( registrationId, @@ -174,7 +167,7 @@ async function handleServerKeys( preKeyObject, signedPreKey.keyId, signedPreKeyObject, - Buffer.from(signedPreKey.signature), + signedPreKey.signature, identityKey, pqPreKeyId, pqPreKeyPublic, diff --git a/ts/textsecure/processDataMessage.ts b/ts/textsecure/processDataMessage.ts index 600dbfbe70..a40f656677 100644 --- a/ts/textsecure/processDataMessage.ts +++ b/ts/textsecure/processDataMessage.ts @@ -333,7 +333,7 @@ export function processGiftBadge( } const receipt = new ReceiptCredentialPresentation( - Buffer.from(giftBadge.receiptCredentialPresentation) + giftBadge.receiptCredentialPresentation ); return { diff --git a/ts/updater/curve.ts b/ts/updater/curve.ts index 352dda1ec3..1e7fb94569 100644 --- a/ts/updater/curve.ts +++ b/ts/updater/curve.ts @@ -3,7 +3,7 @@ import { PrivateKey, PublicKey } from '@signalapp/libsignal-client'; -export function keyPair(): Record { +export function keyPair(): Record { const privKey = PrivateKey.generate(); const pubKey = privKey.getPublicKey(); @@ -13,16 +13,16 @@ export function keyPair(): Record { }; } -export function sign(privateKey: Buffer, message: Buffer): Buffer { +export function sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array { const privKeyObj = PrivateKey.deserialize(privateKey); const signature = privKeyObj.sign(message); return signature; } export function verify( - publicKey: Buffer, - message: Buffer, - signature: Buffer + publicKey: Uint8Array, + message: Uint8Array, + signature: Uint8Array ): boolean { const pubKeyObj = PublicKey.deserialize(publicKey); const result = pubKeyObj.verify(message, signature); diff --git a/ts/updater/signature.ts b/ts/updater/signature.ts index 0a5294636c..a33849d09a 100644 --- a/ts/updater/signature.ts +++ b/ts/updater/signature.ts @@ -21,7 +21,7 @@ export async function generateSignature( updatePackagePath: string, version: string, privateKeyPath: string -): Promise { +): Promise { const privateKey = await loadHexFromPath(privateKeyPath); const message = await generateMessage(updatePackagePath, version); @@ -31,8 +31,8 @@ export async function generateSignature( export async function verifySignature( updatePackagePath: string, version: string, - signature: Buffer, - publicKey: Buffer + signature: Uint8Array, + publicKey: Uint8Array ): Promise { const message = await generateMessage(updatePackagePath, version); @@ -44,7 +44,7 @@ export async function verifySignature( async function generateMessage( updatePackagePath: string, version: string -): Promise { +): Promise { const hash = await _getFileHash(updatePackagePath); const messageString = `${Buffer.from(hash).toString('hex')}-${version}`; @@ -55,7 +55,7 @@ export async function writeSignature( updatePackagePath: string, version: string, privateKeyPath: string -): Promise { +): Promise { const signaturePath = getSignaturePath(updatePackagePath); const signature = await generateSignature( updatePackagePath, @@ -90,7 +90,7 @@ export function hexToBinary(target: string): Buffer { return Buffer.from(target, 'hex'); } -export function binaryToHex(data: Buffer): string { +export function binaryToHex(data: Uint8Array): string { return Buffer.from(data).toString('hex'); } @@ -102,7 +102,7 @@ export async function loadHexFromPath(target: string): Promise { export async function writeHexToPath( target: string, - data: Buffer + data: Uint8Array ): Promise { await writeFile(target, binaryToHex(data)); } diff --git a/ts/util/ServiceId.ts b/ts/util/ServiceId.ts index 0ebd08aae1..083bd141cc 100644 --- a/ts/util/ServiceId.ts +++ b/ts/util/ServiceId.ts @@ -45,9 +45,7 @@ export function fromServiceIdBinaryOrString( context: string ): ServiceIdString | undefined { if (Bytes.isNotEmpty(bytes)) { - return fromServiceIdObject( - ServiceId.parseFromServiceIdBinary(Buffer.from(bytes)) - ); + return fromServiceIdObject(ServiceId.parseFromServiceIdBinary(bytes)); } if (fallback) { return normalizeServiceId(fallback, context); @@ -65,7 +63,7 @@ export function fromAciUuidBytes( bytes: Uint8Array | undefined | null ): AciString | undefined { if (Bytes.isNotEmpty(bytes)) { - return fromAciObject(Aci.fromUuidBytes(Buffer.from(bytes))); + return fromAciObject(Aci.fromUuidBytes(bytes)); } return undefined; } @@ -102,7 +100,7 @@ export function fromPniUuidBytesOrUntaggedString( context: string ): PniString | undefined { if (Bytes.isNotEmpty(bytes)) { - return fromPniObject(Pni.fromUuidBytes(Buffer.from(bytes))); + return fromPniObject(Pni.fromUuidBytes(bytes)); } if (fallback && isUntaggedPniString(fallback)) { return normalizePni(toTaggedPni(fallback), context); diff --git a/ts/util/groupSendEndorsements.ts b/ts/util/groupSendEndorsements.ts index 8606121140..dd7252bee0 100644 --- a/ts/util/groupSendEndorsements.ts +++ b/ts/util/groupSendEndorsements.ts @@ -31,6 +31,7 @@ import { isNightly } from './version'; import { parseStrict } from './schemas'; import { DataReader } from '../sql/Client'; import { maybeUpdateGroup } from '../groups'; +import * as Bytes from '../Bytes'; import { isGroupV2 } from './whatTypeOfConversation'; const log = createLogger('groupSendEndorsements'); @@ -59,7 +60,7 @@ export function decodeGroupSendEndorsementResponse({ ); const response = new GroupSendEndorsementsResponse( - Buffer.from(groupSendEndorsementResponse) + groupSendEndorsementResponse ); const expiration = response.getExpiration().getTime() / 1000; @@ -69,11 +70,11 @@ export function decodeGroupSendEndorsementResponse({ ); const groupSecretParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBase64, 'base64') + Bytes.fromBase64(groupSecretParamsBase64) ); const serverPublicParams = new ServerPublicParams( - Buffer.from(window.getServerPublicParams(), 'base64') + Bytes.fromBase64(window.getServerPublicParams()) ); const groupMembers = groupMembersV2.map(member => { @@ -193,7 +194,7 @@ export class GroupSendEndorsementState { #toEndorsement(contents: Uint8Array): GroupSendEndorsement { let endorsement = this.#endorsementCache.get(contents); if (endorsement == null) { - endorsement = new GroupSendEndorsement(Buffer.from(contents)); + endorsement = new GroupSendEndorsement(contents); this.#endorsementCache.set(contents, endorsement); } return endorsement; @@ -201,7 +202,7 @@ export class GroupSendEndorsementState { #toToken(endorsement: GroupSendEndorsement): GroupSendToken { const groupSecretParams = new GroupSecretParams( - Buffer.from(this.#groupSecretParamsBase64, 'base64') + Bytes.fromBase64(this.#groupSecretParamsBase64) ); const expiration = this.getExpiration(); diff --git a/ts/util/handleMessageSend.ts b/ts/util/handleMessageSend.ts index 9fca8971f4..57022fb5b9 100644 --- a/ts/util/handleMessageSend.ts +++ b/ts/util/handleMessageSend.ts @@ -269,7 +269,7 @@ async function maybeSaveToSendLog( await insertSentProto( { timestamp, - proto: Buffer.from(contentProto), + proto: contentProto, contentHint, urgent: isBoolean(urgent) ? urgent : true, hasPniSignatureMessage: Boolean(hasPniSignatureMessage), diff --git a/ts/util/handleRetry.ts b/ts/util/handleRetry.ts index 07476943bd..bf68c0ab87 100644 --- a/ts/util/handleRetry.ts +++ b/ts/util/handleRetry.ts @@ -678,7 +678,7 @@ async function requestResend(decryptionError: DecryptionErrorEventData) { } const message = DecryptionErrorMessage.forOriginal( - Buffer.from(cipherTextBytes), + cipherTextBytes, cipherTextType, timestamp, senderDevice diff --git a/ts/util/lookupConversationWithoutServiceId.ts b/ts/util/lookupConversationWithoutServiceId.ts index 02322debfd..be5c64c430 100644 --- a/ts/util/lookupConversationWithoutServiceId.ts +++ b/ts/util/lookupConversationWithoutServiceId.ts @@ -143,7 +143,7 @@ export async function lookupConversationWithoutServiceId( export async function checkForUsername( username: string ): Promise { - let hash: Buffer; + let hash: Uint8Array; let fixedUsername = username; if (fixedUsername.startsWith('@')) { fixedUsername = fixedUsername.slice(1); diff --git a/ts/util/pemToDer.ts b/ts/util/pemToDer.ts index 12040e5656..40c9126c61 100644 --- a/ts/util/pemToDer.ts +++ b/ts/util/pemToDer.ts @@ -1,11 +1,13 @@ // Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -export function pemToDer(pem: string): Buffer { +import * as Bytes from '../Bytes'; + +export function pemToDer(pem: string): Uint8Array { const pemContent = pem .replace(/-----BEGIN [^-]+-----/, '') .replace(/-----END [^-]+-----/, '') .replace(/\s+/g, ''); - const derBuffer = Buffer.from(pemContent, 'base64'); + const derBuffer = Bytes.fromBase64(pemContent); return derBuffer; } diff --git a/ts/util/safetyNumber.ts b/ts/util/safetyNumber.ts index ad95f8a198..a9b4d839e3 100644 --- a/ts/util/safetyNumber.ts +++ b/ts/util/safetyNumber.ts @@ -46,16 +46,16 @@ export async function generateSafetyNumber( throw new Error('Could not load their key'); } - const ourKey = PublicKey.deserialize(Buffer.from(ourKeyBuffer)); - const theirKey = PublicKey.deserialize(Buffer.from(theirKeyBuffer)); + const ourKey = PublicKey.deserialize(ourKeyBuffer); + const theirKey = PublicKey.deserialize(theirKeyBuffer); assertDev(theirAci, 'Should have their serviceId'); const fingerprint = Fingerprint.new( ITERATION_COUNT, SERVICE_ID_VERSION, - Buffer.from(uuidToBytes(ourAci)), + uuidToBytes(ourAci), ourKey, - Buffer.from(uuidToBytes(theirAci)), + uuidToBytes(theirAci), theirKey ); diff --git a/ts/util/sendToGroup.ts b/ts/util/sendToGroup.ts index 8c689ae7e4..3e6090b953 100644 --- a/ts/util/sendToGroup.ts +++ b/ts/util/sendToGroup.ts @@ -26,6 +26,7 @@ import { DataWriter } from '../sql/Client'; import { getValue } from '../RemoteConfig'; import type { ServiceIdString } from '../types/ServiceId'; import { ServiceIdKind } from '../types/ServiceId'; +import * as Bytes from '../Bytes'; import { isRecord } from './isRecord'; import { isOlderThan } from './timestamp'; @@ -235,7 +236,7 @@ export async function sendContentMessageToGroup( const sendLogCallback = window.textsecure.messaging.makeSendLogCallback({ contentHint, messageId, - proto: Buffer.from(Proto.Content.encode(contentMessage).finish()), + proto: Proto.Content.encode(contentMessage).finish(), sendType, timestamp, urgent, @@ -583,7 +584,7 @@ export async function sendToGroupViaSenderKey( sendLogId = await DataWriter.insertSentProto( { contentHint, - proto: Buffer.from(Proto.Content.encode(contentMessage).finish()), + proto: Proto.Content.encode(contentMessage).finish(), timestamp, urgent, hasPniSignatureMessage: false, @@ -667,7 +668,7 @@ export async function sendToGroupViaSenderKey( contentHint, timestamp, - contentProto: Buffer.from(Proto.Content.encode(contentMessage).finish()), + contentProto: Proto.Content.encode(contentMessage).finish(), recipients: senderKeyRecipientsWithDevices, urgent, }; @@ -1100,7 +1101,7 @@ function getXorOfAccessKeys( 'Cannot be endorsement in getXorOfAccessKeys' ); - const accessKeyBuffer = Buffer.from(accessKey, 'base64'); + const accessKeyBuffer = Bytes.fromBase64(accessKey); if (accessKeyBuffer.length !== ACCESS_KEY_LENGTH) { throw new Error( `getXorOfAccessKeys: Access key for ${uuid} had length ${accessKeyBuffer.length}` @@ -1128,7 +1129,7 @@ async function encryptForSenderKey({ devices: Array; distributionId: string; groupId?: string; -}): Promise { +}): Promise { const ourAci = window.textsecure.storage.user.getCheckedAci(); const ourDeviceId = window.textsecure.storage.user.getDeviceId(); if (!ourDeviceId) { @@ -1146,7 +1147,7 @@ async function encryptForSenderKey({ ourServiceId: ourAci, zone: GLOBAL_ZONE, }); - const message = Buffer.from(padMessage(contentMessage)); + const message = padMessage(contentMessage); const ciphertextMessage = await window.textsecure.storage.protocol.enqueueSenderKeyJob( @@ -1154,7 +1155,7 @@ async function encryptForSenderKey({ () => groupEncrypt(sender, distributionId, senderKeyStore, message) ); - const groupIdBuffer = groupId ? Buffer.from(groupId, 'base64') : null; + const groupIdBuffer = groupId ? Bytes.fromBase64(groupId) : null; const senderCertificateObject = await senderCertificateService.get( SenderCertificateMode.WithoutE164 ); @@ -1163,7 +1164,7 @@ async function encryptForSenderKey({ } const senderCertificate = SenderCertificate.deserialize( - Buffer.from(senderCertificateObject.serialized) + senderCertificateObject.serialized ); const content = UnidentifiedSenderMessageContent.new( ciphertextMessage, diff --git a/ts/util/zkgroup.ts b/ts/util/zkgroup.ts index 75af7608a3..f1aa13160b 100644 --- a/ts/util/zkgroup.ts +++ b/ts/util/zkgroup.ts @@ -25,6 +25,7 @@ import { fromAciObject, fromPniObject, } from '../types/ServiceId'; +import * as Bytes from '../Bytes'; import { toServiceIdObject } from './ServiceId'; import { strictAssert } from './assert'; @@ -36,15 +37,13 @@ export function decryptGroupBlob( clientZkGroupCipher: ClientZkGroupCipher, ciphertext: Uint8Array ): Uint8Array { - return clientZkGroupCipher.decryptBlob(Buffer.from(ciphertext)); + return clientZkGroupCipher.decryptBlob(ciphertext); } export function decodeProfileKeyCredentialPresentation( presentationBuffer: Uint8Array ): { profileKey: Uint8Array; userId: Uint8Array } { - const presentation = new ProfileKeyCredentialPresentation( - Buffer.from(presentationBuffer) - ); + const presentation = new ProfileKeyCredentialPresentation(presentationBuffer); const userId = presentation.getUuidCiphertext().serialize(); const profileKey = presentation.getProfileKeyCiphertext().serialize(); @@ -61,7 +60,7 @@ export function decryptProfileKey( serviceId: ServiceIdString ): Uint8Array { const profileKeyCiphertext = new ProfileKeyCiphertext( - Buffer.from(profileKeyCiphertextBuffer) + profileKeyCiphertextBuffer ); const profileKey = clientZkGroupCipher.decryptProfileKey( @@ -76,7 +75,7 @@ function decryptServiceIdObj( clientZkGroupCipher: ClientZkGroupCipher, uuidCiphertextBuffer: Uint8Array ): ServiceId { - const uuidCiphertext = new UuidCiphertext(Buffer.from(uuidCiphertextBuffer)); + const uuidCiphertext = new UuidCiphertext(uuidCiphertextBuffer); return clientZkGroupCipher.decryptServiceId(uuidCiphertext); } @@ -112,7 +111,7 @@ export function deriveProfileKeyVersion( profileKeyBase64: string, serviceId: ServiceIdString ): string { - const profileKeyArray = Buffer.from(profileKeyBase64, 'base64'); + const profileKeyArray = Bytes.fromBase64(profileKeyBase64); const profileKey = new ProfileKey(profileKeyArray); const profileKeyVersion = profileKey.getProfileKeyVersion( @@ -125,17 +124,13 @@ export function deriveProfileKeyVersion( export function deriveGroupPublicParams( groupSecretParamsBuffer: Uint8Array ): Uint8Array { - const groupSecretParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBuffer) - ); + const groupSecretParams = new GroupSecretParams(groupSecretParamsBuffer); return groupSecretParams.getPublicParams().serialize(); } export function deriveGroupID(groupSecretParamsBuffer: Uint8Array): Uint8Array { - const groupSecretParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBuffer) - ); + const groupSecretParams = new GroupSecretParams(groupSecretParamsBuffer); return groupSecretParams.getPublicParams().getGroupIdentifier().serialize(); } @@ -143,7 +138,7 @@ export function deriveGroupID(groupSecretParamsBuffer: Uint8Array): Uint8Array { export function deriveGroupSecretParams( masterKeyBuffer: Uint8Array ): Uint8Array { - const masterKey = new GroupMasterKey(Buffer.from(masterKeyBuffer)); + const masterKey = new GroupMasterKey(masterKeyBuffer); const groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey); return groupSecretParams.serialize(); @@ -153,7 +148,7 @@ export function encryptGroupBlob( clientZkGroupCipher: ClientZkGroupCipher, plaintext: Uint8Array ): Uint8Array { - return clientZkGroupCipher.encryptBlob(Buffer.from(plaintext)); + return clientZkGroupCipher.encryptBlob(plaintext); } export function encryptServiceId( @@ -172,7 +167,7 @@ export function generateProfileKeyCredentialRequest( serviceId: ServiceIdString, profileKeyBase64: string ): { context: ProfileKeyCredentialRequestContext; requestHex: string } { - const profileKeyArray = Buffer.from(profileKeyBase64, 'base64'); + const profileKeyArray = Bytes.fromBase64(profileKeyBase64); const profileKey = new ProfileKey(profileKeyArray); const context = @@ -185,7 +180,7 @@ export function generateProfileKeyCredentialRequest( return { context, - requestHex: requestArray.toString('hex'), + requestHex: Bytes.toHex(requestArray), }; } @@ -195,10 +190,10 @@ export function getAuthCredentialPresentation( groupSecretParamsBase64: string ): Uint8Array { const authCredential = new AuthCredentialWithPni( - Buffer.from(authCredentialBase64, 'base64') + Bytes.fromBase64(authCredentialBase64) ); const secretParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBase64, 'base64') + Bytes.fromBase64(groupSecretParamsBase64) ); const presentation = @@ -214,15 +209,14 @@ export function createProfileKeyCredentialPresentation( profileKeyCredentialBase64: string, groupSecretParamsBase64: string ): Uint8Array { - const profileKeyCredentialArray = Buffer.from( - profileKeyCredentialBase64, - 'base64' + const profileKeyCredentialArray = Bytes.fromBase64( + profileKeyCredentialBase64 ); const profileKeyCredential = new ExpiringProfileKeyCredential( profileKeyCredentialArray ); const secretParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBase64, 'base64') + Bytes.fromBase64(groupSecretParamsBase64) ); const presentation = @@ -238,7 +232,7 @@ export function getClientZkAuthOperations( serverPublicParamsBase64: string ): ClientZkAuthOperations { const serverPublicParams = new ServerPublicParams( - Buffer.from(serverPublicParamsBase64, 'base64') + Bytes.fromBase64(serverPublicParamsBase64) ); return new ClientZkAuthOperations(serverPublicParams); @@ -248,7 +242,7 @@ export function getClientZkGroupCipher( groupSecretParamsBase64: string ): ClientZkGroupCipher { const serverPublicParams = new GroupSecretParams( - Buffer.from(groupSecretParamsBase64, 'base64') + Bytes.fromBase64(groupSecretParamsBase64) ); return new ClientZkGroupCipher(serverPublicParams); @@ -258,7 +252,7 @@ export function getClientZkProfileOperations( serverPublicParamsBase64: string ): ClientZkProfileOperations { const serverPublicParams = new ServerPublicParams( - Buffer.from(serverPublicParamsBase64, 'base64') + Bytes.fromBase64(serverPublicParamsBase64) ); return new ClientZkProfileOperations(serverPublicParams); @@ -270,7 +264,7 @@ export function handleProfileKeyCredential( responseBase64: string ): { credential: string; expiration: number } { const response = new ExpiringProfileKeyCredentialResponse( - Buffer.from(responseBase64, 'base64') + Bytes.fromBase64(responseBase64) ); const profileKeyCredential = clientZkProfileCipher.receiveExpiringProfileKeyCredential( @@ -281,7 +275,7 @@ export function handleProfileKeyCredential( const credentialArray = profileKeyCredential.serialize(); return { - credential: credentialArray.toString('base64'), + credential: Bytes.toBase64(credentialArray), expiration: profileKeyCredential.getExpirationTime().getTime(), }; } @@ -290,12 +284,14 @@ export function deriveProfileKeyCommitment( profileKeyBase64: string, serviceId: ServiceIdString ): string { - const profileKeyArray = Buffer.from(profileKeyBase64, 'base64'); + const profileKeyArray = Bytes.fromBase64(profileKeyBase64); const profileKey = new ProfileKey(profileKeyArray); - return profileKey - .getCommitment(toServiceIdObject(serviceId)) - .contents.toString('base64'); + const commitment = profileKey.getCommitment( + toServiceIdObject(serviceId) + ).contents; + + return Bytes.toBase64(commitment); } export function verifyNotarySignature( @@ -304,10 +300,10 @@ export function verifyNotarySignature( signature: Uint8Array ): void { const serverPublicParams = new ServerPublicParams( - Buffer.from(serverPublicParamsBase64, 'base64') + Bytes.fromBase64(serverPublicParamsBase64) ); - const notarySignature = new NotarySignature(Buffer.from(signature)); + const notarySignature = new NotarySignature(signature); - serverPublicParams.verifySignature(Buffer.from(message), notarySignature); + serverPublicParams.verifySignature(message, notarySignature); }