-
Notifications
You must be signed in to change notification settings - Fork 19
Alternative approach at signature creation using PGPainless #56
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
Draft
vanitasvitae
wants to merge
16
commits into
eclipse:master
Choose a base branch
from
vanitasvitae:rpm-pgpainless
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 8 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
d81bbd7
Introduce PgpSignerFactory
vanitasvitae ca41eb9
Implement BC implementation of PgpSignerFactory
vanitasvitae 17ba07e
Add PgpHelper method to read PGPSecretKeyRings by (sub-)key-id
vanitasvitae 481a5e8
Add missing GPG RpmSignatureTag
vanitasvitae 787fda7
Add Factory classes for PgpSignerCreator instances
vanitasvitae 77d1ef0
Add PgpSignatureProcessorFactory class and Bc implementation
vanitasvitae d034c72
Add pgpainless_signer module containing implementations of SignatureP…
vanitasvitae 38ecfe7
Remove unused stuff from pgpainless_signer.pom
vanitasvitae e7936b3
Rename module to packager-pgpainless
vanitasvitae 0d0dd3e
Document 'EcDSA' typo in manual
vanitasvitae a433610
Add documentation to PGPainlessHeaderSignatureProcessor
vanitasvitae fac4c65
Allow signing-backend to choose hash algorithm when 0 is passed
vanitasvitae c8e290b
Tests: Read secret key from rpm/test/resources
vanitasvitae c9393ff
Do not port over RPMv3 style signature processors
vanitasvitae d80e57b
Remove deprecated GPG RpmSignatureTag
vanitasvitae ddf7ad7
Add tests
vanitasvitae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
core/src/main/java/org/eclipse/packager/security/pgp/BcPgpSignerCreator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /* | ||
| * Copyright (c) 2024 Paul Schaub | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0 | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| */ | ||
|
|
||
| package org.eclipse.packager.security.pgp; | ||
|
|
||
| import org.bouncycastle.openpgp.PGPPrivateKey; | ||
|
|
||
| import java.io.OutputStream; | ||
| import java.util.function.Function; | ||
|
|
||
| /** | ||
| * Implementation of {@link PgpSignerCreator} that depends on Bouncy Castle directly. | ||
| * Here, the user needs to pass in the {@link PGPPrivateKey} and digest algorithm they want to use | ||
| * for signing explicitly. | ||
| */ | ||
| public class BcPgpSignerCreator extends PgpSignerCreator { | ||
|
|
||
| private final PGPPrivateKey privateKey; | ||
| private final int hashAlgorithm; | ||
|
|
||
| /** | ||
| * Construct a {@link PgpSignerCreator} that uses Bouncy Castle classes directly and signs | ||
| * using a {@link SigningStream}. | ||
| * | ||
| * @param privateKey private signing key | ||
| * @param hashAlgorithmId OpenPGP hash algorithm ID of the digest algorithm to use for signing | ||
| * @param inlineSigned if true, use the cleartext signature framework to sign data inline. | ||
| * Otherwise, sign using detached signatures. | ||
| */ | ||
| public BcPgpSignerCreator(PGPPrivateKey privateKey, int hashAlgorithmId, boolean inlineSigned) { | ||
| super(inlineSigned); | ||
| this.hashAlgorithm = hashAlgorithmId; | ||
| this.privateKey = privateKey; | ||
| } | ||
|
|
||
| @Override | ||
| public Function<OutputStream, OutputStream> createSigningStream() { | ||
| if (privateKey == null) { | ||
| return null; | ||
| } | ||
|
|
||
| return outputStream -> new SigningStream(outputStream, privateKey, hashAlgorithm, inlineSigned); | ||
| } | ||
| } |
50 changes: 50 additions & 0 deletions
50
core/src/main/java/org/eclipse/packager/security/pgp/BcPgpSignerCreatorFactory.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /* | ||
| * Copyright (c) 2024 Paul Schaub | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0 | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| */ | ||
|
|
||
| package org.eclipse.packager.security.pgp; | ||
|
|
||
| import org.bouncycastle.openpgp.PGPException; | ||
| import org.bouncycastle.openpgp.PGPPrivateKey; | ||
| import org.bouncycastle.openpgp.PGPSecretKey; | ||
| import org.bouncycastle.openpgp.PGPSecretKeyRing; | ||
| import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; | ||
| import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; | ||
|
|
||
| import java.util.NoSuchElementException; | ||
|
|
||
| /** | ||
| * Implementation of the {@link PgpSignerCreatorFactory} that uses BC. | ||
| */ | ||
| public class BcPgpSignerCreatorFactory implements PgpSignerCreatorFactory { | ||
|
|
||
| @Override | ||
| public PgpSignerCreator getSignerCreator( | ||
| PGPSecretKeyRing signingKey, | ||
| long signingKeyId, | ||
| char[] passphrase, | ||
| int hashAlgorithm, | ||
| boolean inlineSigned) { | ||
| PGPSecretKey key = signingKey.getSecretKey(signingKeyId); | ||
| if (key == null) { | ||
| throw new NoSuchElementException("No such signing key"); | ||
| } | ||
| try { | ||
| PGPPrivateKey privateKey = key.extractPrivateKey( | ||
| new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()) | ||
| .build(passphrase)); | ||
| return new BcPgpSignerCreator(privateKey, hashAlgorithm, inlineSigned); | ||
| } catch (PGPException e) { | ||
| throw new RuntimeException("Could not unlock private key."); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
core/src/main/java/org/eclipse/packager/security/pgp/PgpSignerCreator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /* | ||
| * Copyright (c) 2024 Paul Schaub | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0 | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| */ | ||
|
|
||
| package org.eclipse.packager.security.pgp; | ||
|
|
||
| import java.io.OutputStream; | ||
| import java.util.function.Function; | ||
|
|
||
| /** | ||
| * Factory for creating signing streams. | ||
| */ | ||
| public abstract class PgpSignerCreator { | ||
|
|
||
| protected final boolean inlineSigned; | ||
|
|
||
| public PgpSignerCreator(boolean inlineSigned) { | ||
| this.inlineSigned = inlineSigned; | ||
| } | ||
|
|
||
| /** | ||
| * Return a {@link Function} that wraps an {@link OutputStream} into a signing stream. | ||
| * This method has no arguments (key, algorithms etc.) to be implementation agnostic. | ||
| * Subclasses shall pass those details as constructor arguments. | ||
| * | ||
| * @return transforming function | ||
| */ | ||
| public abstract Function<OutputStream, OutputStream> createSigningStream(); | ||
| } |
32 changes: 32 additions & 0 deletions
32
core/src/main/java/org/eclipse/packager/security/pgp/PgpSignerCreatorFactory.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright (c) 2024 Paul Schaub | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0 | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| */ | ||
|
|
||
| package org.eclipse.packager.security.pgp; | ||
|
|
||
| import org.bouncycastle.openpgp.PGPSecretKeyRing; | ||
|
|
||
| /** | ||
| * Factory interface for instantiating {@link PgpSignerCreator} classes. | ||
| * This class acts as the public interface for choosing the OpenPGP signing backend. | ||
| * By default, Bouncy Castle is used via {@link BcPgpSignerCreatorFactory}. | ||
| * TODO: Use dependency injection to allow optional dependencies to replace the default instance. | ||
| */ | ||
| public interface PgpSignerCreatorFactory { | ||
|
|
||
| PgpSignerCreator getSignerCreator( | ||
| PGPSecretKeyRing signingKey, | ||
| long signingKeyId, | ||
| char[] passphrase, | ||
| int hashAlgorithm, | ||
| boolean inlineSigned); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
|
|
||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>org.eclipse.packager</groupId> | ||
| <artifactId>packager</artifactId> | ||
| <version>0.20.1-SNAPSHOT</version> | ||
| </parent> | ||
|
|
||
| <artifactId>packager-pgpainless_signer</artifactId> | ||
| <name>Eclipse Packager :: PGPainless Signer</name> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.eclipse.packager</groupId> | ||
| <artifactId>packager-core</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.eclipse.packager</groupId> | ||
| <artifactId>packager-rpm</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.pgpainless</groupId> | ||
| <artifactId>pgpainless-core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.slf4j</groupId> | ||
| <artifactId>slf4j-api</artifactId> | ||
| </dependency> | ||
|
|
||
| <!-- testing --> | ||
|
|
||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-engine</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-params</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <!-- show log output during tests using logback as the slf4j backend. --> | ||
| <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> | ||
| <dependency> | ||
| <groupId>ch.qos.logback</groupId> | ||
| <artifactId>logback-classic</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.felix</groupId> | ||
| <artifactId>maven-bundle-plugin</artifactId> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
|
|
||
| </project> |
75 changes: 75 additions & 0 deletions
75
...ava/org/eclipse/packager/rpm/signature/pgpainless/PGPainlessHeaderSignatureProcessor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /* | ||
| * Copyright (c) 2024 Paul Schaub | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0 | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| */ | ||
|
|
||
| package org.eclipse.packager.rpm.signature.pgpainless; | ||
|
|
||
| import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; | ||
| import org.bouncycastle.openpgp.PGPSecretKeyRing; | ||
| import org.bouncycastle.openpgp.PGPSignature; | ||
| import org.eclipse.packager.rpm.RpmSignatureTag; | ||
| import org.eclipse.packager.rpm.header.Header; | ||
| import org.pgpainless.encryption_signing.EncryptionResult; | ||
| import org.pgpainless.key.protection.SecretKeyRingProtector; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.io.IOException; | ||
| import java.nio.ByteBuffer; | ||
|
|
||
| public class PGPainlessHeaderSignatureProcessor extends PGPainlessSignatureProcessor { | ||
|
|
||
| private final Logger logger = LoggerFactory.getLogger(PGPainlessHeaderSignatureProcessor.class); | ||
|
|
||
| public PGPainlessHeaderSignatureProcessor(PGPSecretKeyRing key, SecretKeyRingProtector keyProtector, int hashAlgorithm) { | ||
| super(key, keyProtector, hashAlgorithm); | ||
| } | ||
|
|
||
| @Override | ||
| public Logger getLogger() { | ||
| return logger; | ||
| } | ||
|
|
||
| @Override | ||
| public void feedPayloadData(ByteBuffer data) { | ||
| // We only work on header data | ||
| } | ||
|
|
||
| @Override | ||
| public void finish(Header<RpmSignatureTag> signature) { | ||
| try { | ||
| signingStream.close(); | ||
| EncryptionResult result = signingStream.getResult(); | ||
| PGPSignature pgpSignature = result.getDetachedSignatures().flatten().iterator().next(); | ||
| byte[] value = pgpSignature.getEncoded(); | ||
| switch (pgpSignature.getKeyAlgorithm()) { | ||
| // RSA | ||
| case PublicKeyAlgorithmTags.RSA_GENERAL: // 1 | ||
| getLogger().info("RSA HEADER: {}", value); | ||
| signature.putBlob(RpmSignatureTag.RSAHEADER, value); | ||
| break; | ||
|
|
||
| // DSA | ||
| case PublicKeyAlgorithmTags.DSA: // 17 | ||
| case PublicKeyAlgorithmTags.EDDSA_LEGACY: // 22 | ||
| getLogger().info("DSA HEADER: {}", value); | ||
| signature.putBlob(RpmSignatureTag.DSAHEADER, value); | ||
| break; | ||
|
|
||
| default: | ||
| throw new RuntimeException("Unsupported public key algorithm id: " + pgpSignature.getKeyAlgorithm()); | ||
| } | ||
| } catch (IOException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.