I use CAcert.org for most of my X.509 certificates (aka SSL-certificates). It has some very important advantages and disadvantages: being free and being non-default in most systems. Usually it’s not much of a hassle to import the root certificate into a browser, OS or mail client. On Android however, things seemed a little more complex.

CAcert.org does provide some detailed instructions , but they needed some tweaking to work on my MacOSX system. Simply following the instructions got me this helpful error:

keytool error: java.lang.ClassNotFoundException: org.bouncycastle.jce.provider.BouncyCastleProvider

The problem seemed to be that $JAVA_HOME isn’t defined on my system, hence, the required JAR-file (bcprov-jdk16-141.jar) couldn’t be found. After some searching, it appears that on MacOSX (10.6.3), $JAVA_HOME is located here: /System/Library/Frameworks/JavaVM.framework/Home:

$ wget http://bouncycastle.org/download/bcprov-jdk16-141.jar
--2010-05-03 13:25:59--  http://bouncycastle.org/download/bcprov-jdk16-141.jar
Resolving bouncycastle.org (bouncycastle.org)... 203.32.61.81
Connecting to bouncycastle.org (bouncycastle.org)|203.32.61.81|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://downloads.bouncycastle.org/java/bcprov-jdk16-141.jar [following]
--2010-05-03 13:26:00--  http://downloads.bouncycastle.org/java/bcprov-jdk16-141.jar
Resolving downloads.bouncycastle.org (downloads.bouncycastle.org)... 210.15.218.194
Connecting to downloads.bouncycastle.org (downloads.bouncycastle.org)|210.15.218.194|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://www.bouncycastle.org/archive/141/bcprov-jdk16-141.jar [following]
--2010-05-03 13:26:01--  http://www.bouncycastle.org/archive/141/bcprov-jdk16-141.jar
Resolving www.bouncycastle.org (www.bouncycastle.org)... 203.32.61.81
Connecting to www.bouncycastle.org (www.bouncycastle.org)|203.32.61.81|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1680122 (1.6M) [application/java-archive]
Saving to: `bcprov-jdk16-141.jar'

100%[=============================================================================================================================>] 1,680,122   96.9K/s   in 18s     

2010-05-03 13:26:20 (89.6 KB/s) - `bcprov-jdk16-141.jar' saved [1680122/1680122]

$ sudo cp bcprov-jdk16-141.jar /System/Library/Frameworks/JavaVM.framework/Home/lib/ext/.
Password:
$ adb pull /system/etc/security/cacerts.bks cacerts.bks
1678 KB/s (47159 bytes in 0.028s)
0 niels@Raptor ~/Downloads/android-sdk_r05-mac_86/android-sdk-mac_86/tools $ wget http://www.cacert.org/certs/root.crt
--2010-05-03 13:25:22--  http://www.cacert.org/certs/root.crt
Resolving www.cacert.org (www.cacert.org)... 213.154.225.245
Connecting to www.cacert.org (www.cacert.org)|213.154.225.245|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2569 (2.5K) [application/x-x509-ca-cert]
Saving to: `root.crt'

100%[=============================================================================================================================>] 2,569       --.-K/s   in 0s      

2010-05-03 13:25:22 (117 MB/s) - `root.crt' saved [2569/2569]

$ keytool -keystore cacerts.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -storepass changeit -importcert -trustcacerts -alias CACERT -file root.crt
Owner: EMAILADDRESS=support@cacert.org, CN=CA Cert Signing Authority, OU=http://www.cacert.org, O=Root CA
Issuer: EMAILADDRESS=support@cacert.org, CN=CA Cert Signing Authority, OU=http://www.cacert.org, O=Root CA
Serial number: 0
Valid from: Sun Mar 30 14:29:49 CEST 2003 until: Tue Mar 29 14:29:49 CEST 2033
Certificate fingerprints:
 MD5:  A6:1B:37:5E:39:0D:9C:36:54:EE:BD:20:31:46:1F:6B
 SHA1: 13:5C:EC:36:F4:9C:B8:E9:3B:1A:B2:70:CD:80:88:46:76:CE:8F:33
 Signature algorithm name: MD5withRSA
 Version: 3

Extensions: 

#1: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
 CA:true
 PathLen:2147483647
]

#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 16 B5 32 1B D4 C7 F3 E0   E6 8E F3 BD D2 B0 3A EE  ..2...........:.
0010: B2 39 18 D1                                        .9..
]
]

#3: ObjectId: 2.16.840.1.113730.1.8 Criticality=false

#4: ObjectId: 2.16.840.1.113730.1.4 Criticality=false

#5: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
 [DistributionPoint:
 [URIName: https://www.cacert.org/revoke.crl]
]]

#6: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 16 B5 32 1B D4 C7 F3 E0   E6 8E F3 BD D2 B0 3A EE  ..2...........:.
0010: B2 39 18 D1                                        .9..
]

[EMAILADDRESS=support@cacert.org, CN=CA Cert Signing Authority, OU=http://www.cacert.org, O=Root CA]
SerialNumber: [    00]
]

#7: ObjectId: 2.16.840.1.113730.1.13 Criticality=false

Trust this certificate? [no]:  yes
Certificate was added to keystore
$
$ adb shell mount -o remount,rw /system
$ adb push cacerts.bks /system/etc/security/
$ adb shell mount -o remount,ro /system
$
$ sudo rm /System/Library/Frameworks/JavaVM.framework/Home/lib/ext/bcprov-jdk16-141.jar
Password:
$

One Comment

  1. Cristian says:

    Hi,
    very useful tutorial, although i’m having a big problem.
    i manage to update the cacerts keystore on my computer but i can’t put it back on the android. because apparently the /system does not have any empty space, does not even work to replace the existing file with a smaller one. i’m trying on the emulator. do you have any ideas how to fix this??
    thanks