I have problem with generate key hash.
I make 2 key:
C:\openssl\bin>"C:\Program Files\Java\jre7\bin\keytool.exe" -exportcert -alias forumurology -keystore uroweb7228.keystore | openssl sha1 -binary | openssl base64
Enter keystore password: *******
c/6e5fY8Rg3Gshn1TKucia***/A=
C:\openssl\bin>"C:\Program Files\Java\jre7\bin\keytool.exe" -exportcert -alias a
ndroiddebugkey -keystore debug.keystore | openssl sha1 -binary | openssl base64
Enter keystore password: android
3L0oeMh7uk9YWE0sYavUuT***yU=
then save it to my facebook application settings.
When i run release .apk, i have error:
10-21 16:48:11.583: W/fb4a(:<default>):BlueServiceQueue(20097): Exception during service
10-21 16:48:11.583: W/fb4a(:<default>):BlueServiceQueue(20097): com.facebook.http.protocol.ApiException: Key hash ypC1--aybTSQXdzXGLtM-_nXydI does not match any stored key hashes.
10-21 16:48:11.583: W/fb4a(:<default>):BlueServiceQueue(20097): at com.facebook.http.protocol.ApiResponseChecker.b(ApiResponseChecker.java:83)
This is because the device is creating a new key hash which is not in your app settings. So you have to update the keyhash accordingly.. Use this in onCreate()
try {
PackageInfo info = getPackageManager().getPackageInfo("YOUR_PACKAGE_NAME", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}
Related
This is the first time I am doing this SSL pinning on Android.
When creating OkHttp, I am adding this code:
certificatePinner(
CertificatePinner.Builder().add(
"url of the server",
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
).build()
)
the second parameter expects this:
SHA-256 or SHA-1 hashes. Each pin is a hash of a certificate's Subject Public Key Info, base64-encoded and prefixed with either sha256/ or sha1/.
I was given a certificate in a txt file that starts with --BEGIN CERTIFICATE-- and ends with --END CERTIFICATE--.
I am struggling to extract the hash of Public Key Info and convert it to base64.
So far I have tried these methods:
Method 1:
I put the certificate contents without BEGIN CERTIFICATE and END CERTIFICATE into some string variable. Tried to convert it into X509Certificate.
private fun certificateFromString(base64: String): X509Certificate? {
val decoded = Base64.decode(base64, Base64.NO_WRAP)
val inputStream = ByteArrayInputStream(decoded)
return CertificateFactory.getInstance("X.509").generateCertificate(inputStream) as? X509Certificate
}
Then I pass this certificate here to get Sha256 hash of the public key. Also, pay attention to c.encoded and c.publicKey.encoded. I am not sure if the method works correctly.
private fun getFingerprint(c: X509Certificate?): String {
var certificate = ""
try {
val md = MessageDigest.getInstance("SHA-256")
var publicKey = ByteArray(0)
if (c != null) {
publicKey = md.digest(c.encoded) // I tried both
publicKey = md.digest(c.publicKey.encoded) // I tried both
}
val hexString = StringBuilder()
for (aPublicKeyByte in publicKey) {
val appendString = Integer.toHexString(0xFF and aPublicKeyByte.toInt())
if (appendString.length == 1) hexString.append("0")
hexString.append(appendString)
}
certificate = hexString.toString()
} catch (e1: NoSuchAlgorithmException) {
e1.printStackTrace()
} catch (e1: CertificateEncodingException) {
e1.printStackTrace()
}
return certificate
}
then I am converting that string result to base64 like this:
private fun base64(openKey: String): String {
return Base64.encodeToString(openKey.toByteArray(), Base64.NO_WRAP).toString()
}
then I add the resulting String into the CertificatePinner class as sha256/resultingStringInBase64.
Method 2:
I changed the .txt into .pem in order to use openssl command line tools.
openssl rsa -in myCert.pem -pubout> myCert.pub
it returned writing RSA key
and when I open the generated myCert.pub, I see a text with ---BEGUN PUBLIC KEY--- and ---END PUBLIC KEY--- and a long list of letters between them.
Then I ran this to extract the sha256 hash:
openssl rsa -in myCert.pub -pubin -outform der | openssl dgst -sha256
this gave me a 64 character string 2c180286549...b1ba7.
Then I ran the command again but added base64 conversion.
openssl rsa -in myCert.pub -pubin -outform der | openssl dgst -sha256 | openssl enc -base64
The result is completely different than Method 1. Should it be the same? If so, could someone point me in the right direction? Or show how to properly get the SHA256 of Public Key.
My method I just used recently and worked succesfully:
In your Terminal, where the folder containing public key file is located, write the command:
openssl x509 -in yourFile.pem -pubkey -noout | open ssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
The result will be the your desired string (encoded in base64, which means that it'll have 44 characters, including an equal (=) symbol at the end), and must be placed in your Android code after sha256/....
Also, several methods could generate different hashes, so you can have multiple valid strings, meaning that both your generated hashes could be correct.
I want to get my release key hash for Facebook Android SDK.
I followed facebook getting started tutorial
paste following code to my cmd
keytool -exportcert -alias androiddebugkey -keystore C:\Users\USER\.android\debug.keystore | C:\openssl\bin\openssl sha1 -binary | C:\openssl\bin\openssl base64
got
Enter keystore password:
After I enter : android
it came out
YOR7
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore C:\Users\USER\.android\debug.keystore -destkeystore C:\Users\USER\.android\debug.keystore -deststoretype pkcs12".
without Key hash
How can I solve this problem ?
Thanks ~
can u use this code to get key for Facebook or google.
private fun printHashKey() {
try {
//Facebook
Log.i("AppLog", "key:" + FacebookSdk.getApplicationSignature(this))
//google
Log.i("AppLog", SignatureUtils.getOwnSignatureHash(this))
} catch (e: Exception) {
Log.i("AppLog", "error:", e)
}
}
I find the method from Internet
try {
PackageInfo info = getPackageManager().getPackageInfo(
"your.pakege.name",
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("MyKeyHash:", Base64.encodeToString(
md.digest(),
Base64.DEFAULT));
}
} catch (Exception e) {
Log.d("FacebookHashKeyError",e.toString());
}
it turns out my key hash!
my apk is working fine in debug mode. but when I signed apk with release mode then
automatic sms retrivr is not working.
then I search I found I have to generate a hash key on official documentation
https://developers.google.com/identity/sms-retriever/verify#generating_a_one-time_code
where I found two methods
1> by signature helped class- I used but not working
2> second by following command
keytool -exportcert -alias MyAndroidKey -keystore MyProductionKeys.keystore | xxd -p | tr -d "[:space:]" | echo -n com.example.myapp cat | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
but I got xxd command is not found
then I search on the stack then i run a command on git bash command runs but that hash key still not working
It would be easier to generate hash through this code.
Just call below line and print your signature.
ArrayList<String> sigList = (new AppSignatureHelper(this)).getAppSignatures()
Code Reference: https://github.com/googlesamples/android-credentials/blob/master/sms-verification/android/app/src/main/java/com/google/samples/smartlock/sms_verify/AppSignatureHelper.java
Update:
Hash code for debug and release version will be different.
Make sure you are using release specific app hash code for otp message with required format.
AppSignatureHelper will provide hash code using which apk is signed. Build release apk and print hash code in log to get release specific hash code.
Update:
Another approach of generating through command mentioned in : https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string
However if you are using windows, it may not work as you it dont have binary (command) like xxd or tr.
in that case, you have to download those exe from somewhere else.
If you are using git then you can find them at "C:\Program Files\Git\usr\bin\", in that case follow this steps.
Add path "C:\Program Files\Git\usr\bin\" in your environment variables.
Restart your command prompt. so xxd and tr starts working in prompt.
apply mentioned command in link.
keytool -exportcert -alias MY_ANDROID_KEY -keystore MY_PRODUCTION_KEY | xxd -p | tr -d "[:space:]" | echo -n MY_PACKAGE_NAMEcat| sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
Where in command
replace MY_ANDROID_KEY with your key alias
replace MY_PRODUCTION_KEY with your keystore path (some xyz.jks)
replace MY_PACKAGE_NAME with your package name
you will get 11 character long hash key. Hurray.
Here, if you are facing error like tr: write error: Illegal seek,
you can call cammand up to tr like ->
keytool -exportcert -alias MY_ANDROID_KEY -keystore MY_PRODUCTION_KEY | xxd -p | tr -d "[:space:]"
in this case you will get around 1800+ character long signature string.
pass package and signature string to hash method of AppSignatureHelper, it will return your key.
(Here, If at the end you are using AppSignatureHelper, i suggest to go for that first approach only)
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class AppSignatureHelper extends ContextWrapper {
private static final String TAG = "AppSignatureHelper";
private static final String HASH_TYPE = "SHA-256";
public static final int NUM_HASHED_BYTES = 9;
public static final int NUM_BASE64_CHAR = 11;
public AppSignatureHelper(Context context) {
super(context);
}
/**
* Get all the app signatures for the current package
*/
public ArrayList<String> getAppSignatures() {
ArrayList<String> appCodes = new ArrayList<>();
try {
// Get all package signatures for the current package
String packageName = getPackageName();
PackageManager packageManager = getPackageManager();
Signature[] signatures = packageManager.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES).signatures;
// For each signature create a compatible hash
for (Signature signature : signatures) {
String hash = hash(packageName, signature.toCharsString());
if (hash != null) {
appCodes.add(String.format("%s", hash));
}
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Unable to find package to obtain hash.", e);
}
return appCodes;
}
private static String hash(String packageName, String signature) {
String appInfo = packageName + " " + signature;
try {
MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);
messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
byte[] hashSignature = messageDigest.digest();
// truncated into NUM_HASHED_BYTES
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
// encode into Base64
String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);
CommonUtils.base64Val = base64Hash;
Log.e("base64Val",base64Hash);
Log.d(TAG, String.format("pkg: %s -- hash: %s", packageName, base64Hash));
return base64Hash;
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "hash:NoSuchAlgorithm", e);
}
return null;
}
}
You can use base64hash for debug build and if you are making app live, make signed APK and use the value generated from signed APK.
Don't forget to call this class from main application's oncreate()
AppSignatureHelper appSignatureHelper = new AppSignatureHelper(this);
appSignatureHelper.getAppSignatures();
Fingerprint API preview for Android N is found here with Sample App Sample App .As of this writing, createKey() in this method specify key_name,i don't know about key_name,Please anyone tell about key_name
/** Alias for our key in the Android Key Store */
private static final String KEY_NAME = "my_key";
public void createKey() {
// The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
// for your flow. Use of keys is necessary if you need to know if the set of
// enrolled fingerprints has changed.
try {
mKeyStore.load(null);
// Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder
mKeyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
// Require the user to authenticate with a fingerprint to authorize every use
// of the key
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
mKeyGenerator.generateKey();
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
this my part of code,here what is KEY_NAME and key_name get from where
Just run this cmd on your terminal
/home/nn1android01user/Documents/Keystor_alicante/gerber_keystore.jks ->
this is your keystore file path
gerber -> alias name
keytool -exportcert -alias gerber -keystore /home/nn1android01user/Documents/Keystor_alicante/gerber_keystore.jks | openssl sha1 -binary | openssl base64
I tried to generate the Keyhash for integrating the Facebook in our app, but when i generated the keyhash through cmd prompt, it can't generate.
C:\Users\DON\.android>keytool -exportcert -alias androiddebugkey -keystore ~/.an
droid/debug.keystore | openssl sha1 -binary | openssl base64
'keytool' is not recognized as an internal or external command,
operable program or batch file.
and another command I use is:
C:\Program Files\Java\jdk1.6.0_20\bin>keytool -exportcert -alias androiddebugkey
-keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
'openssl' is not recognized as an internal or external command,
operable program or batch file.
What is the problem?
Using this command first download this file http://code.google.com/p/openssl-for-windows/downloads/detail?name=openssl-0.9.8k_WIN32.zip . Then extract the file and run this command:
C:\Program Files\Java\jdk1.6.0_20\bin>keytool -export -alias myAlias -keystore C:\Users\DON\.android\myKeyStore | C:\openssl\bin\openssl sha1 -binary | C:\openssl\bin\openssl enc -a -xtIm30l*********=
DON is my system name and should be replaced with your system name.
Download the openssl-for-windows package.
Extract the zip.
In windows, edit the path system variable that points to <openssl-extracted-folder>/bin
Then run the command.
First do the Facebook sdk setup then main program if you add this, you will get keyhash at console
There will be chances of 3 type keys once is debug and another is release key and after upload google changes signature ,you can provide all these 3 keys to facebook developer account ,then you can check facebook login. depending upon your app mode facebook will match the key.Use toast to see the keyhash ,if you dont know android monitor from android studio
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FacebookSdk.sdkInitialize(getApplicationContext());
AppEventsLogger.activateApp(this);
printKeyHash();
}
private void printKeyHash() {
try {
PackageInfo info = getPackageManager().getPackageInfo(
getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.i("KeyHash:",
Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("jk", "Exception(NameNotFoundException) : " + e);
} catch (NoSuchAlgorithmException e) {
Log.e("mkm", "Exception(NoSuchAlgorithmException) : " + e);
}
}
}
it's late answer but it will help to lazy people like me.. add this code to your Application class, there is no need to download openssl and no need to set the path.. only need is just copy my code.. and keyHash will generated in log.
import com.facebook.FacebookSdk;
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
FacebookSdk.sdkInitialize(getApplicationContext());
AppEventsLogger.activateApp(this);
printKeyHash();
}
private void printKeyHash() {
try {
PackageInfo info = getPackageManager().getPackageInfo(
getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.i("KeyHash:",
Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("jk", "Exception(NameNotFoundException) : " + e);
} catch (NoSuchAlgorithmException e) {
Log.e("mkm", "Exception(NoSuchAlgorithmException) : " + e);
}
}
}
and do not forget add MyApplication class in manifest:
<application
android:name=".application.MyApplication"
</application>
Download openssl from https://code.google.com/archive/p/openssl-for-windows/downloads.
Extract the file and then execute in CMD, replancing the routes and the KeyName
keytool -exportcert -alias KEYNAME -keystore "C:\Users\YOUR_USER\.android\debug.keystore"
| "C:\URL_OPENSSL_EXTRACTED\bin\openssl" sha1 -binary
| "C:\URL_OPENSSL_EXTRACTED\bin\openssl" base64.