├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── dk │ │ └── meznik │ │ └── jan │ │ └── encrypttext │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── dk │ │ │ └── meznik │ │ │ └── jan │ │ │ └── encrypttext │ │ │ ├── EncryptActivity.java │ │ │ ├── MainActivity.java │ │ │ └── util │ │ │ └── Encryption.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_help_white_24dp.png │ │ ├── drawable-mdpi │ │ └── ic_help_white_24dp.png │ │ ├── drawable-xhdpi │ │ └── ic_help_white_24dp.png │ │ ├── drawable-xxhdpi │ │ └── ic_help_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ └── ic_help_white_24dp.png │ │ ├── drawable │ │ ├── border.png~ │ │ ├── edit_text_style.xml │ │ └── edit_text_style_dark.xml │ │ ├── layout │ │ ├── activity_encrypt.xml │ │ ├── activity_main.xml │ │ └── content_encrypt.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-ru │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ ├── colors_blue_grey.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── dk │ └── meznik │ └── jan │ └── encrypttext │ └── ExampleUnitTest.java ├── build.gradle ├── fastlane └── metadata │ └── android │ └── en-US │ ├── full_description.txt │ ├── images │ ├── featureGraphic.png │ ├── icon.png │ ├── phoneScreenshots │ │ ├── sceenshot1.png │ │ ├── sceenshot2.png │ │ └── sceenshot3.png │ ├── sevenInchScreenshots │ │ └── sceenshot2.png │ └── tenInchScreenshots │ │ └── sceenshot2.png │ ├── short_description.txt │ └── title.txt ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── graphics └── icon.svg ├── screenshots ├── screenshot1.png ├── screenshot2.png └── screenshot3.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .idea/caches/build_file_checksums.ser 11 | .idea/codeStyles/Project.xml 12 | .idea/gradle.xml 13 | .idea/jarRepositories.xml 14 | .idea/misc.xml 15 | .idea/modules.xml 16 | .idea/runConfigurations.xml 17 | .idea/vcs.xml 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jan Mezník 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EncryptText App for Android 2 | A simple application to encrypt text. Can be used in combination with many other applications, to increase security and privacy. 3 | 4 | 5 | # Usage 6 | The application can be opened just as any other application. However, to avoid 7 | the tedious application switching, the encryption can happen in-place, in any 8 | application. 9 | 10 | First, select the text you want to encrypt: 11 |

12 | Enter the password at the top ( *optional, but recommended* ), and hit 13 | **ENCRYPT**: 14 |

15 | The encrypted message will appear at the bottom. Click **REPLACE** to close the 16 | application and replace the original text: 17 |

18 | 19 | # Installation 20 | [Get it on F-Droid](https://f-droid.org/packages/dk.meznik.jan.encrypttext/) 23 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "dk.meznik.jan.encrypttext" 8 | minSdkVersion 23 9 | targetSdkVersion 29 10 | versionCode 5 11 | versionName "1.2.3" 12 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | implementation 'androidx.appcompat:appcompat:1.2.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 29 | implementation 'com.google.android.material:material:1.2.0' 30 | testImplementation 'junit:junit:4.12' 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/jan/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/dk/meznik/jan/encrypttext/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dk.meznik.jan.encrypttext; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dk.meznik.jan.encrypttext", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/dk/meznik/jan/encrypttext/EncryptActivity.java: -------------------------------------------------------------------------------- 1 | package dk.meznik.jan.encrypttext; 2 | 3 | import android.app.Activity; 4 | import android.content.ClipData; 5 | import android.content.ClipboardManager; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | import androidx.appcompat.widget.Toolbar; 12 | import android.view.View; 13 | import android.widget.Button; 14 | import android.widget.EditText; 15 | import android.widget.Toast; 16 | 17 | import dk.meznik.jan.encrypttext.util.Encryption; 18 | 19 | public class EncryptActivity extends Activity { 20 | EditText editTextPassword; 21 | EditText editText1; 22 | EditText editText2; 23 | Button buttonEncrypt; 24 | Button buttonDecrypt; 25 | Button buttonReplace; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_encrypt); 31 | 32 | editTextPassword = (EditText)findViewById(R.id.editTextPassword); 33 | editText1 = (EditText)findViewById(R.id.editText1); 34 | editText2 = (EditText)findViewById(R.id.editText2); 35 | buttonEncrypt = (Button)findViewById(R.id.buttonEncrypt); 36 | buttonDecrypt = (Button)findViewById(R.id.buttonDecrypt); 37 | buttonReplace = (Button)findViewById(R.id.buttonReplace); 38 | buttonReplace.setEnabled(false); 39 | 40 | 41 | // Set the editText with text to encrypt, depending on the intent type 42 | CharSequence text = ""; 43 | 44 | if(getIntent().getAction() == null) { 45 | // App started from launcher 46 | } 47 | else if(getIntent().getAction().equals(Intent.ACTION_SEND)) { 48 | text = getIntent().getCharSequenceExtra(Intent.EXTRA_TEXT); 49 | } 50 | else if(getIntent().getAction().equals(Intent.ACTION_PROCESS_TEXT)) { 51 | text = getIntent().getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT); 52 | buttonReplace.setEnabled(true); 53 | 54 | } 55 | editText1.setText(text); 56 | 57 | } 58 | 59 | public void exitWithResult(String data) { 60 | Intent result = new Intent(); 61 | result.putExtra(Intent.EXTRA_PROCESS_TEXT, data); 62 | setResult(RESULT_OK, result); 63 | finish(); 64 | } 65 | 66 | public void buttonEncryptClick(View v) { 67 | String password = editTextPassword.getText().toString(); 68 | String str = editText1.getText().toString(); 69 | String cipher = ""; 70 | try { 71 | cipher = Encryption.encrypt(password, str); 72 | } catch (Exception ex) { 73 | Toast.makeText(this, "Could not encrypt text: " + ex.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); 74 | } 75 | editText2.setText(cipher); 76 | } 77 | 78 | public void buttonDecryptClick(View v) { 79 | String password = editTextPassword.getText().toString(); 80 | String str = editText1.getText().toString(); 81 | String plain = ""; 82 | try { 83 | 84 | plain = Encryption.decrypt(password, str); 85 | 86 | } catch (Exception ex) { 87 | Toast.makeText(this, "Unable to decipher text.", Toast.LENGTH_SHORT).show(); 88 | } 89 | 90 | editText2.setText(plain); 91 | } 92 | 93 | public void buttonReplaceClick(View v) { 94 | exitWithResult(editText2.getText().toString()); 95 | } 96 | 97 | public void editText2Click(View v) { 98 | ClipboardManager clipboardManager = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); 99 | String str = editText2.getText().toString(); 100 | ClipData clipData = ClipData.newPlainText("Text",str ); 101 | clipboardManager.setPrimaryClip(clipData); 102 | Toast.makeText(this, "Copied to clipboard", Toast.LENGTH_SHORT).show(); 103 | } 104 | 105 | public void imageButtonHelpClick(View v) { 106 | Toast.makeText(this, "TEST", Toast.LENGTH_SHORT).show(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/dk/meznik/jan/encrypttext/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dk.meznik.jan.encrypttext; 2 | 3 | import android.content.Intent; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | //setContentView(R.layout.activity_main); 13 | 14 | 15 | Intent intent = new Intent(this, EncryptActivity.class); 16 | startActivity(intent); 17 | finish(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/dk/meznik/jan/encrypttext/util/Encryption.java: -------------------------------------------------------------------------------- 1 | package dk.meznik.jan.encrypttext.util; 2 | 3 | import android.util.Base64; 4 | import android.util.Log; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.security.GeneralSecurityException; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | import javax.crypto.Cipher; 12 | import javax.crypto.spec.IvParameterSpec; 13 | import javax.crypto.spec.SecretKeySpec; 14 | 15 | public class Encryption { 16 | private static final String TAG = "ENCRYPTION"; 17 | 18 | private static final String AES_MODE = "AES/CBC/PKCS7Padding"; 19 | private static final String ENCODING = "UTF-8"; 20 | 21 | private static final String HASH_ALGORITHM = "SHA-256"; 22 | private static final String SALT = "d68a1c8a0a8b8710f7c771065165867fc8e73b50ee6809a7e9f53873b38e3e0d"; 23 | 24 | private static final byte[] ivBytes = {0x42, 0x59, (byte)0xAF, 0x51, (byte)0xFF, (byte)0xB3, 25 | 0x02, 0x68, 0x62, (byte)0xCE,(byte) 0xDA, 0x11, 0x00, (byte)0xE9, 0x44, 0x01}; 26 | 27 | private static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, 28 | UnsupportedEncodingException { 29 | 30 | // Create a SHA-256 hash of the password 31 | final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); 32 | 33 | // Salt the password and get bytes using ENCODING. 34 | // It should not be necessary to salt with AES, but I do it nonetheless 35 | byte[] bytes = (password+SALT).getBytes(ENCODING); 36 | digest.update(bytes, 0, bytes.length); 37 | 38 | // Get the HASH 39 | byte[] key = digest.digest(); 40 | 41 | // Using SHA-256, this returns a 256bit key 42 | return new SecretKeySpec(key, "AES"); 43 | } 44 | 45 | 46 | public static String encrypt(final String password, String message) throws GeneralSecurityException { 47 | try { 48 | final SecretKeySpec key = generateKey(password); 49 | 50 | Cipher cipher = Cipher.getInstance(AES_MODE); 51 | IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); 52 | cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec); 53 | byte[] cipherText = cipher.doFinal(message.getBytes(ENCODING)); 54 | 55 | return Base64.encodeToString(cipherText, Base64.NO_WRAP); 56 | 57 | } catch (UnsupportedEncodingException e) { 58 | throw new GeneralSecurityException(e); 59 | } 60 | } 61 | 62 | public static String decrypt(final String password, String base64EncodedCipherText) 63 | throws GeneralSecurityException { 64 | 65 | try { 66 | final SecretKeySpec key = generateKey(password); 67 | 68 | byte[] decodedCipherText = Base64.decode(base64EncodedCipherText, Base64.NO_WRAP); 69 | 70 | Cipher cipher = Cipher.getInstance(AES_MODE); 71 | IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); 72 | cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec); 73 | 74 | byte[] decryptedBytes = cipher.doFinal(decodedCipherText); 75 | return new String(decryptedBytes, ENCODING); 76 | 77 | } catch (UnsupportedEncodingException e) { 78 | throw new GeneralSecurityException(e); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_help_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable-hdpi/ic_help_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_help_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable-mdpi/ic_help_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_help_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable-xhdpi/ic_help_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_help_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable-xxhdpi/ic_help_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_help_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable-xxxhdpi/ic_help_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/border.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanmanX/EncryptTextApp/81056978a74c54da27560b3da9d12e41543ac9c6/app/src/main/res/drawable/border.png~ -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_text_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_text_style_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_encrypt.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 18 | 19 | 30 | 41 | 42 | 52 | 53 | 56 | 57 |