Summary
-------
Add the capability to sign JAR files with RSASSA-PSS and EdDSA signatures algorithms.
Problem
-------
We've added support for RSASSA-PSS (JDK-8146293) since JDK 11 and EdDSA (JDK-8166597) recently, and we should support them in signed JAR files as well. The usage of the 2 algorithms in Cryptographic Message Syntax (CMS, which is the format we use for signature block files inside a signed JAR file) are defined in https://tools.ietf.org/html/rfc4056 and https://www.rfc-editor.org/rfc/rfc8419.html, respectively.
Solution
--------
Support signing of a JAR file using these algorithms, which means:
1. RSASSA-RSS and EdDSA keys can be used to sign a JAR file
1. New `-sigalg` options: `RSASSA-PSS`, `EdDSA`, `Ed25519`, and `Ed448` (case-insensitive).
We will also support loading signed JAR files signed with these new algorithms.
We will support the [RFC 6211](https://tools.ietf.org/html/rfc6211#page-5) CMSAlgorithmProtection attribute on all algorithms to protect against algorithm substitution attacks (especially for the new RSASSA-PSS algorithm). This is the default style used by `openssl cms` command and BountyCastle's `JcaSignerInfoGeneratorBuilder` class. Users can turn off this feature by setting the `JarSigner.Builder` property `directsign` to `true` or adding the `-directsign` option to the jarsigner tool, which means there will be no signed attributes and the signature is calculated on the .SF file directly.
Specification
-------------
**The `JarSigner` API**
package jdk.security.jarsigner;
public final class JarSigner {
public static class Builder {
/**
* Sets an additional implementation-specific property indicated by
* the specified key.
....
+ * <li>"directsign": "true" if the signature is calculated on the
+ * content directly, "false" if it's calculated on signed attributes
+ * which itself is calculated from the content and stored in the
+ * signer's SignerInfo. Default "false".
....
*/
public Builder setProperty(String key, String value);
**The jarsigner tool**
The `-sigalg` options will support 4 new values: `RSASSA-PSS`, `EdDSA`, `Ed25519` and `Ed448`. The `RSASSA-PSS` algorithm can be used for both an RSA key or an RSASSA-PSS key. The `EdDSA` algorithm can only be used for an EdDSA key. The `Ed25519` algorithm can only be used for a 255-bit EdDSA key. The `Ed448` algorithm can only be used for a 448-bit EdDSA key. The option values are case-insensitive.
The block file extension for `RSASSA-PSS` is still `.RSA`. The block file extension for `EdDSA`, `Ed25519` or `Ed448` is still `.EC`.
A new `-directsign` option will be supported.
**The tooldoc**
In the [jarsigner man page][1],
1. Add info on RSASSA-PSS and EdDSA keys to the table in "Supported Algorithms".
1. Add a new column "block file extension" to this table.
1. The document was written when we only support DSA keys, and it uses the ".DSA" word everywhere. Rename it to "signature block file".
1. Always use ".RSA" in examples.
The exact diff for the jarsigner man page:
@@ -226,18 +226,30 @@
## Supported Algorithms
By default, the `jarsigner` command signs a JAR file using one of the following
-algorithms files depending on the type and size of the private key:
+algorithms and block file extensions depending on the type and size of
+the private key:
-keyalg keysize default sigalg
-------- -------- --------------
-DSA any size SHA256withDSA
-RSA \<= 3072 SHA256withRSA
- \<= 7680 SHA384withRSA
- \> 7680 SHA512withRSA
-EC \< 384 SHA256withECDSA
- \< 512 SHA384withECDSA
- = 512 SHA512withECDSA
-------- -------- --------------
+keyalg keysize default sigalg block file extension
+------- -------- -------------- --------------------
+DSA any size SHA256withDSA .DSA
+RSA \<= 3072 SHA256withRSA .RSA
+ \<= 7680 SHA384withRSA
+ \> 7680 SHA512withRSA
+EC \< 384 SHA256withECDSA .EC
+ \< 512 SHA384withECDSA
+ = 512 SHA512withECDSA
+RSASSA-PSS \<= 3072 RSASSA-PSS (with SHA-256) .RSA
+ \<= 7680 RSASSA-PSS (with SHA-384)
+ \> 7680 RSASSA-PSS (with SHA-512)
+EdDSA 255 Ed25519 .EC
+ 448 Ed448
+------- -------- -------------- ------
+
+* If an RSASSA-PSS key is encoded with parameters, then jarsigner will use the
+same parameters in the signature. Otherwise, jarsigner will use parameters that are
+determined by the size of the key as specified in the table above.
+For example, an 3072-bit RSASSA-PSS key will use RSASSA-PSS as the signature
+algorithm and SHA-256 as the hash and MGF1 algorithms.
These default signature algorithms can be overridden by using the `-sigalg`
option.
@@ -274,10 +286,11 @@
The base file names for these two files come from the value of the `-sigfile`
option. For example, when the option is `-sigfile MKSIGN`, the files are named
-`MKSIGN.SF` and `MKSIGN.DSA`
+`MKSIGN.SF` and `MKSIGN.RSA`. In this document, we assume the signer always
+uses an RSA key.
If no `-sigfile` option appears on the command line, then the base file name
-for the `.SF` and `.DSA` files is the first 8 characters of the alias name
+for the `.SF` and the signature block files is the first 8 characters of the alias name
specified on the command line, all converted to uppercase. If the alias name
has fewer than 8 characters, then the full alias name is used. If the alias
name contains any characters that aren't allowed in a signature file name, then
@@ -318,7 +331,8 @@
file. This file also contains, encoded inside it, the certificate or
certificate chain from the keystore that authenticates the public key
corresponding to the private key used for signing. The file has the extension
-`.DSA`, `.RSA`, or `.EC`, depending on the digest algorithm used.
+`.DSA`, `.RSA`, or `.EC`, depending on the key algorithm used. See the table
+in [Supported Algorithms].
## Signature Time Stamp
@@ -344,9 +358,9 @@
1. Verify the signature of the `.SF` file.
The verification ensures that the signature stored in each signature block
- (`.DSA`) file was generated using the private key corresponding to the
+ file was generated using the private key corresponding to the
public key whose certificate (or certificate chain) also appears in the
- `.DSA` file. It also ensures that the signature is a valid signature of the
+ signature block file. It also ensures that the signature is a valid signature of the
corresponding signature (`.SF`) file, and thus the `.SF` file wasn't
tampered with.
@@ -403,15 +417,15 @@
jarsigner myBundle.jar kevin
```
-When a JAR file is signed multiple times, there are multiple `.SF` and `.DSA`
-files in the resulting JAR file, one pair for each signature. In the previous
+When a JAR file is signed multiple times, there are multiple `.SF` and signature
+block files in the resulting JAR file, one pair for each signature. In the previous
example, the output JAR file includes files with the following names:
```
SUSAN.SF
-SUSAN.DSA
+SUSAN.RSA
KEVIN.SF
-KEVIN.DSA
+KEVIN.RSA
```
## Options for jarsigner
@@ -529,18 +543,18 @@
Certificate Encoding Standard](http://tools.ietf.org/html/rfc1421).
`-sigfile` *file*
-: Specifies the base file name to be used for the generated `.SF` and `.DSA`
+: Specifies the base file name to be used for the generated `.SF` and signature block
files. For example, if file is `DUKESIGN`, then the generated `.SF` and
- `.DSA` files are named `DUKESIGN.SF` and `DUKESIGN.DSA`, and placed in the
+ signature block files are named `DUKESIGN.SF` and `DUKESIGN.RSA`, and placed in the
`META-INF` directory of the signed JAR file.
The characters in the file must come from the set `a-zA-Z0-9_-`. Only
letters, numbers, underscore, and hyphen characters are allowed. All
- lowercase characters are converted to uppercase for the `.SF` and `.DSA`
+ lowercase characters are converted to uppercase for the `.SF` and signature block
file names.
If no `-sigfile` option appears on the command line, then the base file
- name for the `.SF` and `.DSA` files is the first 8 characters of the alias
+ name for the `.SF` and signature block files is the first 8 characters of the alias
name specified on the command line, all converted to upper case. If the
alias name has fewer than 8 characters, then the full alias name is used.
If the alias name contains any characters that aren't valid in a signature
@@ -607,7 +621,7 @@
: If the `-certs` option appears on the command line with the `-verify` and
`-verbose` options, then the output includes certificate information for
each signer of the JAR file. This information includes the name of the type
- of certificate (stored in the `.DSA` file) that certifies the signer's
+ of certificate (stored in the signature block file) that certifies the signer's
public key, and if the certificate is an X.509 certificate (an instance of
the `java.security.cert.X509Certificate`), then the distinguished name of
the signer.
@@ -668,15 +682,22 @@ the following standards:
Standard Algorithm Names.
`-internalsf`
-: In the past, the `.DSA` (signature block) file generated when a JAR file
+: In the past, the signature block file generated when a JAR file
was signed included a complete encoded copy of the `.SF` file (signature
file) also generated. This behavior has been changed. To reduce the overall
- size of the output JAR file, the `.DSA` file by default doesn't contain a
+ size of the output JAR file, the signature block file by default doesn't contain a
copy of the `.SF` file anymore. If `-internalsf` appears on the command
line, then the old behavior is utilized. This option is useful for testing.
In practice, don't use the `-internalsf` option because it incurs higher
overhead.
+`-directsign`
+: By default, jarsigner stores the hash of the `.SF` file and possibly
+ other information in a SignerInfo signedAttributes field, and then
+ calculates the signature on this field. If this option is set, no
+ SignerInfo signedAttributes field is generated and the signature is
+ calculated on the `.SF` file directly.
+
`-sectionsonly`
: If the `-sectionsonly` option appears on the command line, then the `.SF`
file (signature file) generated when a JAR file is signed doesn't include a
@@ -927,8 +941,8 @@
jane`
There is no `-sigfile` specified in the previous command so the generated `.SF`
-and `.DSA` files to be placed in the signed JAR file have default names based
-on the alias name. They are named `JANE.SF` and `JANE.DSA`.
+and signature block files to be placed in the signed JAR file have default names based
+on the alias name. They are named `JANE.SF` and `JANE.RSA`.
If you want to be prompted for the store password and the private key password,
then you could shorten the previous command to the following:
In the [keytool man page][2], document the details on key pair generation for RSASSA-PSS and EdDSA keys (in retrospec).
The exact diff for the keytool man page:
@@ -1221,9 +1221,9 @@
-alias "mykey"
-keysize
- 2048 (when using -genkeypair and -keyalg is "RSA")
- 2048 (when using -genkeypair and -keyalg is "DSA")
+ 2048 (when using -genkeypair and -keyalg is "RSA", "DSA", or "RSASSA-PSS")
256 (when using -genkeypair and -keyalg is "EC")
+ 255 (when using -genkeypair and -keyalg is "EdDSA")
56 (when using -genseckey and -keyalg is "DES")
168 (when using -genseckey and -keyalg is "DESede")
@@ -1248,16 +1248,32 @@
algorithm (`-sigalg` option) is derived from the algorithm of the underlying
private key to provide an appropriate level of security strength as follows:
-keyalg keysize default sigalg
-------- -------- --------------
-DSA any size SHA256withDSA
-RSA \<= 3072 SHA256withRSA
- \<= 7680 SHA384withRSA
- \> 7680 SHA512withRSA
-EC \< 384 SHA256withECDSA
- \< 512 SHA384withECDSA
- = 512 SHA512withECDSA
-------- -------- --------------
+keyalg keysize default sigalg
+------- -------- --------------
+DSA any size SHA256withDSA
+RSA \<= 3072 SHA256withRSA
+ \<= 7680 SHA384withRSA
+ \> 7680 SHA512withRSA
+EC \< 384 SHA256withECDSA
+ \< 512 SHA384withECDSA
+ = 512 SHA512withECDSA
+RSASSA-PSS \<= 3072 RSASSA-PSS (with SHA-256)
+ \<= 7680 RSASSA-PSS (with SHA-384)
+ \> 7680 RSASSA-PSS (with SHA-512)
+EdDSA 255 Ed25519
+ 448 Ed448
+Ed25519 255 Ed25519
+Ed448 448 Ed448
+------- -------- --------------
+
+* An RSASSA-PSS signature algorithm uses a `MessageDigest`
+algorithm as its hash and MGF1 algorithms.
+
+* EdDSA supports 2 key sizes: Ed25519 and Ed448. When generating an EdDSA key
+pair using `-keyalg EdDSA`, a user can specify `-keysize 255` or `-keysize 448`
+to generate Ed25519 or Ed448 key pairs. When no `-keysize` is specified, an
+Ed25519 key pair is generated. A user can also directly specify `-keyalg Ed25519`
+or `-keyalg Ed448` to generate a key pair with the expected key size.
**Note:**
[1]: https://download.java.net/java/early_access/jdk15/docs/specs/man/jarsigner.html
[2]: https://download.java.net/java/early_access/jdk15/docs/specs/man/keytool.html