├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── benchmarks ├── hyperfine-compress-bench.log ├── hyperfine-enc-bench.log └── openssl-speed.txt ├── cbackup.sh └── termux-quickstart.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 4 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/* 2 | !.vscode/settings.json 3 | !.vscode/tasks.json 4 | !.vscode/launch.json 5 | !.vscode/extensions.json 6 | *.code-workspace 7 | 8 | # Local History for Visual Studio Code 9 | .history/ 10 | 11 | /cbackup/* 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Danny Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cbackup 2 | 3 | cbackup is a simple backup/restore script for rooted Android devices. It backs up apps, full app data, and some Android metadata. 4 | 5 | ## Quickstart 6 | 7 | Run the following command in Termux to take a backup: 8 | 9 | ```bash 10 | bash -c "$(curl -L https://git.io/cbackup-quick)" 11 | ``` 12 | 13 | You can also specify a destination folder as an argument, which will be cleared if it already exists and created otherwise: 14 | 15 | ```bash 16 | bash -c "$(curl -L https://git.io/cbackup-quick)" backup /data/local/tmp/cbackup 17 | ``` 18 | 19 | To restore a backup located at `/sdcard/cbackup`: 20 | 21 | ```bash 22 | bash -c "$(curl -L https://git.io/cbackup-quick)" restore 23 | ``` 24 | 25 | Or restore a backup from a custom location: 26 | 27 | ```bash 28 | bash -c "$(curl -L https://git.io/cbackup-quick)" restore /data/local/tmp/cbackup 29 | ``` 30 | 31 | Using a custom path outside of `/sdcard`, e.g. `/data/local/tmp/cbackup`, will work significantly faster on Android 11 and newer. 32 | 33 | If you're worried about piping and running a random script, the [quickstart script](https://github.com/kdrag0n/cbackup/blob/master/termux-quickstart.sh) is short and thoroughly commented, so feel free to download it and read it yourself before running it. 34 | 35 | ## Scope 36 | 37 | cbackup includes the following data for each app: 38 | 39 | - App packages (APKs, including split APKs from Android App Bundles) 40 | - App private data (excluding cache and data explicitly marked as no-backup) 41 | - Per-app Android device IDs (SSAIDs; only restored if you reboot immediately after restoring) 42 | - Granted dangerous runtime permissions 43 | - Whether battery optimization is enabled 44 | - Name of the installer app that installed the app in question, e.g. Play Store 45 | 46 | cbackup **does not** include: 47 | 48 | - Account information registered with Android's AccountManager service 49 | - App external data stored in `/sdcard/Android/data` 50 | - OBBs stored in `/sdcard/Android/obb`, e.g. game resources 51 | - Device-bound keystore encryption keys (not possible to extract by design) 52 | 53 | Some security-centric apps that use device-bound keystore keys to encrypt their data are included in a builtin blacklist, so their data will not be backed up. 54 | 55 | Only apps installed in the primary user profile (Android user ID 0) will be backed up. Work profiles and other users will be excluded. 56 | 57 | ## Usage 58 | 59 | If you run the script with no arguments, it will default to creating a new backup located at `backup_dir` its settings, which is set to `/sdcard/cbackup` by default. 60 | 61 | cbackup accepts the following optional positional arguments: 62 | 63 | - First argument: mode — `backup` or `restore` 64 | - Second argument: backup path 65 | 66 | Example to restore from a backup located at `/data/local/tmp/cbackup`: 67 | 68 | ```bash 69 | ./cbackup.sh restore /data/local/tmp/cbackup 70 | ``` 71 | 72 | And to back up to `/data/local/tmp/cbackup`: 73 | 74 | ```bash 75 | ./cbackup.sh backup /data/local/tmp/cbackup 76 | ``` 77 | 78 | ## Security 79 | 80 | Encryption is mandatory. 81 | 82 | App data archives are encrypted with AES-256-CTR using the OpenSSL command-line tool. The encryption key is derived from the provided password with 200,001 iterations of PBKDF2-HMAC-SHA256, with a random salt for each encrypted file. Because the salt fed into PBKDF2 is random and not tracked across different runs of the OpenSSL tool, the encryption key and IV change for every file. 83 | 84 | Each app also contains a password canary, which is a file encrypted with the same password and parameters that just contains a constant string in it to verify whther the given password is correct. 85 | 86 | App packages and names are not encrypted, so anyone can see which apps you have backed up. It is also possible for an adversary to tamper with the app packages and inject spyware or other data exfiltration code into them, as the signatures are not verified to match the ones that were used when the app was initially backed up. 87 | 88 | AES-256-CTR does not have error propagation or any form of MAC, so an adversary can manipulate the data archives to corrupt them. Future versions of cbackup will use an AEAD such as AES-256-GCM or ChaCha20-Poly1305 to prevent this from happening. 89 | 90 | None of the supplementary metadata such as SSAIDs, battery optimization status, granted permissions, or installer names are encrypted or verified, so adversaries can also tamper with those and grant more permissions than desired. 91 | 92 | All of the security loopholes are planned to be addressed in later versions of cbackup. 93 | 94 | Summary: 95 | 96 | - AES-256-CTR encryption 97 | - PBKDF2-HMAC-SHA256 key derivation 98 | - No AEAD or integrity verification 99 | - Only data is encrypted 100 | 101 | ## Storage format 102 | 103 | The preliminary v0 storage format is currently used by the cbackup shell script. 104 | 105 | ### v0 (preliminary) 106 | 107 | All data related to each app is stored in a folder with the app's package name. The following files will always be present: 108 | 109 | - `backup_version.txt`: plain-text file containing `0\n` 110 | - `password_canary.enc`: encrypted file containing `cbackup-valid` 111 | - `base.apk`: unencrypted base APK file 112 | 113 | The following files may or may not be present, depending on what data is associated with the app that is being backed up: 114 | 115 | - `split_config.*.apk`: unencrypted additional split APKs with resources 116 | - `data.tar.zst.enc`: encrypted tarball archive containing app data, compressed with Zstandard before encrypting 117 | - `permissions.list`: unencrypted list of granted runtime permissions 118 | - `ssaid.xml`: system-generated SSAID entry from the SSAID settings XML 119 | - `battery_opt_disabled`: empty file, the presence of this file indicates that battery optimization is disabled 120 | - `installer_name.txt`: unencrypted plain-text file containing the installer app's package name 121 | 122 | All encrypted files are encrypted using the OpenSSL CLI tool with the AES-256-CTR block cipher and 32-byte key derived from the user's password using 200,001 iterations of PBKDF2 and a random salt stored in the file's header. 123 | 124 | App data includes both main CE-encrypted data as well as DE-encrypted (Direct Boot) data. App, code, and shader caches are always excluded, as well as files placed by apps in the dedicated no-backup folder. 125 | -------------------------------------------------------------------------------- /benchmarks/hyperfine-compress-bench.log: -------------------------------------------------------------------------------- 1 | root[38:5:242m@localhost /data/data/com.termux/files/home 12s 2 | ❯ hyperfine -p 'echo 3 > /proc/sys/vm/drop_caches' 'tar -cf - /data/data/com.termux | cat > /data/local/tmp/asdf' 'tar 3 | -cf - /data/data/com.termux | lz4 -1 - > /data/local/tmp/asdf' 'tar -cf - /data/data/com.termux | lz4 -9 - > /data/loca 4 | l/tmp/asdf' 'tar -cf - /data/data/com.termux | zstd -T1 - > /data/local/tmp/asdf' 'tar -cf - /data/data/com.termux | zs 5 | td -T4 - > /data/local/tmp/asdf' 'tar -cf - /data/data/com.termux | zstd -T0 - > /data/local/tmp/asdf' 'tar -cf - /data 6 | /data/com.termux | gzip > /data/local/tmp/asdf' 7 | Benchmark #1: tar -cf - /data/data/com.termux | cat > /data/local/tmp/asdf 8 |  Time (mean ± σ): 27.291 s ±  0.733 s [User: 925.8 ms, System: 15014.2 ms] 9 |  Range (min … max): 25.641 s … 28.284 s 10 runs 10 |  11 | Benchmark #2: tar -cf - /data/data/com.termux | lz4 -1 - > /data/local/tmp/asdf 12 |  Time (mean ± σ): 33.381 s ±  0.320 s [User: 8.894 s, System: 14.254 s] 13 |  Range (min … max): 32.992 s … 33.845 s 10 runs 14 |  15 | Benchmark #3: tar -cf - /data/data/com.termux | lz4 -9 - > /data/local/tmp/asdf 16 |  Time (mean ± σ): 96.058 s ±  0.913 s [User: 73.358 s, System: 13.661 s] 17 |  Range (min … max): 94.676 s … 97.516 s 10 runs 18 |  19 | Benchmark #4: tar -cf - /data/data/com.termux | zstd -T1 - > /data/local/tmp/asdf 20 |  Time (mean ± σ): 27.346 s ±  0.389 s [User: 11.482 s, System: 14.726 s] 21 |  Range (min … max): 26.551 s … 27.775 s 10 runs 22 |  23 | Benchmark #5: tar -cf - /data/data/com.termux | zstd -T4 - > /data/local/tmp/asdf 24 |  Time (mean ± σ): 26.058 s ±  0.850 s [User: 16.484 s, System: 13.769 s] 25 |  Range (min … max): 24.653 s … 27.682 s 10 runs 26 |  27 | Benchmark #6: tar -cf - /data/data/com.termux | zstd -T0 - > /data/local/tmp/asdf 28 |  Time (mean ± σ): 25.079 s ±  0.753 s [User: 18.672 s, System: 12.983 s] 29 |  Range (min … max): 24.094 s … 26.437 s 10 runs 30 |  31 | Benchmark #7: tar -cf - /data/data/com.termux | gzip > /data/local/tmp/asdf 32 |  Time (mean ± σ): 106.002 s ±  7.253 s [User: 95.856 s, System: 8.835 s] 33 |  Range (min … max): 101.991 s … 123.913 s 10 runs 34 |  35 |  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet PC without any interferenc 36 | es from other programs. It might help to use the '--warmup' or '--prepare' options. 37 |  38 | Summary 39 |  'tar -cf - /data/data/com.termux | zstd -T0 - > /data/local/tmp/asdf' ran 40 |  1.04 ± 0.05 times faster than 'tar -cf - /data/data/com.termux | zstd -T4 - > /data/local/tmp/asdf' 41 |  1.09 ± 0.04 times faster than 'tar -cf - /data/data/com.termux | cat > /data/local/tmp/asdf' 42 |  1.09 ± 0.04 times faster than 'tar -cf - /data/data/com.termux | zstd -T1 - > /data/local/tmp/asdf' 43 |  1.33 ± 0.04 times faster than 'tar -cf - /data/data/com.termux | lz4 -1 - > /data/local/tmp/asdf' 44 |  3.83 ± 0.12 times faster than 'tar -cf - /data/data/com.termux | lz4 -9 - > /data/local/tmp/asdf' 45 |  4.23 ± 0.32 times faster than 'tar -cf - /data/data/com.termux | gzip > /data/local/tmp/asdf' 46 | -------------------------------------------------------------------------------- /benchmarks/hyperfine-enc-bench.log: -------------------------------------------------------------------------------- 1 | root[38:5:242m@localhost /data/data/com.termux/files/home 2 | ❯ hyperfine -p 'echo 3 > /proc/sys/vm/drop_caches' 'tar -cf - /data/data/com.termux | cat > /dev/null' 'tar -cf - /data 3 | /data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -aes-128-ctr -pass env:PASSWORD > /dev/null' 'tar 4 | -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -aes-256-ctr -pass env:PASSWORD > /dev/ 5 | null' 'tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -chacha20 -pass env:PASSWORD 6 |  > /dev/null' 7 | Benchmark #1: tar -cf - /data/data/com.termux | cat > /dev/null 8 |  Time (mean ± σ): 17.394 s ±  0.615 s [User: 777.4 ms, System: 9817.6 ms] 9 |  Range (min … max): 16.098 s … 18.233 s 10 runs 10 |  11 | Benchmark #2: tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -aes-128-ctr -pass en 12 | v:PASSWORD > /dev/null 13 |  Time (mean ± σ): 18.144 s ±  0.676 s [User: 2.563 s, System: 8.973 s] 14 |  Range (min … max): 17.051 s … 19.148 s 10 runs 15 |  16 | Benchmark #3: tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -aes-256-ctr -pass en 17 | v:PASSWORD > /dev/null 18 |  Time (mean ± σ): 18.983 s ±  0.515 s [User: 2.861 s, System: 9.535 s] 19 |  Range (min … max): 18.210 s … 19.736 s 10 runs 20 |  21 | Benchmark #4: tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 -chacha20 -pass env:P 22 | ASSWORD > /dev/null 23 |  Time (mean ± σ): 19.130 s ±  0.895 s [User: 4.169 s, System: 8.136 s] 24 |  Range (min … max): 17.759 s … 20.672 s 10 runs 25 |  26 | Summary 27 |  'tar -cf - /data/data/com.termux | cat > /dev/null' ran 28 |  1.04 ± 0.05 times faster than 'tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 29 | -aes-128-ctr -pass env:PASSWORD > /dev/null' 30 |  1.09 ± 0.05 times faster than 'tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 31 | -aes-256-ctr -pass env:PASSWORD > /dev/null' 32 |  1.10 ± 0.06 times faster than 'tar -cf - /data/data/com.termux | PASSWORD=cbackup-test openssl enc -pbkdf2 -iter 1 33 | -chacha20 -pass env:PASSWORD > /dev/null' 34 | -------------------------------------------------------------------------------- /benchmarks/openssl-speed.txt: -------------------------------------------------------------------------------- 1 | Doing mdc2 for 3s on 16 size blocks: 2697353 mdc2's in 3.00s 2 | Doing mdc2 for 3s on 64 size blocks: 741253 mdc2's in 3.00s 3 | Doing mdc2 for 3s on 256 size blocks: 190725 mdc2's in 2.99s 4 | Doing mdc2 for 3s on 1024 size blocks: 48030 mdc2's in 3.00s 5 | Doing mdc2 for 3s on 8192 size blocks: 6018 mdc2's in 3.00s 6 | Doing mdc2 for 3s on 16384 size blocks: 3009 mdc2's in 3.00s 7 | Doing md4 for 3s on 16 size blocks: 12789030 md4's in 2.99s 8 | Doing md4 for 3s on 64 size blocks: 10466000 md4's in 3.00s 9 | Doing md4 for 3s on 256 size blocks: 6340604 md4's in 3.00s 10 | Doing md4 for 3s on 1024 size blocks: 2461416 md4's in 2.99s 11 | Doing md4 for 3s on 8192 size blocks: 366672 md4's in 3.00s 12 | Doing md4 for 3s on 16384 size blocks: 185831 md4's in 3.00s 13 | Doing md5 for 3s on 16 size blocks: 17760257 md5's in 3.00s 14 | Doing md5 for 3s on 64 size blocks: 10294983 md5's in 2.99s 15 | Doing md5 for 3s on 256 size blocks: 4355528 md5's in 3.00s 16 | Doing md5 for 3s on 1024 size blocks: 1317535 md5's in 3.00s 17 | Doing md5 for 3s on 8192 size blocks: 175409 md5's in 3.00s 18 | Doing md5 for 3s on 16384 size blocks: 88126 md5's in 2.99s 19 | Doing hmac(md5) for 3s on 16 size blocks: 6757843 hmac(md5)'s in 3.00s 20 | Doing hmac(md5) for 3s on 64 size blocks: 5331494 hmac(md5)'s in 3.00s 21 | Doing hmac(md5) for 3s on 256 size blocks: 3132594 hmac(md5)'s in 3.00s 22 | Doing hmac(md5) for 3s on 1024 size blocks: 1180529 hmac(md5)'s in 2.99s 23 | Doing hmac(md5) for 3s on 8192 size blocks: 173026 hmac(md5)'s in 3.00s 24 | Doing hmac(md5) for 3s on 16384 size blocks: 87655 hmac(md5)'s in 3.00s 25 | Doing sha1 for 3s on 16 size blocks: 38892284 sha1's in 3.00s 26 | Doing sha1 for 3s on 64 size blocks: 27741565 sha1's in 2.99s 27 | Doing sha1 for 3s on 256 size blocks: 13767772 sha1's in 3.00s 28 | Doing sha1 for 3s on 1024 size blocks: 4569139 sha1's in 3.00s 29 | Doing sha1 for 3s on 8192 size blocks: 629685 sha1's in 2.99s 30 | Doing sha1 for 3s on 16384 size blocks: 317230 sha1's in 3.00s 31 | Doing sha256 for 3s on 16 size blocks: 37320472 sha256's in 3.00s 32 | Doing sha256 for 3s on 64 size blocks: 27340144 sha256's in 3.00s 33 | Doing sha256 for 3s on 256 size blocks: 13965000 sha256's in 2.99s 34 | Doing sha256 for 3s on 1024 size blocks: 4697434 sha256's in 3.00s 35 | Doing sha256 for 3s on 8192 size blocks: 653953 sha256's in 3.00s 36 | Doing sha256 for 3s on 16384 size blocks: 329652 sha256's in 3.00s 37 | Doing sha512 for 3s on 16 size blocks: 9110529 sha512's in 2.99s 38 | Doing sha512 for 3s on 64 size blocks: 9122130 sha512's in 3.00s 39 | Doing sha512 for 3s on 256 size blocks: 3447543 sha512's in 3.00s 40 | Doing sha512 for 3s on 1024 size blocks: 1202608 sha512's in 3.00s 41 | Doing sha512 for 3s on 8192 size blocks: 169808 sha512's in 2.99s 42 | Doing sha512 for 3s on 16384 size blocks: 85725 sha512's in 3.00s 43 | Doing whirlpool for 3s on 16 size blocks: 3659807 whirlpool's in 3.00s 44 | Doing whirlpool for 3s on 64 size blocks: 1915648 whirlpool's in 3.00s 45 | Doing whirlpool for 3s on 256 size blocks: 783174 whirlpool's in 2.99s 46 | Doing whirlpool for 3s on 1024 size blocks: 232668 whirlpool's in 3.00s 47 | Doing whirlpool for 3s on 8192 size blocks: 30842 whirlpool's in 3.00s 48 | Doing whirlpool for 3s on 16384 size blocks: 15488 whirlpool's in 3.00s 49 | Doing rmd160 for 3s on 16 size blocks: 8626366 rmd160's in 2.99s 50 | Doing rmd160 for 3s on 64 size blocks: 5836135 rmd160's in 3.00s 51 | Doing rmd160 for 3s on 256 size blocks: 2937202 rmd160's in 3.00s 52 | Doing rmd160 for 3s on 1024 size blocks: 983165 rmd160's in 2.99s 53 | Doing rmd160 for 3s on 8192 size blocks: 136179 rmd160's in 3.00s 54 | Doing rmd160 for 3s on 16384 size blocks: 68661 rmd160's in 3.00s 55 | Doing rc4 for 3s on 16 size blocks: 93260092 rc4's in 3.00s 56 | Doing rc4 for 3s on 64 size blocks: 25154609 rc4's in 2.99s 57 | Doing rc4 for 3s on 256 size blocks: 6423336 rc4's in 3.00s 58 | Doing rc4 for 3s on 1024 size blocks: 1614544 rc4's in 3.00s 59 | Doing rc4 for 3s on 8192 size blocks: 202008 rc4's in 3.00s 60 | Doing rc4 for 3s on 16384 size blocks: 101061 rc4's in 2.99s 61 | Doing des cbc for 3s on 16 size blocks: 14391752 des cbc's in 3.00s 62 | Doing des cbc for 3s on 64 size blocks: 3677482 des cbc's in 3.00s 63 | Doing des cbc for 3s on 256 size blocks: 926342 des cbc's in 3.00s 64 | Doing des cbc for 3s on 1024 size blocks: 232086 des cbc's in 2.99s 65 | Doing des cbc for 3s on 8192 size blocks: 29028 des cbc's in 3.00s 66 | Doing des cbc for 3s on 16384 size blocks: 14513 des cbc's in 3.00s 67 | Doing des ede3 for 3s on 16 size blocks: 5446121 des ede3's in 3.00s 68 | Doing des ede3 for 3s on 64 size blocks: 1375381 des ede3's in 2.99s 69 | Doing des ede3 for 3s on 256 size blocks: 344460 des ede3's in 3.00s 70 | Doing des ede3 for 3s on 1024 size blocks: 86177 des ede3's in 3.00s 71 | Doing des ede3 for 3s on 8192 size blocks: 10760 des ede3's in 2.99s 72 | Doing des ede3 for 3s on 16384 size blocks: 5379 des ede3's in 3.00s 73 | Doing aes-128 cbc for 3s on 16 size blocks: 41268884 aes-128 cbc's in 3.00s 74 | Doing aes-128 cbc for 3s on 64 size blocks: 10979529 aes-128 cbc's in 3.00s 75 | Doing aes-128 cbc for 3s on 256 size blocks: 2755282 aes-128 cbc's in 2.99s 76 | Doing aes-128 cbc for 3s on 1024 size blocks: 698183 aes-128 cbc's in 3.00s 77 | Doing aes-128 cbc for 3s on 8192 size blocks: 87616 aes-128 cbc's in 3.00s 78 | Doing aes-128 cbc for 3s on 16384 size blocks: 43821 aes-128 cbc's in 3.00s 79 | Doing aes-192 cbc for 3s on 16 size blocks: 34932022 aes-192 cbc's in 2.99s 80 | Doing aes-192 cbc for 3s on 64 size blocks: 9201352 aes-192 cbc's in 3.00s 81 | Doing aes-192 cbc for 3s on 256 size blocks: 2306303 aes-192 cbc's in 3.00s 82 | Doing aes-192 cbc for 3s on 1024 size blocks: 582198 aes-192 cbc's in 3.00s 83 | Doing aes-192 cbc for 3s on 8192 size blocks: 72929 aes-192 cbc's in 2.99s 84 | Doing aes-192 cbc for 3s on 16384 size blocks: 36574 aes-192 cbc's in 3.00s 85 | Doing aes-256 cbc for 3s on 16 size blocks: 31742528 aes-256 cbc's in 3.00s 86 | Doing aes-256 cbc for 3s on 64 size blocks: 8350663 aes-256 cbc's in 3.00s 87 | Doing aes-256 cbc for 3s on 256 size blocks: 2093272 aes-256 cbc's in 2.99s 88 | Doing aes-256 cbc for 3s on 1024 size blocks: 528410 aes-256 cbc's in 3.00s 89 | Doing aes-256 cbc for 3s on 8192 size blocks: 66262 aes-256 cbc's in 3.00s 90 | Doing aes-256 cbc for 3s on 16384 size blocks: 33177 aes-256 cbc's in 3.00s 91 | Doing aes-128 ige for 3s on 16 size blocks: 37761062 aes-128 ige's in 2.99s 92 | Doing aes-128 ige for 3s on 64 size blocks: 10197296 aes-128 ige's in 3.00s 93 | Doing aes-128 ige for 3s on 256 size blocks: 2668219 aes-128 ige's in 3.00s 94 | Doing aes-128 ige for 3s on 1024 size blocks: 676374 aes-128 ige's in 2.99s 95 | Doing aes-128 ige for 3s on 8192 size blocks: 84906 aes-128 ige's in 3.00s 96 | Doing aes-128 ige for 3s on 16384 size blocks: 42460 aes-128 ige's in 3.00s 97 | Doing aes-192 ige for 3s on 16 size blocks: 32627324 aes-192 ige's in 3.00s 98 | Doing aes-192 ige for 3s on 64 size blocks: 8648957 aes-192 ige's in 2.99s 99 | Doing aes-192 ige for 3s on 256 size blocks: 2249414 aes-192 ige's in 3.00s 100 | Doing aes-192 ige for 3s on 1024 size blocks: 568846 aes-192 ige's in 3.00s 101 | Doing aes-192 ige for 3s on 8192 size blocks: 71335 aes-192 ige's in 3.00s 102 | Doing aes-192 ige for 3s on 16384 size blocks: 35681 aes-192 ige's in 2.99s 103 | Doing aes-256 ige for 3s on 16 size blocks: 29818480 aes-256 ige's in 3.00s 104 | Doing aes-256 ige for 3s on 64 size blocks: 7868731 aes-256 ige's in 3.00s 105 | Doing aes-256 ige for 3s on 256 size blocks: 2040562 aes-256 ige's in 3.00s 106 | Doing aes-256 ige for 3s on 1024 size blocks: 516099 aes-256 ige's in 2.99s 107 | Doing aes-256 ige for 3s on 8192 size blocks: 64655 aes-256 ige's in 3.00s 108 | Doing aes-256 ige for 3s on 16384 size blocks: 32337 aes-256 ige's in 3.00s 109 | Doing ghash for 3s on 16 size blocks: 214931421 ghash's in 3.00s 110 | Doing ghash for 3s on 64 size blocks: 195551609 ghash's in 2.99s 111 | Doing ghash for 3s on 256 size blocks: 64156660 ghash's in 3.00s 112 | Doing ghash for 3s on 1024 size blocks: 17026618 ghash's in 3.00s 113 | Doing ghash for 3s on 8192 size blocks: 2172755 ghash's in 3.00s 114 | Doing ghash for 3s on 16384 size blocks: 1088076 ghash's in 2.99s 115 | Doing camellia-128 cbc for 3s on 16 size blocks: 27895421 camellia-128 cbc's in 3.00s 116 | Doing camellia-128 cbc for 3s on 64 size blocks: 7150236 camellia-128 cbc's in 3.00s 117 | Doing camellia-128 cbc for 3s on 256 size blocks: 1789560 camellia-128 cbc's in 3.00s 118 | Doing camellia-128 cbc for 3s on 1024 size blocks: 450700 camellia-128 cbc's in 2.99s 119 | Doing camellia-128 cbc for 3s on 8192 size blocks: 56424 camellia-128 cbc's in 3.00s 120 | Doing camellia-128 cbc for 3s on 16384 size blocks: 28225 camellia-128 cbc's in 3.00s 121 | Doing camellia-192 cbc for 3s on 16 size blocks: 21381638 camellia-192 cbc's in 2.99s 122 | Doing camellia-192 cbc for 3s on 64 size blocks: 5471053 camellia-192 cbc's in 3.00s 123 | Doing camellia-192 cbc for 3s on 256 size blocks: 1368444 camellia-192 cbc's in 3.00s 124 | Doing camellia-192 cbc for 3s on 1024 size blocks: 344016 camellia-192 cbc's in 3.00s 125 | Doing camellia-192 cbc for 3s on 8192 size blocks: 43073 camellia-192 cbc's in 2.99s 126 | Doing camellia-192 cbc for 3s on 16384 size blocks: 21539 camellia-192 cbc's in 3.00s 127 | Doing camellia-256 cbc for 3s on 16 size blocks: 21384095 camellia-256 cbc's in 3.00s 128 | Doing camellia-256 cbc for 3s on 64 size blocks: 5470858 camellia-256 cbc's in 3.00s 129 | Doing camellia-256 cbc for 3s on 256 size blocks: 1367998 camellia-256 cbc's in 2.99s 130 | Doing camellia-256 cbc for 3s on 1024 size blocks: 344014 camellia-256 cbc's in 3.00s 131 | Doing camellia-256 cbc for 3s on 8192 size blocks: 43072 camellia-256 cbc's in 3.00s 132 | Doing camellia-256 cbc for 3s on 16384 size blocks: 21535 camellia-256 cbc's in 3.00s 133 | Doing idea cbc for 3s on 16 size blocks: 13093430 idea cbc's in 2.99s 134 | Doing idea cbc for 3s on 64 size blocks: 3367089 idea cbc's in 3.00s 135 | Doing idea cbc for 3s on 256 size blocks: 848901 idea cbc's in 3.00s 136 | Doing idea cbc for 3s on 1024 size blocks: 212630 idea cbc's in 2.99s 137 | Doing idea cbc for 3s on 8192 size blocks: 26579 idea cbc's in 3.00s 138 | Doing idea cbc for 3s on 16384 size blocks: 13295 idea cbc's in 3.00s 139 | Doing seed cbc for 3s on 16 size blocks: 15556651 seed cbc's in 3.00s 140 | Doing seed cbc for 3s on 64 size blocks: 3892018 seed cbc's in 2.99s 141 | Doing seed cbc for 3s on 256 size blocks: 983421 seed cbc's in 3.00s 142 | Doing seed cbc for 3s on 1024 size blocks: 246533 seed cbc's in 3.00s 143 | Doing seed cbc for 3s on 8192 size blocks: 30842 seed cbc's in 3.00s 144 | Doing seed cbc for 3s on 16384 size blocks: 15422 seed cbc's in 2.99s 145 | Doing rc2 cbc for 3s on 16 size blocks: 8306444 rc2 cbc's in 3.00s 146 | Doing rc2 cbc for 3s on 64 size blocks: 2111758 rc2 cbc's in 3.00s 147 | Doing rc2 cbc for 3s on 256 size blocks: 530769 rc2 cbc's in 3.00s 148 | Doing rc2 cbc for 3s on 1024 size blocks: 132873 rc2 cbc's in 2.99s 149 | Doing rc2 cbc for 3s on 8192 size blocks: 16616 rc2 cbc's in 3.00s 150 | Doing rc2 cbc for 3s on 16384 size blocks: 8308 rc2 cbc's in 3.00s 151 | Doing blowfish cbc for 3s on 16 size blocks: 21913208 blowfish cbc's in 3.00s 152 | Doing blowfish cbc for 3s on 64 size blocks: 5730331 blowfish cbc's in 2.99s 153 | Doing blowfish cbc for 3s on 256 size blocks: 1452267 blowfish cbc's in 3.00s 154 | Doing blowfish cbc for 3s on 1024 size blocks: 364368 blowfish cbc's in 3.00s 155 | Doing blowfish cbc for 3s on 8192 size blocks: 45597 blowfish cbc's in 3.00s 156 | Doing blowfish cbc for 3s on 16384 size blocks: 22799 blowfish cbc's in 2.99s 157 | Doing cast cbc for 3s on 16 size blocks: 19671849 cast cbc's in 3.00s 158 | Doing cast cbc for 3s on 64 size blocks: 5095224 cast cbc's in 3.00s 159 | Doing cast cbc for 3s on 256 size blocks: 1288427 cast cbc's in 2.99s 160 | Doing cast cbc for 3s on 1024 size blocks: 323253 cast cbc's in 3.00s 161 | Doing cast cbc for 3s on 8192 size blocks: 40441 cast cbc's in 3.00s 162 | Doing cast cbc for 3s on 16384 size blocks: 20223 cast cbc's in 3.00s 163 | Doing rand for 3s on 16 size blocks: 2083320 rand's in 2.99s 164 | Doing rand for 3s on 64 size blocks: 1921935 rand's in 3.00s 165 | Doing rand for 3s on 256 size blocks: 1502788 rand's in 3.00s 166 | Doing rand for 3s on 1024 size blocks: 803720 rand's in 3.00s 167 | Doing rand for 3s on 8192 size blocks: 150440 rand's in 2.99s 168 | Doing rand for 3s on 16384 size blocks: 77806 rand's in 3.00s 169 | Doing 512 bits private rsa's for 10s: 134060 512 bits private RSA's in 9.99s 170 | Doing 512 bits public rsa's for 10s: 1513969 512 bits public RSA's in 9.99s 171 | Doing 1024 bits private rsa's for 10s: 23261 1024 bits private RSA's in 10.00s 172 | Doing 1024 bits public rsa's for 10s: 451361 1024 bits public RSA's in 9.99s 173 | Doing 2048 bits private rsa's for 10s: 3312 2048 bits private RSA's in 9.99s 174 | Doing 2048 bits public rsa's for 10s: 121411 2048 bits public RSA's in 9.99s 175 | Doing 3072 bits private rsa's for 10s: 1062 3072 bits private RSA's in 9.99s 176 | Doing 3072 bits public rsa's for 10s: 55005 3072 bits public RSA's in 9.99s 177 | Doing 4096 bits private rsa's for 10s: 466 4096 bits private RSA's in 10.01s 178 | Doing 4096 bits public rsa's for 10s: 31209 4096 bits public RSA's in 9.99s 179 | Doing 7680 bits private rsa's for 10s: 61 7680 bits private RSA's in 10.15s 180 | Doing 7680 bits public rsa's for 10s: 8976 7680 bits public RSA's in 9.99s 181 | Doing 15360 bits private rsa's for 10s: 10 15360 bits private RSA's in 10.34s 182 | Doing 15360 bits public rsa's for 10s: 2257 15360 bits public RSA's in 9.99s 183 | Doing 512 bits sign dsa's for 10s: 77561 512 bits DSA signs in 10.00s 184 | Doing 512 bits verify dsa's for 10s: 101338 512 bits DSA verify in 9.99s 185 | Doing 1024 bits sign dsa's for 10s: 29999 1024 bits DSA signs in 9.99s 186 | Doing 1024 bits verify dsa's for 10s: 33550 1024 bits DSA verify in 9.99s 187 | Doing 2048 bits sign dsa's for 10s: 8888 2048 bits DSA signs in 9.99s 188 | Doing 2048 bits verify dsa's for 10s: 9301 2048 bits DSA verify in 9.99s 189 | Doing 160 bits sign ecdsa's for 10s: 30126 160 bits ECDSA signs in 9.94s 190 | Doing 160 bits verify ecdsa's for 10s: 32053 160 bits ECDSA verify in 9.98s 191 | Doing 192 bits sign ecdsa's for 10s: 24852 192 bits ECDSA signs in 9.99s 192 | Doing 192 bits verify ecdsa's for 10s: 27291 192 bits ECDSA verify in 9.99s 193 | Doing 224 bits sign ecdsa's for 10s: 16249 224 bits ECDSA signs in 9.99s 194 | Doing 224 bits verify ecdsa's for 10s: 18398 224 bits ECDSA verify in 9.95s 195 | Doing 256 bits sign ecdsa's for 10s: 210462 256 bits ECDSA signs in 9.99s 196 | Doing 256 bits verify ecdsa's for 10s: 61987 256 bits ECDSA verify in 9.99s 197 | Doing 384 bits sign ecdsa's for 10s: 4925 384 bits ECDSA signs in 9.99s 198 | Doing 384 bits verify ecdsa's for 10s: 6349 384 bits ECDSA verify in 9.99s 199 | Doing 521 bits sign ecdsa's for 10s: 1843 521 bits ECDSA signs in 9.99s 200 | Doing 521 bits verify ecdsa's for 10s: 2436 521 bits ECDSA verify in 9.99s 201 | Doing 163 bits sign ecdsa's for 10s: 24280 163 bits ECDSA signs in 9.99s 202 | Doing 163 bits verify ecdsa's for 10s: 12191 163 bits ECDSA verify in 9.99s 203 | Doing 233 bits sign ecdsa's for 10s: 15521 233 bits ECDSA signs in 9.99s 204 | Doing 233 bits verify ecdsa's for 10s: 7846 233 bits ECDSA verify in 9.99s 205 | Doing 283 bits sign ecdsa's for 10s: 8015 283 bits ECDSA signs in 9.99s 206 | Doing 283 bits verify ecdsa's for 10s: 4050 283 bits ECDSA verify in 9.99s 207 | Doing 409 bits sign ecdsa's for 10s: 3779 409 bits ECDSA signs in 9.99s 208 | Doing 409 bits verify ecdsa's for 10s: 1916 409 bits ECDSA verify in 9.99s 209 | Doing 571 bits sign ecdsa's for 10s: 1796 571 bits ECDSA signs in 9.99s 210 | Doing 571 bits verify ecdsa's for 10s: 913 571 bits ECDSA verify in 10.00s 211 | Doing 163 bits sign ecdsa's for 10s: 23145 163 bits ECDSA signs in 9.99s 212 | Doing 163 bits verify ecdsa's for 10s: 11608 163 bits ECDSA verify in 9.99s 213 | Doing 233 bits sign ecdsa's for 10s: 14925 233 bits ECDSA signs in 9.99s 214 | Doing 233 bits verify ecdsa's for 10s: 7510 233 bits ECDSA verify in 9.99s 215 | Doing 283 bits sign ecdsa's for 10s: 7451 283 bits ECDSA signs in 9.99s 216 | Doing 283 bits verify ecdsa's for 10s: 3750 283 bits ECDSA verify in 9.99s 217 | Doing 409 bits sign ecdsa's for 10s: 3451 409 bits ECDSA signs in 10.00s 218 | Doing 409 bits verify ecdsa's for 10s: 1741 409 bits ECDSA verify in 10.00s 219 | Doing 571 bits sign ecdsa's for 10s: 1617 571 bits ECDSA signs in 9.99s 220 | Doing 571 bits verify ecdsa's for 10s: 823 571 bits ECDSA verify in 10.00s 221 | Doing 256 bits sign ecdsa's for 10s: 14492 256 bits ECDSA signs in 9.99s 222 | Doing 256 bits verify ecdsa's for 10s: 16028 256 bits ECDSA verify in 9.99s 223 | Doing 256 bits sign ecdsa's for 10s: 14489 256 bits ECDSA signs in 9.99s 224 | Doing 256 bits verify ecdsa's for 10s: 17123 256 bits ECDSA verify in 9.99s 225 | Doing 384 bits sign ecdsa's for 10s: 4936 384 bits ECDSA signs in 9.99s 226 | Doing 384 bits verify ecdsa's for 10s: 5881 384 bits ECDSA verify in 9.99s 227 | Doing 384 bits sign ecdsa's for 10s: 4973 384 bits ECDSA signs in 9.99s 228 | Doing 384 bits verify ecdsa's for 10s: 6331 384 bits ECDSA verify in 10.00s 229 | Doing 512 bits sign ecdsa's for 10s: 2496 512 bits ECDSA signs in 9.98s 230 | Doing 512 bits verify ecdsa's for 10s: 3177 512 bits ECDSA verify in 9.99s 231 | Doing 512 bits sign ecdsa's for 10s: 2510 512 bits ECDSA signs in 9.99s 232 | Doing 512 bits verify ecdsa's for 10s: 3407 512 bits ECDSA verify in 10.00s 233 | Doing 160 bits ecdh's for 10s: 31965 160-bits ECDH ops in 9.99s 234 | Doing 192 bits ecdh's for 10s: 26111 192-bits ECDH ops in 9.99s 235 | Doing 224 bits ecdh's for 10s: 17068 224-bits ECDH ops in 9.99s 236 | Doing 256 bits ecdh's for 10s: 81026 256-bits ECDH ops in 9.99s 237 | Doing 384 bits ecdh's for 10s: 5178 384-bits ECDH ops in 10.00s 238 | Doing 521 bits ecdh's for 10s: 1942 521-bits ECDH ops in 9.99s 239 | Doing 163 bits ecdh's for 10s: 25276 163-bits ECDH ops in 9.99s 240 | Doing 233 bits ecdh's for 10s: 16348 233-bits ECDH ops in 10.00s 241 | Doing 283 bits ecdh's for 10s: 8401 283-bits ECDH ops in 9.99s 242 | Doing 409 bits ecdh's for 10s: 3983 409-bits ECDH ops in 10.00s 243 | Doing 571 bits ecdh's for 10s: 1892 571-bits ECDH ops in 9.99s 244 | Doing 163 bits ecdh's for 10s: 24018 163-bits ECDH ops in 9.99s 245 | Doing 233 bits ecdh's for 10s: 15570 233-bits ECDH ops in 9.99s 246 | Doing 283 bits ecdh's for 10s: 7771 283-bits ECDH ops in 9.99s 247 | Doing 409 bits ecdh's for 10s: 3611 409-bits ECDH ops in 9.99s 248 | Doing 571 bits ecdh's for 10s: 1702 571-bits ECDH ops in 9.99s 249 | Doing 256 bits ecdh's for 10s: 15217 256-bits ECDH ops in 9.99s 250 | Doing 256 bits ecdh's for 10s: 15215 256-bits ECDH ops in 9.99s 251 | Doing 384 bits ecdh's for 10s: 5185 384-bits ECDH ops in 9.99s 252 | Doing 384 bits ecdh's for 10s: 5229 384-bits ECDH ops in 9.99s 253 | Doing 512 bits ecdh's for 10s: 2613 512-bits ECDH ops in 9.99s 254 | Doing 512 bits ecdh's for 10s: 2630 512-bits ECDH ops in 9.99s 255 | Doing 253 bits ecdh's for 10s: 60687 253-bits ECDH ops in 9.99s 256 | Doing 448 bits ecdh's for 10s: 8994 448-bits ECDH ops in 9.99s 257 | Doing 253 bits sign Ed25519's for 10s: 97314 253 bits Ed25519 signs in 9.99s 258 | Doing 253 bits verify Ed25519's for 10s: 31709 253 bits Ed25519 verify in 9.99s 259 | Doing 456 bits sign Ed448's for 10s: 18076 456 bits Ed448 signs in 9.99s 260 | Doing 456 bits verify Ed448's for 10s: 8203 456 bits Ed448 verify in 10.00s 261 | OpenSSL 1.1.1g 21 Apr 2020 262 | built on: Sun Jul 5 17:28:35 2020 UTC 263 | options:bn(64,64) rc4(char) des(int) aes(partial) idea(int) blowfish(ptr) 264 | compiler: aarch64-linux-android-clang -fPIC -pthread -Wa,--noexecstack -Qunused-arguments -fstack-protector-strong -Oz -DNO_SYSLOG -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DZLIB -DZLIB_SHARED -DNDEBUG -I/data/data/com.termux/files/usr/include 265 | The 'numbers' are in 1000s of bytes per second processed. 266 | type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes 16384 bytes 267 | md2 0.00 0.00 0.00 0.00 0.00 0.00 268 | mdc2 14385.88k 15813.40k 16329.63k 16394.24k 16433.15k 16433.15k 269 | md4 68436.28k 223274.67k 541064.87k 842973.24k 1001259.01k 1014885.03k 270 | md5 94721.37k 220360.84k 371671.72k 449718.61k 478983.51k 482895.11k 271 | hmac(md5) 36041.83k 113738.54k 267314.69k 404301.57k 472476.33k 478713.17k 272 | sha1 207425.51k 593799.38k 1174849.88k 1559599.45k 1725210.54k 1732498.77k 273 | rmd160 46161.16k 124504.21k 250641.24k 336709.35k 371859.46k 374980.61k 274 | rc4 497387.16k 538426.41k 548124.67k 551097.69k 551616.51k 553773.72k 275 | des cbc 76756.01k 78452.95k 79047.85k 79483.63k 79265.79k 79260.33k 276 | des ede3 29045.98k 29439.59k 29393.92k 29415.08k 29480.24k 29376.51k 277 | idea cbc 70065.18k 71831.23k 72439.55k 72820.44k 72578.39k 72608.43k 278 | seed cbc 82968.81k 83307.41k 83918.59k 84149.93k 84219.22k 84506.37k 279 | rc2 cbc 44301.03k 45050.84k 45292.29k 45505.67k 45372.76k 45372.76k 280 | rc5-32/12 cbc 0.00 0.00 0.00 0.00 0.00 0.00 281 | blowfish cbc 116870.44k 122655.91k 123926.78k 124370.94k 124510.21k 124929.37k 282 | cast cbc 104916.53k 108698.11k 110313.48k 110337.02k 110430.89k 110444.54k 283 | aes-128 cbc 220100.71k 234229.95k 235903.74k 238313.13k 239250.09k 239321.09k 284 | aes-192 cbc 186927.21k 196295.51k 196804.52k 198723.58k 199810.83k 199742.81k 285 | aes-256 cbc 169293.48k 178147.48k 179223.29k 180363.95k 180939.43k 181190.66k 286 | camellia-128 cbc 148775.58k 152538.37k 152709.12k 154353.44k 154075.14k 154146.13k 287 | camellia-192 cbc 114416.79k 116715.80k 116773.89k 117424.13k 118011.38k 117631.66k 288 | camellia-256 cbc 114048.51k 116711.64k 117126.25k 117423.45k 117615.27k 117609.81k 289 | sha256 199042.52k 583256.41k 1195665.55k 1603390.81k 1785727.66k 1800339.46k 290 | sha512 48751.99k 194605.44k 294190.34k 410490.20k 465239.84k 468172.80k 291 | whirlpool 19518.97k 40867.16k 67054.36k 79417.34k 84219.22k 84585.13k 292 | aes-128 ige 202065.88k 217542.31k 227688.02k 231641.13k 231849.98k 231888.21k 293 | aes-192 ige 174012.39k 185128.18k 191949.99k 194166.10k 194792.11k 195517.56k 294 | aes-256 ige 159031.89k 167866.26k 174127.96k 176750.96k 176551.25k 176603.14k 295 | ghash 1146300.91k 4185720.06k 5474701.65k 5811752.28k 5933069.65k 5962219.79k 296 | rand 11148.20k 41001.28k 128237.91k 274336.43k 412175.41k 424924.50k 297 | sign verify sign/s verify/s 298 | rsa 512 bits 0.000075s 0.000007s 13419.4 151548.4 299 | rsa 1024 bits 0.000430s 0.000022s 2326.1 45181.3 300 | rsa 2048 bits 0.003016s 0.000082s 331.5 12153.3 301 | rsa 3072 bits 0.009407s 0.000182s 106.3 5506.0 302 | rsa 4096 bits 0.021481s 0.000320s 46.6 3124.0 303 | rsa 7680 bits 0.166393s 0.001113s 6.0 898.5 304 | rsa 15360 bits 1.034000s 0.004426s 1.0 225.9 305 | sign verify sign/s verify/s 306 | dsa 512 bits 0.000129s 0.000099s 7756.1 10143.9 307 | dsa 1024 bits 0.000333s 0.000298s 3002.9 3358.4 308 | dsa 2048 bits 0.001124s 0.001074s 889.7 931.0 309 | sign verify sign/s verify/s 310 | 160 bits ecdsa (secp160r1) 0.0003s 0.0003s 3030.8 3211.7 311 | 192 bits ecdsa (nistp192) 0.0004s 0.0004s 2487.7 2731.8 312 | 224 bits ecdsa (nistp224) 0.0006s 0.0005s 1626.5 1849.0 313 | 256 bits ecdsa (nistp256) 0.0000s 0.0002s 21067.3 6204.9 314 | 384 bits ecdsa (nistp384) 0.0020s 0.0016s 493.0 635.5 315 | 521 bits ecdsa (nistp521) 0.0054s 0.0041s 184.5 243.8 316 | 163 bits ecdsa (nistk163) 0.0004s 0.0008s 2430.4 1220.3 317 | 233 bits ecdsa (nistk233) 0.0006s 0.0013s 1553.7 785.4 318 | 283 bits ecdsa (nistk283) 0.0012s 0.0025s 802.3 405.4 319 | 409 bits ecdsa (nistk409) 0.0026s 0.0052s 378.3 191.8 320 | 571 bits ecdsa (nistk571) 0.0056s 0.0110s 179.8 91.3 321 | 163 bits ecdsa (nistb163) 0.0004s 0.0009s 2316.8 1162.0 322 | 233 bits ecdsa (nistb233) 0.0007s 0.0013s 1494.0 751.8 323 | 283 bits ecdsa (nistb283) 0.0013s 0.0027s 745.8 375.4 324 | 409 bits ecdsa (nistb409) 0.0029s 0.0057s 345.1 174.1 325 | 571 bits ecdsa (nistb571) 0.0062s 0.0122s 161.9 82.3 326 | 256 bits ecdsa (brainpoolP256r1) 0.0007s 0.0006s 1450.7 1604.4 327 | 256 bits ecdsa (brainpoolP256t1) 0.0007s 0.0006s 1450.4 1714.0 328 | 384 bits ecdsa (brainpoolP384r1) 0.0020s 0.0017s 494.1 588.7 329 | 384 bits ecdsa (brainpoolP384t1) 0.0020s 0.0016s 497.8 633.1 330 | 512 bits ecdsa (brainpoolP512r1) 0.0040s 0.0031s 250.1 318.0 331 | 512 bits ecdsa (brainpoolP512t1) 0.0040s 0.0029s 251.3 340.7 332 | op op/s 333 | 160 bits ecdh (secp160r1) 0.0003s 3199.7 334 | 192 bits ecdh (nistp192) 0.0004s 2613.7 335 | 224 bits ecdh (nistp224) 0.0006s 1708.5 336 | 256 bits ecdh (nistp256) 0.0001s 8110.7 337 | 384 bits ecdh (nistp384) 0.0019s 517.8 338 | 521 bits ecdh (nistp521) 0.0051s 194.4 339 | 163 bits ecdh (nistk163) 0.0004s 2530.1 340 | 233 bits ecdh (nistk233) 0.0006s 1634.8 341 | 283 bits ecdh (nistk283) 0.0012s 840.9 342 | 409 bits ecdh (nistk409) 0.0025s 398.3 343 | 571 bits ecdh (nistk571) 0.0053s 189.4 344 | 163 bits ecdh (nistb163) 0.0004s 2404.2 345 | 233 bits ecdh (nistb233) 0.0006s 1558.6 346 | 283 bits ecdh (nistb283) 0.0013s 777.9 347 | 409 bits ecdh (nistb409) 0.0028s 361.5 348 | 571 bits ecdh (nistb571) 0.0059s 170.4 349 | 256 bits ecdh (brainpoolP256r1) 0.0007s 1523.2 350 | 256 bits ecdh (brainpoolP256t1) 0.0007s 1523.0 351 | 384 bits ecdh (brainpoolP384r1) 0.0019s 519.0 352 | 384 bits ecdh (brainpoolP384t1) 0.0019s 523.4 353 | 512 bits ecdh (brainpoolP512r1) 0.0038s 261.6 354 | 512 bits ecdh (brainpoolP512t1) 0.0038s 263.3 355 | 253 bits ecdh (X25519) 0.0002s 6074.8 356 | 448 bits ecdh (X448) 0.0011s 900.3 357 | sign verify sign/s verify/s 358 | 253 bits EdDSA (Ed25519) 0.0001s 0.0003s 9741.1 3174.1 359 | 456 bits EdDSA (Ed448) 0.0006s 0.0012s 1809.4 820.3 360 | -------------------------------------------------------------------------------- /cbackup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cbackup: Simple full app + data + metadata backup/restore script for Android 4 | # 5 | # Required Termux packages: tsu tar sed zstd openssl-tool 6 | # Optional packages: pv 7 | # 8 | # Licensed under the MIT License (MIT) 9 | # 10 | # Copyright (c) 2020 Danny Lin 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to deal 14 | # in the Software without restriction, including without limitation the rights 15 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | # copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in all 20 | # copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | # SOFTWARE. 29 | 30 | set -euo pipefail 31 | shopt -s nullglob dotglob extglob 32 | 33 | # Constants 34 | BACKUP_VERSION="0" 35 | PASSWORD_CANARY="cbackup-valid" 36 | 37 | # Settings 38 | tmp_dir="/data/local/tmp/._cbackup_tmp" 39 | backup_dir="${2:-/sdcard/cbackup}" 40 | encryption_args=(-pbkdf2 -iter 200001 -aes-256-ctr) 41 | debug=false 42 | # WARNING: Hardcoded password FOR TESTING ONLY! 43 | #password="cbackup-test!" 44 | # Known broken/problemtic apps to ignore entirely 45 | app_blacklist=( 46 | # Restoring Magisk Manager may cause problems with root access 47 | com.topjohnwu.magisk 48 | ) 49 | 50 | # Select default action based on filename, because we self-replicate to restore.sh in backups 51 | action="${1:-$([[ "$0" == *"restore"* ]] && echo restore || echo backup)}" 52 | 53 | # Prints an error in bold red 54 | function err() { 55 | echo -e "\e[1;31m$*\e[0m" 56 | } 57 | 58 | # Prints an error in bold red and exits the script 59 | function die() { 60 | echo 61 | err "$*" 62 | echo 63 | 64 | exit 1 65 | } 66 | 67 | # Prints a warning in bold yellow 68 | function warn() { 69 | echo 70 | echo -e "\e[1;33m$*\e[0m" 71 | echo 72 | } 73 | 74 | # Shows an informational message 75 | function msg() { 76 | echo -e "\e[1;32m$*\e[0m" 77 | } 78 | 79 | # Shows a debug message 80 | function dbg() { 81 | if [[ "$debug" == "true" ]]; then 82 | echo "$*" 83 | fi 84 | } 85 | 86 | function ask_password() { 87 | local confirm="$1" 88 | 89 | # Fall back to an empty string to avoid unbound variable errors 90 | if [[ -z "${password:-}" ]]; then 91 | if [[ "$confirm" == "true" ]]; then 92 | read -rsp "Enter password for backup: " password 93 | echo 94 | read -rsp "Confirm password: " password2 95 | echo 96 | 97 | if [[ "$password2" != "$password" ]]; then 98 | die "Mismatching passwords!" 99 | fi 100 | 101 | unset -v password2 102 | echo 103 | else 104 | read -rsp "Enter backup password: " password 105 | fi 106 | fi 107 | } 108 | 109 | function encrypt_to_file() { 110 | PASSWORD="$password" openssl enc -out "$1" "${encryption_args[@]}" -pass env:PASSWORD 111 | } 112 | 113 | function decrypt_file() { 114 | PASSWORD="$password" openssl enc -d -in "$1" "${encryption_args[@]}" -pass env:PASSWORD 115 | } 116 | 117 | function expect_output() { 118 | grep -v "$@" || true 119 | } 120 | 121 | function parse_diskstats_array() { 122 | local diskstats="$1" 123 | local label="$2" 124 | 125 | grep "$label: " <<< "$diskstats" | \ 126 | sed "s/$label: //" | \ 127 | tr -d '"[]' | \ 128 | tr ',' '\n' 129 | } 130 | 131 | function get_app_data_sizes() { 132 | local diskstats pkg_names data_sizes end_idx 133 | declare -n size_map="$1" 134 | 135 | diskstats="$(dumpsys diskstats)" 136 | mapfile -t pkg_names < <(parse_diskstats_array "$diskstats" "Package Names") 137 | mapfile -t data_sizes < <(parse_diskstats_array "$diskstats" "App Data Sizes") 138 | end_idx="$((${#data_sizes[@]} - 1))" 139 | 140 | for i in $(seq 0 $end_idx) 141 | do 142 | # This is a name reference that should be used by the caller. 143 | # shellcheck disable=SC2034 144 | size_map["${pkg_names[$i]}"]="${data_sizes[$i]}" 145 | done 146 | } 147 | 148 | # Setup 149 | ssaid_restored=false 150 | termux_restored=false 151 | app_install_failed=false 152 | android_version="$(getprop ro.build.version.release | cut -d'.' -f1)" 153 | rm -fr "$tmp_dir" 154 | mkdir -p "$tmp_dir" 155 | 156 | # Degrade gracefully if optional commands are not available 157 | # This is a function so we can update it after in-place Termux restoration 158 | function check_optional_cmds() { 159 | unset -f progress_cmd 160 | 161 | if type pv > /dev/null; then 162 | function progress_cmd() { 163 | pv "$@" 164 | } 165 | else 166 | function progress_cmd() { 167 | # Ignore pv arguments 168 | cat 169 | } 170 | fi 171 | } 172 | 173 | check_optional_cmds 174 | 175 | function do_backup() { 176 | rm -fr "$backup_dir" 177 | mkdir -p "$backup_dir" 178 | 179 | ask_password true 180 | 181 | # Get list of user app package names 182 | pm list packages --user 0 > "$tmp_dir/pm_all_pkgs.list" 183 | pm list packages -s --user 0 > "$tmp_dir/pm_sys_pkgs.list" 184 | local apps 185 | apps="$(grep -vf "$tmp_dir/pm_sys_pkgs.list" "$tmp_dir/pm_all_pkgs.list" | sed 's/package://g')" 186 | 187 | # Remove ignored apps 188 | dbg "Ignoring apps: ${app_blacklist[*]}" 189 | tr ' ' '\n' <<< "${app_blacklist[*]}" > "$tmp_dir/pm_ignored.list" 190 | apps="$(grep -vf "$tmp_dir/pm_ignored.list" <<< "$apps")" 191 | 192 | echo "Apps to backup:" 193 | echo "$apps" 194 | echo 195 | echo 196 | 197 | # Get map of app data sizes 198 | declare -A app_data_sizes 199 | get_app_data_sizes app_data_sizes 200 | 201 | # Back up apps 202 | local app 203 | for app in $apps 204 | do 205 | msg "Backing up $app..." 206 | 207 | local app_out app_info 208 | app_out="$backup_dir/$app" 209 | mkdir "$app_out" 210 | app_info="$(dumpsys package "$app")" 211 | 212 | # cbackup metadata 213 | echo "$BACKUP_VERSION" > "$app_out/backup_version.txt" 214 | echo -n "$PASSWORD_CANARY" | encrypt_to_file "$app_out/password_canary.enc" 215 | 216 | # APKs 217 | msg " • APK" 218 | mkdir "$app_out/apk" 219 | local apk_dir 220 | apk_dir="$(grep "codePath=" <<< "$app_info" | sed 's/^\s*codePath=//')" 221 | cp "$apk_dir/"*.apk "$app_out/apk" 222 | 223 | # Data 224 | msg " • Data" 225 | pushd / > /dev/null 226 | 227 | # Collect list of files 228 | local files=( 229 | # CE data for user 0 230 | "data/data/$app/"!(@(cache|code_cache|no_backup)) \ 231 | # DE data for user 0 232 | "data/user_de/0/$app/"!(@(cache|code_cache|no_backup)) 233 | ) 234 | 235 | # Skip backup if file list is empty 236 | if [[ ${#files[@]} -eq 0 ]]; then 237 | echo "Skipping data backup because this app has no data" 238 | else 239 | # Suspend app if possible 240 | local suspended=false 241 | if [[ "$PREFIX" == *"com.termux"* ]] && [[ "$app" == "com.termux" ]]; then 242 | dbg "Skipping app suspend for Termux because we're running inside it" 243 | elif [[ "$android_version" -ge 9 ]]; then 244 | dbg "Suspending app" 245 | pm suspend --user 0 "$app" | expect_output 'new suspended state: true' 246 | suspended=true 247 | else 248 | dbg "Skipping app suspend due to old Android version $android_version" 249 | fi 250 | 251 | # Finally, perform backup if we have files to back up 252 | tar -cf - "${files[@]}" | \ 253 | progress_cmd -s "${app_data_sizes[$app]:-0}" | 254 | zstd -T0 - | \ 255 | encrypt_to_file "$app_out/data.tar.zst.enc" 256 | 257 | # Unsuspend the app now that data backup is done 258 | if $suspended; then 259 | dbg "Unsuspending app" 260 | pm unsuspend --user 0 "$app" | expect_output 'new suspended state: false' 261 | fi 262 | fi 263 | 264 | popd > /dev/null 265 | 266 | # Permissions 267 | msg " • Other" 268 | grep "granted=true, flags=" <<< "$app_info" | \ 269 | sed 's/^\s*\(.*\): granted.*$/\1/g' | \ 270 | sort | \ 271 | uniq > "$app_out/permissions.list" \ 272 | || true 273 | 274 | # SSAID 275 | if grep -q 'package="'"$app"'"' /data/system/users/0/settings_ssaid.xml; then 276 | grep 'package="'"$app"'"' /data/system/users/0/settings_ssaid.xml > "$app_out/ssaid.xml" 277 | fi 278 | 279 | # Battery optimization 280 | if grep -q "$app" /data/system/deviceidle.xml; then 281 | touch "$app_out/battery_opt_disabled" 282 | fi 283 | 284 | # Installer name 285 | if grep -q "installerPackageName=" <<< "$app_info"; then 286 | grep "installerPackageName=" <<< "$app_info" | \ 287 | sed 's/^\s*installerPackageName=//' > "$app_out/installer_name.txt" 288 | fi 289 | 290 | echo 291 | done 292 | 293 | # Copy script into backup for easy restoration 294 | cp "$0" "$backup_dir/restore.sh" 295 | } 296 | 297 | function do_restore() { 298 | # First pass to show the user a list of apps to restore 299 | local apps=() 300 | local app_dir 301 | for app_dir in "$backup_dir/"* 302 | do 303 | if [[ ! -d "$app_dir" ]]; then 304 | dbg "Ignoring non-directory $app_dir" 305 | continue 306 | fi 307 | 308 | dbg "Discovered app $app_dir" 309 | app="$(basename "$app_dir")" 310 | apps+=("$app") 311 | done 312 | 313 | ask_password false 314 | 315 | echo "Apps to restore:" 316 | tr ' ' '\n' <<< "${apps[@]}" 317 | echo 318 | echo 319 | 320 | local installed_apps 321 | installed_apps="$(pm list packages --user 0 | sed 's/package://g')" 322 | 323 | local app 324 | for app in "${apps[@]}" 325 | do 326 | local app_dir="$backup_dir/$app" 327 | msg "Restoring $app..." 328 | 329 | # Check version 330 | if [[ ! -f "$app_dir/backup_version.txt" ]]; then 331 | die "Backup version is missing" 332 | else 333 | local bver 334 | bver="$(cat "$app_dir/backup_version.txt")" 335 | if [[ "$bver" != "$BACKUP_VERSION" ]]; then 336 | die "Incompatible backup version $bver, expected $BACKUP_VERSION" 337 | fi 338 | fi 339 | 340 | # Check password canary 341 | if [[ "$(decrypt_file "$app_dir/password_canary.enc")" != "$PASSWORD_CANARY" ]]; then 342 | die "Incorrect password or corrupted backup!" 343 | fi 344 | 345 | # Check whether we need special in-place restoration for Termux 346 | local termux_inplace 347 | if [[ "$PREFIX" == *"com.termux"* ]] && [[ "$app" == "com.termux" ]]; then 348 | termux_inplace=true 349 | dbg "Performing in-place Termux restore" 350 | else 351 | termux_inplace=false 352 | fi 353 | 354 | # APKs 355 | msg " • APK" 356 | local suspended=false 357 | if $termux_inplace; then 358 | echo "Skipped because we're running in Termux" 359 | else 360 | # Proceed with APK installation 361 | 362 | # Uninstall old app if already installed 363 | # We don't just clear data because there are countless other Android 364 | # metadata values that are hard to clean: SSAIDs, permissions, special 365 | # permissions, etc. 366 | if grep -q "$app" <<< "$installed_apps"; then 367 | dbg "Uninstalling old copy of app" 368 | pm uninstall --user 0 "$app" | expect_output Success 369 | fi 370 | 371 | # Prepare to invoke pm install 372 | local pm_install_args=( 373 | # Allow test packages (i.e. ones installed by Android Studio's "Run" button) 374 | -t 375 | # Only install for user 0 376 | --user 0 377 | # Set expected package name 378 | --pkg "$app" 379 | ) 380 | 381 | # Installed due to device restore (on Android 10+) 382 | if [[ "$android_version" -ge 10 ]]; then 383 | pm_install_args+=(--install-reason 2) 384 | fi 385 | 386 | # Installer name 387 | if [[ -f "$app_dir/installer_name.txt" ]]; then 388 | pm_install_args+=(-i "$(cat "$app_dir/installer_name.txt")") 389 | fi 390 | dbg "PM install args: ${pm_install_args[*]}" 391 | 392 | # Install split APKs 393 | local pm_session 394 | pm_session="$(pm install-create "${pm_install_args[@]}" | sed 's/^.*\[\([[:digit:]]*\)\].*$/\1/')" 395 | dbg "PM session: $pm_session" 396 | 397 | local apk 398 | for apk in "$app_dir/apk/"* 399 | do 400 | # We need to specify size because we're streaming it to pm through stdin 401 | # to avoid creating a temporary file 402 | local apk_size split_name 403 | apk_size="$(wc -c "$apk" | cut -d' ' -f1)" 404 | split_name="$(basename "$apk")" 405 | 406 | dbg "Writing $apk_size-byte APK $apk with split name $split_name to session $pm_session" 407 | cat "$apk" | pm install-write -S "$apk_size" "$pm_session" "$split_name" | expect_output Success 408 | done 409 | 410 | pm install-commit "$pm_session" | expect_output Success || { 411 | err "Installation failed; skipping app" 412 | app_install_failed=true 413 | echo 414 | 415 | continue 416 | } 417 | 418 | if [[ "$android_version" -ge 9 ]]; then 419 | pm suspend --user 0 "$app" | expect_output 'new suspended state: true' 420 | suspended=true 421 | else 422 | dbg "Skipping app suspend due to old Android version $android_version" 423 | fi 424 | fi 425 | 426 | # Get info of newly installed app 427 | local app_info 428 | app_info="$(dumpsys package "$app")" 429 | 430 | # Data 431 | msg " • Data" 432 | local data_dir="/data/data/$app" 433 | local de_data_dir="/data/user_de/0/$app" 434 | 435 | # We can't delete and extract directly to the Termux root because we 436 | # need to use Termux-provided tools for extracting app data 437 | local out_root_dir 438 | if $termux_inplace; then 439 | # This temporary output directory must be in /data/data to apply the 440 | # correct FBE key, so we can avoid a copy when swapping directories 441 | out_root_dir="$(dirname "$data_dir")/._cbackup_termux_inplace_restore" 442 | 443 | dbg "Using $out_root_dir for temporary in-place operations" 444 | rm -fr "$out_root_dir" 445 | mkdir -p "$out_root_dir" 446 | else 447 | out_root_dir="/" 448 | fi 449 | 450 | # Create new data directory for in-place Termux restore 451 | # No extra slash here because both are supposed to be absolute paths 452 | local new_data_dir="$out_root_dir$data_dir" 453 | dbg "New temporary data directory is $new_data_dir" 454 | mkdir -p "$new_data_dir" 455 | chmod 700 "$new_data_dir" 456 | 457 | # Get UID and GIDs 458 | local uid 459 | uid="$(grep "userId=" <<< "$app_info" | head -1 | sed 's/^\s*userId=//')" 460 | dbg "App UID/GID is $uid" 461 | local gid_cache="$((uid + 10000))" 462 | dbg "App cache GID is $gid_cache" 463 | 464 | # Get SELinux context from the system-created data directory 465 | # Parsing the output of ls is not ideal, but Termux doesn't come with any 466 | # tools for this. 467 | # TODO: Fix the sporadic failure codes instead of silencing them with a declaration 468 | # shellcheck disable=SC2012 469 | local secontext="$(/system/bin/ls -a1Z "$data_dir" | head -1 | cut -d' ' -f1)" 470 | dbg "App SELinux context is $secontext" 471 | 472 | # Finally, extract the app data 473 | local data_archive="$app_dir/data.tar.zst.enc" 474 | if [[ -f "$data_archive" ]]; then 475 | dbg "Extracting data with encryption args: ${encryption_args[*]}" 476 | decrypt_file "$app_dir/data.tar.zst.enc" | \ 477 | zstd -d -T0 - | \ 478 | progress_cmd | \ 479 | tar -C "$out_root_dir" -xf - 480 | else 481 | echo "No data backup found" 482 | fi 483 | 484 | # Fix ownership 485 | dbg "Updating data owner to $uid" 486 | chown -R "$uid:$uid" "$new_data_dir" "$de_data_dir" 487 | local cache_dirs=("$new_data_dir/"*cache* "$de_data_dir/"*cache*) 488 | if [[ ${#cache_dirs[@]} -ne 0 ]]; then 489 | dbg "Updating cache owner group to $gid_cache" 490 | chown -R "$uid:$gid_cache" "$new_data_dir/"*cache* "$de_data_dir/"*cache* 491 | fi 492 | 493 | # Fix SELinux context 494 | dbg "Updating SELinux context to $secontext" 495 | # We need to use Android chcon to avoid "Operation not supported on transport endpoint" errors 496 | /system/bin/chcon -hR "$secontext" "$new_data_dir" "$de_data_dir" 497 | 498 | # Perform in-place Termux hotswap if necessary 499 | if $termux_inplace; then 500 | dbg "Hotswapping Termux data for in-place restore" 501 | 502 | # Swap out the old one immediately and defer cleanup to later 503 | # This does leave a small window during which no directory is present, 504 | # but we can't get around that without using the relatively new 505 | # renameat(2) syscall, which isn't exposed by coreutils. 506 | dbg "Swapping out current data directory" 507 | mv "$data_dir" "$out_root_dir/_old_data" 508 | 509 | # ---------------------- DANGER DANGER DANGER ---------------------- 510 | # We need to be careful with the commands we use here because Termux 511 | # executables are no longer available! This backup script will crash 512 | # and the user will be left with a broken Termux install (among other 513 | # unrestored apps) if anything in here breaks. Only Android system 514 | # executables and shell builtins are safe to use in here. 515 | # ---------------------- DANGER DANGER DANGER ---------------------- 516 | 517 | # Swap in the new one ASAP 518 | # LD_PRELOAD points to a file in Termux, so we need to unset it temporarily 519 | dbg "Switching to new data directory" 520 | (unset LD_PRELOAD; /system/bin/mv "$new_data_dir" "$data_dir") 521 | 522 | # Update cwd for the new directory inode 523 | # Fall back to Termux HOME if cwd doesn't exist in the restored env 524 | dbg "Updating $PWD CWD" 525 | cd "$PWD" || cd "$HOME" 526 | 527 | # Rehash PATH cache since we might have new executable paths now 528 | dbg "Refreshing shell PATH cache" 529 | hash -r 530 | 531 | # Check for the presence of optional commands again 532 | dbg "Re-checking for optional commands" 533 | check_optional_cmds 534 | 535 | # ------------------------- END OF DANGER -------------------------- 536 | # At this point, the backup's Termux install has been restored and 537 | # our shell state has been updated to account for the new environment, 538 | # so we can safely use all commands again. 539 | # ------------------------- END OF DANGER -------------------------- 540 | 541 | # Clean up temporary directory structures and old data directory left 542 | # over from swapping 543 | dbg "Deleting old app data directory" 544 | rm -fr "$out_root_dir" 545 | 546 | # Set flag to print Termux restoration warning 547 | termux_restored=true 548 | fi 549 | 550 | # Permissions 551 | msg " • Other" 552 | local perm 553 | for perm in $(cat "$app_dir/permissions.list") 554 | do 555 | dbg "Granting permission $perm" 556 | pm grant --user 0 "$app" "$perm" || warn "Failed to grant permission $perm!" 557 | done 558 | 559 | # SSAID 560 | if [[ -f "$app_dir/ssaid.xml" ]]; then 561 | dbg "Restoring SSAID: $(cat "$app_dir/ssaid.xml")" 562 | cat "$app_dir/ssaid.xml" >> /data/system/users/0/settings_ssaid.xml 563 | ssaid_restored=true 564 | fi 565 | 566 | # Battery optimization 567 | if [[ -f "$app_dir/battery_opt_disabled" ]]; then 568 | dbg "Whitelisting in deviceidle" 569 | dumpsys deviceidle whitelist "+$app" | expect_output Added 570 | fi 571 | 572 | # Unsuspend app now that restoration is finished 573 | if $suspended; then 574 | dbg "Unsuspending app" 575 | pm unsuspend --user 0 "$app" | expect_output 'new suspended state: false' 576 | fi 577 | 578 | echo 579 | done 580 | } 581 | 582 | # Run action 583 | echo "Performing action '$action'" 584 | if [[ "$action" == "backup" ]]; then 585 | do_backup 586 | elif [[ "$action" == "restore" ]]; then 587 | do_restore 588 | else 589 | die "Unknown action '$action'" 590 | fi 591 | 592 | # Cleanup 593 | rm -fr "$tmp_dir" 594 | 595 | echo 596 | echo 597 | msg "========================" 598 | msg "Backup/restore finished!" 599 | msg "========================" 600 | echo 601 | echo 602 | 603 | if [[ "$ssaid_restored" == "true" ]]; then 604 | warn "SSAIDs were restored 605 | ==================== 606 | Warning: Restored SSAIDs will be lost if you do not reboot IMMEDIATELY!" 607 | fi 608 | 609 | if [[ "$termux_restored" == "true" ]]; then 610 | warn "Termux was restored 611 | =================== 612 | Please restart Termux as soon as possible to apply all changes. 613 | If you cannot restart now, running the 'cd' command will fix your current shell instance." 614 | fi 615 | 616 | if [[ "$app_install_failed" == "true" ]]; then 617 | warn "One or more apps failed to install 618 | ================================== 619 | Some apps failed to install, so data was not restored for them. 620 | You may want to check what happened in case you are expecting their data to be restored." 621 | fi 622 | -------------------------------------------------------------------------------- /termux-quickstart.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # cbackup Termux quickstart script 4 | # https://git.io/cbackup-quick 5 | 6 | # Print executed commands and exit on error 7 | set -ve 8 | 9 | # Install dependencies 10 | pkg install -y tsu tar sed zstd openssl-tool pv curl 11 | 12 | # Download main script 13 | curl -LSsO https://raw.githubusercontent.com/kdrag0n/cbackup/master/cbackup.sh 14 | 15 | # We don't use binfmt_script to here, but add the execute permission so the user can manually run it later 16 | chmod +x cbackup.sh 17 | 18 | # Arguments passed to a `sh -c` pipe start at $0, so we need to include it explicitly 19 | # $0 is set to "bash" if no arguments were specified, so we need to ignore it in that case 20 | if [[ "$0" == "bash" ]]; then 21 | args=("$@") 22 | else 23 | args=("$0" "$@") 24 | fi 25 | 26 | # Finally, run the downloaded script and replace the quickstart script's shell with it 27 | exec sudo bash cbackup.sh "${args[@]}" 28 | --------------------------------------------------------------------------------