Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be able to Sign existing RPM file #75

Open
mat1e opened this issue Feb 24, 2023 · 10 comments
Open

Be able to Sign existing RPM file #75

mat1e opened this issue Feb 24, 2023 · 10 comments

Comments

@mat1e
Copy link

mat1e commented Feb 24, 2023

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 ...

@ctron
Copy link
Owner

ctron commented Feb 24, 2023

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:

  1. Lead section
  2. Signature headers
  3. Payload headers
  4. 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.

@mat1e
Copy link
Author

mat1e commented Mar 2, 2023

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.

@ctron
Copy link
Owner

ctron commented Mar 2, 2023

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.

@ctron
Copy link
Owner

ctron commented Mar 2, 2023

I think using RsaHeaderSignatureProcessor might be good enough.

@mat1e
Copy link
Author

mat1e commented Mar 7, 2023

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.

@mat1e
Copy link
Author

mat1e commented Mar 8, 2023

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?

@ctron
Copy link
Owner

ctron commented Mar 8, 2023

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.

@mat1e
Copy link
Author

mat1e commented Mar 9, 2023

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 ?

@ctron
Copy link
Owner

ctron commented Mar 9, 2023

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 :)

@mat1e
Copy link
Author

mat1e commented Mar 9, 2023

Thanks for your help ! I'm trying to implement signature check at least for the units tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants