I'm trying to run google map on android application I have used Debug certificate fingerprint and my package name to get API KEY when I run the application on emulator I got this error
Google Maps Android API: Failed to load map. Error contacting Google servers. This is
probably an authentication issue (but could be due to network errors).
while getting bank screen in the emulator attached below, I'm sure is everything is correct from my side
Activate Maps SDK for Android
Get Debug certificate fingerprint using
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey - storepass android -keypass android
Add the API key into res/value/google_maps_api.xml
could you please help in that
I have found the issue I was using handleSSLHandShake in android app class it's working fine after removing it.
public static void handleSSLHandshake() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((arg0, arg1) -> {
Log.e("verify_url","is => "+arg0);
if(arg0.equals("") ){
return true;
}else{
return false;
}
});
} catch (Exception ignored) {
}
}
Related
thanks in advance for the help.
I developed a suite of api tests in Java TestNG against an api deployed to a non-secure internal QA environment. Recently this application was re-deployed to a new, secure environment. When this happened I began to see the following error on every api request, both GET and POST:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
My first move was to install the appropriate certificate, even though it is signed by DigiCert, so it should be approved by default.
keytool -import -alias ca -file qa4cert.crt -keystore cacerts -storepass changeit
And that had no effect. I also tried adding the certificate via the IDE (Intellij). Again, no effect, still seeing the same error.
Since I was unable to make progress here, and I am still working against an internal QA environment with no sensitive data, I was comfortable dropping the certificate validation and install an all-trusting cert manager. My simple implementation is below:
package test_utils;
import javax.net.ssl.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class SSLTool {
private static boolean isTrustAllCertsInitialized = false;
public static void disableCertificateValidation() {
if (isTrustAllCertsInitialized) {
return;
}
isTrustAllCertsInitialized = true;
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLContext.setDefault(ctx);
System.out.println("new trust manager should be set");
} catch (Exception e) {
e.printStackTrace();
}
return ctx;
}
}
I ran the above code as part of my --before-- implementation in the test suite and verified we reached the end of the try block, so the new All_trusting TrustManager should be set. Unfortunately this also had no effect, I am still seeing the error.
To try and isolate the issue, I processed the same POST request through both Postman and curl, both returned the desired result, no errors.
For sanity's sake I also hit a few public urls both secure and insecure and got the desired results as well.
At this point I'm stumped. Since Postman and curl work, the error must have something to do with my implementation, but I don't understand why it would work with our old environment but not in the new one. A debugging version of my code that makes a failing get request is below. This fails both when run through the ide, and through the command line with maven.
Test File
public class DebugTests extends BaseTest {
#Test
public void debug() {
BaseApi api = new BaseApi();
api.debugGet("<<MYURL>>");
}
BaseTest
#Listeners(Listener.class)
public class BaseTest {
#BeforeMethod
public void before() {
// the below function is used to disable certificate validation. It is ONLY meant to be used in testing environments
// if used in production it exposes our test suite to MITM attacks.
SSLTool.disableCertificateValidation();
}
#AfterMethod
public void after() {
}
}
Relevant Code from the API object
public BaseApi() {
SSLContext ctx = SSLTool.disableCertificateValidation();
client = HttpClients.custom().setSSLContext(ctx).build();
System.out.println("trust manager set");
}
public void debugGet(String endpoint) {
try {
client.execute(this.buildGetConnection(endpoint, false));
} catch (Exception e) {
e.printStackTrace();
}
}
protected HttpGet buildGetConnection(String endpoint) {
return this.buildGetConnection(endpoint, true);
}
protected HttpGet buildGetConnection(String endpoint, boolean auth) {
//TODO build a switch to change testing environments based off command line
HttpGet get = new HttpGet(rootUrl + endpoint);
if(auth) {
StsAuthApi authApi = new StsAuthApi();
get.setHeader("Authorization", "Bearer " + authApi.getToken());
}
get.setHeader("accept","application/json");
get.setHeader("Content-Type","application/xml");
System.out.println("making GET request to " + rootUrl + endpoint);
return get;
}
In my debugging implementation rooturl is an empty string so the url matches the string supplied via the test case.
HttpClients.createDefault() will not use your null trust manager. It internally creates and initialises an SSLContext like this:
final SSLContext sslContext = SSLContext.getInstance(SSLContextBuilder.TLS);
sslContext.init(null, null, null);
You can create the HttpClient like this instead:
HttpClients.custom()
.setSSLContext(ctx)
.build();
Where ctx is the one you created in the disableCertificateValidation() method.
The question about why it didn't work when you added your certificate to cacerts is still open. If you did that correctly then the default client should have used it. You can set the system property javax.net.debug=all if you want to debug that one further (it will print out your truststore when it's first initialised into a context).
I have an application that needs to run plug-ins written by the same company, but discovered at run-time.
For security, I want the application to authenticate that each plug-in was written by us. No third-party code needs to perform the authentication.
What is an easy way to perform this authentication?
Is it reasonable to get by with challenge-response, or do I need to sign the plug-in jar?
If I need to sign the plug-in jar, what APIs would I use to authenticate?
This is the answer I came to after reading and experimentation.
In this case, a self-signed certificate may be sufficient, since no third-party code needs to authenticate. The hosting code can use the public key to verify the plug-in.
Details
The examples below use the default key algorithm. You may wish to specify a more secure algorithm with -keyalg.
Make the keystore, a public/private key pair, and a self-signed certificate containing the public key
keytool -genkeypair -alias myalias -validity 365 -keystore mykeystore
Validity is measured in days.
Export the certificate containing the public key
keytool -export -keystore mykeystore -alias myalias -file mycertificate.cer
At build time, sign the plug-in jar
jarsigner -keystore mykeystore -signedjar my_signed.jar my_unsigned.jar myalias
At run time, authenticate the plug-in jar contents
This test harness can be used to test the code that follows.
public class CEVerify {
public static void main(String[] args) throws IOException, CertificateException {
File jarFile = new File( "C:\\myplugins\\my_signed.jar" );
String certificatePath = "C:\\mycertificates\\mycertificate.cer";
File certificateFile = new File( certificatePath );
PublicKey publicKey = getPublicKeyFromCertificate( certificateFile );
JarFile jar = new JarFile( jarFile );
boolean isVerified = verify( jar, publicKey );
if ( isVerified ) {
System.out.println( "Verified!" );
}
else {
System.err.println( "NOT verified!" );
}
}
You can extract the public key from the certificate like this:
private static PublicKey
getPublicKeyFromCertificate( File certificateFile )
throws CertificateException, FileNotFoundException
{
CertificateFactory certificateFactory = CertificateFactory.getInstance( "X.509" );
FileInputStream inCertificate = new FileInputStream( certificateFile );
Certificate certificate = certificateFactory.generateCertificate( inCertificate );
return certificate.getPublicKey();
}
Given a jar file and a public key, you can verify appropriate entries in the jar. You may need to exclude other files if you used a different -keyalg, like RSA.
private static boolean
verify( JarFile jar, PublicKey publicKey ) throws IOException {
Enumeration<JarEntry> jarEntries = jar.entries();
while ( jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
if ( jarEntry.isDirectory()) {
continue;
}
else {
String entryName = jarEntry.getName();
if ( entryName.endsWith( ".SF" ) || entryName.endsWith( ".DSA" )) {
continue;
}
else if ( ! verifyJarEntry( jar, publicKey, jarEntry )) {
return false;
}
}
}
return true;
}
And this authenticates a particular file in a jar. Note the need to read all the bytes in the jar entry before its certificates can be obtained.
private static boolean
verifyJarEntry( JarFile jar, PublicKey publicKey, JarEntry jarEntry)
throws IOException
{
try {
InputStream in = jar.getInputStream( jarEntry );
readAllOf( in );
// public Certificate[] getCertificates()
// ... This method can only be called once the JarEntry has been
// completely verified by reading from the entry input stream
// until the end of the stream has been reached. Otherwise, this
// method will return null.
Certificate[] certificates = jarEntry.getCertificates();
if ((null == certificates) || (0 == certificates.length)) {
return false;
} else {
for (int i = 0; i < certificates.length; ++i) {
Certificate certificate = certificates[i];
try {
certificate.verify( publicKey );
return true;
} catch (Exception e) {
continue;
}
}
return false;
}
} catch (SecurityException e) {
return false;
}
}
Finally, this is the method called above to read all the bytes in a jar entry.
private static void readAllOf(InputStream in) throws IOException {
byte[] buffer = new byte[4096];
while ( 0 < in.read( buffer )) {
continue;
}
}
When I get keytool for login Facebook, I can't get it.
'keytool' is not recognized as an internal or external command, operable program or batch file.
Try below code to get Key Hash
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add code to print out the key hash
try {
PackageInfo info = getPackageManager().getPackageInfo(
"com.facebook.samples.hellofacebook",
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) {
}
Abive code will run successfully if openssl is installed on the pc and the working directory is bin folder of the JRE.
C:\Program Files\Java\jre<version_number>\bin>
version_number depends on installed version of JRE. Download openssl and give the absolute path of the openssl executable. Sample code is shown below
keytool -exportcert -alias <RELEASE_KEY_ALIAS> -keystore <RELEASE_KEY_PATH> | "C:\Users\Anand\Documents\openssl\bin\openssl.exe" sha1 -binary | "C:\Users\Anand\Documents\openssl\bin\openssl.exe" base64
i use custom DummySocketFactory and DummyTrustMAnager to connect to smtp over TLS.
DummySocketFactory:
package XMailMessenger;
public class DummySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslcontext = SSLContext.getInstance("TLS");
//Security.removeProvider("SunJSSE");
sslcontext.init(null,
new TrustManager[] { new DummyTrustManager()},
null );
factory = (SSLSocketFactory)sslcontext.getSocketFactory();
} catch(Exception ex) {
System.out.println(ex.toString());
}
}
public static SocketFactory getDefault() {
SocketFactory a = new DummySSLSocketFactory();
if ( a == null ) { System.out.println("1"); }
return a;
}
...
DummyTrustManager:
public class DummyTrustManager implements X509TrustManager{
public void checkClientTrusted(X509Certificate[] cert, String authType) {
// everything is trusted
}
public void checkServerTrusted(X509Certificate[] cert, String authType) {
// everything is trusted
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
//return null;
}
}
in sending e-mail i receive exception as in subject, this exception goes from function sslcontext.init in DummySSLSocketFactory. I debug it and noticed , that in code:
private X509TrustManager chooseTrustManager(TrustManager[] tm)
throws KeyManagementException {
// We only use the first instance of X509TrustManager passed to us.
for (int i = 0; tm != null && i < tm.length; i++) {
if (tm[i] instanceof X509TrustManager) {
if (SunJSSE.isFIPS() &&
!(tm[i] instanceof X509TrustManagerImpl)) {
throw new KeyManagementException
("FIPS mode: only SunJSSE TrustManagers may be used");
}
if (tm[i] instanceof X509ExtendedTrustManager) {
return (X509TrustManager)tm[i];
} else {
return new AbstractTrustManagerWrapper(
(X509TrustManager)tm[i]);
}
}
}
// nothing found, return a dummy X509TrustManager.
return DummyX509TrustManager.INSTANCE;
}
exception occures in if (SunJSSE.isFIPS() &&
!(tm[i] instanceof X509TrustManagerImpl)) expression.
I suppose that tm[i] contains my DummyTrustManager , it can not be extended from X509TrustManagerImpl so my question is : How to disable Fips in SunJSSE ?
SunJSSE can be configured to run on FIPS-140 compliant mode as long as it uses a FIPS-140 certified cryptographic hardware or software provider that implements all cryptographic algorithms required by JSSE (ex. Network Security Services – NSS, Sun Cryptographic Accelerator 6000, nCipher, etc).
To enable FIPS mode, edit the file ${java.home}/lib/security/java.security and modify the line that lists com.sun.net.ssl.internal.ssl.Provider and associate the name of the FIPS-140 cryptographic provider (ex. SunPKCS11-NSS). The name of the provider is a string that concatenates the prefix SunPKCS11- with the name of the specified PKCS#11 provider in its configuration file.
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
SunPKCS11-NSS
In case of using NSS as cryptographic software token (Make use of NSS 3.1.1. or above), assuming the libraries are located under the /opt/nss/lib directory and its key database files (with the suffix .db) are under the /opt/nss/fipsdb directory, the sample configuration for representing NSS will be as follows:
# Use NSS as a FIPS-140 compliant cryptographic token
# SunPKCS11-NSS
name = NSS
nssLibraryDirectory = /opt/nss/lib
nssSecmodDirectory = /opt/nss/fipsdb
nssModule = fips
In FIPS mode, SunJSSE will perform SSL/TLS 1.0 based communication and cryptographic operations including symmetric and asymmetric encryption, signature generation and verification, message digests and message authentication codes, key generation and key derivation, random number generation, etc.
To anyone having a giant headache when you need to install a tomcat webapp on a third party server, I lost 1 hour trying to bypass this damn thing...
I solved in this way, without touching anything in the webapp.
Add this java parameter:
-Djava.security.disableSystemPropertiesFile=true
Source:
https://access.redhat.com/documentation/en-us/openjdk/8/pdf/configuring_openjdk_8_on_rhel_with_fips/OpenJDK-8-Configuring_OpenJDK_8_on_RHEL_with_FIPS-en-US.pdf
Also, if the app needs to connect to a Windows Server, you might want to disable FIPS there too:
In Control Panel, click Administrative Tools -> Local Security Policy.
In Security Settings -> Local Policies -> Security Options.
Under Policy in the right pane, double-click System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing, and then click Disabled.
Reboot the server
(bonus)
If you want to uninstall FIPS from the server, follow this giude (I didn't test it):
https://www.bggofurther.com/2021/02/disable-fips-mode-on-centos-7/
We are working on encryption-decryption using applet. We find some unexpected issue with digital certificate. One system has certificate and we can't find the private key from that certificate but by installing the same certificate again works fine.
Java Plug-in 10.25.2.17
Using JRE version 1.7.0_25-b17 Java HotSpot(TM) 64-Bit Server VM
User home directory = C:\Users\admin
To access private key we are using below code.
private PrivateKey getPrivateKeyFromKeyStore(String pubkey, KeyStore browser) {
PrivateKey privateKey = null;
String pubKey1 = "";
if (browser != null) {
try {
Field spiField = KeyStore.class.getDeclaredField("keyStoreSpi");
spiField.setAccessible(true);
KeyStoreSpi spi = (KeyStoreSpi) spiField.get(browser);
Field entriesField = spi.getClass().getSuperclass().getDeclaredField("entries");
entriesField.setAccessible(true);
#SuppressWarnings("rawtypes")
Collection entries = (Collection) entriesField.get(spi);
for (Object entry : entries) {
String alias = (String) invokeGetter(entry, "getAlias");
X509Certificate[] certificateChain = (X509Certificate[]) invokeGetter(entry, "getCertificateChain");
for (X509Certificate current : certificateChain) {
pubKey1 = this.bASE64Encoder.encode(current.getPublicKey().getEncoded());
if (pubkey.equals(pubKey1) && !pubkey.equals("")) {
privateKey = (PrivateKey) invokeGetter(entry, "getPrivateKey");
return privateKey;
}
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return privateKey;
}
You won't find private key in certificate because it must be in your keystore, of course, if you generated your cert with its CSR :)
As a tip, I may ask is the cert expired for example?
Anyway, the question is pretty unclear :( If you have cert you must have the keystore which was used to sign your app... It would be better you give more details...