-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add pgpainless_signer module containing implementations of SignatureP…
…rocessors and SignerCreators
- Loading branch information
1 parent
77d1ef0
commit d034c72
Showing
9 changed files
with
715 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,83 @@ | ||
<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> | ||
<dependency> | ||
<groupId>org.apache.commons</groupId> | ||
<artifactId>commons-compress</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.tukaani</groupId> | ||
<artifactId>xz</artifactId> | ||
</dependency> | ||
<!-- enable to have Zstd support on local runs | ||
<dependency> | ||
<groupId>com.github.luben</groupId> | ||
<artifactId>zstd-jni</artifactId> | ||
<version>1.5.2-5</version> | ||
<optional>true</optional> | ||
</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 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); | ||
} | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
...main/java/org/eclipse/packager/rpm/signature/pgpainless/PGPainlessSignatureProcessor.java
This file contains 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,122 @@ | ||
/* | ||
* 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.PGPException; | ||
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.eclipse.packager.rpm.signature.SignatureProcessor; | ||
import org.pgpainless.PGPainless; | ||
import org.pgpainless.algorithm.CompressionAlgorithm; | ||
import org.pgpainless.algorithm.HashAlgorithm; | ||
import org.pgpainless.encryption_signing.EncryptionResult; | ||
import org.pgpainless.encryption_signing.EncryptionStream; | ||
import org.pgpainless.encryption_signing.ProducerOptions; | ||
import org.pgpainless.encryption_signing.SigningOptions; | ||
import org.pgpainless.key.protection.SecretKeyRingProtector; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.nio.ByteBuffer; | ||
|
||
public class PGPainlessSignatureProcessor implements SignatureProcessor { | ||
|
||
protected final EncryptionStream signingStream; | ||
private final Logger logger = LoggerFactory.getLogger(PGPainlessSignatureProcessor.class); | ||
|
||
public PGPainlessSignatureProcessor(PGPSecretKeyRing key, SecretKeyRingProtector keyProtector, int hashAlgorithm) { | ||
OutputStream sink = new OutputStream() { | ||
@Override | ||
public void write(int i) { | ||
// Discard plaintext | ||
} | ||
}; | ||
try { | ||
signingStream = PGPainless.encryptAndOrSign() | ||
.onOutputStream(sink) | ||
.withOptions( | ||
ProducerOptions.sign( | ||
SigningOptions.get() | ||
.overrideHashAlgorithm(HashAlgorithm.requireFromId(hashAlgorithm)) | ||
.addDetachedSignature(keyProtector, key) | ||
).setAsciiArmor(false) | ||
.overrideCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED) | ||
); | ||
} catch (PGPException | IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void feedHeader(ByteBuffer header) { | ||
feedData(header); | ||
} | ||
|
||
@Override | ||
public void feedPayloadData(ByteBuffer data) { | ||
feedData(data); | ||
} | ||
|
||
private void feedData(ByteBuffer data) { | ||
try { | ||
if (data.hasArray()) { | ||
signingStream.write(data.array(), data.position(), data.remaining()); | ||
} else { | ||
final byte[] buffer = new byte[data.remaining()]; | ||
data.get(buffer); | ||
signingStream.write(buffer); | ||
} | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
protected Logger getLogger() { | ||
return logger; | ||
} | ||
|
||
@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: {}", value); | ||
signature.putBlob(RpmSignatureTag.PGP, value); | ||
break; | ||
|
||
// DSA | ||
case PublicKeyAlgorithmTags.DSA: // 17 | ||
case PublicKeyAlgorithmTags.EDDSA_LEGACY: // 22 | ||
getLogger().info("DSA: {}", value); | ||
signature.putBlob(RpmSignatureTag.GPG, value); | ||
break; | ||
|
||
default: | ||
throw new RuntimeException("Unsupported public key algorithm id: " + pgpSignature.getKeyAlgorithm()); | ||
} | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
...va/org/eclipse/packager/rpm/signature/pgpainless/PGPainlessSignatureProcessorFactory.java
This file contains 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,43 @@ | ||
/* | ||
* 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.openpgp.PGPSecretKeyRing; | ||
import org.eclipse.packager.rpm.signature.PgpSignatureProcessorFactory; | ||
import org.eclipse.packager.rpm.signature.SignatureProcessor; | ||
import org.pgpainless.key.protection.SecretKeyRingProtector; | ||
import org.pgpainless.util.Passphrase; | ||
|
||
public class PGPainlessSignatureProcessorFactory extends PgpSignatureProcessorFactory { | ||
|
||
private final PGPSecretKeyRing key; | ||
private final SecretKeyRingProtector keyProtector; | ||
private final int hashAlgorithm; | ||
|
||
public PGPainlessSignatureProcessorFactory(PGPSecretKeyRing key, char[] passphrase, int hashAlgorithm) { | ||
this.key = key; | ||
this.keyProtector = SecretKeyRingProtector.unlockAnyKeyWith(new Passphrase(passphrase)); | ||
this.hashAlgorithm = hashAlgorithm; | ||
} | ||
|
||
@Override | ||
public SignatureProcessor createHeaderSignatureProcessor() { | ||
return new PGPainlessHeaderSignatureProcessor(key, keyProtector, hashAlgorithm); | ||
} | ||
|
||
@Override | ||
public SignatureProcessor createSignatureProcessor() { | ||
return new PGPainlessSignatureProcessor(key, keyProtector, hashAlgorithm); | ||
} | ||
} |
Oops, something went wrong.