rpm-builder
rpm-builder copied to clipboard
Be able to Sign existing RPM file
Hello @ctron,
I'm looking for a way to sign existing RPM files with Java and to include the signature in the header. Reading your code really help me to understand how RPM is built and how rpm-packager works.
Actually I didn't find any way to sign an existing RPM. So I would like to know your opinion to make this, or if there is a simplier way that I don't know.
For the moment, I was thinking about a Class RpmOutputStream wich would be construct with a RpmInputStream and allows to modify somes part of the file like metadatas ...
Hm, this can be tricky. I know this topic came up once or twice. And I am glad the code could help you learn :)
I think it should be possible to build something. As there are two header sections, one "only" needs to take the existing file, and write a new signature header, including the signature. All the rest can probably stay as is.
Having said that, there currently is no functionality in the code-base to perform this task. Reading and writing back an RPM file could work, but is not a non-destructive process, as the RPM library involved doesn't implement 100% of the RPM "spec". It can read and understand what is required, and write a file with the expected outcome. But, there is not 100% model of "an RPM" internally.
But I also think that you don't really need to read and understand the full RPM. The basic structure is:
- Lead section
- Signature headers
- Payload headers
- Payload
One can simply copy 1, 3, and 4. Digest 3 + 4, sign the digest, and then write 1, new 2, 3, and 4.
If you are interested in working on this, I might be able to guide you into the right direction. It might also be better to take the base feature to the base library: https://github.com/eclipse/packager … adding a Maven command for this later on in this project.
I'm working on https://github.com/groupe-edf/packager/tree/feature_sign_existing_rpm. I start to understand a little bit the structure of an RPM file, now I'm seen how I can use RpmInputStream to get the differents parts.
I think this is heading in the right direction. I don't think you need to implement the SignatureProcessor
interface, but leverage one of the others and just call them.
I think using RsaHeaderSignatureProcessor
might be good enough.
I think I am close to the solution. I have somes doubts about writing the signature header, and maybe I didn't read the payload correctly. But I will test the signature process tomorrow.
I get an error when I try to parse the file again after signature. I got : java.io.IOException: File corrupt: Expected entry magic [-114, -83, -24], read: [0, 0, 0]
I checked and it is because RpmInputStream is not reading completely the signature header... For this reason, the index is not correctly up to date when reading the payload header.
In the writeSignatureHeader method of RpmWriter, I see a "padding" is written into the file but I don't know what it is. I don't put any padding when I write signature header.
Do you have any idea?
Right, the signature header must be a size that can be divided by 8. If that's not the case, then you need to add more zero bytes until this is true.
It is working now. After import the public key :
rpm --checksig org.eclipse.scada-0.2.1-1.noarch.rpm
org.eclipse.scada-0.2.1-1.noarch.rpm: sha1 (md5) pgp md5 OK
But I would like to develop a "SignatureChecker" directly in packager. Do you have an idea how I can do that ? I know how to extract the signature header and check PGP signature but I don't know if I have to perform MD5 or SHA1/SHA256 checks at the same time ?
Yay :) Cool, great achievement.
Implementing a validation tool would be cool indeed. But would also be much more complicated. I don't want to discourage you :)
I a nutshell, you need to:
- Read the signature headers (for validating it later)
- Read the actual headers (which contain the digests of the files
- Read the payload and calculate digests (on the fly) for all content
That would give you:
-
Two maps of digests (one from the headers, one from your tool) for the payload (files), those must be equal
With that, you know that the files in the payload are what the headers expect them to be.
-
Next, you need to crate a digest of the header section and validate the (stored) signature (which is key + digest)
With that, you know that that the header section was signed with the private key (which belongs to the public key) and was not changed
-
Last, you need to make a decision if you trust the public key
This can be done by providing a list of valid public keys. If using certificates, you need to also validate the chain of trust of them, starting from the leaf certificate which contains the public key, up to a trust anchor that you somehow define.
And I probably missed something here :)
Thanks for your help ! I'm trying to implement signature check at least for the units tests.