How to encrypt without a random number in Android - android

I currently have an accessory that uses AES/CBC without a random number on the key. Instead, the message itself includes a random number and the key is hard-coded. I'm trying to do the same thing on my Android to exchange with the accessory through BLE. Somehow I can't figure out how generate a Key-class object without using a random number.
Here's an example of what I'd like to be able to do:
public byte[] encrypt(byte[] key, byte[] input) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding ");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(input);
}
Here's what I've tried:
public byte[] encrypt(byte[] key, byte[] input) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom(key);
secureRandom.setSeed(key);
keyGenerator.init(128, secureRandom);
SecretKey secretkey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding ");
cipher.init(Cipher.ENCRYPT_MODE, secretkey);
return cipher.doFinal(input);
}
public byte[] encrypt(byte[] key, byte[] input) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES/CBC/NoPadding ");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding ");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(input);
}
Unfortunately both of those alter the key before the encryption.
How can I use my key "as is"?

If you want to encrypt with your own key without salt or using any random, you can do as following.
byte[] keyBuf= new byte[32];
byte[] b= key.getBytes("UTF-8");
int len= b.length;
if (len > keyBuf.length) len = keyBuf.length;
System.arraycopy(b, 0, keyBuf, 0, len);
SecretKey keySpec = new SecretKeySpec(keyBuf, "AES");
byte[] ivBuf= new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(ivBuf);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
Where key is my custom key as a String and b my key as a bytes[]. Initializing the cipher this way avoid the salting and allow you to always use your own key to encrypt anything.

Related

PBKDF2 Key Derivative in Android Studio is not working

I am trying to implement PBKDF2 with Hmac Sha1 in my android app for encrypting the password.
But the encoded key is too short and returns incorrect value comparing to what i get from https://8gwifi.org/pbkdf.jsp website.
Below is the code i use
char [] salt="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".toCharArray();
byte [] serversalt="E4jmftOIsX4TYB6qPUuX6VteIKExLfgQ9I9DTY5VbOTRT7NGqrgc!1130053051!1657429480328".getBytes();
try {
SecretKey sk=generateKey1(salt,serversalt);
System.out.println("key:"+sk.getEncoded().toString());
}catch (Exception e){ System.out.println(e.toString());
public static SecretKey generateKey1(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, 4, 128);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
Expected key is 7b3318d9fedb813a3c474ec043681fef
but i'm getting [B#b5971bf
Try use:
SecretKey sk = generateKey1(salt,serversalt);
String key = Base64.encodeToString(sk.getEncoded(), Base64.DEFAULT);
In my case is working and key is the same as i get from https://8gwifi.org/pbkdf.jsp website.

Android SecretKey to String and back

I need to know how to generate a String of a SecretKey and convert it back into a SecretKey.
I first generated a SecretKey using the KeyGenerator like in the code below and I used it and it worked, but I also saved the SecretKey as a private value using getEncoded(). Now when I regenerate the SecretKey and use it in my code I get the error:
W/System.err: java.security.InvalidKeyException: Unsupported key size: 43 bytes
I thought the following code should result in logging two equivalent Strings, but it does not.
KeyGenerator keyGen = null;
keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key= keygen.generateKey();
byte[] keyBytes = key.getEncoded();
SecretKey keyCopy = new SecretKeySpec(keyBytes, "AES");
Log.d("key string: ", key.getEncoded().toString());
Log.d("keyCopy string: ", keyCopy.getEncoded().toString());
As per the comments I edited the above code from byte[] keyBytes = key.getEncoded().toString().getBytes(); to byte[] keyBytes = key.getEncoded(); removing redundancy.
As the comments have stated. toString() does not return a representation of the object itself, in this case, but something variable. While it returns values that differ for each byte array, encoding them into base65 using Base64.encodeToString(key.getEncoded(), Base64.DEFAULT) results in equivalent representations of both the original key and its copy.
KeyGenerator keyGen = null;
keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key= keygen.generateKey();
byte[] keyBytes = key.getEncoded();
SecretKey keyCopy = new SecretKeySpec(keyBytes, "AES");
Log.d("key string: ", Base64.encodeToString(key.getEncoded(), Base64.DEFAULT));
Log.d("keyCopy string: ", Base64.encodeToString(keyCopy.getEncoded(), Base64.DEFAULT));

Cross platform AES/CBC encryption decryption between openssl C and android

I just want AES/CBC 128 bit encryption decryption in openSSl c and Android with identical result.
I have to send encrypted data using pre defined 16 bytes key from android to c via bluetooth.
So is there any common mechanism which i can use in both to produce identical result of encryption and decryption.
Any help would be appreciate.
Thank you.
I found a solution which work perfectly for Android.
I am going to post the answer if it would help anyone.
static String IV = "AAAAAAAAAAAAAAAA";
static String encryptionKey = "0123456789ABCDEF";
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding"/*, "SunJCE"*/);
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding"/*, "SunJCE"*/);
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
//To Encrypt
byte[] cipher = encrypt(plaintext, encryptionKey);
System.out.print("cipher: ");
//To Decrypt
String decrypted = decrypt(cipher, encryptionKey);
System.out.println("decrypt: " + decrypted);

Decryption Output has strange symbols

I am working on encrypting (and later decrypting) strings in .Net and Java (on Android), using AES encryption , in the .Net side every thing is OK, in the Android(Java) side the output string of the posted code has unknown symbols.
String stdiv = "1234567890123456";
String txtinput = txtview1.getText().toString();
String mainkey = "0000999988887777";
byte[] key;
key = mainkey.getBytes("UTF8");
byte[] iv = stdiv.getBytes("UTF8");
byte[] input = txtinput.getBytes("UTF8");
Cipher cipher;
cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");
SecretKeySpec keyspec = new SecretKeySpec(key, "AES" );
IvParameterSpec paramspec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keyspec, paramspec);
byte[] result = cipher.doFinal(input);
String str=new String(result,"UTF8");
txtview2.setText(str);

android encryption

I want to encrypt/decrypt some passwords in the SQLite database of my application. To do that I have searched on the internet and I have found the AES algorithm.
I have this code:
public String encript(String dataToEncrypt)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// I'm using AES encription
if(!dataToEncrypt.equals("")){
String key = "FMVWf8d_sm#fz";
Cipher c = Cipher.getInstance("AES");
SecretKeySpec k;
try {
k = new SecretKeySpec(key.getBytes(), "AES");
c.init(Cipher.ENCRYPT_MODE, k);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new String(c.doFinal(Base64.decode(dataToEncrypt)));
}
return "";
}
public String decript(String encryptedData)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
if(!encryptedData.equals("")){
String key = "FMVWf8d_sm#fz";
Cipher c = Cipher.getInstance("AES");
SecretKeySpec k = new SecretKeySpec(Base64.decode(key), "AES");
c.init(Cipher.DECRYPT_MODE, k);
return new String(c.doFinal(Base64.decode(encryptedData)));
}
return "";
}
After running this I get this error on encrypt method:
01-27 14:50:51.698: ERROR/ACTIVITY(782):
java.security.InvalidKeyException: Key length not 128/192/256 bits.
I have seen some other cases here on stackoverflow but I want to give the key to the AES not to generate it...
Can somebody help me with this? If there is other encryption method to use but without using another jars or external classes and to let me give the key.
Thank you very much!
The error message makes it perfectly clear: your encryption key must be of certain size: 128, 192 or 256 bits. And your key is 104 bits. Note, that as you want to use only printable characters in your key, the length of the key should be 192 or longer bits, cause your alphabet (set of characters that you use) makes encryption weaker.
Usual practice is such:
Get password (in your case String key = "FMVWf8d_sm#fz";)
Generate using some hash function key with length 128, 192 or 256
Put it into encryption algorithm
Have fun
So you are missing key generation stage. Do smth like:
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
// Instantiate the cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted =
cipher.doFinal((args.length == 0 ?
"This is just an example" : args[0]).getBytes());
System.out.println("encrypted string: " + asHex(encrypted));
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original =
cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " +
originalString + " " + asHex(original));

Categories

Resources