├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── libraries │ ├── animated_vector_drawable_25_0_0.xml │ ├── appcompat_v7_25_0_0.xml │ ├── espresso_core_2_2_2.xml │ ├── espresso_idling_resource_2_2_2.xml │ ├── exposed_instrumentation_api_publish_0_5.xml │ ├── hamcrest_core_1_3.xml │ ├── hamcrest_integration_1_3.xml │ ├── hamcrest_library_1_3.xml │ ├── javawriter_2_1_1.xml │ ├── javax_annotation_api_1_2.xml │ ├── javax_inject_1.xml │ ├── jsr305_2_0_1.xml │ ├── junit_4_12.xml │ ├── rules_0_5.xml │ ├── runner_0_5.xml │ ├── support_annotations_25_0_0.xml │ ├── support_compat_25_0_0.xml │ ├── support_core_ui_25_0_0.xml │ ├── support_core_utils_25_0_0.xml │ ├── support_fragment_25_0_0.xml │ ├── support_media_compat_25_0_0.xml │ ├── support_v4_25_0_0.xml │ └── support_vector_drawable_25_0_0.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── pkcs8_rsa_private_key.pem │ ├── rsa_public_key.pem │ └── test.txt │ ├── java │ └── com │ │ └── blakequ │ │ └── rsademo │ │ ├── MainActivity.java │ │ └── javalib │ │ ├── ArrayUtils.java │ │ ├── Base64.java │ │ ├── Base64InputStream.java │ │ ├── Base64OutputStream.java │ │ ├── Base64Utils.java │ │ ├── FileEncryptionManager.java │ │ ├── FileUtils.java │ │ ├── RSAProvider.java │ │ └── Shared.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_grpctest.xml │ ├── activity_main.xml │ └── activity_restest.xml │ ├── menu │ └── main.xml │ ├── values-v11 │ └── styles.xml │ ├── values-v14 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── import-summary.txt ├── rsa ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── blakequ │ │ └── rsa │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── blakequ │ │ │ └── rsa │ │ │ ├── ArrayUtils.java │ │ │ ├── Base64Utils.java │ │ │ ├── FileEncryptionManager.java │ │ │ ├── FileUtils.java │ │ │ └── RSAProvider.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── blakequ │ └── rsa │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | 39 | # Keystore files 40 | *.jks 41 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/libraries/animated_vector_drawable_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/appcompat_v7_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/espresso_core_2_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/espresso_idling_resource_2_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/exposed_instrumentation_api_publish_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_integration_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_library_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/javawriter_2_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/javax_annotation_api_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/javax_inject_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/jsr305_2_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/junit_4_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/rules_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/runner_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/support_annotations_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/support_compat_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_core_ui_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_core_utils_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_fragment_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_media_compat_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_v4_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/support_vector_drawable_25_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 33 | 34 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Android 46 | 47 | 48 | Android > Lint > Correctness 49 | 50 | 51 | Android > Lint > Performance 52 | 53 | 54 | Java 55 | 56 | 57 | Java language level migration aidsJava 58 | 59 | 60 | 61 | 62 | Android 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 84 | 85 | C:\Users\PLUSUB\AppData\Roaming\Subversion 86 | 87 | 88 | 89 | 90 | 91 | 92 | 97 | 98 | 99 | 100 | 101 | 102 | 1.7 103 | 104 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-rsa 2 | rsa encryption and decryption by android 3 | 4 | [![License][licence_svg]][licence_url] 5 | [![Download][bintray_svg]][bintray_url] 6 | 7 | # Import 8 | add to build.gradle,${latest.version} is [![Download][bintray_svg]][bintray_url] 9 | ``` 10 | dependencies { 11 | compile 'com.blakequ.rsa:rsa:${latest.version}' 12 | } 13 | ``` 14 | maven 15 | ``` 16 | 17 | com.blakequ.rsa 18 | rsa 19 | ${latest.version} 20 | pom 21 | 22 | ``` 23 | 24 | 25 | # How to use 26 | you can download example and study how to use 27 | 28 | For server code, you can find in example:com/blakequ/rsademo/javalib 29 | 30 | ## 1. set key 31 | 32 | ``` 33 | FileEncryptionManager mFileEncryptionManager = FileEncryptionManager.getInstance(); 34 | //1.you can use generate public and private key 35 | mFileEncryptionManager.generateKey(); 36 | //you can invoke getPublickey() and getPrivateKey() to save key to local file 37 | 38 | //or 2.set public key and private key by youself(not use auto generate key) 39 | mFileEncryptionManager.setRSAKey(String publicKey, String privateKey); 40 | mFileEncryptionManager.setRSAKey(RSAPublicKey publicKey, RSAPrivateKey privateKey) 41 | ``` 42 | 43 | ## 2. encrypt file or data 44 | ``` 45 | byte[] data = FileUtils.getBytesFromInputStream(getResources().getAssets().open("*.txt")); 46 | //from byte array 47 | byte[] result = mFileEncryptionManager.encryptFileByPublicKey(data, saveEncryFile); 48 | //or from file 49 | byte[] result = mFileEncryptionManager.encryptFileByPublicKey(ogirialFile, saveEncryFile); 50 | ``` 51 | 52 | ## 3. decrypt file or data 53 | ``` 54 | byte[] result = mFileEncryptionManager.decryptFileByPrivateKey(encryFile, decryFile); 55 | byte[] result = mFileEncryptionManager.decryptFileByPrivateKey(encryByteData, decryFile); 56 | ``` 57 | 58 | # link 59 | - [BLOG](www.blakequ.com) 60 | - [JAVA_RSA](https://github.com/kobezone/java-android-rsa) 61 | 62 | 63 | [bintray_svg]: https://api.bintray.com/packages/haodynasty/maven/AndroidRSA/images/download.svg 64 | [bintray_url]: https://bintray.com/haodynasty/maven/AndroidRSA/_latestVersion 65 | [licence_svg]: https://img.shields.io/badge/license-Apache%202-green.svg 66 | [licence_url]: https://www.apache.org/licenses/LICENSE-2.0 -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.blakequ.rsademo" 9 | minSdkVersion 18 10 | targetSdkVersion 25 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | lintOptions { 21 | disable 'InvalidPackage' 22 | } 23 | } 24 | 25 | dependencies { 26 | compile 'com.android.support:appcompat-v7:25.0.0' 27 | // compile 'com.blakequ.rsa:rsa:1.1' 28 | compile project(':rsa') 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/assets/pkcs8_rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ9FN1w8gfXSBP1/ 3 | fWtC4gicvB7t+XZ20Qn3eBOaMT1zYf6QtUQ1aAQKIlVDmyidA1/BOgwp07Rvc6V/ 4 | imAEp4tOGtrP8vedgliVuqMcLeNONSdlzSW66alcayjHrb4+5IYGV9vzMk7qGLHg 5 | ZX++HJBUKkb1piqATvPJNFlhf1vJAgMBAAECgYA736xhG0oL3EkN9yhx8zG/5RP/ 6 | WJzoQOByq7pTPCr4m/Ch30qVerJAmoKvpPumN+h1zdEBk5PHiAJkm96sG/PTndEf 7 | kZrAJ2hwSBqptcABYk6ED70gRTQ1S53tyQXIOSjRBcugY/21qeswS3nMyq3xDEPK 8 | XpdyKPeaTyuK86AEkQJBAM1M7p1lfzEKjNw17SDMLnca/8pBcA0EEcyvtaQpRvaL 9 | n61eQQnnPdpvHamkRBcOvgCAkfwa1uboru0QdXii/gUCQQDGmkP+KJPX9JVCrbRt 10 | 7wKyIemyNM+J6y1ZBZ2bVCf9jacCQaSkIWnIR1S9UM+1CFE30So2CA0CfCDmQy+y 11 | 7A31AkB8cGFB7j+GTkrLP7SX6KtRboAU7E0q1oijdO24r3xf/Imw4Cy0AAIx4KAu 12 | L29GOp1YWJYkJXCVTfyZnRxXHxSxAkEAvO0zkSv4uI8rDmtAIPQllF8+eRBT/deD 13 | JBR7ga/k+wctwK/Bd4Fxp9xzeETP0l8/I+IOTagK+Dos8d8oGQUFoQJBAI4Nwpfo 14 | MFaLJXGY9ok45wXrcqkJgM+SN6i8hQeujXESVHYatAIL/1DgLi+u46EFD69fw0w+ 15 | c7o0HLlMsYPAzJw= 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /app/src/main/assets/rsa_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfRTdcPIH10gT9f31rQuIInLwe 3 | 7fl2dtEJ93gTmjE9c2H+kLVENWgECiJVQ5sonQNfwToMKdO0b3Olf4pgBKeLThra 4 | z/L3nYJYlbqjHC3jTjUnZc0luumpXGsox62+PuSGBlfb8zJO6hix4GV/vhyQVCpG 5 | 9aYqgE7zyTRZYX9byQIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /app/src/main/assets/test.txt: -------------------------------------------------------------------------------- 1 | --#start#! /usr/local/bin/lua 2 | 3 | -- Created by IntelliJ IDEA. 4 | -- User: quhao 5 | -- Date: 2015/10/16 6 | -- Time: 11:41 7 | -- To change this template use File | Settings | File Templates. 8 | 9 | --[[---------------globle var and method-----------------------------------------]] 10 | -- the array max length, you can define 11 | -----------Print 函数重写--------------------- -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.os.Environment; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | import android.widget.TextView; 12 | 13 | import com.blakequ.rsa.Base64Utils; 14 | import com.blakequ.rsa.FileEncryptionManager; 15 | import com.blakequ.rsa.FileUtils; 16 | import com.blakequ.rsa.RSAProvider; 17 | 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | 21 | public class MainActivity extends AppCompatActivity implements View.OnClickListener 22 | { 23 | private Button btn1, btn2,btn_click,btn_click2;// 加密,解密 24 | private EditText et1, et2, et3;// 需加密的内容,加密后的内容,解密后的内容 25 | private TextView mTvInfo; 26 | String publicKey, privateKey; 27 | File saveEncryPath, saveDecryPath; 28 | FileEncryptionManager mFileEncryptionManager; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) 32 | { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | initView(); 36 | mFileEncryptionManager = FileEncryptionManager.getInstance(); 37 | File sdcard = Environment.getExternalStorageDirectory(); 38 | saveEncryPath = new File(sdcard.getPath()+"/diapers_encry.txt"); 39 | saveDecryPath = new File(sdcard.getPath()+"/diapers_decry.txt"); 40 | //1.生成秘钥 41 | try { 42 | //自动生成 43 | mFileEncryptionManager.generateKey(); 44 | publicKey = mFileEncryptionManager.getPublicKey(); 45 | privateKey = mFileEncryptionManager.getPrivateKey(); 46 | //也可以从文件读取 47 | // InputStream inPublic = getResources().getAssets().open("rsa_public_key.pem"); 48 | // privateKey = FileUtils.readString(inPublic); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | 54 | private void initView() 55 | { 56 | btn1 = (Button) findViewById(R.id.btn1); 57 | btn2 = (Button) findViewById(R.id.btn2); 58 | btn1.setOnClickListener(this); 59 | btn2.setOnClickListener(this); 60 | btn_click = (Button) findViewById(R.id.btn_click); 61 | btn_click.setOnClickListener(this); 62 | btn_click2 = (Button) findViewById(R.id.btn_click2); 63 | btn_click2.setOnClickListener(this); 64 | et1 = (EditText) findViewById(R.id.et1); 65 | et2 = (EditText) findViewById(R.id.et2); 66 | et3 = (EditText) findViewById(R.id.et3); 67 | mTvInfo = (TextView) findViewById(R.id.tv_info); 68 | } 69 | 70 | @Override 71 | public void onClick(View v) 72 | { 73 | switch (v.getId()) 74 | { 75 | // 加密 76 | case R.id.btn1: 77 | String source = et1.getText().toString().trim(); 78 | try 79 | { 80 | // 加密 81 | byte[] encryptByte = mFileEncryptionManager.encryptByPublicKey(source.getBytes()); 82 | // 为了方便观察吧加密后的数据用base64加密转一下,要不然看起来是乱码,所以解密是也是要用Base64先转换 83 | String afterencrypt = Base64Utils.encode(encryptByte); 84 | et2.setText(afterencrypt); 85 | } catch (Exception e) 86 | { 87 | e.printStackTrace(); 88 | } 89 | break; 90 | // 解密 91 | case R.id.btn2: 92 | String encryptContent = et2.getText().toString().trim(); 93 | try 94 | { 95 | // 因为RSA加密后的内容经Base64再加密转换了一下,所以先Base64解密回来再给RSA解密 96 | byte[] decryptByte = mFileEncryptionManager.decryptByPrivateKey(Base64Utils.decode(encryptContent)); 97 | et3.setText(new String(decryptByte)); 98 | } catch (Exception e) 99 | { 100 | e.printStackTrace(); 101 | } 102 | break; 103 | case R.id.btn_click: 104 | try { 105 | //公钥加密 106 | byte[] data = FileUtils.getBytesFromInputStream(getResources().getAssets().open("test.txt")); 107 | Log.e("MainActivity", "---------\n加密前数据:"+new String(data, "UTF-8")); 108 | long start=System.currentTimeMillis(); 109 | byte[] result = mFileEncryptionManager.encryptFileByPublicKey(data, saveEncryPath); 110 | long end=System.currentTimeMillis(); 111 | Log.e("MainActivity","公钥加密耗时 cost time---->"+(end-start)); 112 | Log.e("MainActivity","加密后数据---->\n"+new String(result, "UTF-8")); 113 | } catch (Exception e) { 114 | e.printStackTrace(); 115 | } 116 | break; 117 | case R.id.btn_click2: 118 | try { 119 | //私钥解密 120 | byte[] data = FileUtils.getBytesFromInputStream(new FileInputStream(saveEncryPath)); 121 | Log.e("MainActivity", "--------------\n解密前数据:"+new String(data, "UTF-8")); 122 | long start=System.currentTimeMillis(); 123 | byte[] result = mFileEncryptionManager.decryptFileByPrivateKey(saveEncryPath, saveDecryPath); 124 | long end=System.currentTimeMillis(); 125 | Log.e("MainActivity","私钥解密耗时 cost time---->"+(end-start)); 126 | Log.e("MainActivity","解密后数据---->\n"+new String(result, "UTF-8")); 127 | } catch (Exception e) { 128 | e.printStackTrace(); 129 | } 130 | break; 131 | default: 132 | break; 133 | } 134 | } 135 | 136 | public void test() { 137 | try { 138 | System.err.println("公钥加密——私钥解密"); 139 | String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗111?"; 140 | System.out.println("\r加密前文字:\r\n" + source); 141 | byte[] data = source.getBytes(); 142 | // byte[] encodedData = RSAUtils.encryptSimpleData(data, RSAUtils.loadPublicKey(PUBLICKEY)); 143 | byte[] encodedData = RSAProvider.encryptPublicKey(data, publicKey); 144 | System.out.println("加密后文字:\r\n" + new String(encodedData)); 145 | Log.e("MainActivity","加密前后数据长度 "+data.length+"-->"+encodedData.length); 146 | // byte[] decodedData = RSAUtils.decryptSimpleData(encodedData, RSAUtils.loadPrivateKey(PRIVATEKEY)); 147 | byte[] decodedData = RSAProvider.decryptPrivateKey(encodedData, privateKey); 148 | String target = new String(decodedData); 149 | System.out.println("解密后文字: " + target); 150 | }catch (Exception e){ 151 | Log.e("System", "test: 解密失败" ); 152 | e.printStackTrace(); 153 | } 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo.javalib; 2 | 3 | /** 4 | *

Operations on arrays, primitive arrays (like {@code int[]}) and 5 | * primitive wrapper arrays (like {@code Integer[]}). 6 | * 7 | *

This class tries to handle {@code null} input gracefully. 8 | * An exception will not be thrown for a {@code null} 9 | * array input. However, an Object array that contains a {@code null} 10 | * element may throw an exception. Each method documents its behaviour. 11 | * 12 | *

#ThreadSafe# 13 | * @since 2.0 14 | */ 15 | 16 | public class ArrayUtils { 17 | 18 | /** 19 | * An empty immutable {@code byte} array. 20 | */ 21 | public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 22 | 23 | 24 | /** 25 | * Copies the specified range of the specified array into a new array. 26 | * The initial index of the range (from) must lie between zero 27 | * and original.length, inclusive. The value at 28 | * original[from] is placed into the initial element of the copy 29 | * (unless from == original.length or from == to). 30 | * Values from subsequent elements in the original array are placed into 31 | * subsequent elements in the copy. The final index of the range 32 | * (to), which must be greater than or equal to from, 33 | * may be greater than original.length, in which case 34 | * (byte)0 is placed in all elements of the copy whose index is 35 | * greater than or equal to original.length - from. The length 36 | * of the returned array will be to - from. 37 | * 38 | * @param original the array from which a range is to be copied 39 | * @param from the initial index of the range to be copied, inclusive 40 | * @param to the final index of the range to be copied, exclusive. 41 | * (This index may lie outside the array.) 42 | * @return a new array containing the specified range from the original array, 43 | * truncated or padded with zeros to obtain the required length 44 | * @throws ArrayIndexOutOfBoundsException if {@code from < 0} 45 | * or {@code from > original.length} 46 | * @throws IllegalArgumentException if from > to 47 | * @throws NullPointerException if original is null 48 | * @since 1.6 49 | */ 50 | public static byte[] copyOfRange(byte[] original, int from, int to) { 51 | int newLength = to - from; 52 | if (newLength < 0) 53 | throw new IllegalArgumentException(from + " > " + to); 54 | byte[] copy = new byte[newLength]; 55 | System.arraycopy(original, from, copy, 0, 56 | Math.min(original.length - from, newLength)); 57 | return copy; 58 | } 59 | 60 | /** 61 | *

Produces a new {@code byte} array containing the elements 62 | * between the start and end indices. 63 | * 64 | *

The start index is inclusive, the end index exclusive. 65 | * Null array input produces null output. 66 | * 67 | * @param array the array 68 | * @param startIndexInclusive the starting index. Undervalue (<0) 69 | * is promoted to 0, overvalue (>array.length) results 70 | * in an empty array. 71 | * @param endIndexExclusive elements up to endIndex-1 are present in the 72 | * returned subarray. Undervalue (< startIndex) produces 73 | * empty array, overvalue (>array.length) is demoted to 74 | * array length. 75 | * @return a new array containing the elements between 76 | * the start and end indices. 77 | * @since 2.1 78 | */ 79 | public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) { 80 | if (array == null) { 81 | return null; 82 | } 83 | if (startIndexInclusive < 0) { 84 | startIndexInclusive = 0; 85 | } 86 | if (endIndexExclusive > array.length) { 87 | endIndexExclusive = array.length; 88 | } 89 | final int newSize = endIndexExclusive - startIndexInclusive; 90 | if (newSize <= 0) { 91 | return EMPTY_BYTE_ARRAY; 92 | } 93 | 94 | final byte[] subarray = new byte[newSize]; 95 | System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); 96 | return subarray; 97 | } 98 | 99 | /** 100 | *

Adds all the elements of the given arrays into a new array. 101 | *

The new array contains all of the element of {@code array1} followed 102 | * by all of the elements {@code array2}. When an array is returned, it is always 103 | * a new array. 104 | * 105 | *

106 |      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
107 |      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
108 |      * ArrayUtils.addAll([], [])         = []
109 |      * 
110 | * 111 | * @param array1 the first array whose elements are added to the new array. 112 | * @param array2 the second array whose elements are added to the new array. 113 | * @return The new byte[] array. 114 | * @since 2.1 115 | */ 116 | public static byte[] addAll(final byte[] array1, final byte... array2) { 117 | if (array1 == null) { 118 | return clone(array2); 119 | } else if (array2 == null) { 120 | return clone(array1); 121 | } 122 | final byte[] joinedArray = new byte[array1.length + array2.length]; 123 | System.arraycopy(array1, 0, joinedArray, 0, array1.length); 124 | System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); 125 | return joinedArray; 126 | } 127 | 128 | /** 129 | *

Clones an array returning a typecast result and handling 130 | * {@code null}. 131 | * 132 | *

This method returns {@code null} for a {@code null} input array. 133 | * 134 | * @param array the array to clone, may be {@code null} 135 | * @return the cloned array, {@code null} if {@code null} input 136 | */ 137 | public static byte[] clone(final byte[] array) { 138 | if (array == null) { 139 | return null; 140 | } 141 | return array.clone(); 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/Base64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java Base64 - A pure Java library for reading and writing Base64 3 | * encoded streams. 4 | * 5 | * Copyright (C) 2007-2009 Carlo Pelliccia (www.sauronsoftware.it) 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License version 9 | * 2.1, as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License version 2.1 along with this program. 18 | * If not, see . 19 | */ 20 | package com.blakequ.rsademo.javalib; 21 | 22 | import java.io.ByteArrayInputStream; 23 | import java.io.ByteArrayOutputStream; 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | import java.io.FileOutputStream; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.OutputStream; 30 | import java.io.UnsupportedEncodingException; 31 | 32 | /** 33 | *

34 | * Base64 encoding and decoding utility methods, both for binary and textual 35 | * informations. 36 | *

37 | * 38 | * @author Carlo Pelliccia 39 | * @since 1.1 40 | * @version 1.3 41 | */ 42 | public class Base64 { 43 | 44 | /** 45 | *

46 | * Encodes a string. 47 | *

48 | *

49 | * Before the string is encoded in Base64, it is converted in a binary 50 | * sequence using the system default charset. 51 | *

52 | * 53 | * @param str 54 | * The source string. 55 | * @return The encoded string. 56 | * @throws RuntimeException 57 | * If an unexpected error occurs. 58 | */ 59 | public static String encode(String str) throws RuntimeException { 60 | byte[] bytes = str.getBytes(); 61 | byte[] encoded = encode(bytes); 62 | try { 63 | return new String(encoded, "ASCII"); 64 | } catch (UnsupportedEncodingException e) { 65 | throw new RuntimeException("ASCII is not supported!", e); 66 | } 67 | } 68 | 69 | /** 70 | *

71 | * Encodes a string. 72 | *

73 | *

74 | * Before the string is encoded in Base64, it is converted in a binary 75 | * sequence using the supplied charset. 76 | *

77 | * 78 | * @param str 79 | * The source string 80 | * @param charset 81 | * The charset name. 82 | * @return The encoded string. 83 | * @throws RuntimeException 84 | * If an unexpected error occurs. 85 | * @since 1.2 86 | */ 87 | public static String encode(String str, String charset) 88 | throws RuntimeException { 89 | byte[] bytes; 90 | try { 91 | bytes = str.getBytes(charset); 92 | } catch (UnsupportedEncodingException e) { 93 | throw new RuntimeException("Unsupported charset: " + charset, e); 94 | } 95 | byte[] encoded = encode(bytes); 96 | try { 97 | return new String(encoded, "ASCII"); 98 | } catch (UnsupportedEncodingException e) { 99 | throw new RuntimeException("ASCII is not supported!", e); 100 | } 101 | } 102 | 103 | /** 104 | *

105 | * Decodes the supplied string. 106 | *

107 | *

108 | * The supplied string is decoded into a binary sequence, and then the 109 | * sequence is encoded with the system default charset and returned. 110 | *

111 | * 112 | * @param str 113 | * The encoded string. 114 | * @return The decoded string. 115 | * @throws RuntimeException 116 | * If an unexpected error occurs. 117 | */ 118 | public static String decode(String str) throws RuntimeException { 119 | byte[] bytes; 120 | try { 121 | bytes = str.getBytes("ASCII"); 122 | } catch (UnsupportedEncodingException e) { 123 | throw new RuntimeException("ASCII is not supported!", e); 124 | } 125 | byte[] decoded = decode(bytes); 126 | return new String(decoded); 127 | } 128 | 129 | /** 130 | *

131 | * Decodes the supplied string. 132 | *

133 | *

134 | * The supplied string is decoded into a binary sequence, and then the 135 | * sequence is encoded with the supplied charset and returned. 136 | *

137 | * 138 | * @param str 139 | * The encoded string. 140 | * @param charset 141 | * The charset name. 142 | * @return The decoded string. 143 | * @throws RuntimeException 144 | * If an unexpected error occurs. 145 | * @since 1.2 146 | */ 147 | public static String decode(String str, String charset) 148 | throws RuntimeException { 149 | byte[] bytes; 150 | try { 151 | bytes = str.getBytes("ASCII"); 152 | } catch (UnsupportedEncodingException e) { 153 | throw new RuntimeException("ASCII is not supported!", e); 154 | } 155 | byte[] decoded = decode(bytes); 156 | try { 157 | return new String(decoded, charset); 158 | } catch (UnsupportedEncodingException e) { 159 | throw new RuntimeException("Unsupported charset: " + charset, e); 160 | } 161 | } 162 | 163 | /** 164 | *

165 | * Encodes a binary sequence. 166 | *

167 | *

168 | * If data are large, i.e. if you are working with large binary files, 169 | * consider to use a {@link Base64OutputStream} instead of loading too much 170 | * data in memory. 171 | *

172 | * 173 | * @param bytes 174 | * The source sequence. 175 | * @return The encoded sequence. 176 | * @throws RuntimeException 177 | * If an unexpected error occurs. 178 | * @since 1.2 179 | */ 180 | public static byte[] encode(byte[] bytes) throws RuntimeException { 181 | return encode(bytes, 0); 182 | } 183 | 184 | /** 185 | *

186 | * Encodes a binary sequence, wrapping every encoded line every 187 | * wrapAt characters. A wrapAt value less than 1 disables 188 | * wrapping. 189 | *

190 | *

191 | * If data are large, i.e. if you are working with large binary files, 192 | * consider to use a {@link Base64OutputStream} instead of loading too much 193 | * data in memory. 194 | *

195 | * 196 | * @param bytes 197 | * The source sequence. 198 | * @param wrapAt 199 | * The max line length for encoded data. If less than 1 no wrap 200 | * is applied. 201 | * @return The encoded sequence. 202 | * @throws RuntimeException 203 | * If an unexpected error occurs. 204 | * @since 1.2 205 | */ 206 | public static byte[] encode(byte[] bytes, int wrapAt) 207 | throws RuntimeException { 208 | ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); 209 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 210 | try { 211 | encode(inputStream, outputStream, wrapAt); 212 | } catch (IOException e) { 213 | throw new RuntimeException("Unexpected I/O error", e); 214 | } finally { 215 | try { 216 | inputStream.close(); 217 | } catch (Throwable t) { 218 | ; 219 | } 220 | try { 221 | outputStream.close(); 222 | } catch (Throwable t) { 223 | ; 224 | } 225 | } 226 | return outputStream.toByteArray(); 227 | } 228 | 229 | /** 230 | *

231 | * Decodes a binary sequence. 232 | *

233 | *

234 | * If data are large, i.e. if you are working with large binary files, 235 | * consider to use a {@link Base64InputStream} instead of loading too much 236 | * data in memory. 237 | *

238 | * 239 | * @param bytes 240 | * The encoded sequence. 241 | * @return The decoded sequence. 242 | * @throws RuntimeException 243 | * If an unexpected error occurs. 244 | * @since 1.2 245 | */ 246 | public static byte[] decode(byte[] bytes) throws RuntimeException { 247 | ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); 248 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 249 | try { 250 | decode(inputStream, outputStream); 251 | } catch (IOException e) { 252 | throw new RuntimeException("Unexpected I/O error", e); 253 | } finally { 254 | try { 255 | inputStream.close(); 256 | } catch (Throwable t) { 257 | ; 258 | } 259 | try { 260 | outputStream.close(); 261 | } catch (Throwable t) { 262 | ; 263 | } 264 | } 265 | return outputStream.toByteArray(); 266 | } 267 | 268 | /** 269 | *

270 | * Encodes data from the given input stream and writes them in the given 271 | * output stream. 272 | *

273 | *

274 | * The supplied input stream is read until its end is reached, but it's not 275 | * closed by this method. 276 | *

277 | *

278 | * The supplied output stream is nor flushed neither closed by this method. 279 | *

280 | * 281 | * @param inputStream 282 | * The input stream. 283 | * @param outputStream 284 | * The output stream. 285 | * @throws IOException 286 | * If an I/O error occurs. 287 | */ 288 | public static void encode(InputStream inputStream, OutputStream outputStream) 289 | throws IOException { 290 | encode(inputStream, outputStream, 0); 291 | } 292 | 293 | /** 294 | *

295 | * Encodes data from the given input stream and writes them in the given 296 | * output stream, wrapping every encoded line every wrapAt 297 | * characters. A wrapAt value less than 1 disables wrapping. 298 | *

299 | *

300 | * The supplied input stream is read until its end is reached, but it's not 301 | * closed by this method. 302 | *

303 | *

304 | * The supplied output stream is nor flushed neither closed by this method. 305 | *

306 | * 307 | * @param inputStream 308 | * The input stream from which clear data are read. 309 | * @param outputStream 310 | * The output stream in which encoded data are written. 311 | * @param wrapAt 312 | * The max line length for encoded data. If less than 1 no wrap 313 | * is applied. 314 | * @throws IOException 315 | * If an I/O error occurs. 316 | */ 317 | public static void encode(InputStream inputStream, 318 | OutputStream outputStream, int wrapAt) throws IOException { 319 | Base64OutputStream aux = new Base64OutputStream(outputStream, wrapAt); 320 | copy(inputStream, aux); 321 | aux.commit(); 322 | } 323 | 324 | /** 325 | *

326 | * Decodes data from the given input stream and writes them in the given 327 | * output stream. 328 | *

329 | *

330 | * The supplied input stream is read until its end is reached, but it's not 331 | * closed by this method. 332 | *

333 | *

334 | * The supplied output stream is nor flushed neither closed by this method. 335 | *

336 | * 337 | * @param inputStream 338 | * The input stream from which encoded data are read. 339 | * @param outputStream 340 | * The output stream in which decoded data are written. 341 | * @throws IOException 342 | * If an I/O error occurs. 343 | */ 344 | public static void decode(InputStream inputStream, OutputStream outputStream) 345 | throws IOException { 346 | copy(new Base64InputStream(inputStream), outputStream); 347 | } 348 | 349 | /** 350 | *

351 | * Encodes data from the given source file contents and writes them in the 352 | * given target file, wrapping every encoded line every wrapAt 353 | * characters. A wrapAt value less than 1 disables wrapping. 354 | *

355 | * 356 | * @param source 357 | * The source file, from which decoded data are read. 358 | * @param target 359 | * The target file, in which encoded data are written. 360 | * @param wrapAt 361 | * The max line length for encoded data. If less than 1 no wrap 362 | * is applied. 363 | * @throws IOException 364 | * If an I/O error occurs. 365 | * @since 1.3 366 | */ 367 | public static void encode(File source, File target, int wrapAt) 368 | throws IOException { 369 | InputStream inputStream = null; 370 | OutputStream outputStream = null; 371 | try { 372 | inputStream = new FileInputStream(source); 373 | outputStream = new FileOutputStream(target); 374 | Base64.encode(inputStream, outputStream, wrapAt); 375 | } finally { 376 | if (outputStream != null) { 377 | try { 378 | outputStream.close(); 379 | } catch (Throwable t) { 380 | ; 381 | } 382 | } 383 | if (inputStream != null) { 384 | try { 385 | inputStream.close(); 386 | } catch (Throwable t) { 387 | ; 388 | } 389 | } 390 | } 391 | } 392 | 393 | /** 394 | *

395 | * Encodes data from the given source file contents and writes them in the 396 | * given target file. 397 | *

398 | * 399 | * @param source 400 | * The source file, from which decoded data are read. 401 | * @param target 402 | * The target file, in which encoded data are written. 403 | * @throws IOException 404 | * If an I/O error occurs. 405 | * @since 1.3 406 | */ 407 | public static void encode(File source, File target) throws IOException { 408 | InputStream inputStream = null; 409 | OutputStream outputStream = null; 410 | try { 411 | inputStream = new FileInputStream(source); 412 | outputStream = new FileOutputStream(target); 413 | Base64.encode(inputStream, outputStream); 414 | } finally { 415 | if (outputStream != null) { 416 | try { 417 | outputStream.close(); 418 | } catch (Throwable t) { 419 | ; 420 | } 421 | } 422 | if (inputStream != null) { 423 | try { 424 | inputStream.close(); 425 | } catch (Throwable t) { 426 | ; 427 | } 428 | } 429 | } 430 | } 431 | 432 | /** 433 | *

434 | * Decodes data from the given source file contents and writes them in the 435 | * given target file. 436 | *

437 | * 438 | * @param source 439 | * The source file, from which encoded data are read. 440 | * @param target 441 | * The target file, in which decoded data are written. 442 | * @throws IOException 443 | * If an I/O error occurs. 444 | * @since 1.3 445 | */ 446 | public static void decode(File source, File target) throws IOException { 447 | InputStream inputStream = null; 448 | OutputStream outputStream = null; 449 | try { 450 | inputStream = new FileInputStream(source); 451 | outputStream = new FileOutputStream(target); 452 | decode(inputStream, outputStream); 453 | } finally { 454 | if (outputStream != null) { 455 | try { 456 | outputStream.close(); 457 | } catch (Throwable t) { 458 | ; 459 | } 460 | } 461 | if (inputStream != null) { 462 | try { 463 | inputStream.close(); 464 | } catch (Throwable t) { 465 | ; 466 | } 467 | } 468 | } 469 | } 470 | 471 | /** 472 | * Copies data from a stream to another. 473 | * 474 | * @param inputStream 475 | * The input stream. 476 | * @param outputStream 477 | * The output stream. 478 | * @throws IOException 479 | * If a unexpected I/O error occurs. 480 | */ 481 | private static void copy(InputStream inputStream, OutputStream outputStream) 482 | throws IOException { 483 | // 1KB buffer 484 | byte[] b = new byte[1024]; 485 | int len; 486 | while ((len = inputStream.read(b)) != -1) { 487 | outputStream.write(b, 0, len); 488 | } 489 | } 490 | 491 | } 492 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/Base64InputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java Base64 - A pure Java library for reading and writing Base64 3 | * encoded streams. 4 | * 5 | * Copyright (C) 2007-2009 Carlo Pelliccia (www.sauronsoftware.it) 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License version 9 | * 2.1, as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License version 2.1 along with this program. 18 | * If not, see . 19 | */ 20 | package com.blakequ.rsademo.javalib; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | /** 26 | *

27 | * A base64 encoding input stream. 28 | *

29 | * 30 | *

31 | * A Base64InputStream reads from an underlying stream which is 32 | * supposed to be a base64 encoded stream. Base64InputStream decodes 33 | * the data read from the underlying stream and returns the decoded bytes to the 34 | * caller. 35 | *

36 | * 37 | * @author Carlo Pelliccia 38 | */ 39 | public class Base64InputStream extends InputStream { 40 | 41 | /** 42 | * The underlying stream. 43 | */ 44 | private InputStream inputStream; 45 | 46 | /** 47 | * The buffer. 48 | */ 49 | private int[] buffer; 50 | 51 | /** 52 | * A counter for values in the buffer. 53 | */ 54 | private int bufferCounter = 0; 55 | 56 | /** 57 | * End-of-stream flag. 58 | */ 59 | private boolean eof = false; 60 | 61 | /** 62 | *

63 | * It builds a base64 decoding input stream. 64 | *

65 | * 66 | * @param inputStream 67 | * The underlying stream, from which the encoded data is read. 68 | */ 69 | public Base64InputStream(InputStream inputStream) { 70 | this.inputStream = inputStream; 71 | } 72 | 73 | public int read() throws IOException { 74 | if (buffer == null || bufferCounter == buffer.length) { 75 | if (eof) { 76 | return -1; 77 | } 78 | acquire(); 79 | if (buffer.length == 0) { 80 | buffer = null; 81 | return -1; 82 | } 83 | bufferCounter = 0; 84 | } 85 | return buffer[bufferCounter++]; 86 | } 87 | 88 | /** 89 | * Reads from the underlying stream, decodes the data and puts the decoded 90 | * bytes into the buffer. 91 | */ 92 | private void acquire() throws IOException { 93 | char[] four = new char[4]; 94 | int i = 0; 95 | do { 96 | int b = inputStream.read(); 97 | if (b == -1) { 98 | if (i != 0) { 99 | throw new IOException("Bad base64 stream"); 100 | } else { 101 | buffer = new int[0]; 102 | eof = true; 103 | return; 104 | } 105 | } 106 | char c = (char) b; 107 | if (Shared.chars.indexOf(c) != -1 || c == Shared.pad) { 108 | four[i++] = c; 109 | } else if (c != '\r' && c != '\n') { 110 | throw new IOException("Bad base64 stream"); 111 | } 112 | } while (i < 4); 113 | boolean padded = false; 114 | for (i = 0; i < 4; i++) { 115 | if (four[i] != Shared.pad) { 116 | if (padded) { 117 | throw new IOException("Bad base64 stream"); 118 | } 119 | } else { 120 | if (!padded) { 121 | padded = true; 122 | } 123 | } 124 | } 125 | int l; 126 | if (four[3] == Shared.pad) { 127 | if (inputStream.read() != -1) { 128 | throw new IOException("Bad base64 stream"); 129 | } 130 | eof = true; 131 | if (four[2] == Shared.pad) { 132 | l = 1; 133 | } else { 134 | l = 2; 135 | } 136 | } else { 137 | l = 3; 138 | } 139 | int aux = 0; 140 | for (i = 0; i < 4; i++) { 141 | if (four[i] != Shared.pad) { 142 | aux = aux | (Shared.chars.indexOf(four[i]) << (6 * (3 - i))); 143 | } 144 | } 145 | buffer = new int[l]; 146 | for (i = 0; i < l; i++) { 147 | buffer[i] = (aux >>> (8 * (2 - i))) & 0xFF; 148 | } 149 | } 150 | 151 | public void close() throws IOException { 152 | inputStream.close(); 153 | } 154 | } -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/Base64OutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java Base64 - A pure Java library for reading and writing Base64 3 | * encoded streams. 4 | * 5 | * Copyright (C) 2007-2009 Carlo Pelliccia (www.sauronsoftware.it) 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License version 9 | * 2.1, as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License version 2.1 along with this program. 18 | * If not, see . 19 | */ 20 | package com.blakequ.rsademo.javalib; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | 25 | /** 26 | *

27 | * A base64 decoding output stream. 28 | *

29 | * 30 | *

31 | * It encodes in base64 everything passed to the stream, and it puts the encoded 32 | * data into the underlying stream. 33 | *

34 | * 35 | * @author Carlo Pelliccia 36 | */ 37 | public class Base64OutputStream extends OutputStream { 38 | 39 | /** 40 | * The underlying stream. 41 | */ 42 | private OutputStream outputStream = null; 43 | 44 | /** 45 | * A value buffer. 46 | */ 47 | private int buffer = 0; 48 | 49 | /** 50 | * How many bytes are currently in the value buffer? 51 | */ 52 | private int bytecounter = 0; 53 | 54 | /** 55 | * A counter for the current line length. 56 | */ 57 | private int linecounter = 0; 58 | 59 | /** 60 | * The requested line length. 61 | */ 62 | private int linelength = 0; 63 | 64 | /** 65 | *

66 | * It builds a base64 encoding output stream writing the encoded data in the 67 | * given underlying stream. 68 | *

69 | * 70 | *

71 | * The encoded data is wrapped to a new line (with a CRLF sequence) every 76 72 | * bytes sent to the underlying stream. 73 | *

74 | * 75 | * @param outputStream 76 | * The underlying stream. 77 | */ 78 | public Base64OutputStream(OutputStream outputStream) { 79 | this(outputStream, 76); 80 | } 81 | 82 | /** 83 | *

84 | * It builds a base64 encoding output stream writing the encoded data in the 85 | * given underlying stream. 86 | *

87 | * 88 | *

89 | * The encoded data is wrapped to a new line (with a CRLF sequence) every 90 | * wrapAt bytes sent to the underlying stream. If the 91 | * wrapAt supplied value is less than 1 the encoded data will not 92 | * be wrapped. 93 | *

94 | * 95 | * @param outputStream 96 | * The underlying stream. 97 | * @param wrapAt 98 | * The max line length for encoded data. If less than 1 no wrap 99 | * is applied. 100 | */ 101 | public Base64OutputStream(OutputStream outputStream, int wrapAt) { 102 | this.outputStream = outputStream; 103 | this.linelength = wrapAt; 104 | } 105 | 106 | public void write(int b) throws IOException { 107 | int value = (b & 0xFF) << (16 - (bytecounter * 8)); 108 | buffer = buffer | value; 109 | bytecounter++; 110 | if (bytecounter == 3) { 111 | commit(); 112 | } 113 | } 114 | 115 | public void close() throws IOException { 116 | commit(); 117 | outputStream.close(); 118 | } 119 | 120 | /** 121 | *

122 | * It commits 4 bytes to the underlying stream. 123 | *

124 | */ 125 | protected void commit() throws IOException { 126 | if (bytecounter > 0) { 127 | if (linelength > 0 && linecounter == linelength) { 128 | outputStream.write("\r\n".getBytes()); 129 | linecounter = 0; 130 | } 131 | char b1 = Shared.chars.charAt((buffer << 8) >>> 26); 132 | char b2 = Shared.chars.charAt((buffer << 14) >>> 26); 133 | char b3 = (bytecounter < 2) ? Shared.pad : Shared.chars.charAt((buffer << 20) >>> 26); 134 | char b4 = (bytecounter < 3) ? Shared.pad : Shared.chars.charAt((buffer << 26) >>> 26); 135 | outputStream.write(b1); 136 | outputStream.write(b2); 137 | outputStream.write(b3); 138 | outputStream.write(b4); 139 | linecounter += 4; 140 | bytecounter = 0; 141 | buffer = 0; 142 | } 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/Base64Utils.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo.javalib; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | 11 | /** *//** 12 | *

13 | * BASE64编码解码工具包 14 | *

15 | *

16 | * 依赖javabase64-1.3.1.jar 17 | *

18 | * 19 | * @author jun 20 | * @date 2012-5-19 21 | * @version 1.0 22 | */ 23 | public class Base64Utils { 24 | 25 | /** *//** 26 | * 文件读取缓冲区大小 27 | */ 28 | private static final int CACHE_SIZE = 1024; 29 | 30 | /** *//** 31 | *

32 | * BASE64字符串解码为二进制数据 33 | *

34 | * 35 | * @param base64 36 | * @return 37 | * @throws Exception 38 | */ 39 | public static byte[] decode(String base64) throws Exception { 40 | return Base64.decode(base64.getBytes()); 41 | } 42 | 43 | /** *//** 44 | *

45 | * 二进制数据编码为BASE64字符串 46 | *

47 | * 48 | * @param bytes 49 | * @return 50 | * @throws Exception 51 | */ 52 | public static String encode(byte[] bytes) throws Exception { 53 | return new String(Base64.encode(bytes)); 54 | } 55 | 56 | /** *//** 57 | *

58 | * 将文件编码为BASE64字符串 59 | *

60 | *

61 | * 大文件慎用,可能会导致内存溢出 62 | *

63 | * 64 | * @param filePath 文件绝对路径 65 | * @return 66 | * @throws Exception 67 | */ 68 | public static String encodeFile(String filePath) throws Exception { 69 | byte[] bytes = fileToByte(filePath); 70 | return encode(bytes); 71 | } 72 | 73 | /** *//** 74 | *

75 | * BASE64字符串转回文件 76 | *

77 | * 78 | * @param filePath 文件绝对路径 79 | * @param base64 编码字符串 80 | * @throws Exception 81 | */ 82 | public static void decodeToFile(String filePath, String base64) throws Exception { 83 | byte[] bytes = decode(base64); 84 | byteArrayToFile(bytes, filePath); 85 | } 86 | 87 | /** *//** 88 | *

89 | * 文件转换为二进制数组 90 | *

91 | * 92 | * @param filePath 文件路径 93 | * @return 94 | * @throws Exception 95 | */ 96 | public static byte[] fileToByte(String filePath) throws Exception { 97 | byte[] data = new byte[0]; 98 | File file = new File(filePath); 99 | if (file.exists()) { 100 | FileInputStream in = new FileInputStream(file); 101 | ByteArrayOutputStream out = new ByteArrayOutputStream(2048); 102 | byte[] cache = new byte[CACHE_SIZE]; 103 | int nRead = 0; 104 | while ((nRead = in.read(cache)) != -1) { 105 | out.write(cache, 0, nRead); 106 | out.flush(); 107 | } 108 | out.close(); 109 | in.close(); 110 | data = out.toByteArray(); 111 | } 112 | return data; 113 | } 114 | 115 | /** *//** 116 | *

117 | * 二进制数据写文件 118 | *

119 | * 120 | * @param bytes 二进制数据 121 | * @param filePath 文件生成目录 122 | */ 123 | public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { 124 | InputStream in = new ByteArrayInputStream(bytes); 125 | File destFile = new File(filePath); 126 | if (!destFile.getParentFile().exists()) { 127 | destFile.getParentFile().mkdirs(); 128 | } 129 | destFile.createNewFile(); 130 | OutputStream out = new FileOutputStream(destFile); 131 | byte[] cache = new byte[CACHE_SIZE]; 132 | int nRead = 0; 133 | while ((nRead = in.read(cache)) != -1) { 134 | out.write(cache, 0, nRead); 135 | out.flush(); 136 | } 137 | out.close(); 138 | in.close(); 139 | } 140 | 141 | 142 | } 143 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/FileEncryptionManager.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo.javalib; 2 | 3 | import android.util.Log; 4 | 5 | import com.blakequ.rsa.Base64Utils; 6 | import com.blakequ.rsa.FileUtils; 7 | 8 | import java.io.File; 9 | import java.security.interfaces.RSAPrivateKey; 10 | import java.security.interfaces.RSAPublicKey; 11 | import java.util.Map; 12 | 13 | /** 14 | * Copyright (C) BlakeQu All Rights Reserved 15 | *

16 | * Licensed under the blakequ.com License, Version 1.0 (the "License"); 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | *

23 | * author : quhao
24 | * date : 2017/2/22 21:13
25 | * last modify author :
26 | * version : 1.0
27 | * description: file encryption manager
28 | * notice:
29 | *

  • 1. first step: set public and private key. 如果输入的秘钥(公钥和私钥)都是经过Base64.encode处理的,Base64Utils.encode(key.getEncoded()),如果是自己生成的需要先行处理
  • 30 | *
  • 2. encrypt and decrypt file by method
  • 31 | */ 32 | 33 | public class FileEncryptionManager { 34 | private static FileEncryptionManager INSTANCE; 35 | private String publicKey; 36 | private String privateKey; 37 | 38 | private FileEncryptionManager() { 39 | } 40 | 41 | public static FileEncryptionManager getInstance(){ 42 | if (INSTANCE == null){ 43 | INSTANCE = new FileEncryptionManager(); 44 | } 45 | return INSTANCE; 46 | } 47 | 48 | /** 49 | * set the key of encrypt and decrypt 50 | * @param publicKey 51 | * @param privateKey 52 | * @param isEncode is encoded by Base64 53 | * @see com.blakequ.rsa.Base64Utils#encode 54 | * @see #generateKey() () 55 | */ 56 | public void setRSAKey(String publicKey, String privateKey, boolean isEncode) throws Exception { 57 | if (isEncode){ 58 | this.publicKey = publicKey; 59 | this.privateKey = privateKey; 60 | }else { 61 | this.publicKey = com.blakequ.rsa.Base64Utils.encode(publicKey.getBytes()); 62 | this.privateKey = com.blakequ.rsa.Base64Utils.encode(privateKey.getBytes()); 63 | } 64 | } 65 | 66 | /** 67 | * set the key of encrypt and decrypt 68 | * @param publicKey 69 | * @param privateKey 70 | * @see #generateKey() () 71 | */ 72 | public void setRSAKey(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws Exception { 73 | this.publicKey = com.blakequ.rsa.Base64Utils.encode(publicKey.getEncoded()); 74 | this.privateKey = Base64Utils.encode(privateKey.getEncoded()); 75 | } 76 | 77 | /** 78 | * generate public and private key 79 | * @throws Exception 80 | * @see #setRSAKey(RSAPublicKey, RSAPrivateKey) 81 | * @see #setRSAKey(String, String, boolean) 82 | */ 83 | public void generateKey() throws Exception { 84 | Map map = RSAProvider.generateKeyPair(); 85 | this.privateKey = RSAProvider.getPrivateKeyBytes(map); 86 | this.publicKey = RSAProvider.getPublicKeyBytes(map); 87 | } 88 | 89 | public String getPublicKey() { 90 | return publicKey; 91 | } 92 | 93 | public String getPrivateKey() { 94 | return privateKey; 95 | } 96 | 97 | /** 98 | * sign data by private key 99 | * @param data the data by encrypted 100 | * @return 101 | * @throws Exception 102 | * @see #verifyByPublicKey(byte[], String) 103 | */ 104 | public String signByPrivateKey(byte[] data) throws Exception { 105 | if (privateKey == null || privateKey.isEmpty()){ 106 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 107 | } 108 | return RSAProvider.sign(data, privateKey); 109 | } 110 | 111 | /** 112 | * verify data by sign 113 | * @param data the data by encrypted 114 | * @param sign 115 | * @return 116 | * @throws Exception 117 | * @see #signByPrivateKey(byte[]) 118 | */ 119 | public boolean verifyByPublicKey(byte[] data, String sign) throws Exception { 120 | if (publicKey == null || publicKey.isEmpty()){ 121 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 122 | } 123 | return RSAProvider.verify(data, publicKey, sign); 124 | } 125 | 126 | /** 127 | * encrypt by public key 128 | * @param data 129 | * @return 130 | * @throws Exception 131 | */ 132 | public byte[] encryptByPublicKey(byte[] data) throws Exception { 133 | if (publicKey == null || publicKey.isEmpty()){ 134 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 135 | } 136 | return RSAProvider.encryptPublicKey(data, publicKey); 137 | } 138 | 139 | /** 140 | * decrypt by private key 141 | * @param data 142 | * @return 143 | * @throws Exception 144 | */ 145 | public byte[] decryptByPrivateKey(byte[] data) throws Exception { 146 | if (privateKey == null || privateKey.isEmpty()){ 147 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 148 | } 149 | return RSAProvider.decryptPrivateKey(data, privateKey); 150 | } 151 | 152 | /** 153 | * encrypt by private key 154 | * @param data 155 | * @return 156 | * @throws Exception 157 | */ 158 | public byte[] encryptByPrivateKey(byte[] data) throws Exception { 159 | if (privateKey == null || privateKey.isEmpty()){ 160 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 161 | } 162 | return RSAProvider.encryptPublicKey(data, privateKey); 163 | } 164 | 165 | /** 166 | * decrypt by public key 167 | * @param data 168 | * @return 169 | * @throws Exception 170 | */ 171 | public byte[] decryptByPublicKey(byte[] data) throws Exception { 172 | if (publicKey == null || publicKey.isEmpty()){ 173 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 174 | } 175 | return RSAProvider.decryptPrivateKey(data, publicKey); 176 | } 177 | 178 | /** 179 | * using public key encrypt file 180 | * @param inputFile the file of wait to encrypt 181 | * @param outFile 182 | * @return encrypted data 183 | */ 184 | public byte[] encryptFileByPublicKey(File inputFile, File outFile) throws Exception { 185 | if (publicKey == null || publicKey.isEmpty()){ 186 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 187 | } 188 | byte[] data = FileUtils.getDataFromFile(inputFile); 189 | byte[] encryData = RSAProvider.encryptPublicKey(data, publicKey); 190 | if (outFile != null){ 191 | boolean result = FileUtils.saveDataToFile(encryData, outFile); 192 | Log.d("FileEncryptionManager", "save file result "+result); 193 | } 194 | return encryData; 195 | } 196 | 197 | /** 198 | * using private key decrypt file 199 | * @param inputFile the file is encrypted 200 | * @param outFile 201 | * @return origial data by decrypted 202 | */ 203 | public byte[] decryptFileByPrivateKey(File inputFile, File outFile) throws Exception { 204 | if (privateKey == null || privateKey.isEmpty()){ 205 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 206 | } 207 | byte[] data = FileUtils.getDataFromFile(inputFile); 208 | byte[] decryData = RSAProvider.decryptPrivateKey(data, privateKey); 209 | if (outFile != null){ 210 | boolean result = FileUtils.saveDataToFile(decryData, outFile); 211 | Log.d("FileEncryptionManager", "save file result "+result); 212 | } 213 | return decryData; 214 | } 215 | 216 | /** 217 | * using public key encrypt file 218 | * @param inputData the file of wait to encrypt 219 | * @param outFile 220 | * @return encrypted data 221 | */ 222 | public byte[] encryptFileByPublicKey(byte[] inputData, File outFile) throws Exception { 223 | if (publicKey == null || publicKey.isEmpty()){ 224 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 225 | } 226 | byte[] encryData = RSAProvider.encryptPublicKey(inputData, publicKey); 227 | if (outFile != null){ 228 | boolean result = FileUtils.saveDataToFile(encryData, outFile); 229 | Log.d("FileEncryptionManager", "save file result "+result); 230 | } 231 | return encryData; 232 | } 233 | 234 | /** 235 | * using private key decrypt file 236 | * @param inputData the file is encrypted 237 | * @param outFile 238 | * @return origial data by decrypted 239 | */ 240 | public byte[] decryptFileByPrivateKey(byte[] inputData, File outFile) throws Exception { 241 | if (privateKey == null || privateKey.isEmpty()){ 242 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 243 | } 244 | byte[] decryData = RSAProvider.decryptPrivateKey(inputData, privateKey); 245 | if (outFile != null){ 246 | boolean result = FileUtils.saveDataToFile(decryData, outFile); 247 | Log.d("FileEncryptionManager", "save file result "+result); 248 | } 249 | return decryData; 250 | } 251 | 252 | /** 253 | * using private key encrypt file 254 | * @param inputFile the file of wait to encrypt 255 | * @param outFile 256 | * @return encrypted data 257 | */ 258 | public byte[] encryptFileByPrivateKey(File inputFile, File outFile) throws Exception { 259 | if (privateKey == null || privateKey.isEmpty()){ 260 | throw new IllegalArgumentException("PrivateKey is empty, you should invoke setRSAKey or generateKey"); 261 | } 262 | byte[] data = FileUtils.getDataFromFile(inputFile); 263 | byte[] encryData = RSAProvider.encryptPrivateKey(data, privateKey); 264 | if (outFile != null){ 265 | boolean result = FileUtils.saveDataToFile(encryData, outFile); 266 | Log.d("FileEncryptionManager", "save file result "+result); 267 | } 268 | return encryData; 269 | } 270 | 271 | /** 272 | * using public key decrypt file 273 | * @param inputFile the file is encrypted 274 | * @param outFile 275 | * @return origial data by decrypted 276 | */ 277 | public byte[] decryptFileByPublicKey(File inputFile, File outFile) throws Exception { 278 | if (publicKey == null || publicKey.isEmpty()){ 279 | throw new IllegalArgumentException("PublicKey is empty, you should invoke setRSAKey or generateKey"); 280 | } 281 | byte[] data = FileUtils.getDataFromFile(inputFile); 282 | byte[] decryData = RSAProvider.decryptPublicKey(data, publicKey); 283 | if (outFile != null){ 284 | boolean result = FileUtils.saveDataToFile(decryData, outFile); 285 | Log.d("FileEncryptionManager", "save file result "+result); 286 | } 287 | return decryData; 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo.javalib; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | 13 | /** 14 | * Copyright (C) BlakeQu All Rights Reserved 15 | *

    16 | * Licensed under the blakequ.com License, Version 1.0 (the "License"); 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | *

    23 | * author : quhao
    24 | * date : 2017/2/22 21:08
    25 | * last modify author :
    26 | * version : 1.0
    27 | * description: 28 | */ 29 | 30 | public class FileUtils { 31 | 32 | /** 33 | * 注意保持加密内容的时候不能先将byte数组转换为string,因为转换为string的时候,后面会默认加上结束符,造成解密失败,故而在读取和写入都使用byte数组 34 | * @param data 35 | * @param filePath 36 | */ 37 | public static boolean saveDataToFile(byte[] data, File filePath){ 38 | if (data == null || filePath == null){ 39 | throw new IllegalArgumentException("Input data is null or output path is null"); 40 | } 41 | boolean result = false; 42 | try { 43 | result = write(filePath, data, false); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | return result; 48 | } 49 | 50 | /** 51 | * 从文件读取byte数组 52 | * @param sourceFile 53 | * @return 54 | * @throws FileNotFoundException 55 | */ 56 | public static byte[] getDataFromFile(File sourceFile) throws FileNotFoundException { 57 | return getBytesFromInputStream(new FileInputStream(sourceFile)); 58 | } 59 | 60 | /** 61 | * 从输入流中读取byte数组 62 | * String filePath 63 | */ 64 | public static byte[] getBytesFromInputStream(InputStream inputStream){ 65 | byte[] buffer = null; 66 | ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); 67 | byte[] b = new byte[1000]; 68 | try { 69 | int n; 70 | while ((n = inputStream.read(b)) != -1) { 71 | bos.write(b, 0, n); 72 | } 73 | buffer = bos.toByteArray(); 74 | } catch (FileNotFoundException e) { 75 | e.printStackTrace(); 76 | } catch (IOException e) { 77 | e.printStackTrace(); 78 | } finally { 79 | try { 80 | inputStream.close(); 81 | bos.close(); 82 | } catch (IOException e) { 83 | e.printStackTrace(); 84 | } 85 | } 86 | return buffer; 87 | } 88 | 89 | 90 | /** 91 | * 读取密钥信息 92 | * 93 | * @param in 94 | * @return 95 | * @throws IOException 96 | */ 97 | public static String readString(InputStream in) throws IOException { 98 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 99 | String readLine = null; 100 | StringBuilder sb = new StringBuilder(); 101 | while ((readLine = br.readLine()) != null) { 102 | if (readLine.charAt(0) == '-') { 103 | continue; 104 | } else { 105 | sb.append(readLine); 106 | sb.append('\r'); 107 | } 108 | } 109 | 110 | return sb.toString(); 111 | } 112 | 113 | /** 114 | * 将内容写文件 115 | * @param file 116 | * @param content 117 | * @param append 118 | * @return 119 | */ 120 | private static boolean write(File file, byte[] content, boolean append) { 121 | if(file != null && content != null) { 122 | if(!file.exists()) { 123 | file = createNewFile(file); 124 | } 125 | 126 | FileOutputStream ops = null; 127 | 128 | try { 129 | ops = new FileOutputStream(file, append); 130 | ops.write(content); 131 | return true; 132 | } catch (Exception var15) { 133 | var15.printStackTrace(); 134 | } finally { 135 | try { 136 | ops.close(); 137 | } catch (IOException var14) { 138 | var14.printStackTrace(); 139 | } 140 | ops = null; 141 | } 142 | 143 | return false; 144 | } 145 | return false; 146 | } 147 | 148 | /** 149 | * 创建新文件 150 | * @param file 151 | * @return 152 | */ 153 | private static File createNewFile(File file) { 154 | try { 155 | if(file.exists()) { 156 | return file; 157 | } else { 158 | File e = file.getParentFile(); 159 | if(!e.exists()) { 160 | e.mkdirs(); 161 | } 162 | 163 | if(!file.exists()) { 164 | file.createNewFile(); 165 | } 166 | 167 | return file; 168 | } 169 | } catch (IOException var2) { 170 | var2.printStackTrace(); 171 | return null; 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/RSAProvider.java: -------------------------------------------------------------------------------- 1 | package com.blakequ.rsademo.javalib; 2 | 3 | import com.blakequ.rsa.ArrayUtils; 4 | import com.blakequ.rsa.Base64Utils; 5 | import com.blakequ.rsa.FileUtils; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.math.BigInteger; 10 | import java.security.Key; 11 | import java.security.KeyFactory; 12 | import java.security.KeyPair; 13 | import java.security.KeyPairGenerator; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.security.PrivateKey; 16 | import java.security.PublicKey; 17 | import java.security.Signature; 18 | import java.security.interfaces.RSAPrivateKey; 19 | import java.security.interfaces.RSAPublicKey; 20 | import java.security.spec.InvalidKeySpecException; 21 | import java.security.spec.PKCS8EncodedKeySpec; 22 | import java.security.spec.X509EncodedKeySpec; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | import javax.crypto.Cipher; 27 | 28 | /** 29 | * Copyright (C) BlakeQu All Rights Reserved 30 | *

    31 | * Licensed under the blakequ.com License, Version 1.0 (the "License"); 32 | * Unless required by applicable law or agreed to in writing, software 33 | * distributed under the License is distributed on an "AS IS" BASIS, 34 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | * See the License for the specific language governing permissions and 36 | * limitations under the License. 37 | *

    38 | * author : quhao
    39 | * date : 2017/2/22 16:03
    40 | * last modify author :
    41 | * version : 1.0
    42 | * description: 43 | */ 44 | 45 | public class RSAProvider { 46 | 47 | /** 48 | * KEY_ALGORITHM 49 | */ 50 | public static final String KEY_ALGORITHM = "RSA"; 51 | /** 52 | * 加密Key的长度等于1024 53 | */ 54 | public static int KEYSIZE = 1024; 55 | /** 56 | * 解密时必须按照此分组解密 57 | */ 58 | public static int decodeLen = KEYSIZE / 8; 59 | /** 60 | * 加密时小于117即可 61 | */ 62 | public static int encodeLen = 110;//(DEFAULT_KEY_SIZE / 8) - 11; 63 | /** 64 | * 公钥 65 | */ 66 | private static final String PUBLIC_KEY = "publicKey"; 67 | /** 68 | * 私钥 69 | */ 70 | private static final String PRIVATE_KEY = "privateKey"; 71 | /** 72 | * MODULES 73 | */ 74 | private static final String MODULES = "RSAModules"; 75 | /** 76 | * 签名算法 77 | */ 78 | public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 79 | /** 80 | * 加密填充方式,android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding" ,这造成了在android机上加密后无法在服务器上解密的原因 81 | */ 82 | public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding"; 83 | 84 | /** 85 | * 86 | * 生成KeyPair 87 | * @return 88 | * @throws Exception 89 | */ 90 | public static Map generateKeyPair() throws Exception { 91 | KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); 92 | keyPairGen.initialize(KEYSIZE); 93 | KeyPair keyPair = keyPairGen.generateKeyPair(); 94 | 95 | // 公钥 96 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 97 | 98 | // 私钥 99 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 100 | BigInteger modules = privateKey.getModulus(); 101 | 102 | Map keys = new HashMap(3); 103 | keys.put(PUBLIC_KEY, publicKey); 104 | keys.put(PRIVATE_KEY, privateKey); 105 | keys.put(MODULES, modules); 106 | return keys; 107 | } 108 | 109 | public static byte[] getModulesBytes(Map keys) { 110 | BigInteger big = (BigInteger) keys.get(MODULES); 111 | return big.toByteArray(); 112 | } 113 | 114 | /** 115 | * 116 | * 取得私钥 117 | * @return 118 | * @throws Exception 119 | */ 120 | public static String getPrivateKeyBytes(Map keys) throws Exception { 121 | Key key = (Key) keys.get(PRIVATE_KEY); 122 | return Base64Utils.encode(key.getEncoded()); 123 | } 124 | 125 | /** 126 | * 取得公钥 127 | * 128 | * @return 129 | * @throws Exception 130 | */ 131 | public static String getPublicKeyBytes(Map keys) throws Exception { 132 | Key key = (Key) keys.get(PUBLIC_KEY); 133 | return Base64Utils.encode(key.getEncoded()); 134 | } 135 | 136 | /** 137 | * 用私钥对信息生成数字签名 138 | * 139 | * @param data 已加密数据 140 | * @param privateKey 私钥(BASE64编码) 141 | * 142 | * @return 143 | * @throws Exception 144 | */ 145 | public static String sign(byte[] data, String privateKey) throws Exception { 146 | PrivateKey privateK = loadPrivateKey(privateKey); 147 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 148 | signature.initSign(privateK); 149 | signature.update(data); 150 | return Base64Utils.encode(signature.sign()); 151 | } 152 | 153 | /** 154 | * 校验数字签名 155 | * 156 | * @param data 已加密数据 157 | * @param publicKey 公钥(BASE64编码) 158 | * @param sign 数字签名 159 | * 160 | * @return 161 | * @throws Exception 162 | * 163 | */ 164 | public static boolean verify(byte[] data, String publicKey, String sign) 165 | throws Exception { 166 | PublicKey publicK = loadPublicKey(publicKey); 167 | Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 168 | signature.initVerify(publicK); 169 | signature.update(data); 170 | return signature.verify(Base64Utils.decode(sign)); 171 | } 172 | 173 | /** 174 | * 175 | * 通过私钥加密 176 | * @param encryptedData 177 | * @param key 178 | * @return 179 | * @throws Exception 180 | */ 181 | public static byte[] encryptPrivateKey(byte[] encryptedData, String key) throws Exception { 182 | if (encryptedData == null){ 183 | throw new IllegalArgumentException("Input encryption data is null"); 184 | } 185 | byte[] encode = new byte[] {}; 186 | for (int i = 0; i < encryptedData.length; i += encodeLen) { 187 | byte[] subarray = com.blakequ.rsa.ArrayUtils.subarray(encryptedData, i, i + encodeLen); 188 | byte[] doFinal = encryptByPrivateKey(subarray, key); 189 | encode = com.blakequ.rsa.ArrayUtils.addAll(encode, doFinal); 190 | } 191 | return encode; 192 | } 193 | 194 | /** 195 | * 通过公钥解密 196 | * @param encode 197 | * @param key 198 | * @return 199 | * @throws Exception 200 | */ 201 | public static byte[] decryptPublicKey(byte[] encode, String key) throws Exception { 202 | if (encode == null){ 203 | throw new IllegalArgumentException("Input encryption data is null"); 204 | } 205 | byte [] buffers = new byte[]{}; 206 | for (int i = 0; i < encode.length; i += decodeLen) { 207 | byte[] subarray = com.blakequ.rsa.ArrayUtils.subarray(encode, i, i + decodeLen); 208 | byte[] doFinal = decryptByPublicKey(subarray, key); 209 | buffers = com.blakequ.rsa.ArrayUtils.addAll(buffers, doFinal); 210 | } 211 | return buffers; 212 | } 213 | 214 | /** 215 | * 216 | * 通过公钥加密 217 | * @param encryptedData 218 | * @param key 219 | * @return 220 | * @throws Exception 221 | */ 222 | public static byte[] encryptPublicKey(byte[] encryptedData, String key) throws Exception { 223 | if (encryptedData == null){ 224 | throw new IllegalArgumentException("Input encryption data is null"); 225 | } 226 | byte[] encode = new byte[] {}; 227 | for (int i = 0; i < encryptedData.length; i += encodeLen) { 228 | byte[] subarray = com.blakequ.rsa.ArrayUtils.subarray(encryptedData, i, i + encodeLen); 229 | byte[] doFinal = encryptByPublicKey(subarray, key); 230 | encode = com.blakequ.rsa.ArrayUtils.addAll(encode, doFinal); 231 | } 232 | return encode; 233 | } 234 | 235 | /** 236 | * 通过私钥解密 237 | * @param encode 238 | * @param key 239 | * @return 240 | * @throws Exception 241 | */ 242 | public static byte[] decryptPrivateKey(byte[] encode, String key) throws Exception { 243 | if (encode == null){ 244 | throw new IllegalArgumentException("Input data is null"); 245 | } 246 | byte [] buffers = new byte[]{}; 247 | for (int i = 0; i < encode.length; i += decodeLen) { 248 | byte[] subarray = com.blakequ.rsa.ArrayUtils.subarray(encode, i, i + decodeLen); 249 | byte[] doFinal = decryptByPrivateKey(subarray, key); 250 | buffers = ArrayUtils.addAll(buffers, doFinal); 251 | } 252 | return buffers; 253 | } 254 | 255 | /** 256 | * 从字符串中加载公钥 257 | * 258 | * @param publicKeyStr 公钥数据字符串 259 | * @throws Exception 加载公钥时产生的异常 260 | */ 261 | public static PublicKey loadPublicKey(String publicKeyStr) throws Exception { 262 | try { 263 | byte[] buffer = Base64Utils.decode(publicKeyStr); 264 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 265 | //表示根据 ASN.1 类型 SubjectPublicKeyInfo 进行编码的公用密钥的 ASN.1 编码。 266 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); 267 | return keyFactory.generatePublic(keySpec); 268 | } catch (NoSuchAlgorithmException e) { 269 | throw new Exception("无此算法"); 270 | } catch (InvalidKeySpecException e) { 271 | throw new Exception("公钥非法"); 272 | } catch (NullPointerException e) { 273 | throw new Exception("公钥数据为空"); 274 | } 275 | } 276 | 277 | /** 278 | * 从字符串中加载私钥
    279 | * 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。 280 | * 281 | * @param privateKeyStr 282 | * @return 283 | * @throws Exception 284 | */ 285 | public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { 286 | try { 287 | byte[] buffer = Base64Utils.decode(privateKeyStr); 288 | //表示按照 ASN.1 类型 PrivateKeyInfo 进行编码的专用密钥的 ASN.1 编码。 289 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); 290 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); 291 | return keyFactory.generatePrivate(keySpec); 292 | } catch (NoSuchAlgorithmException e) { 293 | throw new Exception("无此算法"); 294 | } catch (InvalidKeySpecException e) { 295 | throw new Exception("私钥非法"); 296 | } catch (NullPointerException e) { 297 | throw new Exception("私钥数据为空"); 298 | } 299 | } 300 | 301 | /** 302 | * 从文件中输入流中加载公钥 303 | * 304 | * @param in 公钥输入流 305 | * @throws Exception 加载公钥时产生的异常 306 | */ 307 | public static PublicKey loadPublicKey(InputStream in) throws Exception { 308 | try { 309 | return loadPublicKey(FileUtils.readString(in)); 310 | } catch (IOException e) { 311 | throw new Exception("公钥数据流读取错误"); 312 | } catch (NullPointerException e) { 313 | throw new Exception("公钥输入流为空"); 314 | } 315 | } 316 | 317 | /** 318 | * 读取私钥 319 | * 320 | * @param in 321 | * @return 322 | * @throws Exception 323 | */ 324 | public static PrivateKey loadPrivateKey(InputStream in) throws Exception { 325 | try { 326 | return loadPrivateKey(FileUtils.readString(in)); 327 | } catch (IOException e) { 328 | throw new Exception("私钥数据读取错误"); 329 | } catch (NullPointerException e) { 330 | throw new Exception("私钥输入流为空"); 331 | } 332 | } 333 | 334 | /** 335 | * 用私钥解密 336 | * @param data 337 | * @param key 338 | * @return 339 | * @throws Exception 340 | */ 341 | private static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception { 342 | if (data == null){ 343 | throw new IllegalArgumentException("Input data is null"); 344 | } 345 | //取得私钥 346 | Key privateKey = loadPrivateKey(key); 347 | // 对数据解密 348 | Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); 349 | cipher.init(Cipher.DECRYPT_MODE, privateKey); 350 | 351 | return cipher.doFinal(data); 352 | } 353 | 354 | /** 355 | * 356 | * 用公钥解密 357 | * @param data 358 | * @param key 359 | * @return 360 | * @throws Exception 361 | */ 362 | private static byte[] decryptByPublicKey(byte[] data, String key) throws Exception { 363 | if (data == null){ 364 | throw new IllegalArgumentException("Input data is null"); 365 | } 366 | //取得公钥 367 | Key publicKey = loadPublicKey(key); 368 | // 对数据解密 369 | Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);//publicKey.getAlgorithm() 370 | cipher.init(Cipher.DECRYPT_MODE, publicKey); 371 | 372 | return cipher.doFinal(data); 373 | } 374 | 375 | /** 376 | * 377 | * 用公钥加密 378 | * @param data 379 | * @param key 380 | * @return 381 | * @throws Exception 382 | */ 383 | private static byte[] encryptByPublicKey(byte[] data, String key) throws Exception { 384 | if (data == null){ 385 | throw new IllegalArgumentException("Input data is null"); 386 | } 387 | // 取得公钥 388 | Key publicKey = loadPublicKey(key); 389 | // 对数据加密 390 | Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); 391 | cipher.init(Cipher.ENCRYPT_MODE, publicKey); 392 | 393 | return cipher.doFinal(data); 394 | } 395 | 396 | /** 397 | * 用私钥加密 398 | * 399 | * @param data 400 | * @param key 401 | * @return 402 | * @throws Exception 403 | */ 404 | private static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception { 405 | if (data == null){ 406 | throw new IllegalArgumentException("Input data is null"); 407 | } 408 | // 取得私钥 409 | Key privateKey = loadPrivateKey(key); 410 | // 对数据加密 411 | Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); 412 | cipher.init(Cipher.ENCRYPT_MODE, privateKey); 413 | 414 | return cipher.doFinal(data); 415 | } 416 | 417 | } 418 | -------------------------------------------------------------------------------- /app/src/main/java/com/blakequ/rsademo/javalib/Shared.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java Base64 - A pure Java library for reading and writing Base64 3 | * encoded streams. 4 | * 5 | * Copyright (C) 2007-2009 Carlo Pelliccia (www.sauronsoftware.it) 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License version 9 | * 2.1, as published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License version 2.1 along with this program. 18 | * If not, see . 19 | */ 20 | package com.blakequ.rsademo.javalib; 21 | 22 | /** 23 | * Package related utilities. 24 | * 25 | * @author Carlo Pelliccia 26 | */ 27 | class Shared { 28 | 29 | static String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 30 | 31 | static char pad = '='; 32 | 33 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haodynasty/android-rsa/8b732fa37720028406a74f4ab182a53d8544eec2/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haodynasty/android-rsa/8b732fa37720028406a74f4ab182a53d8544eec2/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haodynasty/android-rsa/8b732fa37720028406a74f4ab182a53d8544eec2/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haodynasty/android-rsa/8b732fa37720028406a74f4ab182a53d8544eec2/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_grpctest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 16 | 23 | 24 | 25 | 29 |