I tried to encrypt plaintext using the below code. The code seems encrypt the text but it doesnt decrypt to plaintext back. What am I doing wrong ?
The code:
Entity entity = new Entity("password");
byte[] ciphertext = crypto.encrypt(("data to encrypt").getBytes(),entity);
plaintext = crypto.decrypt(ciphertext,entity)
Output:
Ecrypted text:[B#417a110
Decrypted text:[B#417df20
The following code can encrypt/decrypt string
KeyChain keyChain = new SharedPrefsBackedKeyChain(context, CryptoConfig.KEY_256);
crypto = AndroidConceal.get().createDefaultCrypto(keyChain);
public static String encrypt(String key, String value) throws KeyChainException, CryptoInitializationException, IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
OutputStream cryptoStream = crypto.getCipherOutputStream(bout, Entity.create(key));
cryptoStream.write(value.getBytes("UTF-8"));
cryptoStream.close();
String result = Base64.encodeToString(bout.toByteArray(), Base64.DEFAULT);
bout.close();
return result;
}
public static String decrypt(String key, String value) throws KeyChainException, CryptoInitializationException, IOException {
ByteArrayInputStream bin = new ByteArrayInputStream(Base64.decode(value, Base64.DEFAULT));
InputStream cryptoStream = crypto.getCipherInputStream(bin, Entity.create(key));
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int read = 0;
byte[] buffer = new byte[1024];
while ((read = cryptoStream.read(buffer)) != -1) {
bout.write(buffer, 0, read);
}
cryptoStream.close();
String result = new String(bout.toByteArray(), "UTF-8");
bin.close();
bout.close();
return result;
}
I have found the answer.
The reason is we were printing the byte array instead of the String.
The array is going to comprise of a set of bytes so that's what we saw when we printed them out in the logcat.
To see the actual String, we just need to put the byte[] into a new String(byte[]) - this is taken from the official facebook examples with my modifications:
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(getActivity()),
new SystemNativeCryptoLibrary());
if (!crypto.isAvailable()) {
Log.e("Crypto","Crypto is missing");
}
String password = "Password";
Entity entity = new Entity("TEST");
byte[] encryptedPass = new byte[0];
byte[] b = password.getBytes(Charset.forName("UTF-8"));
try {
encryptedPass = crypto.encrypt(b, entity);
Log.e("Crypto Encrypted", new String(encryptedPass));
byte[] decryptedPass = crypto.decrypt(encryptedPass, entity);
Log.e("Crypto Decrypted ", new String(decryptedPass));
} catch (KeyChainException e) {
e.printStackTrace();
} catch (CryptoInitializationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Results:
08-02 19:31:11.237 29364-29364/? E/Crypto Encrypted﹕
0��&�?B�6���H���`��"�1��xx� 08-02 19:31:11.237 29364-29364/?
E/Crypto Decrypted﹕ Password
Base64.encodeToString(cipherText, Base64.DEFAULT); then store it.
It might be a little too late but I had the same issue and managed to get the plain text after the decryption.
What you really need to do is to use ByteArrayOutputStream like the following code:
Entity entity = new Entity("password");
byte[] ciphertext = crypto.encrypt(("data to encrypt").getBytes(),entity);
byte[] plainText = crypto.decrypt(ciphertext,entity);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(plainText, 0, plainText.length);
String decryptedPassword = out.toString();
out.close();
Hope this helps.
Related
As files in android assets can be easily hacked by converting .apk to .zip. I have some propitiatory model which I need to use in android application. I am working on how to encrypt the assets of the application. ( I will use firebase for retreiving the key for decryption to make it more secure )
I am pretty successful in encrypting and decrypting images (png and jpg) using cipher library in android.
Following is the code which I used for the purpose.
String fake = "sadhkja6";
byte[] encodedKey = Base64.decode(fake, Base64.DEFAULT);
yourKey= new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id);
bitmap = Bitmap.createScaledBitmap(bitmap, 500,500, true);
byte[] output = getBytes(bitmap);
byte[] output = getBytesFile();
saveFile(output);
public static byte[] encodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(
new byte[cipher.getBlockSize()]));
encrypted = cipher.doFinal(fileData);
return encrypted;
}
public byte[] getBytes(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress( Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bitmap.recycle();
return byteArray;
}
public static byte[] encodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(
new byte[cipher.getBlockSize()]));
encrypted = cipher.doFinal(fileData);
return encrypted;
}
void saveFile(byte[] array) {
String decrypted_file = "encypted.png";
try {
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator, decrypted_file);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
yourKey = generateKey();
byte[] filesBytes = encodeFile(yourKey, array);
bos.write(filesBytes);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
But when I use the same code for encyrpting tensorflow models, the model is not successfully decompiled resulting in app crash. Most probably because we are loading the model in bytes which may cause problems.
Please tell me how can I use the cyphering technique for securing my tensorflow model. Thank you very much.
I am trying to compress a large string object. This is what i tried, but i am unable to understand how to get compressed data, and how to define different type of compression tools.
This is what i got from Android docs.
byte[] input = jsonArray.getBytes("UTF-8");
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
compresser.end();
compresser.deflate(output) gives me a int number, 100
but i am unable to understand which method will give me the compressed output that i can send to service.
The algorithm that I compress my data with is Huffman. You can find it by a simple search. But in your case maybe it helps you:
public static byte[] compress(String data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data.getBytes());
gzip.close();
byte[] compressed = bos.toByteArray();
bos.close();
return compressed;
}
And to decompress it you can use:
public static String decompress(byte[] compressed) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
The documentation for Deflator shows that the output gets put into the buffer output
try {
// Encode a String into bytes
String inputString = "blahblahblah";
byte[] input = inputString.getBytes("UTF-8");
// Compress the bytes
byte[] output = new byte[100];
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
compresser.end();
// Decompress the bytes
Inflater decompresser = new Inflater();
decompresser.setInput(output, 0, compressedDataLength);
byte[] result = new byte[100];
int resultLength = decompresser.inflate(result);
decompresser.end();
// Decode the bytes into a String
String outputString = new String(result, 0, resultLength, "UTF-8");
} catch(java.io.UnsupportedEncodingException ex) {
// handle
} catch (java.util.zip.DataFormatException ex) {
// handle
}
all code you need to ENCODE, COMPRESS , DECOMPRESS , DECODE
I creating an application in which I am using mandrill app API to send emails. Emails without attachment are delivering, but when I attach image to it, it is received as damaged image at receiver side. Here it is required to convert file into base64 string to pass in json array. I used this code:
public static String encodeImagetoBase64(Bitmap img) {
Bitmap image = img;
ByteArrayOutputStream byteOStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, byteOStream);
byte[] b = byteOStream.toByteArray();
String imageEncoded = Base64.encodeToString(b, Base64.DEFAULT);
Log.e("Look", imageEncoded);
return imageEncoded;
}
So can anyone tell me the solution, why image is getting damaged.
Similarly I also want to convert files with extension ".txt,.doc,.docx,.pptx,.pdf,.xls" etc as attachment, so please suggest me any source for that. Thanx
I am using this method and it is working:
public static String getFileBinary(String uploadFilePath) {
String encodedString = "0";
if (uploadFilePath.length() < 2)
return encodedString;
try {
InputStream inputStream = new FileInputStream(uploadFilePath);//You can get an inputStream using any IO API
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
bytes = output.toByteArray();
encodedString = Base64.encodeToString(bytes, Base64.DEFAULT);
} catch (IOException es) {
}
return encodedString;
}
Here the report contain the path(pathname in sdcard in string format)
File dir = Environment.getExternalStorageDirectory();
File yourFile = new File(dir, report);
String encodeFileToBase64Binary = encodeFileToBase64Binary(yourFile);
private static String encodeFileToBase64Binary(File fileName) throws IOException {
byte[] bytes = loadFile(fileName);
byte[] encoded = Base64.encodeBase64(bytes);
String encodedString = new String(encoded);
return encodedString;
}
in the byte[] encoded line getting this error.
The method encodeBase64(byte[]) is undefined for the type Base64
String value = Base64.encodeToString(bytes, Base64.DEFAULT);
But you can directly convert it in to String .Hope this will work for you.
An updated, more efficient, Kotlin version, that bypasses Bitmaps and doesn't store entire ByteArray's in memory (risking OOM errors).
fun convertImageFileToBase64(imageFile: File): String {
return ByteArrayOutputStream().use { outputStream ->
Base64OutputStream(outputStream, Base64.DEFAULT).use { base64FilterStream ->
imageFile.inputStream().use { inputStream ->
inputStream.copyTo(base64FilterStream)
}
}
return#use outputStream.toString()
}
}
I believe these 2 sample codes will help at least someone the same way many have helped me through this platform. Thanks to StackOverflow.
// Converting Bitmap image to Base64.encode String type
public String getStringImage(Bitmap bmp) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
return encodedImage;
}
// Converting File to Base64.encode String type using Method
public String getStringFile(File f) {
InputStream inputStream = null;
String encodedFile= "", lastVal;
try {
inputStream = new FileInputStream(f.getAbsolutePath());
byte[] buffer = new byte[10240];//specify the size to allow
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
encodedFile = output.toString();
}
catch (FileNotFoundException e1 ) {
e1.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
lastVal = encodedFile;
return lastVal;
}
I will be glad to answer any question regarding to these codes.
To convert a file to Base64:
File imgFile = new File(filePath);
if (imgFile.exists() && imgFile.length() > 0) {
Bitmap bm = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bOut);
String base64Image = Base64.encodeToString(bOut.toByteArray(), Base64.DEFAULT);
}
Convert Any file, image or video or text into base64
1.Import the below Dependancy
compile 'commons-io:commons-io:2.4'
2.Use below Code to convert file to base64
File file = new File(filePath); //file Path
byte[] b = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(b);
for (int j = 0; j < b.length; j++) {
System.out.print((char) b[j]);
}
} catch (FileNotFoundException e) {
System.out.println("File Not Found.");
e.printStackTrace();
} catch (IOException e1) {
System.out.println("Error Reading The File.");
e1.printStackTrace();
}
byte[] byteFileArray = new byte[0];
try {
byteFileArray = FileUtils.readFileToByteArray(file);
} catch (IOException e) {
e.printStackTrace();
}
String base64String = "";
if (byteFileArray.length > 0) {
base64String = android.util.Base64.encodeToString(byteFileArray, android.util.Base64.NO_WRAP);
Log.i("File Base64 string", "IMAGE PARSE ==>" + base64String);
}
You can try this.
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
...
byte[] byteArray = byteArrayOutputStream.toByteArray();
base64Value = Base64.encodeToString(byteArray, Base64.DEFAULT);
public static String uriToBase64(Uri uri, ContentResolver resolver, boolean thumbnail) {
String encodedBase64 = "";
try {
byte[] bytes = readBytes(uri, resolver, thumbnail);
encodedBase64 = Base64.encodeToString(bytes, 0);
} catch (IOException e1) {
e1.printStackTrace();
}
return encodedBase64;
}
private static byte[] readBytes(Uri uri, ContentResolver resolver, boolean thumbnail)
throws IOException {
// this dynamically extends to take the bytes you read
InputStream inputStream = resolver.openInputStream(uri);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
if (!thumbnail) {
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
// we need to know how may bytes were read to write them to the
// byteBuffer
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
} else {
Bitmap imageBitmap = BitmapFactory.decodeStream(inputStream);
int thumb_width = imageBitmap.getWidth() / 2;
int thumb_height = imageBitmap.getHeight() / 2;
if (thumb_width > THUMBNAIL_SIZE) {
thumb_width = THUMBNAIL_SIZE;
}
if (thumb_width == THUMBNAIL_SIZE) {
thumb_height = ((imageBitmap.getHeight() / 2) * THUMBNAIL_SIZE)
/ (imageBitmap.getWidth() / 2);
}
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, thumb_width, thumb_height, false);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteBuffer);
}
// and then we can return your byte array.
return byteBuffer.toByteArray();
}
and call it in this way
String image = BitmapUtils.uriToBase64(Uri.fromFile(file), context.getContentResolver());
I want to encrypt / decrypt files ( of reasonable size ). I have my code working corrects using AES/CBC/PKCS5Padding . The problem is that it takes really long time to encrypt big files. SO now I am planning to use openSSL.
Is there a link that explains how to use openssl from a java app? How can I integrate it to my java app?
Thanks a lot for any links / points in this regard.
Thanks for your help and time
My code using BC:
public class BouncyCastleProvider_AES_CBC {
public Cipher encryptcipher, decryptCipher;
String TAG = "DataEncryptDecrypt";
private static final String RANDOM_ALGORITHM = "SHA1PRNG";
// The default block size
public static int blockSize = 16;
// Buffer used to transport the bytes from one stream to another
byte[] buf = new byte[blockSize]; //input buffer
byte[] obuf = new byte[512]; //output buffer
// The key
byte[] key = null;
// The initialization vector needed by the CBC mode
byte[] IV = null;
public BouncyCastleProvider_AES_CBC(String passwd){
//for a 192 key you must install the unrestricted policy files
// from the JCE/JDK downloads page
key =passwd.getBytes();
key = "SECRETSECRET_1SE".getBytes();
Log.i( "SECRETSECRET_1SECRET_2", "length"+ key.length);
//default IV value initialized with 0
IV = new byte[blockSize];
InitCiphers();
}
public BouncyCastleProvider_AES_CBC(String pass, byte[] iv){
//get the key and the IV
IV = new byte[blockSize];
System.arraycopy(iv, 0 , IV, 0, iv.length);
}
public BouncyCastleProvider_AES_CBC(byte[] pass, byte[]iv){
//get the key and the IV
key = new byte[pass.length];
System.arraycopy(pass, 0 , key, 0, pass.length);
IV = new byte[blockSize];
System.arraycopy(iv, 0 , IV, 0, iv.length);
}
public void InitCiphers()
{
try {
//1. create the cipher using Bouncy Castle Provider
encryptcipher =
Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
//2. create the key
SecretKey keyValue = new SecretKeySpec(key,"AES");
//3. create the IV
AlgorithmParameterSpec IVspec = new IvParameterSpec(IV);
//4. init the cipher
encryptcipher.init(Cipher.ENCRYPT_MODE, keyValue, IVspec);
encryptcipher.getOutputSize(100);
//1 create the cipher
decryptCipher =
Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
//2. the key is already created
//3. the IV is already created
//4. init the cipher
decryptCipher.init(Cipher.DECRYPT_MODE, keyValue, IVspec);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
public String encryptData(String inputFileName) {
String outFilename = null;
File inputFile = new File(inputFileName);
try {
// step 3 - not needed, as we have all the blocks on hand
// step 4 - call doFinal()
outFilename = ".".concat(CommonUtils.getHash(inputFile.getName()));
InputStream fis;
OutputStream fos;
fis = new BufferedInputStream(new FileInputStream(inputFileName));
fos = new BufferedOutputStream(new FileOutputStream(
inputFile.getParent() + "/" + outFilename));
Log.i(TAG, "Output path:" + inputFile.getParent() + "/" + outFilename);
int bufferLength = (inputFile.length()>10000000?10000000:1000);
byte[] buffer = new byte[bufferLength];
int noBytes = 0;
byte[] cipherBlock = new byte[encryptcipher
.getOutputSize(buffer.length)];
int cipherBytes;
while ((noBytes = fis.read(buffer)) != -1) {
cipherBytes = encryptcipher.update(buffer, 0, noBytes,
cipherBlock);
fos.write(cipherBlock, 0, cipherBytes);
}
// always call doFinal
cipherBytes = encryptcipher.doFinal(cipherBlock, 0);
fos.write(cipherBlock, 0, cipherBytes);
// close the files
fos.close();
fis.close();
Log.i("encrpty", "done");
inputFile.delete();
}
catch (Exception ex) {
ex.printStackTrace();
}
return inputFile.getParent() + "/" + outFilename;
}
public void decryptData(String inputFileName, String outputFileName) {
InputStream fis;
OutputStream fos;
try {
fis = new BufferedInputStream(new FileInputStream(
inputFileName));
fos = new BufferedOutputStream(new FileOutputStream(
outputFileName));
byte[] buffer = new byte[blockSize*100];
int noBytes = 0;
byte[] cipherBlock = new byte[decryptCipher
.getOutputSize(buffer.length)];
int cipherBytes;
while ((noBytes = fis.read(buffer)) != -1) {
cipherBytes = decryptCipher.update(buffer, 0, noBytes,
cipherBlock);
fos.write(cipherBlock, 0, cipherBytes);
}
// allways call doFinal
cipherBytes = decryptCipher.doFinal(cipherBlock, 0);
fos.write(cipherBlock, 0, cipherBytes);
// close the files
fos.close();
fis.close();
new File(inputFileName).delete();
Log.i("decrypt", "done");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public byte[] generateSalt() {
byte[] salt = new byte[16];
try {
SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
random.nextBytes(salt);
}
catch(Exception ex) {
ex.printStackTrace();
}
return salt;
}
}
The Guardian Project has build files for Android. Once you build it, you need write a simple JNI wrapper that does the encryption/decryption using OpenSSL APIs (EVP, etc), then call this from your app. You need to include he openssl and your JNI wrapper in the app and load them on startup using System.loadLibrary().
https://github.com/guardianproject/openssl-android
Additionally:
don't derive a password from a string directly, use a proper derivation algorithm.
don't use a fixed IV, especially all zeros