[tor-bugs] #26536 [Applications/Tor Browser]: Create APK signing keys

Tor Bug Tracker & Wiki blackhole at torproject.org
Wed May 8 17:29:40 UTC 2019


#26536: Create APK signing keys
-------------------------------------------------+-------------------------
 Reporter:  sysrqb                               |          Owner:  tbb-
                                                 |  team
     Type:  task                                 |         Status:
                                                 |  needs_information
 Priority:  Medium                               |      Milestone:
Component:  Applications/Tor Browser             |        Version:
 Severity:  Normal                               |     Resolution:
 Keywords:  tbb-mobile, TBA-a3, tbb-8.5-must,    |  Actual Points:
  TorBrowserTeam201904                           |
Parent ID:                                       |         Points:
 Reviewer:                                       |        Sponsor:
                                                 |  Sponsor8
-------------------------------------------------+-------------------------
Changes (by sysrqb):

 * cc: eighthave (added)


Comment:

 This is a little-bit of a brain dump. I went on a deep-dive into the code
 for APK signing and using a nitrokey as a key store. As far as I
 understand it, the answer is "you can't because the stars didn't align
 correctly" - but I'm CCing Hans in case I missed something. Maybe this
 works if we get `opensc-pkcs11` packages from `stretch-backport`?

 At the beginning, I followed some of the
 [https://geoffreymetais.github.io/code/key-signing/ existing] guides for
 putting a signing certificate in PKCS12 key store onto the nitrokey.
 Unfortunately, that didn't work because importing the certificate via
 `keytool` failed. When keytool "stored" the key, it gave key type as an
 ASCII string instead of the binary number. This resulted in:
 {{{
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11] card-
 openpgp.c:2827:pgp_store_key: Unknown key type 49.
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11] card-
 openpgp.c:2828:pgp_store_key: returning with: -1300 (Invalid arguments)
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11] card-
 openpgp.c:3009:pgp_card_ctl: returning with: -1300 (Invalid arguments)
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11] card.c:961:sc_card_ctl:
 returning with: -1300 (Invalid arguments)
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11]
 pkcs15-openpgp.c:142:openpgp_store_key: returning with: -1300 (Invalid
 arguments)
 0x70d49bdbc700 19:54:34.511 [opensc-pkcs11]
 pkcs15-lib.c:1683:sc_pkcs15init_store_private_key: Card specific 'store
 key' failed: -1300 (Invalid arguments)
 }}}

 Eventually, I found the documentation on the OpenSC
 [https://github.com/OpenSC/OpenSC/wiki/OpenPGP-card#6-import-key-resp-
 certificate wiki page], and I successfully imported the certificate and
 key:
 {{{
 pkcs15-init --delete-objects privkey,pubkey,chain --id 3 --store-private-
 key secret_and_certificate.p12 --format pkcs12 --auth-id 3 --verify-pin
 }}}

 And reading the stored public key and certificate information works
 {{{
 $ pkcs15-tool --read-public-key 3
 Using reader with a card: Nitrokey Nitrokey Pro (000039610000000000000000)
 00 00
 -----BEGIN PUBLIC KEY-----
 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8+4jHWnOQ18yStSqOYrv
 MTGHaudFY0KLYfatjGXFIv3fbtzCT25hWtl4WY+MWVxjLy1R34Il7CZ0KvdHnYtF
 7qN5rHwh6GZb37KsjwAIwLR6K6icqjnFgcCCfTVZnaPW4P1ARd1Ove7eOXkL5t1j
 C2unkIvrOeIOqpxC28xbt7T3pD8OL53ZHgduLHzcwvj5tiZijzZoMeuRfS5U3vhZ
 3wQghEYKrcsdU/+BFPjWZklJkrJgryt/TN2At3MylreeiDHLyLpUsCjPMgLf2oSF
 VUBWfGKu2BPzK67hN84/wUmhCbCjbjL8sooqjS58L2fZsYn/0uU//47drenQXT4z
 Vg5z7L8fjFggdycq57Xp0W4DdqCrOWBrIInnjLxKN9pNhfWWXbQgy213cXNIohtJ
 NY8MNHQtp0tp9nRqKYjrgV4pEKf0kvUuFNzBdBS+c1WU5ratYr8KcB06PdJ0VwUB
 AeVozzJTak5/0GmQi6zPIZe7nEwlhURt8r2iPE7dpnHPGogYA5WZUQcfjQOsjf84
 qwCr+IyHzTeDgVAy+SiBaRlOrY6goopRjNjsCgzVxggA3haDoENrCaAmUkq+3/lO
 DXrG7z4G+IZceAvBgYxkE0OJ/zDUMxBT6iWR1lgIIVxoeNH7Pk/nYnuSb7nBAxp3
 j2/+h7v+NRQbNvJxsFB1518CAwEAAQ==
 -----END PUBLIC KEY-----
 $ keytool -providerClass sun.security.pkcs11.SunPKCS11 -providerArg
 ~/pkcs11_java.cfg -providerName SunPKCS11-OpenSC-PKCS11 -keystore NONE
 -storetype PKCS11 -list
 Enter keystore password:
 Keystore type: PKCS11
 Keystore provider: SunPKCS11-OpenSC-PKCS11

 Your keystore contains 1 entry

 Cardholder certificate, PrivateKeyEntry,
 Certificate fingerprint (SHA-256):
 EE:82:97:2E:1E:30:2F:67:9B:C7:0F:45:A4:EE:24:E0:80:80:05:BB:28:00:A1:E1:6F:68:3D:93:FC:79:C4:EF
 }}}

 However, signing with `apksigner` does not:
 {{{
 $ apksigner sign --provider-class sun.security.pkcs11.SunPKCS11
 --provider-arg pkcs11_java.cfg --ks NONE --ks-type SunPKCS11-OpenSC-PKCS11
 tor-browser-8.5a11-android-x86-multi-qa.apk
 Exception in thread "main" java.lang.NoSuchMethodException:
 sun.security.pkcs11.SunPKCS11.<init>(java.lang.String)
         at java.base/java.lang.Class.getConstructor0(Class.java:3350)
         at java.base/java.lang.Class.getConstructor(Class.java:2152)
         at
 com.android.apksigner.ApkSignerTool$ProviderInstallSpec.installProvider(ApkSignerTool.java:600)
         at
 com.android.apksigner.ApkSignerTool$ProviderInstallSpec.access$400(ApkSignerTool.java:575)
         at
 com.android.apksigner.ApkSignerTool.sign(ApkSignerTool.java:259)
         at com.android.apksigner.ApkSignerTool.main(ApkSignerTool.java:89)
 }}}

 After digging into this, and tracing why `keytool` works but `apksigner`
 does not, I found `apksigner` makes a bad assumption about how the
 keystore is instantiated. In particular, when using a PKCS11 keystore,
 `keytool`
 [https://hg.openjdk.java.net/jdk/jdk/file/865ec913f916/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java#l274
 instantiates the class] and then
 [https://hg.openjdk.java.net/jdk/jdk/file/865ec913f916/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java#l277
 configures it] (two steps process).

 However, `apksigner` tries to do this in one step - by passing the
 configuration
 [https://android.googlesource.com/platform/tools/apksig/+/refs/heads/master/src/apksigner/java/com/android/apksigner/SignerParams.java#212
 into the constructor]. This fails because the `SunPKCS11` class doesn't
 define a one-parameter constructor, and this is why we get the
 `java.lang.NoSuchMethodException`.

 I tried finding an alternative method of configuring this, but I found
 this is related to the version of Java I'm using. In
 [https://hg.openjdk.java.net/jdk/jdk/file/a1ee9743f4ee/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
 Java 8], the exists a single-parameter String constructor in SunPKCS11,
 but Java 11 does not have one. Unfortunately, I switched from Java 8 (in
 Debian Stretch) to Java 11 (in Fedora 29) because there was a bug in
 `opensc-pkcs11` that was patched in a newer version but it isn't available
 in Stretch. (I lost the link to the bug, but I'll paste it later if I find
 it).

 Currently, when I try signing using Java 8, I get this - and I'm stuck:
 {{{
 $ OPENSC_DEBUG=9 ./android-sdk-linux/build-tools/28.0.2/apksigner sign
 --verbose --provider-class sun.security.pkcs11.SunPKCS11 --provider-arg
 pkcs11_java.cfg --ks NONE --ks-type PKCS11 tor-browser-8.5a11-android-x86
 -multi-qa.apk
 [snip]
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11] slot.c:328:card_detect:
 Nitrokey Nitrokey Pro (000039610000000000000000) 00 00: Detection ended
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11] slot.c:357:card_detect_all:
 All cards detected
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-global.c:503:C_GetSlotInfo: C_GetSlotInfo() get slot rv 0
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-global.c:530:C_GetSlotInfo: C_GetSlotInfo() flags 0x7
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-global.c:531:C_GetSlotInfo: C_GetSlotInfo(0x0) = CKR_OK
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-session.c:191:C_GetSessionInfo:
 C_GetSessionInfo(hSession:0x7771d8255e30)
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-session.c:199:C_GetSessionInfo: C_GetSessionInfo(slot:0x0)
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-session.c:216:C_GetSessionInfo: C_GetSessionInfo(0x7771d8255e30) =
 CKR_OK
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-object.c:336:C_FindObjectsInit: C_FindObjectsInit(slot = 0)
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_TOKEN =
 TRUE
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_CLASS =
 CKO_PRIVATE_KEY
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 misc.c:254:session_start_operation: called
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 misc.c:255:session_start_operation: Session 0x7771d8255e30, type 0
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 pkcs11-object.c:406:C_FindObjectsInit: 0 matching objects
 0x7771e08c9700 17:05:15.124 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:59:sc_find_release: freeing 0 handles used 0  at (nil)
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:336:C_FindObjectsInit: C_FindObjectsInit(slot = 0)
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_TOKEN =
 TRUE
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_CLASS =
 CKO_CERTIFICATE
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:254:session_start_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:255:session_start_operation: Session 0x7771d8255e30, type 0
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:406:C_FindObjectsInit: 0 matching objects
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:59:sc_find_release: freeing 0 handles used 0  at (nil)
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:336:C_FindObjectsInit: C_FindObjectsInit(slot = 0)
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_TOKEN =
 TRUE
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:337:C_FindObjectsInit: C_FindObjectsInit(): CKA_CLASS =
 CKO_SECRET_KEY
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:254:session_start_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:255:session_start_operation: Session 0x7771d8255e30, type 0
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:406:C_FindObjectsInit: 0 matching objects
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 misc.c:276:session_get_operation: called
 0x7771e08c9700 17:05:15.125 [opensc-pkcs11]
 pkcs11-object.c:59:sc_find_release: freeing 0 handles used 0  at (nil)
 Failed to load signer "signer #1": NONE does not contain key entries
 }}}

 While, `pkcs15-tool --dump` shows:
 {{{
 $ pkcs15-tool --dump
 Using reader with a card: Nitrokey Nitrokey Pro (000039610000000000000000)
 00 00
 PKCS#15 Card [OpenPGP card]:
         Version        : 0
         Serial number  : 000500003961
         Manufacturer ID: ZeitControl
         Language       : de
         Flags          : PRN generation, EID compliant
 [...]
 Private RSA Key [Authentication key]
         Object Flags   : [0x3], private, modifiable
         Usage          : [0x222], decrypt, unwrap, nonRepudiation
         Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract,
 local
         ModLength      : 4096
         Key ref        : 2 (0x2)
         Native         : yes
         Auth ID        : 02
         ID             : 03
         MD:guid        : 7300fc9e-b71d-2853-11d7-e05d5d9a91e4

 Public RSA Key [Authentication key]
         Object Flags   : [0x2], modifiable
         Usage          : [0x51], encrypt, wrap, verify
         Access Flags   : [0x2], extract
         ModLength      : 4096
         Key ref        : 0 (0x0)
         Native         : no
         Path           : a401
         ID             : 03

 X.509 Certificate [Cardholder certificate]
         Object Flags   : [0x0]
         Authority      : no
         Path           : 3f007f21
         ID             : 03
         Encoded serial : 02 09 00CC76B8E0E29658BE
 }}}

 For the record:
 {{{
 $ cat pkcs11_java.cfg
 name = OpenSC-PKCS11
 description = SunPKCS11 via OpenSC
 library = /usr/lib64/opensc-pkcs11.so
 slotListIndex = 0
 }}}

--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/26536#comment:14>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online


More information about the tor-bugs mailing list