Android: How to get SHA1/MD5 fingerprint programmatically? - android

I'm trying to implement a way to communicate with my backend-server and be sure that my backend only answers, if it's my application which is calling.
So my idea is, that i just send the SHA1/MD5 fingerprint with the HTTPS POST request and verify it on the backend server. If the fingerprint matches, the server will answer.
So my first question is: How do I get these programmatically at runtime? Is it even possible?
The second question is: Can it be that easy? Or do i really have to set up an OAuth-Server (or use the google-api)?...The thing is, that I think that OAuth is a bit overkill for my use case and I don't want to handle the expiration/refresh-token stuff.

I have complemented the solution, proposed by Zulqumain Jutt, to be able to get the the result in the common form, like:
KeyHelper: MD5 56:ff:2f:1f:55:fa:79:3b:2c:ba:c9:7d:e3:b1:d2:af
public class KeyHelper {
/**
* #param key string like: SHA1, SHA256, MD5.
*/
#SuppressLint("PackageManagerGetSignatures") // test purpose
static void get(Context context, String key) {
try {
final PackageInfo info = context.getPackageManager()
.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
final MessageDigest md = MessageDigest.getInstance(key);
md.update(signature.toByteArray());
final byte[] digest = md.digest();
final StringBuilder toRet = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
if (i != 0) toRet.append(":");
int b = digest[i] & 0xff;
String hex = Integer.toHexString(b);
if (hex.length() == 1) toRet.append("0");
toRet.append(hex);
}
Log.e(KeyHelper.class.getSimpleName(), key + " " + toRet.toString());
}
} catch (PackageManager.NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
}
}

You can generate one something like in below example:
private void getKeyHash(String hashStretagy) {
PackageInfo info;
try {
info = getPackageManager().getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance(hashStretagy);
md.update(signature.toByteArray());
String something = new String(Base64.encode(md.digest(), 0));
Log.e("KeyHash -->>>>>>>>>>>>" , something);
// Notification.registerGCM(this);
}
} catch (PackageManager.NameNotFoundException e1) {
Log.e("name not found" , e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm" , e.toString());
} catch (Exception e) {
Log.e("exception" , e.toString());
}
}
use Like This:
getKeyHash("SHA");
getKeyHash("MD5");
First Answer: You can use above method it's secure and unique i use it all the time.
Second Answer: You can Use Auth keys but that entirely depends on you , what are you comfortable with

What you're trying to do is impossible. Anything you send to the server as an id can be copied by another application. That's why you have user's with passwords that aren't in the application- the password from an outside source is the only way to be sure the request is valid. And that only proves the user is valid, not that its from your application.

Kotlin Version of Artur's
Example key string: "SHA1" or "SHA256" or "MD5".
fun getSig(context: Context, key: String) {
try {
val info = context.packageManager.getPackageInfo(
BuildConfig.APPLICATION_ID,
PackageManager.GET_SIGNATURES
)
for (signature in info.signatures) {
val md = MessageDigest.getInstance(key)
md.update(signature.toByteArray())
val digest = md.digest()
val toRet = StringBuilder()
for (i in digest.indices) {
if (i != 0) toRet.append(":")
val b = digest[i].toInt() and 0xff
val hex = Integer.toHexString(b)
if (hex.length == 1) toRet.append("0")
toRet.append(hex)
}
val s = toRet.toString()
Log.e("sig", s)
}
} catch (e1: PackageManager.NameNotFoundException) {
Log.e("name not found", e1.toString())
} catch (e: NoSuchAlgorithmException) {
Log.e("no such an algorithm", e.toString())
} catch (e: Exception) {
Log.e("exception", e.toString())
}
}

Related

Web3j new account transacting with testrpc

I'm new to blockchain development. Currently, I'm learning the Ethereum platform and it sounds a very good environment to start with. I tested the web3j library on my Android application and it works fine. I used the following code to connect to my testrpc node:
Web3j web3 = Web3jFactory.build(new HttpService("http://192.168.1.108:8545"));
BigInteger gasPrice = BigInteger.valueOf(20000000000L);
BigInteger gasLimit = BigInteger.valueOf(500000L);
BigInteger nonce = null;
String contractAddress="0x0dd3b0efbce5c4eba2dc9b8500ecafb0b1cec28f";
String from = "0x2d6fcee3c3435ebda9184bdddf8481a87b7d1948";
List<Type> inputParameters = new ArrayList<>();
String hash ="232131231232141231231231231232123123123";
byte[] b =Arrays.copyOfRange(new BigInteger(hash, 16).toByteArray(), 1, 33);
Type _telNumber = new Bytes32(b);
Type _publicKey = new Bytes32(b);
inputParameters.add(_telNumber);
inputParameters.add(_publicKey);
Function function = new Function("addPerson",
inputParameters,
Collections.<TypeReference<?>>emptyList());
String functionEncoder = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createFunctionCallTransaction(from, nonce,gasPrice,gasLimit,contractAddress,new BigInteger("0"), functionEncoder);
try {
EthSendTransaction transactionResponse = web3.ethSendTransaction(transaction).sendAsync().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
The above code worked and I was able to interact with a smart contract (call a function).
The main problem is that the from parameter is hardcoded (I got it from the testrpc list of accounts).
What I want to achieve: I want to create an application in which the users can create new wallets (accounts), and use them to transact with the network. I created the wallets succesfully using the following code:
String filePath = Environment.getExternalStorageDirectory().toString() + "/Pictures";
Web3j web3 = Web3jFactory.build(new HttpService("http://192.168.1.108:8545"));
Web3ClientVersion web3ClientVersion = null;
try {
String fileName = WalletUtils.generateNewWalletFile("your password",new File(filePath),false);
Log.d("FILENAME",fileName);
Credentials credentials = WalletUtils.loadCredentials(
"your password",
filePath+"/"+fileName);
myAddress = credentials.getAddress();
Log.d("My address",credentials.getAddress());
} catch (CipherException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
What's the next step? Should I broadcast my address to the network?
The main problem is that the from parameter is hardcoded (I got it from the testrpc list of accounts).
You can call your file and decrypt it to get your address, every time you create a new account you generate a file with your keys.
val credentialsOne = WalletUtils.loadCredentials("your password", "your path")
When you connect with your node, it will automatically detect the address

How to store the client_secret in android

I have an API which I will call from an android app. The authentication is with oauth2 and I have the ressource owner password-flow.
So when I want to get an accesstoken I need username, password, clientId and clientSecret.
My problem is: How can I store the clientSecret in my app? I read that someone stores it in bytes an generates the string when he needs it.
My idea was to use the signature(SHA) as clientSecret.
So I found this function:
private String getKeyHash(String packagename)
{
String hash = "";
try
{
PackageInfo info = getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures)
{
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String sign= Base64.encodeToString(md.digest(), Base64.DEFAULT);
Log.e("MY KEY HASH:", sign);
Toast.makeText(getApplicationContext(),sign, Toast.LENGTH_LONG).show();
}
}
catch (PackageManager.NameNotFoundException e)
{
}
catch (NoSuchAlgorithmException e)
{
}
return hash;
}
Which is the better/safest solution?
Or is there a better way?

How to read SHA and MD5 fingerprint programmatically in Android

Hello I want to read SHA and MD5 fingerprint value of keystore programmatically of my app from which it was signed.
I'll take either SHA or MD5 value as key for security. This key I will use in the code to encrypt something and decrypt same at server end.
Is there any way to find this or is there any way to do same using different good approach. This should be in such a way nobody other can find this key.
Thanks in advance.
PackageInfo info;
try {
info = getPackageManager().getPackageInfo(
"com.your.package.name", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String hash_key = new String(Base64.encode(md.digest(), 0));
}
} catch (NameNotFoundException e1) {
} catch (NoSuchAlgorithmException e) {
} catch (Exception e) {
}
try this:
/**
*
* #param pkg packageName
* #return
*/
public String getSingInfo (String pkg) {
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
Signature[] signs = packageInfo.signatures;
Signature sign = signs[0];
String s = getMd5(sign);
return "md5:" + s ;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
private String getMd5 (Signature signature) {
return encryptionMD5(signature.toByteArray());
}
public static String encryptionMD5(byte[] byteStr) {
MessageDigest messageDigest = null;
StringBuffer md5StrBuff = new StringBuffer();
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(byteStr);
byte[] byteArray = messageDigest.digest();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
} else {
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5StrBuff.toString();
}
Find the path of your application's APK file by calling Context.getPackageCodePath()
Copy that APK to a writeable directory of your choice
Use apk-parser to get the information you need from the APK (see example below)
That library is able to decompress the APK file and parse all of its content. An example extracted from the apk-parser's Github page, tailored to your needs:
try {
ApkParser apkParser = new ApkParser(new File(filePath));
ApkSignStatus signStatus = apkParser.verifyApk(); // not needed
List<CertificateMeta> certs = apkParser.getCertificateMetas();
for (CertificateMeta certificateMeta : certs) {
System.out.println(certificateMeta.getCertMd5());
}
} catch (Exception e) {
e.printStackTrace();
}
Added below solution in-case if someone is looking for it for the first time, and don't know how to get it from studio as well.
Many times we search and get suggestion links.
Easiest Way
Open Android Studio
Open Your Project
Click on Gradle (From Right Side Panel, you will see Gradle Bar)
Click on Refresh (Click on Refresh from Gradle Bar, you will see List Gradle scripts of your Project)
Click on Your Project (Your Project Name form List (root))
Click on Tasks
Click on android
Double Click on signingReport (You will get SHA1 and MD5 in Run Bar)
Check Screenshot below:

Facebook API Exception

i just implemented Facebook log in into my android application. when i try to log in with Facebook i got following exception in log-cat.
Error Log :
com.facebook.http.protocol.ApiException: Key hash oZgj_um2MGi1eYpfTqwytjLMN10 does not match any stored key hashes
I already added this key hash into my developer account app page.But still i am facing same issue.
Your HashKey is wrong. It should have 28 characters while your hash key 27 characters the hashkey always ends with =. So I think you have missed it. Please check it again and
Change your hashkey by generating it programatically from the following code given in Facebook Docs and defined at Facebook Integration in Android Application
PackageInfo info;
try {
info = getPackageManager().getPackageInfo("com.example.yourpackagename", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String something = new String(Base64.encode(md.digest(), 0));
//String something = new String(Base64.encodeBytes(md.digest()));
Log.e("hash key", something);
}
} catch (NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}

verify md5sum on android

I would like to offer a md5 verifier in my android app which compares the server md5 and the just created one on the device.
The output should be like correct or incorrect and not that the user has to compare the hashes.
I already found out that it's possible to get the hash on android via
/system/xbin/busybox md5sum /sdcard/Download/FILENAME
. Of cause I can print the output of the command to screen but that's not what I want.
Because I don't want to reinvent the wheel is something like that already available? SHA1 would be possible too, both hashes are available.
Please help!
I have used this method to calculate md5 inside of Android Application
private String getMD5(String file){
String md5 = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
FileInputStream is = this.openFileInput(file);
DigestInputStream dis = new DigestInputStream(is, md);
byte data[] = new byte[1024];
#SuppressWarnings("unused")
int count;
while ((count = dis.read(data)) != -1) {
}
byte[] digest = md.digest();
for (int i=0; i < digest.length; i++) {
md5 += Integer.toString( ( digest[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return md5;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return md5;
}
With "the server md5" I guess you mean another file on the server containing an md5 hash.
So you could just download the md5 file, open it and compare the string inside with your calculated md5.

Categories

Resources