7

We're working on a Cordova app and having difficulty signing the Android version of the app.

Using the command

jarsigner -keystore keystore.p12 -storetype pkcs12 android-release-unsigned.apk 1

gives the following exception

java.io.IOException: DerInputStream.getLength(): Redundant length bytes found

which comes from this line in OpenJDK apparently this was added to fix CVE-2016-5546 although I don't know enough about crypto to really understand it.

Exporting the certificate with openssl and creating a new p12 from that works fine but changes the signature which means the play store rejects the upload.

The keystore we have came from another company that we originally outsourced the app development to.

Any jarsigner or keytool command throws the same exception which I guess makes sense since they all use the same Java lib

Jacek Kuzemczak
  • 455
  • 5
  • 7

7 Answers7

5

We had the same problem. We have found that JDK 1.8.0_112 doesn't have the bug that you're talking about. So we resolved the problem in this way:

At first we converted temp_keystore.p12 into mycert.keystore by using the following command (Java\jdk1.8.0_112\bin\keytool.exe):

keytool -importkeystore -srckeystore temp_keystore.p12 -destkeystore mycert.keystore -srcstoretype pkcs12

Then we use the following command (Java\jdk1.8.0_112\bin\jarsigner.exe):

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mycert.keystore ReadyForSigning.apk 1

to sign apk. ("1" at the end of command is the alias)

PS.: Converting from .p12 to .keystore may be not necessary.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
Olexandr Vovk
  • 66
  • 1
  • 3
  • Yeah you're right it seems to be magically working now we're on 131. From the commit it looks like they put in a flag to skip the new check. – Jacek Kuzemczak Jun 14 '17 at 13:41
4

I have spent hours finding a solution to this problem. Tried five different JDKs and nothing worked. I have an old PKCS12 certificate for a very popular playstore app that I have "inherited" from the previous developer, and JDK 8 + 9 will not use it. Olexandr's solution didn't help either.

Finally, almost by shear luck, I managed to find a solution here, in Weijung Wang's reponse. It involves exporting and reimporting the certificate using openssl. I then reimported the P12 keystore in the JKS keystore and it now works with JDK 8.

Quote:

weijun Weijun Wang added a comment - 2017-02-28 15:55
Openssl is able to remove the redundant 0s when extracting the private key. We can use the following 2 commands to normalize an affected pkcs12 file:

  1. openssl pkcs12 -in pkcs12-file -out key-and-cert -nodes -passin pass:abcXYZ

  2. openssl pkcs12 -in key-and-cert -export -out new-pkcs12-file -passout pass:abcXYZ

Community
  • 1
  • 1
Anders Emil
  • 457
  • 3
  • 13
3

I have been having the same error, and Olexandr's solution wouldn't work, as using keytool on JDK8 (update 151) would throw an error while reading the certificate, which was generated with JDK7. As from Anders answer, using OpenSSL worked with (pasting the command lines for future reference) :

openssl pkcs12 -in android.p12 -out android_fixed.cert -nodes -passin pass:your_p12_password
openssl pkcs12 -in android_fixed.cert -export -out android_cert.p12 -passout pass:your_p12_password
fnicollet
  • 151
  • 2
  • 4
3

I have keystore generated with JDK6. As workaround, I have been using JDK 1.8.0_112 by setting JDK under [Project Structure] - [SDK Location] - [JDK location].

I have solved with steps below (using macOS).

Convert to PKCS12 using JDK 1.8.0_112

/Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/keytool -importkeystore -srckeystore original.keystore -destkeystore 1.8.0_112.p12 -deststoretype PKCS12 -storepass ***** -destkeypass *****

Process with OpenSSL (Thanks to Weijung Wang and Anders Emil)

openssl pkcs12 -in 1.8.0_112.p12 -out 1.8.0_112.cert -nodes -passin pass:*****
openssl pkcs12 -in 1.8.0_112.cert -export -out 1.8.0_112.export.p12 -passout pass:*****

Convert to JKS using JDK 1.8.0_161.

Here I need to specify -destkeypass, -srcalias, and -destalias. Note that alias is "1" after openSSL commands, so needed to set alias.

/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/bin/keytool -importkeystore -srckeystore 1.8.0_112.export.p12 -srcstoretype pkcs12 -destkeystore 1.8.0_112.keystore -deststoretype jks -deststorepass ***** -destkeypass ***** -srcalias 1 -destalias youralias

So the results of fingerprints shows like this.

Original keystore:
     SHA1: 6C:9E:...:C5:8A

Original apk:
     SHA1: DA:4C:...:3F:02

Modified keystore:
     SHA1: C8:4A:...:2A:23

Modified apk:
     SHA1: DA:4C:...:3F:02
Water
  • 540
  • 7
  • 7
  • If the keystore fingerprints are different, then how would it be accepted as a valid release? Google Play console is giving me an error that fingerprints are different. – Vas Jun 30 '18 at 07:01
  • @Vas Original keystore was made incorrectly by JDK6, and original apk shows different fingerprint which didn't seem to match, however fingerprints from modified keystore and apk match. Google play should accept modified apk as fingerprints are the same. – Water Jul 02 '18 at 06:50
  • @JanineKroser Actually they did accept my apk and update is published on Google play. – Water Sep 20 '18 at 02:26
  • @Water How did you get the SHA1 of the APKs to verify that this worked? – anthonylawson Feb 08 '21 at 21:18
  • 1
    @anthonylawson Install old app signed with JDK6 on device, then try to install new app signed with JDK 1.8.0_161. If app is overwritten and run without error, it means success. – Water Feb 09 '21 at 23:51
  • @Water Yeah, I followed the instructions here and get INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.blah.blah signatures do not match previously installed version; ignoring! – anthonylawson Feb 10 '21 at 15:45
1

@Water's solution didn't worked for me. The signature of the generated apk was different than the original one.

I finally got it working by upgrading to Google's new app signing by uploading the private key generated with pepk tool and asked their support to reset the upload key.

Jun
  • 3,422
  • 3
  • 28
  • 58
  • Are you saying that you managed to convince them to change the signing key for you? Or what do you mean by "reset the upload key" – Anders Emil Oct 13 '20 at 05:46
  • If you use google app signing, you can ask to reset the upload key. – Jun Oct 13 '20 at 13:30
0

I FOUND AN AWESOME SOLUTION

I too was manually signing my APK's because of this, but now that Google is requiring targetSDK=30, it is also requiring using V2 signing scheme. This is something I don't know how to do manually.

BUT I FOUND A FIX!

Just set the JDK used by Android Studio to something slightly older in File -> Project Structure -> JDK Location. By default it uses its embedded JDK but you can point it to anything. I'm using 1.8.0_45 for example. And I can now just use Build -> Generate Signed APK directly with my old "broken" keystore again!

Someday Android Studio might require the latest "buggy" JDK again, but for now I'm set.

Allan
  • 11
  • 1
0

In many cases the problem is the Java version. If you very had old PKCS12 .p12 file (like mine) you would need Java 6 to read it. The old keys use weaker encryption 1024 bit encryption I think.

So just use the keytool command line like this (I needed to get the SHA1 key):

"C:\Program Files\Java\jdk1.6.0_45\bin\keytool" -exportcert -keystore cert.p12 -storepass <yourpass> -list -v -storetype PKCS12
Deyan Vitanov
  • 695
  • 5
  • 18