27

After a while of not updating my applications in the Play Store I tried to sign one of my APK with my keystore, only to find that the keystore and alias password doesn't work anymore. The keystore password I was able to reset using this gist: gist.github.com/zach-klippenstein/4631307 and works fine now. This happens for two different keystores for two different applications.

Running keytool -list -keystore mykeystore resulted in:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

myalias, Dec 23, 2014, PrivateKeyEntry, 
Certificate fingerprint (SHA1): 85:8F:69......

I am 100% sure that the alias password is the same as the keystore password, but it doesn't seem to work. I've tried signing the APK in Android Studio and with jarsigner -keystore mykeystore -storepass mykeystorepassword app-debug.apk myalias but the response is always: jarsigner: unable to recover key from keystore.

I tried moving the alias to a new keystore file with keytool -importkeystore -srckeystore mykeystore -destkeystore newkeystore -srcalias myalias it then asks me to enter new password for the new keystore and the password for the old keystore (both work), only after entering the alias password I get an exception:

Enter destination keystore password:  
Re-enter new password: 
Enter source keystore password:  
Enter key password for <myalias>
keytool error: java.security.UnrecoverableKeyException: Cannot recover key

After some Googling I found that for some people the keystore stopped working after updating to another JDK version or Android Studio version, so I am wondering if that is the case for me also. The keystore was created in 2014 so I was probably on JDK7 at the time (I am now at 8). It is also suspicious two keystores mysteriously stop working..

Can this be fixed somehow?

EDIT:

I tried the solution from Jan and got the following results:

keytool -importkeystore -srckeystore mykeystore -destkeystore newkeystore -deststoretype pkcs12 gives me the same exception: keytool error: java.security.UnrecoverableKeyException: Cannot recover key.

After running this command: keytool -importkeystore -srckeystore newkeystore -srcstoretype pkcs12 -destkeystore finalkeystore -deststoretype jks I get this error: keytool error: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.

SECOND EDIT:

I also tried signing the apk on a PC with JDK7, no luck.

THIRD EDIT:

I tried using the KeyStore Explorer and it opens the keystore file just fine and shows one entry (not expired). When I try to open the private key I get the same exception. Stacktrace:

java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(KeyProtector.java:328)
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:146)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:96)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineGetKey(JavaKeyStore.java:70)
at java.security.KeyStore.getKey(KeyStore.java:1023)
at net.sf.keystore_explorer.gui.actions.KeyStoreExplorerAction.unlockEntry(KeyStoreExplorerAction.java:154)
at net.sf.keystore_explorer.gui.actions.KeyStoreExplorerAction.getEntryPassword(KeyStoreExplorerAction.java:123)
at net.sf.keystore_explorer.gui.actions.KeyPairPrivateKeyDetailsAction.doAction(KeyPairPrivateKeyDetailsAction.java:69)
at net.sf.keystore_explorer.gui.actions.KeyStoreExplorerAction.actionPerformed(KeyStoreExplorerAction.java:93)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Niels Masdorp
  • 2,214
  • 1
  • 16
  • 29
  • Have you tried other passwords, may be an `empty` password. – always_a_rookie Feb 24 '16 at 21:45
  • I pretty much tried everything password-wise.. – Niels Masdorp Feb 25 '16 at 12:28
  • have you tried "changeit" as the password, and have you tried doing a `which keytool` to see which JDK it's coming from? Maybe you have multiple JDK's installed and somethings going on there... also, possibly brute force your password [using this](http://stackoverflow.com/a/21920961/26510) – Brad Parks Feb 26 '16 at 15:22
  • Have you tried with the previous jdk? May be the trick – Oldskultxo Feb 26 '16 at 15:25
  • Yes same result when signing on JDK7 (which is what I believe I was on at the time) – Niels Masdorp Feb 26 '16 at 15:26
  • @BradParks I only have one JDK on this machine (JDK8) and I highly doubt the password is wrong. I did try to brute-force it with no success. – Niels Masdorp Feb 26 '16 at 15:38
  • Try opening the keystore with `KeyStore Explorer` (http://keystore-explorer.org/), and see if it is throwing the same exception. – always_a_rookie Feb 26 '16 at 15:42
  • @always_a_rookie_to_learn the keystore opens fine in the explorer, only when I try to show the details about the key in the keystore I get the same exception. I've posted the stacktrace to the question. – Niels Masdorp Feb 26 '16 at 15:50
  • Did you try [this solution](http://stackoverflow.com/a/35317139/26510) or [this one](http://stackoverflow.com/a/34493311/26510) ? You could also try using a different JDK (OpenJDK) or finding the source to the JDK and looking at what the line is at that fail. You can also debug into the JDK as well... – Brad Parks Feb 27 '16 at 11:50
  • Please check the file-size of the keystore against a backup _older_ then the last time you know it worked. If it isn’t the same size, try this backup. – Loxley Mar 01 '16 at 05:47
  • Have you tried adding a space at the end of the password? The key password is obviously different from the keystore password, but it might be a subtle difference like an invisible character. – Omikron Mar 01 '16 at 22:46
  • @Loxley thanks for the tip, but I only have one version of the keystore, I stored it in dropbox, thats it. – Niels Masdorp Mar 02 '16 at 08:52
  • @Omikron I tried that already, thanks for your comment. I doubt entering the wrong password will give me an UnrecoverableKeyException though.. – Niels Masdorp Mar 02 '16 at 08:53
  • Of course it will give an `UnrecoverableKeyException`. Try it yourself: `keytool -genkey -alias test -keystore keystore.jks -storepass 123456 -keypass "123456 "` then `keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore2.jks -srcalias test -srcstorepass 123456 -srckeypass 123456 -deststorepass 123456` – Omikron Mar 02 '16 at 10:13
  • @Omikron You are right. However, when I create a new keystore with `keytool -genkey -alias testalias -keystore testkeystore.jks -storepass 123456 -keypass "123456"` and use it with `jarsigner -keystore testkeystore.jks -storepass mykeystorepassword app-debug.apk testalias` It signs the jar without asking for the alias password. But when I try to sign the jar with the normal keystore (same command) it asks for the key of the alias which results in `jarsigner: unable to recover key from keystore`, which is weird. Is this because the alias password might be different than the keystore password? – Niels Masdorp Mar 02 '16 at 13:57
  • @Omikron also when I create a keystore with your command and use `keytool -keypasswd -alias test -keystore keystore.jks` it only asks for my keystore password and lets me change the key password after that.. When I try the same thing with my keystore it first asks for my keystore password and then prompts me to enter my key password for the . Am I missing something here? – Niels Masdorp Mar 02 '16 at 14:03
  • If you provide no key password on the command line, keytool and jarsigner first try to use the store password to unlock the key. Only if this fails (i.e. the two passwords are different) the user is prompted for the key password (see [keytool documentation](http://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html)). – Omikron Mar 02 '16 at 14:07
  • Alright, I suppose that makes sense. That leaves two options, either the password is not what I thought it was (even when I did use it successfully to sign multiple times and never changed it) or the key is somehow corrupt. Do you know a way to verify/find out if the thing is corrupt? – Niels Masdorp Mar 02 '16 at 14:11
  • Actually, the purpose of the store password is to ensure the keystore's integrity, so it is most probably not corrupt. But I don't know of any way to verify this. – Omikron Mar 02 '16 at 14:22
  • Well the keystore password was also not working.. I was able to reset that password using this gist: https://gist.github.com/zach-klippenstein/4631307 so maybe thats a clue. – Niels Masdorp Mar 02 '16 at 15:32
  • You should have mentioned that in the question. We cannot rule out data corruption then. – Omikron Mar 02 '16 at 17:28

3 Answers3

6

Try

keytool -importkeystore -srckeystore old.keystore -destkeystore new.keystore -deststoretype pkcs12

and

keytool -importkeystore -srckeystore new.keystore -srcstoretype pkcs12 -destkeystore final.keystore -deststoretype jks

as suggested in this question.

Tobi Nary
  • 4,387
  • 4
  • 26
  • 48
0

I had the exact same issue as yours and was getting the exact same results on trying Smoke Dispensers and other solutions as below:

keytool -importkeystore -srckeystore mykeystore -destkeystore newkeystore -deststoretype pkcs12 gives me the same exception: keytool error: java.security.UnrecoverableKeyException: Cannot recover key.

After running this command: keytool -importkeystore -srckeystore newkeystore -srcstoretype pkcs12 -destkeystore finalkeystore -deststoretype jks I get this error: keytool error: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.

I however was able to get it to work after realizing that I was using the incorrect password for the alias. So try the below command and see if you are able to guess the right password and simultaneously change it to one which you can remember.

keytool -keypasswd  -alias mykey -keystore mykeystore
FBP
  • 335
  • 3
  • 13
-2

I would do this.

The command would error out on me each time:

keytool -importkeystore -srckeystore old.keystore -destkeystore new.keystore -v

keytool -importkeystore -srckeystore old.keystore -destkeystore new.keystore -deststoretype pkcs12

After extracting the private key and storing as PKCS12, I think extracted my private key and put it back into a brand new Java Keystore:

keytool -importkeystore -srckeystore new.keystore -srcstoretype pkcs12 -destkeystore final.keystore -deststoretype jks

Kumar Utsav
  • 2,331
  • 3
  • 20
  • 35