From 280f3e005e27e7059c87d7b62373e37d7e7b5d0c Mon Sep 17 00:00:00 2001 From: Konstantin Schaper Date: Thu, 26 Nov 2020 13:08:10 +0100 Subject: [PATCH] work on getting signatures running --- .../java/sonia/scm/repository/GitUtil.java | 44 +++++-------------- .../scm/repository/spi/GitTagCommand.java | 2 +- .../scm/repository/spi/GitTagsCommand.java | 18 ++++---- .../repository/spi/GitTagsCommandTest.java | 39 +++++++++------- 4 files changed, 45 insertions(+), 58 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index b1e0ec2b34..f41628f8e0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -422,16 +422,8 @@ public final class GitUtil } /** - * Method description - * - * - * @param repository - * @param revWalk - * @param ref - * - * @return - * - * @throws IOException + * Returns the commit for the given ref. + * If the given ref is for a tag, the commit that this tag belongs to is returned instead. */ public static RevCommit getCommit(org.eclipse.jgit.lib.Repository repository, RevWalk revWalk, Ref ref) @@ -710,22 +702,20 @@ public final class GitUtil return name; } - private static final byte[] GPG_HEADER = {'P', 'G', 'P'}; + private static final String GPG_HEADER = "-----BEGIN PGP SIGNATURE-----"; - public static Optional getTagSignature(RevObject revObject, GPG gpg) { + public static Optional getTagSignature(RevObject revObject, GPG gpg, RevWalk revWalk) throws IOException { if (revObject instanceof RevTag) { - RevTag tag = (RevTag) revObject; - byte[] raw = tag.getFullMessage().getBytes(); - - int start = RawParseUtils.headerStart(GPG_HEADER, raw, 0); - if (start < 0) { + final byte[] bytes = revWalk.getObjectReader().open(revObject.getId()).getBytes(); + final String message = new String(bytes); + final int signatureStartIndex = message.indexOf(GPG_HEADER); + if (signatureStartIndex < 0) { return Optional.empty(); } - int end = RawParseUtils.headerEnd(raw, start); - byte[] signature = Arrays.copyOfRange(raw, start, end); + final String signature = message.substring(signatureStartIndex); - String publicKeyId = gpg.findPublicKeyId(signature); + String publicKeyId = gpg.findPublicKeyId(signature.getBytes()); if (Strings.isNullOrEmpty(publicKeyId)) { // key not found return Optional.of(new Signature(publicKeyId, "gpg", SignatureStatus.NOT_FOUND, null, Collections.emptySet())); @@ -739,19 +729,7 @@ public final class GitUtil PublicKey publicKey = publicKeyById.get(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - byte[] headerPrefix = Arrays.copyOfRange(raw, 0, start - GPG_HEADER.length - 1); - baos.write(headerPrefix); - - byte[] headerSuffix = Arrays.copyOfRange(raw, end + 1, raw.length); - baos.write(headerSuffix); - } catch (IOException ex) { - // this will never happen, because we are writing into memory - throw new IllegalStateException("failed to write into memory", ex); - } - - boolean verified = publicKey.verify(baos.toByteArray(), signature); + boolean verified = publicKey.verify(message.substring(0, signatureStartIndex - 1).getBytes(), signature.getBytes()); return Optional.of(new Signature( publicKeyId, "gpg", diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagCommand.java index 4d9814f5c4..ca3bd78c6e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagCommand.java @@ -111,7 +111,7 @@ public class GitTagCommand extends AbstractGitCommand implements TagCommand { try (RevWalk walk = new RevWalk(git.getRepository())) { revObject = walk.parseTag(ref.getObjectId()); - final Optional tagSignature = GitUtil.getTagSignature(revObject, gpg); + final Optional tagSignature = GitUtil.getTagSignature(revObject, gpg, walk); tagSignature.ifPresent(tag::addSignature); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagsCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagsCommand.java index 06e500ce4c..64a038b3ce 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagsCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitTagsCommand.java @@ -82,7 +82,7 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand { List tagList = git.tagList().call(); tags = Lists.transform(tagList, - new TransformFuntion(git.getRepository(), revWalk, gpg, git)); + new TransformFunction(git.getRepository(), revWalk, gpg, git)); } catch (GitAPIException ex) { throw new InternalRepositoryException(repository, "could not read tags from repository", ex); } finally { @@ -100,13 +100,13 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand { * @author Enter your name here... * @version Enter version here..., 12/07/06 */ - private static class TransformFuntion implements Function { + private static class TransformFunction implements Function { /** * the logger for TransformFuntion */ private static final Logger logger = - LoggerFactory.getLogger(TransformFuntion.class); + LoggerFactory.getLogger(TransformFunction.class); //~--- constructors ------------------------------------------------------- @@ -116,10 +116,10 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand { * @param repository * @param revWalk */ - public TransformFuntion(org.eclipse.jgit.lib.Repository repository, - RevWalk revWalk, - GPG gpg, - Git git) { + public TransformFunction(org.eclipse.jgit.lib.Repository repository, + RevWalk revWalk, + GPG gpg, + Git git) { this.repository = repository; this.revWalk = revWalk; this.gpg = gpg; @@ -149,12 +149,12 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand { try { RevTag revTag = GitUtil.getTag(repository, revWalk, ref); - final Optional tagSignature = GitUtil.getTagSignature(revTag, gpg); + final Optional tagSignature = GitUtil.getTagSignature(revTag, gpg, revWalk); if (tagSignature.isPresent()) { tag.addSignature(tagSignature.get()); } } catch (IncorrectObjectTypeException e) { - // Ignore, this must be a lightweight tag + // Ignore because it is a lightweight tag which cannot have signatures } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitTagsCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitTagsCommandTest.java index 27711d8b55..456096d736 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitTagsCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitTagsCommandTest.java @@ -24,41 +24,33 @@ package sonia.scm.repository.spi; -import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.ArgumentMatchers; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.repository.Tag; import sonia.scm.security.GPG; +import sonia.scm.security.PublicKey; import java.io.IOException; import java.util.List; +import java.util.Optional; -import static org.assertj.core.api.Assertions.anyOf; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; @SubjectAware(configuration = "classpath:sonia/scm/configuration/shiro.ini", username = "admin", password = "secret") @RunWith(MockitoJUnitRunner.class) public class GitTagsCommandTest extends AbstractGitCommandTestBase { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Rule - public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule(); - - @Rule - public ShiroRule shiro = new ShiroRule(); - @Mock GPG gpg; + @Mock + PublicKey publicKey; + @Test public void shouldGetDatesCorrectly() throws IOException { final GitContext gitContext = createContext(); @@ -79,7 +71,24 @@ public class GitTagsCommandTest extends AbstractGitCommandTestBase { @Test public void shouldGetSignatures() throws IOException { - Mockito.when(gpg.findPublicKeyId(ArgumentMatchers.any())).thenReturn("2BA27721F113C005CC16F06BAE63EFBC49F140CF"); + when(gpg.findPublicKeyId(ArgumentMatchers.any())).thenReturn("2BA27721F113C005CC16F06BAE63EFBC49F140CF"); + when(gpg.findPublicKey("2BA27721F113C005CC16F06BAE63EFBC49F140CF")).thenReturn(Optional.of(publicKey)); + String signature = "-----BEGIN PGP SIGNATURE-----\n" + + "\n" + + "iQEzBAABCgAdFiEEK6J3IfETwAXMFvBrrmPvvEnxQM8FAl+9acoACgkQrmPvvEnx\n" + + "QM9abwgAnGP+Y/Ijli+PAsimfOmZQWYepjptoOv9m7i3bnHv8V+Qg6cm51I3E0YV\n" + + "R2QaxxzW9PgS4hcES+L1qs8Lwo18RurF469eZEmNb8DcUFJ3sEWeHlIl5wZNNo/v\n" + + "jJm0d9LNcSmtAIiQ8eDMoGdFXJzHewGickLOSsQGmfZgZus4Qlsh7r3BZTI1Zwd/\n" + + "6jaBFctX13FuepCTxq2SjEfRaQHIYkyFQq2o6mjL5S2qfYJ/S//gcCCzxllQrisF\n" + + "5fRW3LzLI4eXFH0vua7+UzNS2Rwpifg2OENJA/Kn+3R36LWEGxFK9pNqjVPRAcQj\n" + + "1vSkcjK26RqhAqCjNLSagM8ATZrh+g==\n" + + "=kUKm\n" + + "-----END PGP SIGNATURE-----\n"; + String signedContent = "Tagger: Arthur Dent \n" + + "Date: Tue Nov 24 21:37:46 2020 +0100\n" + + "\n" + + "this tag is signed"; + when(publicKey.verify(signedContent.getBytes(), signature.getBytes())).thenReturn(true); final GitContext gitContext = createContext(); final GitTagsCommand tagsCommand = new GitTagsCommand(gitContext, gpg);