I'm currently developing an Android app that generates an RSA key pair, builds and sends an PKCS#10 certification request to one CA, waits for the CA's response (which contains the certificate-chain including the issued for the end-entity), and then builds the PKCS#12 KeyStore to be installed within the Android KeyStore.
I just show you below some piece of code:
// It removes Android-BC
Security.removeProvider("BC");
// I've tried with SpongyCastle but it also fails.
// I've previously imported BC jars.
Security.addProvider(new BouncyCastleProvider());
KeyStore ks = KeyStore.getInstance("PKCS12","BC");
ks.load(null);
// KeyPair generated by RSA with BC, and certificates obtained from CA.
PrivateKey prvK;
Certificate eeCert, caCert;
PKCS12BagAttributeCarrier caCertBagAttr =
(PKCS12BagAttributeCarrier) caCert;
caCertBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("CA"));
PKCS12BagAttributeCarrier certBagAttr =
(PKCS12BagAttributeCarrier) eeCert;
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate"));
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
Certificate[] chain = new Certificate[2];
chain[1] = caCert;
chain[0] = eeCert;
PKCS12BagAttributeCarrier privBagAttr =
(PKCS12BagAttributeCarrier) prvK;
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate Key"));
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
// Finally, keystore is saved to file.
ks.setKeyEntry("P12", prvK, null, chain);
saveP12File(ks);
The thing is that everything is working OK when I run it on my Windows PC (BouncyCastle 1.49), but that PKCS#12 file created when I run it on Android cannot be used on SSL handshake or signing because Logcat says that it doesn't have any associated PrivateKey.
If I print the full content of the KeyStore on Java after loading the file, it seems that everything is right, but when I use on Android Browser or when I take it and install on Windows, its private key can't be used.
Same code on Android and PC, same version of BC, PKCS#12 doesn't seem to be malformed.
Can anybody help me?
Thanks in advance.
EDIT
I have built a servlet that generates an RSA Key Pair and sends back to my app in PEM format.
All seems work OK:
I can generate a valid (encrypting with public and decrypting test works good) RSA keypair either on Android device or through the external servlet.
I receive both CA and EE certificates from the CA.
I'm able to build a "valid" PKCS12 (I called it valid because it can be read by Android, Windows)
But:
I'm not able to open an SSL channel using the EE certificate as client-certificate for handshake. Either on Windows or Android.
I have uploaded to my Dropbox:
CA certificate
EE certificate issued by the CA
Private Key for the EE certificate
Public Key for the EE certificate
PKCS12 created on Android
Java Android Code
Tested against Tomcat with empty trustStore (doesnt' matter which CA issued client-certificate) unsuccessfully.
Does anybody see something that could explain it?
Related
While using AndroidKeyStore KeyGenerator to create a new ceritificate for key attestation, why Android doesn't provide an option in KeyGenParameterSpec to allow developer to create a CA with additional SubjectAltName?
The reason to ask is that if we would like to create a self-defined gRPC channel (over HTTP2) for example, using this AndroidKeyStore-generated CA for attestation, the CN will always be unchanged as "Android Keystore Key" even setCertificateSubject() is invoked and there is no valid hostname (FQDN, IP-Address) can be verified in TLS session in GrpcUtil.checkAuthority().
The current workaround is to modified the gRPC library to call disableCheckAuthority() when utilizing OkHttp Connection.
How to set SubAltName in an attestation CA generated from Android KeyStore?
Recently, I've been testing the certificate pinning implementation provided by OkHttp using version 4.9.0 + Retrofit 2.9.0; And I've noticed that the hash check is not conjunctive but rather disjunctive.
According to the example implementation the certificate chain of publicobject.com:
Peer certificate chain:
sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
If we change the certificate and we do so with the same provider and/or root as before, we would get something like:
Peer certificate chain:
sha256/dklfnskvAAQFvandjfjASAFjvjvg45nbwskdvur5548=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
Only the first hash changes, naturally I would assume that communications with the site should stop working since our implementation now has an incorrect hash, but that is not the case because the other three are the same as before.
Is it my error when creating a new certificate?
Is this the correct behavior or an error?
Is there a way to check for all hashes in the chain to be correct?
There's 4 certificates involved in that particular handshake, and OkHttp is happy if any of them match one of your signatures.
This means you can survive either of these operational events:
changing your certificate authority (your organization public key stays the same)
losing your public key and switching it out (the CA stays the same)
But if you change certificate authorities and you get a new public key, clients won't connect until you update their pins.
I was implementing secure calling from asterisk official site tutorial
And after a lot of effort and understanding of ssl and certificates, I have managed to secure it only 1 way.
Following was the best clue and direction:
SSL using self signed certs on linphone
How can I make use of client certificates (which the above tutorial generated) to validate clients also on server; called full ssl authentication
I read about this setting in linphonerc file: "verify_client_certs=1" but I don't know where to put client certs?
Hi you can check on our wiki to more information about client certificats.
https://wiki.linphone.org/wiki/index.php/Security:ClientCertAuth
Security:ClientCertAuth
1. Creating Client certificate
Generate a Certificate Signing Request
Creates a new private key and a certificate request with CN=username#domain
example test#test.linphone.org
openssl req -new -keyout key.pem -out newreq.pem
Sign the client certificate
Creates newcert.pem certificate signed by root certificate. You will need to enter the passphrase of the cacert.pem
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
Then extract the private key in a new file
openssl rsa -in key.pem -out clientkey.pem
Parameters for linphone
In linphonerc add path to client/key certificate
[sip]
client_cert_chain=/pathTo/newcert.pem
client_cert_key=/pathTo/clientkey.pem
Please, confirm where in following command we use cacert.pem
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
also i have trying to use self signed ca certficate to setup asterisk with linphone. But i could'nt figure where in linphone app i have to put the client cert or even would it work if i just add my rootca.pem to the rootca.pem in the provided source for linphone-android
I am trying desperately to export my signed APK after building my Unity project for Android as a "Google development build" and opening it in Android Studio.
I have looked at several other questions and am trying to follow https://developer.android.com/studio/publish/app-signing.html but am having a problem creating my keystore. I have followed the tutorial verbatim but can't create a valid path for the keystone -
I don't understand what I need to do. I have tried /home/users/keystores/android.jks I have tried /home/users/keystores/myprojectname.jks and just sticking it on my desktop. These are the errors Im getting-
I have tried locating android.jks but can't find anything using finder. Is it because I am on a mac? What am I doing wrong here? How can I generate my keystore so I can publish?
/home/users/keystores/ is most likely not a valid path on your mac. Try to create the keystore in a valid location like in your user's home directory:
/home/YOUR_USERNAME/
Verify that the keystore file has been created in that location.
#skyguy You have to create a keystore first using the keytool.
The keygen tool can be accessed via command line and is already included in the JDK.
If you scroll down that link I posted in my comment above, you will see the following example -
Suppose you want to create a keystore for managing your public/private key pair and certificates from entities you trust.
Generating Your Key Pair The first thing you need to do is create a
keystore and generate the key pair. You could use a command such as
the following:
keytool -genkeypair -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US"
-alias business -keypass kpi135 -keystore /working/mykeystore
-storepass ab987c -validity 180 (Please note: This must be typed as a single line. Multiple lines are used in the examples just for legibility purposes.)
This command creates the keystore named "mykeystore" in the "working"
directory (assuming it doesn't already exist), and assigns it the
password "ab987c". It generates a public/private key pair for the
entity whose "distinguished name" has a common name of "Mark Jones",
organizational unit of "JavaSoft", organization of "Sun" and
two-letter country code of "US". It uses the default "DSA" key
generation algorithm to create the keys, both 1024 bits long.
It creates a self-signed certificate (using the default "SHA1withDSA"
signature algorithm) that includes the public key and the
distinguished name information. This certificate will be valid for 180
days, and is associated with the private key in a keystore entry
referred to by the alias "business". The private key is assigned the
password "kpi135".
The command could be significantly shorter if option defaults were
accepted. As a matter of fact, no options are required; defaults are
used for unspecified options that have default values, and you are
prompted for any required values. Thus, you could simply have the
following:
keytool -genkeypair
In this case, a keystore entry with alias "mykey" is created, with a newly-generated key pair and a certificate
that is valid for 90 days. This entry is placed in the keystore named
".keystore" in your home directory. (The keystore is created if it
doesn't already exist.) You will be prompted for the distinguished
name information, the keystore password, and the private key password.
The rest of the examples assume you executed the -genkeypair command
without options specified, and that you responded to the prompts with
values equal to those given in the first -genkeypair command, above (a
private key password of "kpi135", etc.)
Once you have created a keystore, you can point to its location and sign your apk.
My .key file like:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1j6eGXbHpqigZ1K//wnuyr5v/L2jFm7dzTtHJx8ZoMQ4CbsG
My .pem file like:
-----BEGIN CERTIFICATE-----
MIIE4zCCA8ugAwIBAgIDBOziMA0GCSqGSIb3DQEBBQUAMDwxCzAJBgNVBAYTAlVT
I don't know how many steps of authenticate at here. I only want to create a ssl socket to an IP and port, and send/receive data in that socket.
I tried to use keystock, but perhaps I don't understand deep about it, I always get wrong.
Please give me a guide, or sample code.
Thanks so much.
I assume that the .key and .pem file represents your client certificate you have to use for performing an HTTPS client authentication. Unfortunately Java/Android prefers a different format, therefore I recommend you to import both file into a BKS file.
Creating a BKS file and importing existing .key+.pem file is very simple using KeyStore Explorer. After starting KeyStore Explorer select File -> New Keystore -> BKSv1. Afterwards you can execute Tools -> Import Key Pair and select the .pem file. Afterwards KeyStore Explorer will ask you for selecting the .key file.
Finally save the key store protected with a password of your choice.
The created BKSv1 file can now be used in your Android app. See for example the code posted in this question: Using client/server certificates for two way authentication SSL socket on Android
When creating a SSL connection, you just need the socket to allow the connection with your server, enabling it as a trusted source. To do so, you need to have your SSL certificate in X509 format and then create your connection as stated in this article.
Here's a guide on generating X.509 certificates.