How to calculate hash of APK file programmatically? - android

I want to calculate the MD5 hash of the APK file from inside the app.
PackageInfo info = App.getInstance().getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA);
File file = new File(info.applicationInfo.sourceDir);
String hash = MD5.calculateMD5(file);
The MD5 hash is calculated like this:
private String calculateMD5() {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
return null;
}
InputStream is;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
return null;
}
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
String output = bigInt.toString(16);
output = String.format("%32s", output).replace(' ', '0');
return output;
} catch (IOException e) {
throw new RuntimeException("Unable to process file for MD5", e);
} finally {
try {
is.close();
} catch (IOException e) {
}
}
}
However I keep getting the same hash when running in the emulator, even when I change the source code.
What is wrong here?

Double check that you are truly running against a modified build. I suggest completely uninstalling and then reinstalling after the code change. I learned this the hard way after debugging an web app for two hours to find that I hadn't deployed the change I made.

Related

How to do RSA encryption for IOS using Ionic

I'm developing a native android app and hybrid IOS app. I'm encrypting the password before sending the request to BL. Below is my native code.
public String Encrypt (String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
try {
AssetManager assets = context.getAssets();
byte[] key = readFully(
assets.open("encryption.der", AssetManager.ACCESS_BUFFER));
KeySpec publicKeySpec = new X509EncodedKeySpec(key);
KeyFactory kf = KeyFactory.getInstance("RSA");
Key pk = kf.generatePublic(publicKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pk);
ByteArrayOutputStream out = new ByteArrayOutputStream();
CipherOutputStream cout = new CipherOutputStream(out, cipher);
try {
cout.write(plain.getBytes(UTF_8));
cout.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
cout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
encrypted = new String(encode(out.toByteArray(), DEFAULT), "UTF-8");
return encrypted;
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
static byte[] readFully(InputStream inputStream) throws IOException {
InputStream in = new BufferedInputStream(inputStream);
byte[] tmp = new byte[1024];
int readLen, size = 0;
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((readLen = in.read(tmp)) != -1) {
if (((long) size + readLen) > Integer.MAX_VALUE) {
// woah! did we just ship an app of 2GB?
throw new IllegalStateException("Invalid file. File size exceeds expected "
+ "maximum of 2GB");
}
size += readLen;
out.write(tmp, 0, readLen);
}
return out.toByteArray();
}
I have my key in encryption.der file. Everything works fine in android. Now coming to IOS which I'm using Ionic to develop. I'm not able to achieve the encryption part. I have used the "cryptico" : link : https://github.com/wwwtyro/cryptico/blob/master/README.md .
And finally converting to Base64 like these.
var EncryptionPassword = cryptico.encrypt($scope.userInfo.Password, publicKey);
$scope.encPass = base64.encode(EncryptionPassword.cipher);
But I'm getting ArrayIndexOutOfBound Exception from BL. Can you suggest exact same solution has android for angularjs too. So RSA encrytion works on both IOS and Android.
Create a Service and place your public Key inside that.
.service('Settings', function(){
this.publicKey = 'MIIBIjANBgdcssvsvsfvsfvsfvrefvfvfviuwoihijwfoiw278499080989i09M+KC8MYYOu/NRLmFg85LRrfRszyI/vZ/k8982789uiwbgchdbhU+3joQZoJ3Sxq/GbIIFf/3y4f9DuKI53y1qR2qD4xIskfa9rPVqvBtAu2KSNRd8V4J8RKI2gT2YEA+A3Z0mQq4GBRS8iYmGLqRQyPfNUSankylBrTpOIVFBZORdZehjJMmwl98UynyfnyMIHUIFuhefuibiufbeufbsoijn93fD7nxt+siZryfazn3EAgBaTKTV/U5xIepzDN6ZYJ4qnC93u6erdb1X4m1zU6RGapwzCOPOORTyzw/uWJ8twcODNt0cqVp+sYQIDAQAB';
})
Now in your JS encrypt using public key and JSEncrypt.
var encrypt = new JSEncrypt(); encrypt.setPublicKey(Settings.publicKey);
EncryptionPin = encrypt.encrypt($scope.customerInfo.Pin);
EncryptionPin is the final key.

Copying preloaded database, adding carriage returns

I have an app which comes with a preloaded database.
My temporary copy function is like so
private void copyDatabase() {
AssetManager assetManager = context.getResources().getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(DATABASE_NAME);
out = new FileOutputStream(DATABASE_FILE);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) > 0){
out.write(buffer, 0, read);
}
} catch (IOException e) {
Log.e("error", e.getMessage());
} finally {
if(in != null) {
try {
in.close();
}catch (IOException e) {
Log.e("error", e.getMessage());
}
}
if(out != null) {
try {
out.close();
}catch (IOException e) {
Log.e("error", e.getMessage());
}
}
}
}
However on Android 2.2 I keep getting an error "database disk image malformed". So I went ahead and copied it off the device, onto my computer. And sure enough, it wouldn't open. I did a hex compare on the two files and there are 10 instances where 1 byte is different. Hex 0D has been added 10 times in random spots in the malformed copy.
The copy routine works fine in 3.x+. I also have developed other apps with the same method and don't have an issue.
Any ideas?
Not sure what the issue was, but I created a new sqlite database, imported the data, and that seemed to work.

acess file in raw folder in android by calling them from their names

My code is below:
I am not able to use a string in the file name. Any suggestions?
If i use R.raw.anyString , it shows error
tv3.setText(readTxt());
}
private String readTxt(){
InputStream inputStream = getResources().openRawResource(R.raw.filname);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
This code works great for me:
InputSource inputSource = new InputSource(ApplicationContext.get()
.getResources().openRawResource(R.raw.countries));
i use it to open XML file and parse it later on i my code.

Download all types of file from Dropbox

I am working on Dropbox. I see the documentation. This is my code to display list:
Entry entryCheck = mApi.metadata("/", 100, null, true, null);
Log.i("Item Name", entryCheck.fileName());
Log.i("Is Folder", String.valueOf(entryCheck.isDir));
I got all list from dropbox but my question is that
Here entryCheck.isDir always give me true value if it is file or directory so how i can know which is file or which one is directory?
How i downloaded that files.
I tried with this but it is not working:
private boolean downloadDropboxFile(String dbPath, File localFile,
DropboxAPI<?> api) throws IOException {
BufferedInputStream br = null;
BufferedOutputStream bw = null;
try {
if (!localFile.exists()) {
localFile.createNewFile(); // otherwise dropbox client will fail
// silently
}
DropboxInputStream fin = mApi.getFileStream("dropbox", dbPath);
br = new BufferedInputStream(fin);
bw = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[4096];
int read;
while (true) {
read = br.read(buffer);
if (read <= 0) {
break;
}
bw.write(buffer, 0, read);
}
} catch (DropboxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// in finally block:
if (bw != null) {
bw.close();
}
if (br != null) {
br.close();
}
}
return true;
}
This will work
String inPath ="mnt/sdcard/"+filename;
File file=new File(inPath);
try {
mFos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
mErrorMsg = "Couldn't create a local file to store the image";
return false;
}
mApi.getFile("/"+filename, null, mFos, null);
This downloads the file and store it in the sdcard location inPath.
You have to do it in a new thread,not in main thread.Use AsyncTask.
http://www.androiddesignpatterns.com/2012/06/app-force-close-honeycomb-ics.html
this link explains why..

reading .key file android

I have problem when i try to read a .key file. This file is created by a normal java (J2SE) and i read it from android application. When i read this file from android it gives me nothing and i have done some debugging and i noticed that it can't read the file. Also i have checked if i can read the file (using file.canRead()) and it appears that i can't. Notice that i created normal java application (J2SE) with the same code and it worked successfully.
The code I have used is this:
public KeyPair LoadKeyPair(String algorithm, String publicFileName, String privateFileName) {
// Read Public Key.
PublicKey publicKey = null;
PrivateKey privateKey = null;
try {
File filePublicKey = new File(publicFileName);
FileInputStream fis = new FileInputStream(publicFileName); // The program stops here
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
// Read Private Key.
File filePrivateKey = new File(privateFileName);
fis = new FileInputStream(privateFileName);
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
// Generate KeyPair.
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
encodedPublicKey);
publicKey = keyFactory.generatePublic(publicKeySpec);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
privateKey = keyFactory.generatePrivate(privateKeySpec);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new KeyPair(publicKey, privateKey);
}
Is a .key file just like a .pem file?
If so, I just do something like this, because PemReader is in BouncyCastleProvider, and THAT is a mess! Too much code for too few things that I want to use
if(mKey==null){
BufferedReader pubFile = new BufferedReader(new InputStreamReader(mCtx.getResources().openRawResource(R.raw.public.pem)));
try {
String line = new String();
StringBuilder key = new StringBuilder();
while((line = pubFile.readLine())!= null){
if(!line.contains("----")){
key.append(line);
}
}
mKey = key.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
pubFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
As you can see, I have my public.pem in the res/raw/ folder within my application. Of course, I dont have a .pem with the private key in it. I sign with my public key and verify that the info was signed with a public key made from the private key I keep on my server.
Hope that answers your question and is clear enough.
Did you add in the Manifest the following line?
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE"/>

Categories

Resources