mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 08:25:44 +01:00
fixes gpg verification
This commit is contained in:
@@ -24,29 +24,27 @@
|
||||
|
||||
package sonia.scm.security.gpg;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredInputStream;
|
||||
import org.bouncycastle.openpgp.PGPCompressedData;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.openpgp.PGPSignatureList;
|
||||
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
|
||||
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.security.PublicKey;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static sonia.scm.security.gpg.PgpPublicKeyExtractor.getFromRawKey;
|
||||
|
||||
public class GpgKey implements PublicKey {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GpgKey.class);
|
||||
@@ -90,35 +88,59 @@ public class GpgKey implements PublicKey {
|
||||
public boolean verify(InputStream stream, byte[] signature) {
|
||||
boolean verified = false;
|
||||
try {
|
||||
ArmoredInputStream armoredInputStream = new ArmoredInputStream(new ByteArrayInputStream(signature));
|
||||
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(armoredInputStream, null);
|
||||
PGPSignature pgpSignature = ((PGPSignatureList) pgpObjectFactory.nextObject()).get(0);
|
||||
|
||||
PGPContentVerifierBuilderProvider provider = new JcaPGPContentVerifierBuilderProvider();
|
||||
|
||||
Optional<PGPPublicKey> pgpPublicKey = getFromRawKey(raw);
|
||||
|
||||
if (pgpPublicKey.isPresent()) {
|
||||
pgpSignature.init(provider, pgpPublicKey.get());
|
||||
|
||||
char[] buffer = new char[1024];
|
||||
int bytesRead = 0;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
|
||||
|
||||
while (bytesRead != -1) {
|
||||
bytesRead = in.read(buffer, 0, 1024);
|
||||
pgpSignature.update(new String(buffer).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
verified = pgpSignature.verify();
|
||||
}
|
||||
|
||||
verified = verify(stream, asDecodedStream(signature));
|
||||
} catch (IOException | PGPException e) {
|
||||
LOG.error("Could not verify GPG key", e);
|
||||
}
|
||||
|
||||
return verified;
|
||||
}
|
||||
|
||||
private boolean verify(InputStream stream, InputStream signature) throws IOException, PGPException {
|
||||
PGPObjectFactory pgpObjectFactory = new JcaPGPObjectFactory(signature);
|
||||
Object o = pgpObjectFactory.nextObject();
|
||||
if (o instanceof PGPSignatureList) {
|
||||
return verify(stream, ((PGPSignatureList) o).get(0));
|
||||
} else if (o instanceof PGPCompressedData) {
|
||||
return verify(stream, ((PGPCompressedData) o).getDataStream());
|
||||
} else {
|
||||
LOG.warn("could not find valid signature, only found {}", o);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verify(InputStream stream, PGPSignature signature) throws IOException, PGPException {
|
||||
PGPPublicKey publicKey = findKey(signature);
|
||||
if (publicKey != null) {
|
||||
JcaPGPContentVerifierBuilderProvider provider = new JcaPGPContentVerifierBuilderProvider();
|
||||
signature.init(provider, publicKey);
|
||||
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[1024];
|
||||
while ((bytesRead = stream.read(buffer, 0, buffer.length)) != -1) {
|
||||
signature.update(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
return signature.verify();
|
||||
} else {
|
||||
LOG.warn("failed to parse public gpg key");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private PGPPublicKey findKey(PGPSignature signature) throws IOException {
|
||||
PGPObjectFactory pgpObjectFactory = new JcaPGPObjectFactory(asDecodedStream(raw));
|
||||
PGPPublicKeyRing keyRing = (PGPPublicKeyRing) pgpObjectFactory.nextObject();
|
||||
return keyRing.getPublicKey(signature.getKeyID());
|
||||
}
|
||||
|
||||
private InputStream asDecodedStream(String content) throws IOException {
|
||||
return asDecodedStream(content.getBytes(StandardCharsets.US_ASCII));
|
||||
}
|
||||
|
||||
private InputStream asDecodedStream(byte[] bytes) throws IOException {
|
||||
return PGPUtil.getDecoderStream(new ByteArrayInputStream(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,8 +49,6 @@ import static sonia.scm.security.gpg.PgpPublicKeyExtractor.getFromRawKey;
|
||||
@Singleton
|
||||
public class PublicKeyStore {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PublicKeyStore.class);
|
||||
|
||||
private static final String STORE_NAME = "gpg_public_keys";
|
||||
private static final String SUBKEY_STORE_NAME = "gpg_public_sub_keys";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user