As I learned from https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html the procedure of signing jar file with jarsigner is following:
The manifest file is updated with a list of hashes for each file:
Name: com/qarks/util/files/diff/ui/main/DiffMergeFrame.class SHA-256-Digest: GZgPXG9YnmVGXb+hFwnJF4im4hb/qixX2Gs+ZNpdGFU=
Name: com/qarks/util/ui/swing/PrintManager.class SHA-256-Digest: cO6XolXrk5NlHBocDF0fzojlwSAKlDoGsY/jdJ0fzdY=
The signature file (*.SF) is created. It contains:
The signature block file (*.RSA, *.DSA) is created. It stores the digital signature of the *.SF signature file.
So, I'd like to know why do we need *.SF at all - why can't we just sign a manifest file, instead of *.SF file?
And also what's the purpose of having hashes of hashes in *.SF file (additional check? in what cases?)?
Signature file (.SF) represents the signer of the .jar file - there can technically be more than one.
To answer your second question imagine a case where a .jar file is modified after it has already been signed. The manifest file would have been changed and therefore the hash in .SF (*-Digest-Manifest) would no longer match that of the current .manifest file.
However, if only new files were added to the .jar it would still pass validation, as the validation algorithm (among other things) looks at each entry in the .SF and validates the hashes against the respective entries in the manifest (new entries in the manifest would be ignored).
To sum it up, .SF is used to verify that none of the files, that were in the .jar at the moment of signing, have been changed.
You can read more about signature validation here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With