Bug 2176704

Summary: Presence of SHA1 hashes causes SHA-256 signed jar verification to fail in OpenJDK 8u362
Product: [Fedora] Fedora Reporter: Clive Brettingham-Moore <clive-fedora>
Component: java-1.8.0-openjdkAssignee: Severin Gehwolf <sgehwolf>
Status: ASSIGNED --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 37CC: ahughes, dbhole, jerboaa, jvanek, msrb, sgehwolf
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
minimal jar with sha256 signature and sha1 extra hashes
none
example jar with first entry having only SHA-256 hash, but subsequent ones having both SHA1 and SHA-256 none

Description Clive Brettingham-Moore 2023-03-09 02:26:21 UTC
Created attachment 1949196 [details]
minimal jar with sha256 signature and sha1 extra hashes

Description of problem:
If a signed jar contains SHA1 content hashes in addition to SHA-256 the content will be reported as unsigned (eg jarsigner -verify doesn't report an algorithm problem like it would with an SHA1 signed jar, instead list entries as unsigned). The problem seems to be in the platform verification code, but jarsigner is a convenient test case.
OpenJDK 11 and OpenJDK 17 will validate the jar without issue.

Additionally the problematic check seems to only be applied to the first entry in the jar file - if the first entry has SHA-256 only, then subsequent ones will verify ok even they they use deprecated algorithms.

Version-Release number of selected component (if applicable):
java-1.8.0-openjdk-devel-1.8.0.362.b09-2.fc37.x86_64
but seems to be an upstream OpenJDK 8u362 issue (eg Eclipse Temurin affected too)

How reproducible:
Issue seems to be consistently reproducible when conditions are met as described.

Steps to Reproduce:
1. Given jar with the extra hashes (attached), or eg sign with sha1 (in a version that will let you) then re-sign with sha256 (need to have appropriate keystore config):
jarsigner -digestalg SHA1 example-sha-both.jar dpipwe-code-sign
jarsigner -digestalg SHA-256 example-sha-both.jar dpipwe-code-sign

(Usually this will be due to a pre-existing jar sha1 signed sometime in the past getting resigned with SHA-256 subsequently)

2. try to verify it:
jarsigner -verify -verbose example-sha-both.jar

Actual results:

jarsigner -verify reports unsigned entries

Expected results:

Jar passes as valid, eg what we see from Java 17 (earlier Java 8 same).

Additional info:

Additional debug logging can be seen by setting system properties eg:
jarsigner -J-Djava.security.debug=jar -verify -verbose example-sha-both.jar

or even more verbose showing algorithm check calls:
jarsigner -J-Djava.security.debug=jar,certpath -verify -verbose example-sha-both.jar

Comment 1 Clive Brettingham-Moore 2023-03-09 02:40:54 UTC
Created attachment 1949199 [details]
example jar with first entry having only SHA-256 hash, but subsequent ones having both SHA1 and SHA-256

Attached example jar where first sha-256 only entry allows jar to pass even when containing later SHA1 entries.

debug logging reveals it validates both hashes for the later entries

jarsigner -J-Djava.security.debug=jar -verify -verbose example-sha-both-shadowed.jar
(snip)
jar: beginEntry META-INF/1.txt
jar: Manifest Entry: META-INF/1.txt digest=SHA-256
jar:   manifest 4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865
jar:   computed 4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865
jar:
jar: beginEntry a.txt
jar: Manifest Entry: a.txt digest=SHA-256
jar:   manifest 87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
jar:   computed 87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
jar:
jar: Manifest Entry: a.txt digest=SHA1
jar:   manifest 3f786850e387550fdab836ed7e6dc881de23001b
jar:   computed 3f786850e387550fdab836ed7e6dc881de23001b
jar:
jar: beginEntry b.txt
jar: Manifest Entry: b.txt digest=SHA-256
jar:   manifest 0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f
jar:   computed 0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f
jar:
jar: Manifest Entry: b.txt digest=SHA1
jar:   manifest 89e6c98d92887913cadf06b2adb97f26cde4849b
jar:   computed 89e6c98d92887913cadf06b2adb97f26cde4849b
jar:

s         395 Wed Mar 08 17:11:06 AEDT 2023 META-INF/MANIFEST.MF
          471 Wed Mar 08 17:11:06 AEDT 2023 META-INF/DPIPWE-C.SF
         5762 Wed Mar 08 17:11:06 AEDT 2023 META-INF/DPIPWE-C.RSA
            0 Wed Mar 08 16:53:16 AEDT 2023 META-INF/
sm          2 Wed Mar 08 17:08:32 AEDT 2023 META-INF/1.txt
sm          2 Wed Mar 08 16:51:46 AEDT 2023 a.txt
sm          2 Wed Mar 08 16:51:54 AEDT 2023 b.txt

  s = signature was verified 
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope

- Signed by "CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU"
    Digest algorithm: SHA-256
    Signature algorithm: SHA256withRSA, 4096-bit key

jar verified.

Comment 2 Clive Brettingham-Moore 2023-03-09 02:44:44 UTC
For completeness debug logging from Java 8u362 on dual hash jar:

Seems to validate HSA-256 hashes, then fail on encountering SHA1

/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.362.b09-2.fc37.x86_64/bin/jarsigner -J-Djava.security.debug=jar -verify -verbose example-sha-both.jar

(snip)
jar: beginEntry a.txt
jar: Manifest Entry: a.txt digest=SHA-256
jar:   manifest 87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
jar:   computed 87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7
jar:
jar: Digest algorithm is restricted: java.security.cert.CertPathValidatorException: denyAfter constraint check failed: SHA1 used with Constraint date: 2019-01-01; params date: 2023-03-09T02:41:52.208Z used with a.txt entry in META-INF/MANIFEST.MF file.
jar: beginEntry b.txt
jar: Manifest Entry: b.txt digest=SHA-256
jar:   manifest 0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f
jar:   computed 0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f
jar:
jar: Digest algorithm is restricted: java.security.cert.CertPathValidatorException: denyAfter constraint check failed: SHA1 used with Constraint date: 2019-01-01; params date: 2023-03-09T02:41:52.213Z used with b.txt entry in META-INF/MANIFEST.MF file.

s         309 Wed Mar 08 17:01:16 AEDT 2023 META-INF/MANIFEST.MF
          385 Wed Mar 08 17:01:16 AEDT 2023 META-INF/DPIPWE-C.SF
         5762 Wed Mar 08 17:01:16 AEDT 2023 META-INF/DPIPWE-C.RSA
            0 Wed Mar 08 16:53:16 AEDT 2023 META-INF/
 m   ?      2 Wed Mar 08 16:51:46 AEDT 2023 a.txt
 m   ?      2 Wed Mar 08 16:51:54 AEDT 2023 b.txt

  s = signature was verified 
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope
  ? = unsigned entry

- Signed by "CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU"
    Digest algorithm: SHA-256
    Signature algorithm: SHA256withRSA, 4096-bit key

jar verified.

Warning: 
This jar contains unsigned entries which have not been integrity-checked.

Comment 3 Severin Gehwolf 2023-03-10 10:57:19 UTC
Thanks for the report. I'll look into it.

Comment 4 Severin Gehwolf 2023-03-10 12:26:36 UTC
This appears to be a missing backport of https://bugs.openjdk.org/browse/JDK-8278851

Comment 5 Severin Gehwolf 2023-03-10 15:17:17 UTC
Confirmed. It's caused by the missing backport of JDK-8278851. I'm going to propose it upstream and if all goes well it should be available in 8u382 (July).

./images/j2sdk-image/bin/jarsigner -J-showversion -verify -certs -verbose example-sha-both.jar 
openjdk version "1.8.0_372-internal-fastdebug"
OpenJDK Runtime Environment (build 1.8.0_372-internal-fastdebug-b03)
OpenJDK 64-Bit Server VM (build 25.372-b03-fastdebug, mixed mode)


s         309 Wed Mar 08 17:01:16 CET 2023 META-INF/MANIFEST.MF

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]

          385 Wed Mar 08 17:01:16 CET 2023 META-INF/DPIPWE-C.SF
         5762 Wed Mar 08 17:01:16 CET 2023 META-INF/DPIPWE-C.RSA
            0 Wed Mar 08 16:53:16 CET 2023 META-INF/
sm          2 Wed Mar 08 16:51:46 CET 2023 a.txt

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]

sm          2 Wed Mar 08 16:51:54 CET 2023 b.txt

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]


  s = signature was verified 
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope

- Signed by "CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU"
    Digest algorithm: SHA-256
    Signature algorithm: SHA256withRSA, 4096-bit key

jar verified.

Warning: 
This jar contains signatures that do not include a timestamp. Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as 2024-01-29).

The signer certificate will expire on 2024-01-29.

Comment 6 Severin Gehwolf 2023-03-10 16:15:28 UTC
The issue doesn't happen with an 8u352 build. So this is likely caused by https://bugs.openjdk.org/browse/JDK-8269039

./jdk8u352-b08/bin/jarsigner -J-showversion -verify -certs -verbose example-sha-both.jar 
openjdk version "1.8.0_352"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_352-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.352-b08, mixed mode)


s         309 Wed Mar 08 17:01:16 CET 2023 META-INF/MANIFEST.MF

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]

          385 Wed Mar 08 17:01:16 CET 2023 META-INF/DPIPWE-C.SF
         5762 Wed Mar 08 17:01:16 CET 2023 META-INF/DPIPWE-C.RSA
            0 Wed Mar 08 16:53:16 CET 2023 META-INF/
sm          2 Wed Mar 08 16:51:46 CET 2023 a.txt

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]

sm          2 Wed Mar 08 16:51:54 CET 2023 b.txt

      >>> Signer
      X.509, CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU
      [certificate is valid from 1/18/23 1:00 AM to 1/29/24 12:59 AM]
      X.509, CN=DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1, O="DigiCert, Inc.", C=US
      [certificate is valid from 4/29/21 2:00 AM to 4/29/36 1:59 AM]
      X.509, CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US
      [trusted certificate]


  s = signature was verified 
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope

- Signed by "CN=DPIPWE, O=DPIPWE, L=Hobart, ST=Tasmania, C=AU"
    Digest algorithm: SHA-256
    Signature algorithm: SHA256withRSA, 4096-bit key

jar verified.

Warning: 
This jar contains signatures that do not include a timestamp. Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as 2024-01-29).

The signer certificate will expire on 2024-01-29.

Comment 7 Severin Gehwolf 2023-03-10 17:35:48 UTC
Upstream pr: https://github.com/openjdk/jdk8u-dev/pull/282

Comment 8 Clive Brettingham-Moore 2023-03-14 23:08:09 UTC
Thanks, that was fast.