how to encrypt/decrypt text in android studio on different activities - java

I tried developing an text encryption/decryption app in android studio. So here on the MainActivity.java i ran a sample code of encryption & decryption.
MainActivity.java
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class MainActivity extends AppCompatActivity {
Button btn,btn2;
static final String TAG = "SymmetricAlgorithmAES";
String secr="k";
String secr2="d";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//code to use my specified defined key
byte[] key = new byte[0];
try {
key = (secr+secr2).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec sks = new SecretKeySpec(key, "AES");
// Original text
String theTestText = "This is just a simple test";
TextView tvorig = (TextView)findViewById(R.id.tvorig);
tvorig.setText("\n[ORIGINAL]:\n" + theTestText + "\n");
// Encode the original data with AES
byte[] encodedBytes = null;
try {
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, sks);
encodedBytes = c.doFinal(theTestText.getBytes());
} catch (Exception e) {
Log.e(TAG, "AES encryption error");
}
TextView tvencoded = (TextView)findViewById(R.id.tvencoded);
tvencoded.setText("" +
Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");
// Decode the encoded data with AES
byte[] decodedBytes = null;
try {
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, sks);
decodedBytes = c.doFinal(encodedBytes);
} catch (Exception e) {
Log.e(TAG, "AES decryption error");
}
TextView tvdecoded = (TextView)findViewById(R.id.tvdecoded);
tvdecoded.setText("[DECODED]:\n" + new String(decodedBytes) + "\n");
}
The above code works properly with correct output. But when i try to modify the code and try to write encryption and decryption in different activities, but the decryption part does not work properly.
Here is the code for encryption part which works properly without any error.
Encryption.java
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Encryption extends AppCompatActivity {
static final String TAG = "SymmetricAlgorithmAES";
String secr="k";
String secr2="d";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.encryption);
enc_text_edt=(EditText)findViewById(R.id.enc_text_edt);
enc_text_btn=(Button)findViewById(R.id.enc_text_btn);
enctv=(TextView)findViewById(R.id.enctv);
//code to use my specified defined key
byte[] key = new byte[0];
try {
key = (secr+secr2).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec sks = new SecretKeySpec(key, "AES");
final SecretKeySpec finalSks = sks;
enc_text_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
// Encode the original data with AES
byte[] encodedBytes = null;
try {
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, finalSks);
encodedBytes = c.doFinal(enc_text_edt.getText().toString().getBytes());
} catch (Exception e) {
Log.e(TAG, "AES encryption error");
}
enctv.setText("[ENCRYPTED]:\n" +
Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");
enc_text_edt.setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
code of Decryption
Decryption.java
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Decryption extends AppCompatActivity {
Button dec_text_btn;
TextView dec_edtext_view, dectv;
static final String TAG = "SymmetricAlgorithmAES";
String secr = "k";
String secr2 = "d";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.decryption);
dec_text_btn = (Button) findViewById(R.id.dec_text_btn);
dec_edtext_view = (EditText) findViewById(R.id.dec_edtext_view);
dectv = (TextView) findViewById(R.id.dectv);
//code to use my specified defined key
byte[] key = new byte[0];
try {
key = (secr + secr2).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec sks = new SecretKeySpec(key, "AES");
final SecretKeySpec finalSks = sks;
dec_text_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
// Decode the encoded data with AES
byte[] decodedBytes = null;
try {
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, finalSks);
decodedBytes= c.doFinal(dec_edtext_view.getText().toString().getBytes());
} catch (Exception e) {
Log.e(TAG, "AES encryption error");
}
dectv.setText("[DECRYPTED]:\n" + new String(decodedBytes) + "\n");
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "creptography exception see log cat....", Toast.LENGTH_SHORT).show();
}
}
});
}
}
Please help me with the error. While executing Decryption part it directly shows exception "creptography exception see log cat".

After reading your code I think I have found the problem, you encode to Base64 but never decode. In the Encryption you do the following
enctv.setText("[ENCRYPTED]:\n" +
Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");
and I can guess the user copies it to the decryption field but after they click the button you do
decodedBytes= c.doFinal(dec_edtext_view.getText().toString().getBytes());
instead of decoding from Base64.
I would also like to add a few notes:
You're security is not safe, you barely achieved any layer of security when the keys are in plane site like this.
Note 1:
Keys should be generated randomly with a SecureRandom.
You can easily do it by doing the following:
byte[] key = new byte[16];
new SecureRandom().nextBytes(key);
Note 2:
Use an initialization vector aka IV this is useful in case the user has typed the same message. For example consider the following scenario you encrypt "Hello World" and it comes out as "ABCDEFGHIJK". Now you send it again and it is again "ABCDEFGHIJK".
With an IV it will be different everytime as long as you generate a new IV per message, you should append this IV to the message so later in decryption you can extract it.
Note 3:
When declaring a Cipher use more than AES.
There is a great article about how to increase your security and knowledge: article link
Note 4:
If an exception occurs don't continue on like nothing happend, you should handle it correctly and not continue on code that depends on what caused the exception.
Note 5:
Learn Java more in depth instead of jumping to cryptography, you're fields should be private and some final don't declare null if you might be planning to use it later, if you do check if its null. Don't declare "UTF-8" in get bytes, have a constant declaring a Charset such as "UTF-8" this is easily done with Charset.forName("UTF-8")

I agree with everything OughtToPrevail said.
Also, you should probably get all of that out of your activity and into a helper class. That way it will be reusable, and you can test the in and out of it (without copying and pasting) with something that would look like this:
public void myEncryptionTest(){
String message = "This is the message to encrypt and decrypt.";
String pass = "pass";
String encryption = Crypto.myEncrypt(message.getBytes(), pass);
byte[] decryption = Crypto.myDecrypt(encryption, pass);
String decrypted = new String(decryption);
Log.d("****DECRYPTION: ", decrypted);
}
Where the helper class is called "Crypto" and the two static functions you're testing are "myEncrypt" and "myDecrypt."

Related

Not able to decrypt(AES) in iOS(Swift) from Java

I am unable to decrypt data on iOS(Swift) which I am getting from the Java server. But if I encrypt a data on iOS and then decrypt, it works well. There might be some variance on both side's AES code which I am not able to identify. Please help me.
Similar question asked here: https://github.com/krzyzanowskim/CryptoSwift/issues/458
iOS Decryptor
let password = "SOME_ENCRYPTION_KEY"
let iv = AES256Crypter.randomIv()
let key = try AES256Crypter.createKey(password: password.data(using: .utf8)!, salt: salt)
let aes = try AES256Crypter(key: key, iv: iv)
let encryptedData = "encrypted_data".data(using: .utf8)
let decryptedData = try aes.decrypt(encryptedData!)
let decryptedString = String(decoding: decryptedData, as: UTF8.self)
print("Decrypted string: \(decryptedString)")
Java Encryptor
SecretKeySpec secretKey;
try {
byte[] key = ENCRYPTION_KEY.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
} catch (Exception e) {
System.out.println("\nException while encrypting " + strToEncrypt + " \nerror: " + e.getMessage());
}
Below is the code for Encryption in Java
and Decryption for iOS(Swift and Android(Kotlin). This works well but I am still open for a better solution.
Java Code
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class EncryptionUtils {
private static String ENCRYPTION_KEY = "1234512345123456";
public static void main(String[] args) {
String encyString = new EncryptionUtils().encrypted("HJUSER153");
System.out.println("Encrypted String:" + encyString);
}
public String encrypted(String strToEncrypt) {
try {
IvParameterSpec ivspec = new IvParameterSpec(ENCRYPTION_KEY.getBytes());
SecretKeySpec keyspec = new SecretKeySpec(ENCRYPTION_KEY.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
//encrypted = cipher.doFinal(text.getBytes());
} catch (Exception e) {
System.out.println("\nException while encrypting " + strToEncrypt + " \nerror: " + e.getMessage());
}
return null;
}
}
iOS Swift Code
Add this in pod file -
pod 'CryptoSwift'
import CryptoSwift
func decrypt(input:String)->String?{
let key = "1234512345123456"
do{
let d=Data(base64Encoded: input)
let decrypted = try AES(key: key, iv: key, padding: .pkcs5).decrypt(
d!.bytes)
return String(data: Data(decrypted), encoding: .utf8)
}catch{
}
return nil
}
Android
import android.util.Base64
import java.security.NoSuchAlgorithmException
import javax.crypto.Cipher
import javax.crypto.NoSuchPaddingException
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
class CypherHelper {
private var ivspec: IvParameterSpec? = null
private var keyspec: SecretKeySpec? = null
private var cipher: Cipher? = null
private val ENCRYPTION_KEY: String = "1234567890123456"
init {
ivspec = IvParameterSpec(ENCRYPTION_KEY.toByteArray(Charsets.UTF_8))
keyspec = SecretKeySpec(ENCRYPTION_KEY.toByteArray(), "AES")
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: NoSuchPaddingException) {
e.printStackTrace()
}
}
fun decrypt(valueToDecrypt: String): String {
var decryptValue: String = ""
val enc = CypherHelper()
if (valueToDecrypt.isEmpty())
decryptValue = String(enc.decryptInternal(valueToDecrypt)!!)
return decryptValue
}
private fun decryptInternal(code: String?): ByteArray? {
if (code == null || code.isEmpty()) {
throw Exception("Empty string")
}
var decrypted: ByteArray? = null
try {
cipher?.init(Cipher.DECRYPT_MODE, keyspec, ivspec)
decrypted = cipher?.doFinal(Base64.decode(code, Base64.DEFAULT))
} catch (e: Exception) {
throw Exception("[decrypt] " + e.message)
}
return decrypted
}
}

How to decrypt string using Java that the string was encrypred by gpg?

My problem is with symmetric decryption. Not asymmetric decryption. So the correct answer is here Decrypt PGP encrypted file with passphrase only in Java
I use gpg to encrypt "hello":
[root#shc-sma-cd13 opt]# echo "hello" | gpg --symmetric --armor --cipher-algo AES256 --passphrase "2R79P7z5f8350VEp" --batch
-----BEGIN PGP MESSAGE-----
Version: GnuPG v2.0.22 (GNU/Linux)
jA0ECQMC1XpaSrXhBAfU0jsBXw817k4k4iT++AGV8MUev4/gKkuIwAW2VaJsEANa
+0ZuqZgFp/8N7AndRhyNj5WGcloQQkLkwvIV3Q==
=GwQi
-----END PGP MESSAGE-----
I use Java to decrypt the string:
public class AESUtils1 {
private static final String KEY_VAL = "2R79P7z5f8350VEp";
public static String AESDecode(String content) {
try {
SecretKey key = new SecretKeySpec(KEY_VAL.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] byte_content = new BASE64Decoder().decodeBuffer(content);
byte[] byte_decode = cipher.doFinal(byte_content);
String AES_decode = new String(byte_decode, "utf-8");
return AES_decode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
//如果有错就返加nulll
return null;
}
public static void main(String[] args) {
String encryptString = "jA0ECQMC1XpaSrXhBAfU0jsBXw817k4k4iT++AGV8MUev4/gKkuIwAW2VaJsEANa\n" +
" +0ZuqZgFp/8N7AndRhyNj5WGcloQQkLkwvIV3Q==\n" +
" =GwQi";
String decryptString = AESDecode(encryptString);
System.out.println("decryptString: " + decryptString);
}
}
But it fails with error message:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at com.hpe.itsma.itsmaInstaller.AESUtils1.AESDecode(AESUtils1.java:33)
at com.hpe.itsma.itsmaInstaller.AESUtils1.main(AESUtils1.java:57)
decryptString: null
I am curious that what is the real encrypted string from gpg that I can put it into Java. The output of gpg is different from using Java to encrypt "hello".
And another interesting thing is that every time I run command echo "hello" | gpg --symmetric --armor --cipher-algo AES256 --passphrase "2R79P7z5f8350VEp" --batch, the result is always different. Is that possible to decrypt the string which is encrypted by gpg. Or the wrong way I used of gpg?
Thanks all. Finally, I figure out the solution. Cause my data was symmetric encrypted. The decryption will be different from the asymmetric decryption. I put my code below, also you can find the same answer here Decrypt PGP encrypted file with passphrase only in Java
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
import org.bouncycastle.util.io.Streams;
import java.io.*;
import java.security.NoSuchProviderException;
import java.security.Security;
public class SymmetricDecyption {
public static byte[] decrypt(byte[] var0, char[] var1) throws IOException, PGPException, NoSuchProviderException {
ByteArrayInputStream var2 = new ByteArrayInputStream(var0);
InputStream var11 = PGPUtil.getDecoderStream(var2);
PGPObjectFactory var3 = new PGPObjectFactory(var11);
Object var5 = var3.nextObject();
PGPEncryptedDataList var4;
if (var5 instanceof PGPEncryptedDataList) {
var4 = (PGPEncryptedDataList) var5;
} else {
var4 = (PGPEncryptedDataList) var3.nextObject();
}
PGPPBEEncryptedData var6 = (PGPPBEEncryptedData) var4.get(0);
InputStream var7 = var6.getDataStream((new JcePBEDataDecryptorFactoryBuilder((new JcaPGPDigestCalculatorProviderBuilder()).setProvider("BC").build())).setProvider("BC").build(var1));
PGPObjectFactory var8 = new PGPObjectFactory(var7);
PGPCompressedData var9 = (PGPCompressedData) var8.nextObject();
var8 = new PGPObjectFactory(var9.getDataStream());
PGPLiteralData var10 = (PGPLiteralData) var8.nextObject();
return Streams.readAll(var10.getInputStream());
}
public static void main(String[] var0) throws Exception {
String password = "2R79P7z5f8350VEp";
File file = new File("C:\\Users\\zhongtao.CORPDOM\\Desktop\\file.txt.asc");
InputStream input = new FileInputStream(file);
byte[] byt = new byte[input.available()];
input.read(byt);
Security.addProvider(new BouncyCastleProvider());
byte[] var5 = decrypt(byt, password.toCharArray());
System.out.println("Decrypted data is: " + new String(var5));
}
}

Android Studio cannot decrypt message in AES

hi, i try to implement aes in some open source code messaging application. for encrypted message, its work find to me. but i have difficulty to decrypt back message.
in this class, i can encrypted message and it work fine.
MessageActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.message);
messageView = (TextView) findViewById(R.id.message_view);
final Button button = (Button) findViewById(R.id.btn_send);
final EditText message = (EditText) findViewById(R.id.edit_message);
this.setTitle("Group Chat");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String str = message.getText().toString();
byte[] cipherText = null;
try {
cipherText = AESEncryption.encryptText(str, AESEncryption.thisKey());
} catch (Exception e) {
e.printStackTrace();
}
String msgStr = new String(cipherText);
addMessage("This phone", str);
message.setText("");
// Send to other clients as a group chat message
for (AllEncompasingP2PClient c : MeshNetworkManager.routingTable.values()) {
if (c.getMac().equals(MeshNetworkManager.getSelf().getMac()))
continue;
Sender.queuePacket(new Packet(Packet.TYPE.MESSAGE, msgStr.getBytes(), c.getMac(),
WiFiDirectBroadcastReceiver.MAC));
}
}
});
Receiver.java
/////////////// this messsage receiver part///////////////////////
byte[] thisMsg = p.getData();
String decryptedText = null;
try {
decryptedText = AESEncryption.decryptText(thisMsg, AESEncryption.thisKey());
} catch (Exception e) {
e.printStackTrace();
}
final String message = p.getSenderMac() + " says:\n" + decryptedText;
final String msg = new String(p.getData());
final String name = p.getSenderMac();
//////////////////////////////////////
if (!MeshNetworkManager.routingTable.contains(p.getSenderMac())) {
/*
* Update your routing table if for some reason this
* guy isn't in it
*/
MeshNetworkManager.routingTable.put(p.getSenderMac(),
new AllEncompasingP2PClient(p.getSenderMac(), p.getSenderIP(),
p.getSenderMac(),
MeshNetworkManager.getSelf().getGroupOwnerMac()));
}
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (activity.isVisible) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
} else {
MessageActivity.addMessage(name, msg);
}
}
});
updatePeerList();
AESEncryption.java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
//import javax.xml.bind.DatatypeConverter;
public class AESEncryption {
public static SecretKey getSecretEncryptionKey() throws Exception{
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
SecretKey secKey = generator.generateKey();
return secKey;
}
public static byte[] encryptText(String plainText,SecretKey secKey) throws Exception{
// AES defaults to AES/ECB/PKCS5Padding in Java 7
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
return byteCipherText;
}
public static String decryptText(byte[] byteCipherText, SecretKey secKey) throws Exception {
// AES defaults to AES/ECB/PKCS5Padding in Java 7
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.DECRYPT_MODE, secKey);
byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
return new String(bytePlainText);
}
public static SecretKey thisKey() throws Exception{
SecretKey secKey = AESEncryption.getSecretEncryptionKey();
return secKey;
}
}
in this class where i code the decrypted message. but when i run the code, the messages not decrypt and show ciphert text instead.if someone can correct me, its will great.
The same key must be used for both encryption and decryption for the same message.
It seems the same key is not being used for both encryption and decryption, both methods call SecretKey thisKey() which seems to generate a random key.
On encryption call SecretKey thisKey(), use it for encryption and save the key to use on decryption. On decryption do not call SecretKey thisKey(), use the key created for encryption.

How securely store sensitive data (short string) into keystore

I need to store sensitive datas (little string) into the keystore.
The example described here is pretty much exactly what I need to do.
Problem: I don't understand it very well, I'm totally newbie in that subject (Cipher, encryption, RSA...)
https://medium.com/#ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3#.oqvxbjn8m
So this is the class that I'm working on (based on this article mentioned here above) :
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.security.KeyPairGeneratorSpec;
import android.security.keystore.KeyProperties;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Calendar;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.x500.X500Principal;
public class SecondActivity extends AppCompatActivity {
static final String TAG = "SimpleKeystoreApp";
static final String CIPHER_PROVIDER = "AndroidOpenSSL";
private static final String RSA_MODE = "RSA/ECB/PKCS1Padding";
private static final String AES_MODE = "AES/ECB/PKCS7Padding";
private static final String KEY_ALIAS = "this is my alias";
private static final String SHARED_PREFENCE_NAME = "my shared_prefs";
private static final String ENCRYPTEDKEY_KEY = "encrypted_key";
private static final String TO_BE_ENCRYPTED_KEY = "this is my test";
private static final String ANDROID_KEYSTORE = "AndroidKeyStore";
KeyStore keyStore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
keyStore.load(null);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
createNewKeys();
try {
generateAndStoreAESKey();
} catch (Exception e) {
Log.d(TAG, "couldn't generateAndStoreAESKey:" + e.getMessage());
}
String encrypted = null;
try {
encrypted = encrypt(getApplicationContext(), TO_BE_ENCRYPTED_KEY.getBytes());
Log.d(TAG, "encrypted:" + encrypted);
} catch (Exception e) {
Log.d(TAG, "couldn't encrypt:" + e.getMessage());
}
try {
decrypt(getApplicationContext(), encrypted.getBytes());
Log.d(TAG, "decrypted:" + encrypted);
} catch (Exception e) {
Log.d(TAG, "couldn't decrypt:" + e.getMessage());
}
setContentView(R.layout.activity_main);
}
public void createNewKeys() {
Log.d(TAG, "___ createNewKeys");
try {
// Create new key if needed
// Generate the RSA key pairs
keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
keyStore.load(null);
// Generate the RSA key pairs
if (!keyStore.containsAlias(KEY_ALIAS)) {
// Generate a key pair for encryption
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 30);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
.setAlias(KEY_ALIAS)
.setSubject(new X500Principal("CN=" + KEY_ALIAS))
.setSerialNumber(BigInteger.TEN)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE);
kpg.initialize(spec);
kpg.generateKeyPair();
KeyPair keyPair = kpg.generateKeyPair();
Log.d(TAG, "Public Key is: " + keyPair.getPublic().toString());
}
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occured", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
private void generateAndStoreAESKey() throws Exception{
Log.d(TAG, "___ generateAndStoreAESKey");
SharedPreferences pref = getApplicationContext().getSharedPreferences(SHARED_PREFENCE_NAME, Context.MODE_PRIVATE);
String enryptedKeyB64 = pref.getString(ENCRYPTEDKEY_KEY, null);
if (enryptedKeyB64 == null) {
byte[] key = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(key);
byte[] encryptedKey = rsaEncrypt(key);
enryptedKeyB64 = Base64.encodeToString(encryptedKey, Base64.DEFAULT);
SharedPreferences.Editor edit = pref.edit();
edit.putString(ENCRYPTEDKEY_KEY, enryptedKeyB64);
edit.commit();
}
}
private SecretKeySpec getSecretKey(Context context) throws Exception{
SharedPreferences pref = context.getSharedPreferences(SHARED_PREFENCE_NAME, Context.MODE_PRIVATE);
String enryptedKeyB64 = pref.getString(ENCRYPTEDKEY_KEY, null);
// need to check null, omitted here
byte[] encryptedKey = Base64.decode(enryptedKeyB64, Base64.DEFAULT);
byte[] key = rsaDecrypt(encryptedKey);
return new SecretKeySpec(key, "AES");
}
public String encrypt(Context context, byte[] input) throws Exception{
Cipher c = Cipher.getInstance(AES_MODE, "BC");
c.init(Cipher.ENCRYPT_MODE, getSecretKey(context));
byte[] encodedBytes = c.doFinal(input);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
return encryptedBase64Encoded;
}
public byte[] decrypt(Context context, byte[] encrypted) throws Exception{
Cipher c = Cipher.getInstance(AES_MODE, "BC");
c.init(Cipher.DECRYPT_MODE, getSecretKey(context));
byte[] decodedBytes = c.doFinal(encrypted);
return decodedBytes;
}
private byte[] rsaEncrypt(byte[] secret) throws Exception{
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
// Encrypt the text
Cipher inputCipher = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);
inputCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, inputCipher);
cipherOutputStream.write(secret);
cipherOutputStream.close();
byte[] vals = outputStream.toByteArray();
return vals;
}
private byte[] rsaDecrypt(byte[] encrypted) throws Exception {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
Cipher output = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(encrypted), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
return bytes;
}
}
I have a InvalidKeyException: Need RSA private or public key being thrown when I call
outputCipher.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
in
private byte[] rsaDecrypt(byte[] encrypted)
So I need to be able to decrypt the private key stored in the keystore, but this operation gives me an error.
I don't understand why. Maybe there is something wrong in the flow?
Please explain me in simple words what I'm doing wrong.
#Robert answer in a comment resolved my issue:
I removed CIPHER_PROVIDER from
Cipher inputCipher = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);

AESDecryption in Blackberry

I have an application which displays image downloaded from server. the image is encrypted and kept in the server using AES. I need to decrypt the image at the client side. The code used for encryption is as follows
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
public class Crypto {
Cipher ecipher;
Cipher dcipher;
/**
* Input a string that will be md5 hashed to create the key.
* #return void, cipher initialized
*/
public Crypto(){
try{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
this.setupCrypto(kgen.generateKey());
} catch (Exception e) {
e.printStackTrace();
}
}
public Crypto(String key){
SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
this.setupCrypto(skey);
}
private void setupCrypto(SecretKey key){
try
{ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ecipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
dcipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// Buffer used to transport the bytes from one stream to another
byte[] buf = new byte[1024];
public void encrypt(InputStream in, OutputStream out){
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0){
out.write(buf, 0, numRead);
}
out.close();
}
catch (java.io.IOException e){
e.printStackTrace();
}
}
public void decrypt(InputStream in, OutputStream out){
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
private static byte[] getMD5(String input){
try{
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(bytesOfMessage);
} catch (Exception e){
return null;
}
}
public static void main(String args[]){
try {
Crypto encrypter = new Crypto("yursxjdlbkuikeqe"); ///key for decryption logic
encrypter.encrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg.pkcs5"));
encrypter.decrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg.pkcs5"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg"));
System.out.println("DONE");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I am not able to decrypt this using Blackberry AESDecryptor Engine. I am new to this crypto graphy. Is it possible to decrypt using AESDecryptor engine. I am attaching the code which I am using. Please help me in solving this
public MyScreen(){
// Set the displayed title of the screen
setTitle("MyTitle");
byte[] keyData = new String("yursxjdlbkuikeqe").getBytes();
byte[] cipherText = openFile("file:///SDCard/Lighthouse.jpg.pkcs5");
try {
imageData = decrypt(keyData, cipherText);
} catch (CryptoException e) {
System.out.println("::::::::::::::::::::::::::::::::::Crypto Exception:::::::"+e.getMessage());
} catch (IOException e) {
System.out.println("::::::::::::::::::::::::::::::::::IO Exception:::::::"+e.getMessage());
}
if(imageData!=null){
writeByteData(imageData);
// EncodedImage image = EncodedImage.createEncodedImage(imageData, 0, imageData.length);
// add(new BitmapField(image.getBitmap()));
System.out.println("------------------Image saved successfully-----------");
}else{
System.out.println("-------------------Image Data is null");
}
}
public static byte[] decrypt(byte[] keyData, byte[] ciphertext) throws CryptoException, IOException {
// First, create the AESKey again.
/*String str=new String(keyData);
System.out.println(str);*/
AESKey key = new AESKey(keyData,0,128);
System.out.println("Key is ::"+key.getAlgorithm()+"Length:"+key.getBitLength());
//
// // Now, create the decryptor engine.
AESDecryptorEngine engine = new AESDecryptorEngine(key);
PKCS5UnformatterEngine uengine = new PKCS5UnformatterEngine(engine);
/
// // Create the BlockDecryptor to hide the decryption details away.
ByteArrayInputStream input = new ByteArrayInputStream(ciphertext);
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
byte[] plaintextAndHash = new byte[1024];
ByteArrayOutputStream output = new ByteArrayOutputStream();
int bytesRead=0;
do{
bytesRead =decryptor.read(plaintextAndHash);
if(bytesRead!=-1){
output.write(plaintextAndHash,0,bytesRead);
}
}
while(bytesRead!=-1);
return output.toByteArray();
}
You don't really say what your problem is, but at least the following line looks incorrect:
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
It should be
BlockDecryptor decryptor = new BlockDecryptor(uengine, input);
I just changed engine to uengine
RIM's APIs make this pretty easy but it is a little tough to find the documentation. Check out the Javadocs for the package net.rim.device.api.crypto at:
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/package-summary.html
You should look through all of it but the answer is in number 7: Encryptor and decryptor factories.
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/doc-files/factories.html
The DecryptorFactory can create an input stream that you can just read as any InputStream.

Categories

Resources