JDK-8228481 : Upgrade the default PKCS12 encryption/MAC algorithms
  • Type: CSR
  • Component: security-libs
  • Sub-Component: java.security
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 7-pool,8-pool,11-pool,15-pool,16
  • Submitted: 2019-07-22
  • Updated: 2022-08-01
  • Resolved: 2020-10-14
Related Reports
CSR :  
CSR :  
Description
Summary
-------

Upgrade the default algorithms used in PKCS 12 to use new PBES2 based encryption and stronger algorithms like AES and SHA-2.

Problem
-------

PKCS12 is the default keystore format since JDK 9, but we have been using weak algorithms which was the standard of 1990s. The algorithms are becoming a security issue now especially for the key protection algorithms which is used to protect private keys.

Many OSes and browsers have since adopted stronger algorithms but the level of support is not consistent among them. The strong key algorithm is now supported by all major OSes and browsers, but algorithms for certificate protection and integrity protection are not.

The latest Windows Server 2019 (and Windows 10) now provides two options when exporting private keys into a pkcs12 file: "legacy" and "stronger".

The latest OpenSSL 3.0.0 will only accept new algorithms based on PBES2 unless the `-legacy` option is specified.

Solution
--------

Upgrade the algorithms used in certificate encryption, key encryption, and integrity protection to the values as described in the specification below. These algorithms are the same as the stronger algorithms used in Windows Server 2019 and openssl 3.0.0. Please note we've lowered the iteration counts to 10000. This is the recommended iteration count as described in NIST Special Publication 800-63B “5.1.1.2 Memorized Secret Verifiers”. The default iteration counts are 2000 for Windows Server 2019 and 2048 for openssl 3.0.0.

We will also define a new system property named "keystore.pkcs12.legacy". When set, will override the settings above to use the older algorithms and iteration counts.

Specification
-------------

First, make the following change in java.security.

    diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
    index b84a9d3e0cc..ddc4b87d6ee 100644
    --- a/src/java.base/share/conf/security/java.security
    +++ b/src/java.base/share/conf/security/java.security
    @@ -1144,33 +1144,33 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep
     # The algorithm used to encrypt a certificate. This can be any non-Hmac PBE
     # algorithm defined in the Cipher section of the Java Security Standard
     # Algorithm Names Specification. When set to "NONE", the certificate
    -# is not encrypted. The default value is "PBEWithSHA1AndRC2_40".
    -#keystore.pkcs12.certProtectionAlgorithm = PBEWithSHA1AndRC2_40
    +# is not encrypted. The default value is "PBEWithHmacSHA256AndAES_256".
    +#keystore.pkcs12.certProtectionAlgorithm = PBEWithHmacSHA256AndAES_256
    
     # The iteration count used by the PBE algorithm when encrypting a certificate.
    -# This value must be a positive integer. The default value is 50000.
    -#keystore.pkcs12.certPbeIterationCount = 50000
    +# This value must be a positive integer. The default value is 10000.
    +#keystore.pkcs12.certPbeIterationCount = 10000
    
     # The algorithm used to encrypt a private key or secret key. This can be
     # any non-Hmac PBE algorithm defined in the Cipher section of the Java
     # Security Standard Algorithm Names Specification. The value must not be "NONE".
    -# The default value is "PBEWithSHA1AndDESede".
    -#keystore.pkcs12.keyProtectionAlgorithm = PBEWithSHA1AndDESede
    +# The default value is "PBEWithHmacSHA256AndAES_256".
    +#keystore.pkcs12.keyProtectionAlgorithm = PBEWithHmacSHA256AndAES_256
    
     # The iteration count used by the PBE algorithm when encrypting a private key
     # or a secret key. This value must be a positive integer. The default value
    -# is 50000.
    -#keystore.pkcs12.keyPbeIterationCount = 50000
    +# is 10000.
    +#keystore.pkcs12.keyPbeIterationCount = 10000
    
     # The algorithm used to calculate the optional MacData at the end of a PKCS12
     # file. This can be any HmacPBE algorithm defined in the Mac section of the
     # Java Security Standard Algorithm Names Specification. When set to "NONE",
    -# no Mac is generated. The default value is "HmacPBESHA1".
    -#keystore.pkcs12.macAlgorithm = HmacPBESHA1
    +# no Mac is generated. The default value is "HmacPBESHA256".
    +#keystore.pkcs12.macAlgorithm = HmacPBESHA256
    
     # The iteration count used by the MacData algorithm. This value must be a
    -# positive integer. The default value is 100000.
    -#keystore.pkcs12.macIterationCount = 100000
    +# positive integer. The default value is 10000.
    +#keystore.pkcs12.macIterationCount = 10000
    
     #
     # Enhanced exception message information

Second, define a new system property named `keystore.pkcs12.legacy` that will automatically override the system/security properties above to use the older algorithms and iteration counts. This system property is equivalent to

    -Dkeystore.pkcs12.certProtectionAlgorithm=PBEWithSHA1AndRC2_40
    -Dkeystore.pkcs12.keyProtectionAlgorithm=PBEWithSHA1AndDESede
    -Dkeystore.pkcs12.macAlgorithm=HmacPBESHA1
    -Dkeystore.pkcs12.certPbeIterationCount=50000
    -Dkeystore.pkcs12.keyPbeIterationCount=50000
    -Dkeystore.pkcs12.macIterationCount=100000

There is no value defined for this property. When this system property is set, all other system/security properties defined in this CSR are ignored.

Comments
Moving to Approved.
14-10-2020

Finalize the CSR. One change since proposed: all iteration counts are now 10000 because 1) secure enough per NIST requirement 2) fast. Benchmark Mode Samples Score Score error Units c.p.MyBenchmark.instrong10000 thrpt 10 48.180 4.309 ops/s c.p.MyBenchmark.instrong2048 thrpt 10 240.210 17.000 ops/s c.p.MyBenchmark.instrong50000 thrpt 10 9.037 0.291 ops/s c.p.MyBenchmark.inweak2048 thrpt 10 347.224 13.426 ops/s c.p.MyBenchmark.inweak50000 thrpt 10 12.683 0.383 ops/s c.p.MyBenchmark.outstrong10000 thrpt 10 50.355 1.542 ops/s c.p.MyBenchmark.outstrong2048 thrpt 10 242.516 8.829 ops/s c.p.MyBenchmark.outstrong50000 thrpt 10 9.176 0.219 ops/s c.p.MyBenchmark.outweak2048 thrpt 10 333.360 11.649 ops/s c.p.MyBenchmark.outweak50000 thrpt 10 12.637 0.338 ops/s Unit is operation per second. in for parsing, out for generation, with weak and strong algorithms and different iteration counts. strong is slower than weak but strong10000 (proposed) is faster than weak50000 (current).
08-10-2020

The updated CSR looks good to me.
08-10-2020

Moving to Provisional.
12-04-2020