18

I am trying to install the self-signed certificate for my web server in Android 4.3. I have the .crt file in the root of the SD card (which is actually emulated as I have no SD card in the slot).

To install the certificate I go to Setting -> General -> Security -> Credential Storage -> Install from device storage.

I get a dialog box showing the name of the certificate (the filename minus the .crt extension) which I can modify (but don't), a "used for" pull down with "VPN and apps" selected and text at the bottom of the dialog which informs "Package contains: one user certificate". Everything looks okay, so I click "Ok". The dialog goes away and a toast message pops up with "[name] installed".

However if I immediately go to "Trusted credentials and select "User" there is nothing there! The new cert is also not under "System" but I would not expect it there. If I go to a browser after this and try going to my web site, I still get the warning that the site's certificate is not trusted. I have also tried rebooting, but it doesn't make a difference.

What am I doing wrong? The complete lack of error messages isn't helpful. Is it possible my certificate is in the wrong format? I have tried using the .crt file in the server's ssl directory and I have tried converting it to DER format.

Update: I read somewhere that Android requires certificates to be in p12 format, so I converted the Apache2 certificate to p12 using the following command:

openssl pkcs12 -export -inkey server.key -in server.crt -out ~/server.p12

I then repeated the above steps, got the same success message, and then proceeded to still not see the certificate in the user credentials and I still get the untrusted certificate error from the mobile browser.

1 Answer 1

19

I had the same problem getting Android to really install the certificate, until I found this site which describes a method that worked for me. It boils down to the following steps:

  1. Create a private key and public x509 certificate with v3_req extensions and enabled as a CA:

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout /etc/ssl/private/my_site.key -out /etc/ssl/certs/my_site.crt -reqexts v3_req -extensions v3_ca

  2. Convert the certificate to DER format, which is understood by Android:

    sudo openssl x509 -in /etc/ssl/certs/my_site.crt -outform der -out my_site.der.crt

  3. Use any method to get the my_site.der.crt to your Android device - I found it easy to just have the file hosted by my web server and download it via the Android browser, which then automatically lets you install it.

Although I would've liked step 1 to be broken into two (1a. generation of private key and 1b. generation of public certificate), I didn't invest too much time investigating how to do that. Please let me know in a comment if you found a way that works, thanks.

(Rather than add a comment, I feel this really belongs as part of the answer for future reference, so I am editing it in. --Michael)

Instead of creating a certificate enabled as a CA, I created a self-signed CA and then re-signed my existing key/csr with the new CA. Then I added the self-signed CA to Android and voila! It worked!

Generating the self-signed CA:

openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem

Re-signing an existing CSR I had from creation of the key from the

openssl x509 -req -in existing.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out existing.crt -days 3649

Now using a modified form of your second command I converted the CA certificate to DER form:

openssl x509 -in /etc/apache2/ssl/rootCA.pem -outform der -out ~/rootCA.der.crt

The great thing about this is, any additional untrusted certificates that are now re-signed with the new self-signed CA will now be trusted on any device than has the new CA installed without needing to install anything else. This doesn't exactly solve the problem of trusting sites you have no control over, but it might make it easier if you have any influence over (say) your IT department for an internal server or something.

14
  • 1
    I already have the certificate I need to install, so I tried step 2 and it still is not showing up in User Trusted Credentials after it claims to succeed in installing, and Chrome still displays the "untrusted site" error after restarting.
    – Michael
    May 28, 2014 at 16:21
  • 1
    Could there be something about the v3_req extension and enabled as CA that the certificate is required to have for Android to use it? If so, is there a command that I can use to take an existing certificate and add that information to it, as I don't have control over all the certs I want to install.
    – Michael
    May 28, 2014 at 16:22
  • 3
    To answer the first half of my previous question, I read the page you had linked, and it appears that the problem is that Android refuses to install self-signed certificates (but not self-signed CAs). This seems to be un(der)-documented, and the fact that Android pretends to install makes it even worse. But the question remains, if I have a self-signed cert that I don't have control over, is there some way to "CA"-ify it so I can install it?
    – Michael
    May 28, 2014 at 16:26
  • 1
    @I hope you don't mind, I'm going to edit your answer to include my solution, rather than including it in the comments, as it really belong as part of the answer.
    – Michael
    May 29, 2014 at 5:16
  • 1
    I don't get it how the existing.csr signing request is generated. I think this is the last missing point for a complete step by step tutorial.
    – cguenther
    Jan 5, 2015 at 17:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .