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

Support for new algorithm in ShowMojo #524

Merged
merged 1 commit into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/main/java/org/simplify4u/plugins/ShowMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package org.simplify4u.plugins;

import javax.inject.Inject;

import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;

import io.vavr.control.Try;
import lombok.AccessLevel;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -31,7 +31,6 @@
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.shared.utils.logging.MessageBuilder;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.bouncycastle.openpgp.PGPUtil;
import org.simplify4u.plugins.pgp.ArtifactInfo;
import org.simplify4u.plugins.pgp.KeyInfo;
import org.simplify4u.plugins.pgp.SignatureCheckResult;
Expand Down Expand Up @@ -130,9 +129,8 @@ private boolean processArtifact(Map.Entry<Artifact, Artifact> artifactEntry) {
messageBuilder.a("PGP signature:").newline();
messageBuilder.a("\tversion: ").strong(signature.getVersion()).newline();
messageBuilder.a("\talgorithm: ")
.strong(Try.of(() ->
PGPUtil.getSignatureName(signature.getKeyAlgorithm(), signature.getHashAlgorithm())).get())
.newline();
.strong(signatureUtils.digestName(signature.getHashAlgorithm()) + " with "
+ signatureUtils.keyAlgorithmName(signature.getKeyAlgorithm())).newline();
messageBuilder.a("\tkeyId: ").strong(signature.getKeyId()).newline();
messageBuilder.a("\tcreate date: ").strong(signature.getDate()).newline();
messageBuilder.a("\tstatus: ");
Expand Down
83 changes: 57 additions & 26 deletions src/main/java/org/simplify4u/plugins/pgp/SignatureUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Optional;

import javax.inject.Named;
import javax.inject.Singleton;

Expand Down Expand Up @@ -60,7 +61,6 @@ public class SignatureUtils {
* Check PGP signature for bad algorithms.
*
* @param hashAlgorithm PGP signature hashAlgorithm
*
* @return Returns null if no bad algorithms used, or algorithm name if used.
*/
public String checkWeakHashAlgorithm(int hashAlgorithm) {
Expand Down Expand Up @@ -97,9 +97,7 @@ public String checkWeakHashAlgorithm(int hashAlgorithm) {
* Load PGPSignature from input stream.
*
* @param input the input stream having PGPSignature content
*
* @return Returns the (first) read PGP signature.
*
* @throws SignatureException In case of failure loading signature.
*/
public PGPSignature loadSignature(InputStream input) throws SignatureException {
Expand Down Expand Up @@ -140,11 +138,9 @@ public PGPSignature loadSignature(InputStream input) throws SignatureException {
* Load PGPSignature from file.
*
* @param file the file having PGPSignature content
*
* @return Returns the (first) read PGP signature.
*
* @throws SignatureException In case of failure loading signature.
* @throws IOException In case of IO failures.
* @throws IOException In case of IO failures.
*/
public PGPSignature loadSignature(File file) throws IOException, SignatureException {
try (InputStream in = new FileInputStream(file)) {
Expand All @@ -157,7 +153,6 @@ public PGPSignature loadSignature(File file) throws IOException, SignatureExcept
*
* @param signature the PGP signature instance. The instance is expected to be initialized.
* @param file the file to read
*
* @throws IOException In case of failure to open the file or failure while reading its content.
*/
public void readFileContentInto(final PGPSignature signature, final File file) throws IOException {
Expand All @@ -174,9 +169,7 @@ public void readFileContentInto(final PGPSignature signature, final File file) t
* Retrieve Key Id from signature ISSUER_FINGERPRINT subpackage or standard keyId.
*
* @param signature the PGP signature instance
*
* @return Returns the keyId from signature
*
* @throws SignatureException In case of problem with signature data
*/
public KeyId retrieveKeyId(PGPSignature signature) throws SignatureException {
Expand All @@ -201,7 +194,6 @@ public KeyId retrieveKeyId(PGPSignature signature) throws SignatureException {
.map(PGPSignatureSubpacketVector::getIssuerKeyID)
.filter(id -> id != 0L);


if (!issuerKeyId.isPresent()) {
issuerKeyId = hashedSubPackets
.map(PGPSignatureSubpacketVector::getIssuerKeyID)
Expand Down Expand Up @@ -250,11 +242,10 @@ public KeyId retrieveKeyId(PGPSignature signature) throws SignatureException {
* @param artifactAsc The artifact contains signature
* @param onlyResolve Only resolve signature and keys
* @param cache PGP cache for access public key
*
* @return check verification result
*/
private SignatureCheckResult checkSignature(Artifact artifact, Artifact artifactAsc,
boolean onlyResolve, PGPKeysCache cache) {
boolean onlyResolve, PGPKeysCache cache) {

SignatureCheckResult.SignatureCheckResultBuilder signatureCheckResultBuilder = SignatureCheckResult.builder();

Expand Down Expand Up @@ -332,10 +323,10 @@ private SignatureCheckResult checkSignature(Artifact artifact, Artifact artifact
}

Boolean verifyStatus = Try.of(() -> {
signature.init(new BcPGPContentVerifierBuilderProvider(), publicKey);
readFileContentInto(signature, artifact.getFile());
return signature.verify();
}).onFailure(e -> signatureCheckResultBuilder.errorCause(e).status(SignatureStatus.ERROR))
signature.init(new BcPGPContentVerifierBuilderProvider(), publicKey);
readFileContentInto(signature, artifact.getFile());
return signature.verify();
}).onFailure(e -> signatureCheckResultBuilder.errorCause(e).status(SignatureStatus.ERROR))
.getOrNull();

if (verifyStatus == null) {
Expand All @@ -355,7 +346,6 @@ private SignatureCheckResult checkSignature(Artifact artifact, Artifact artifact
* @param artifact The artifact to check signature
* @param artifactAsc The artifact contains signature
* @param cache PGP cache for access public key
*
* @return check verification result
*/
public SignatureCheckResult checkSignature(Artifact artifact, Artifact artifactAsc, PGPKeysCache cache) {
Expand All @@ -369,22 +359,19 @@ public SignatureCheckResult checkSignature(Artifact artifact, Artifact artifactA
* @param artifact The artifact to check signature
* @param artifactAsc The artifact contains signature
* @param cache PGP cache for access public key
*
* @return check verification result
*/
public SignatureCheckResult resolveSignature(Artifact artifact, Artifact artifactAsc, PGPKeysCache cache) {
return checkSignature(artifact, artifactAsc, true, cache);
}

/**
* Map Public-Key algorithms id to name
*
* @param keyAlgorithm key algorithm id
*
* @return key algorithm name
*
* @throws UnsupportedOperationException if algorithm is is not known
*/
* Map Public-Key algorithms id to name
*
* @param keyAlgorithm key algorithm id
* @return key algorithm name
* @throws UnsupportedOperationException if algorithm is is not known
*/
public String keyAlgorithmName(int keyAlgorithm) {
switch (keyAlgorithm) {
case PublicKeyAlgorithmTags.RSA_GENERAL:
Expand Down Expand Up @@ -431,4 +418,48 @@ public String keyAlgorithmName(int keyAlgorithm) {
throw new UnsupportedOperationException("Unknown key algorithm value encountered: " + keyAlgorithm);
}
}

public String digestName(int hashAlgorithm) {
switch (hashAlgorithm) {
case HashAlgorithmTags.SHA1:
return "SHA1";
case HashAlgorithmTags.DOUBLE_SHA:
return "double-width SHA";
case HashAlgorithmTags.MD2:
return "MD2";
case HashAlgorithmTags.MD4:
return "MD4";
case HashAlgorithmTags.MD5:
return "MD5";
case HashAlgorithmTags.HAVAL_5_160:
return "HAVAL (5 pass, 160-bit)";
case HashAlgorithmTags.RIPEMD160:
return "RIPEMD160";
case HashAlgorithmTags.SHA256:
return "SHA256";
case HashAlgorithmTags.SHA384:
return "SHA384";
case HashAlgorithmTags.SHA512:
return "SHA512";
case HashAlgorithmTags.SHA224:
return "SHA224";
case HashAlgorithmTags.SHA3_256:
case HashAlgorithmTags.SHA3_256_OLD:
return "SHA256";
case HashAlgorithmTags.SHA3_384:
return "SHA384";
case HashAlgorithmTags.SHA3_512:
case HashAlgorithmTags.SHA3_512_OLD:
return "SHA512";
case HashAlgorithmTags.SHA3_224:
return "SHA224";
case HashAlgorithmTags.TIGER_192:
return "TIGER";
case HashAlgorithmTags.SM3:
return "SM3";
default:
throw new UnsupportedOperationException(
"Unknown hash algorithm tag in digestName: " + hashAlgorithm);
}
}
}
27 changes: 16 additions & 11 deletions src/test/java/org/simplify4u/plugins/ShowMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -69,14 +70,13 @@ public class ShowMojoTest {
@InjectMocks
private ShowMojo mojo;


@Test
void shouldReturnMojoName() {
assertThat(mojo.getMojoName()).isEqualTo(ShowMojo.MOJO_NAME);
}

public static String[] invalidArtifactNames() {
return new String[]{null, "test", "test:test", "test:test:1.0:type:class:class"};
return new String[] {null, "test", "test:test", "test:test:1.0:type:class:class"};
}

@ParameterizedTest
Expand All @@ -103,9 +103,10 @@ void shouldProcessArtifact() throws MojoFailureException, MojoExecutionException
//given
mojo.setArtifact("groupId:artifactId:1.0.0:war");

when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(), isNull())).thenReturn(artifact);
when(artifactResolver.resolveSignatures(anyCollection())).thenReturn(Collections.singletonMap(artifact, artifactAsc));

when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(),
isNull())).thenReturn(artifact);
when(artifactResolver.resolveSignatures(anyCollection())).thenReturn(
Collections.singletonMap(artifact, artifactAsc));

SignatureCheckResult signatureCheckResult = aSignatureCheckResultBuilder()
.status(SignatureStatus.SIGNATURE_VALID)
Expand All @@ -122,7 +123,8 @@ void shouldProcessArtifact() throws MojoFailureException, MojoExecutionException
verify(artifactResolver).resolveSignatures(anyCollection());

verify(signatureUtils).checkSignature(artifact, artifactAsc, pgpKeysCache);
verify(signatureUtils).keyAlgorithmName(anyInt());
verify(signatureUtils, times(2)).keyAlgorithmName(anyInt());
verify(signatureUtils).digestName(anyInt());

verify(pgpKeysCache).init(any(), any());

Expand All @@ -138,7 +140,8 @@ void shouldProcessArtifactWithPom() throws MojoFailureException, MojoExecutionEx
mojo.setArtifact("groupId:artifactId:1.0.0:war");
mojo.setShowPom(true);

when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(), isNull()))
when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(),
isNull()))
.thenReturn(artifact);

// when
Expand All @@ -150,7 +153,6 @@ void shouldProcessArtifactWithPom() throws MojoFailureException, MojoExecutionEx
verify(artifactResolver).resolvePom(artifact);
verify(artifactResolver).resolveSignatures(anyCollection());


verify(pgpKeysCache).init(any(), any());

verifyNoMoreInteractions(artifactResolver, pgpKeysCache, signatureUtils, repositorySystem);
Expand All @@ -165,7 +167,8 @@ void shouldFailForNotResolvedArtifact() throws IOException {
//given
mojo.setArtifact("groupId:artifactId:1.0.0:war");

when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(), isNull()))
when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(),
isNull()))
.thenReturn(artifact);

when(artifactResolver.resolveSignatures(anyCollection()))
Expand All @@ -187,7 +190,8 @@ void shouldFailForNotResolvedArtifact() throws IOException {
verify(artifactResolver).resolveArtifact(artifact);
verify(artifactResolver).resolveSignatures(anyCollection());

verify(signatureUtils).keyAlgorithmName(anyInt());
verify(signatureUtils, times(2)).keyAlgorithmName(anyInt());
verify(signatureUtils).digestName(anyInt());

verify(pgpKeysCache).init(any(), any());

Expand All @@ -203,7 +207,8 @@ void shouldFailForNotResolvedSignature() throws MojoExecutionException, IOExcept
//given
mojo.setArtifact("groupId:artifactId:1.0.0:war");

when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(), isNull()))
when(repositorySystem.createArtifactWithClassifier(anyString(), anyString(), anyString(), anyString(),
isNull()))
.thenReturn(artifact);

when(artifactResolver.resolveSignatures(anyCollection()))
Expand Down
25 changes: 22 additions & 3 deletions src/test/java/org/simplify4u/plugins/pgp/SignatureUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void testCheckWeakHashAlgorithmAllAlgorithms(int algorithm, boolean strong) {
}

public static Object[][] providerSignatureHashAlgorithms() {
return new Object[][]{
return new Object[][] {
{HashAlgorithmTags.MD5, false},
{HashAlgorithmTags.SHA1, true},
{HashAlgorithmTags.RIPEMD160, true},
Expand Down Expand Up @@ -303,7 +303,6 @@ void checkSignaturePositiveFlow() throws IOException, PGPException {
.build());
}


public static Object[] keyAlgorithms() {
return Arrays.stream(PublicKeyAlgorithmTags.class.getDeclaredFields())
.map(filed -> Try.of(() -> filed.getInt(null)).get())
Expand All @@ -317,9 +316,29 @@ void keyAlgorithmNameShouldBeResolved(int keyAlgorithm) {
}

@Test
void unKnownKeyAlgorithmThrowExceptio() {
void unKnownKeyAlgorithmThrowException() {
assertThatCode(() -> signatureUtils.keyAlgorithmName(9999998))
.isExactlyInstanceOf(UnsupportedOperationException.class)
.hasMessage("Unknown key algorithm value encountered: 9999998");
}

public static Object[] digestAlgorithms() {
return Arrays.stream(HashAlgorithmTags.class.getDeclaredFields())
.map(filed -> Try.of(() -> filed.getInt(null)).get())
.toArray();
}

@ParameterizedTest
@MethodSource("digestAlgorithms")
void digestNameShouldBeResolved(int keyAlgorithm) {
assertThat(signatureUtils.digestName(keyAlgorithm)).isNotBlank();
}

@Test
void unKnownDigestNameThrowException() {
assertThatCode(() -> signatureUtils.digestName(9999998))
.isExactlyInstanceOf(UnsupportedOperationException.class)
.hasMessage("Unknown hash algorithm tag in digestName: 9999998");
}

}