From 499c0ba523ec8a465fffeeee2d180dc69b4fe4dc Mon Sep 17 00:00:00 2001 From: Sven Bunge Date: Sun, 17 Jan 2016 17:14:16 +0100 Subject: [PATCH] Implement digester for SHA-256 Closes #2 --- .../codehaus/plexus/digest/ChecksumFile.java | 37 +++++----- .../plexus/digest/Sha256Digester.java | 38 +++++++++++ .../digest/StreamingSha256Digester.java | 33 +++++++++ src/test/examples/openssl.jar.sha256 | 1 + src/test/examples/plain.jar.sha256 | 1 + .../examples/redback-authz-open.jar.sha256 | 1 + src/test/examples/single-space.jar.sha256 | 1 + src/test/examples/space-asterisk.jar.sha256 | 1 + .../plexus/digest/ChecksumFileTest.java | 5 ++ .../codehaus/plexus/digest/DigesterTest.java | 67 ++++++++++++++----- 10 files changed, 152 insertions(+), 33 deletions(-) create mode 100644 src/main/java/org/codehaus/plexus/digest/Sha256Digester.java create mode 100644 src/main/java/org/codehaus/plexus/digest/StreamingSha256Digester.java create mode 100644 src/test/examples/openssl.jar.sha256 create mode 100644 src/test/examples/plain.jar.sha256 create mode 100644 src/test/examples/redback-authz-open.jar.sha256 create mode 100644 src/test/examples/single-space.jar.sha256 create mode 100644 src/test/examples/space-asterisk.jar.sha256 diff --git a/src/main/java/org/codehaus/plexus/digest/ChecksumFile.java b/src/main/java/org/codehaus/plexus/digest/ChecksumFile.java index 7eeb142..276d185 100644 --- a/src/main/java/org/codehaus/plexus/digest/ChecksumFile.java +++ b/src/main/java/org/codehaus/plexus/digest/ChecksumFile.java @@ -33,6 +33,10 @@ @Named public class ChecksumFile { + @Inject + @Named ( "sha256" ) + private Digester digestSha256; + @Inject @Named ( "sha1" ) private Digester digestSha1; @@ -76,31 +80,34 @@ public boolean isValidChecksum( File checksumFile ) throws DigesterException, Fi } String path = checksumFile.getAbsolutePath(); - Digester digester = null; + Digester digester = findDigesterByFileSuffix(path); + + File referenceFile = new File( path.substring( 0, path.length() - digester.getFilenameExtension().length() ) ); + + String rawChecksum = FileUtils.fileRead( checksumFile, "UTF-8" ); + String expectedChecksum = DigestUtils.cleanChecksum( rawChecksum, digester, referenceFile.getName() ); + + String actualChecksum = digester.calc( referenceFile ); + + return StringUtils.equalsIgnoreCase( expectedChecksum, actualChecksum ); + } + private Digester findDigesterByFileSuffix(String path) throws DigesterException { if ( path.endsWith( digestMd5.getFilenameExtension() ) ) { - digester = digestMd5; + return digestMd5; } else if ( path.endsWith( digestSha1.getFilenameExtension() ) ) { - digester = digestSha1; + return digestSha1; } - // TODO: Add more digester implementations here. - - if ( digester == null ) + else if ( path.endsWith( digestSha256.getFilenameExtension() ) ) { - throw new DigesterException( "Unable to determine digester type from filename " + path ); + return digestSha256; } + // TODO: Add more digester implementations here. - File referenceFile = new File( path.substring( 0, path.length() - digester.getFilenameExtension().length() ) ); - - String rawChecksum = FileUtils.fileRead( checksumFile, "UTF-8" ); - String expectedChecksum = DigestUtils.cleanChecksum( rawChecksum, digester, referenceFile.getName() ); - - String actualChecksum = digester.calc( referenceFile ); - - return StringUtils.equalsIgnoreCase( expectedChecksum, actualChecksum ); + throw new DigesterException( "Unable to determine digester type from filename " + path ); } /** diff --git a/src/main/java/org/codehaus/plexus/digest/Sha256Digester.java b/src/main/java/org/codehaus/plexus/digest/Sha256Digester.java new file mode 100644 index 0000000..695caab --- /dev/null +++ b/src/main/java/org/codehaus/plexus/digest/Sha256Digester.java @@ -0,0 +1,38 @@ +package org.codehaus.plexus.digest; + +/* + * Copyright 2001-2006 The Codehaus. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import javax.inject.Named; + +/** + * Digester that does SHA256 Message Digesting Only. + * + */ +@Named( "sha256" ) +public class Sha256Digester + extends AbstractDigester +{ + public String getFilenameExtension() + { + return ".sha256"; + } + + public Sha256Digester() + { + super( new StreamingSha256Digester() ); + } +} diff --git a/src/main/java/org/codehaus/plexus/digest/StreamingSha256Digester.java b/src/main/java/org/codehaus/plexus/digest/StreamingSha256Digester.java new file mode 100644 index 0000000..e6d7ca6 --- /dev/null +++ b/src/main/java/org/codehaus/plexus/digest/StreamingSha256Digester.java @@ -0,0 +1,33 @@ +package org.codehaus.plexus.digest; + +/* + * Copyright 2001-2006 The Codehaus. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import javax.inject.Named; + +/** + * An SHA-256 implementation of the streaming digester. + * + */ +@Named( "sha256" ) +public class StreamingSha256Digester + extends AbstractStreamingDigester +{ + public StreamingSha256Digester() + { + super( "SHA-256" ); + } +} diff --git a/src/test/examples/openssl.jar.sha256 b/src/test/examples/openssl.jar.sha256 new file mode 100644 index 0000000..03a4075 --- /dev/null +++ b/src/test/examples/openssl.jar.sha256 @@ -0,0 +1 @@ +SHA256(openssl.jar)= c8708900fd00167e6912c5e99c6bddaf5526a7f0c9ce78ce6a0cc08c2713d32a diff --git a/src/test/examples/plain.jar.sha256 b/src/test/examples/plain.jar.sha256 new file mode 100644 index 0000000..b91f0f8 --- /dev/null +++ b/src/test/examples/plain.jar.sha256 @@ -0,0 +1 @@ +c8708900fd00167e6912c5e99c6bddaf5526a7f0c9ce78ce6a0cc08c2713d32a diff --git a/src/test/examples/redback-authz-open.jar.sha256 b/src/test/examples/redback-authz-open.jar.sha256 new file mode 100644 index 0000000..2d311a7 --- /dev/null +++ b/src/test/examples/redback-authz-open.jar.sha256 @@ -0,0 +1 @@ +fb342200c89233cc37ba8e164189301fdbcf1b74c7ab54c662c4261cf615d743 redback-authz-open.jar diff --git a/src/test/examples/single-space.jar.sha256 b/src/test/examples/single-space.jar.sha256 new file mode 100644 index 0000000..1c1d18a --- /dev/null +++ b/src/test/examples/single-space.jar.sha256 @@ -0,0 +1 @@ +c8708900fd00167e6912c5e99c6bddaf5526a7f0c9ce78ce6a0cc08c2713d32a single-space.jar diff --git a/src/test/examples/space-asterisk.jar.sha256 b/src/test/examples/space-asterisk.jar.sha256 new file mode 100644 index 0000000..4d1eba3 --- /dev/null +++ b/src/test/examples/space-asterisk.jar.sha256 @@ -0,0 +1 @@ +c8708900fd00167e6912c5e99c6bddaf5526a7f0c9ce78ce6a0cc08c2713d32a *space-asterisk.jar diff --git a/src/test/java/org/codehaus/plexus/digest/ChecksumFileTest.java b/src/test/java/org/codehaus/plexus/digest/ChecksumFileTest.java index 669e5da..dc07422 100644 --- a/src/test/java/org/codehaus/plexus/digest/ChecksumFileTest.java +++ b/src/test/java/org/codehaus/plexus/digest/ChecksumFileTest.java @@ -45,18 +45,23 @@ void isValidChecksum() assertTrue( checksum.isValidChecksum( new File( exampleDir, "redback-authz-open.jar.md5" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "redback-authz-open.jar.sha1" ) ) ); + assertTrue( checksum.isValidChecksum( new File( exampleDir, "redback-authz-open.jar.sha256" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "plain.jar.md5" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "plain.jar.sha1" ) ) ); + assertTrue( checksum.isValidChecksum( new File( exampleDir, "plain.jar.sha256" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "single-space.jar.md5" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "single-space.jar.sha1" ) ) ); + assertTrue( checksum.isValidChecksum( new File( exampleDir, "single-space.jar.sha256" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "space-asterisk.jar.md5" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "space-asterisk.jar.sha1" ) ) ); + assertTrue( checksum.isValidChecksum( new File( exampleDir, "space-asterisk.jar.sha256" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "openssl.jar.md5" ) ) ); assertTrue( checksum.isValidChecksum( new File( exampleDir, "openssl.jar.sha1" ) ) ); + assertTrue( checksum.isValidChecksum( new File( exampleDir, "openssl.jar.sha256" ) ) ); } @Test diff --git a/src/test/java/org/codehaus/plexus/digest/DigesterTest.java b/src/test/java/org/codehaus/plexus/digest/DigesterTest.java index d8ce933..515957e 100644 --- a/src/test/java/org/codehaus/plexus/digest/DigesterTest.java +++ b/src/test/java/org/codehaus/plexus/digest/DigesterTest.java @@ -22,6 +22,7 @@ import javax.inject.Inject; import javax.inject.Named; import java.io.File; +import java.util.Objects; import static org.junit.jupiter.api.Assertions.*; @@ -37,12 +38,20 @@ class DigesterTest private static final String SHA1 = "2a7b459938e12a2dc35d1bf6cff35e9c2b592fa9"; + private static final String SHA256 = "56bfadc51bd0591ae1af06d28f4b3f86736007b213bfa95016681c7f8b27090c"; + private static final String WRONG_SHA1 = "4d8703779816556cdb8be7f6bb5c954f4b5730e2"; + private final File file = new File(Objects.requireNonNull(getClass().getResource("/test-file.txt")).getPath()); + @Inject @Named( "sha1" ) private Digester sha1Digest; + @Inject + @Named( "sha256" ) + private Digester sha256Digest; + @Inject @Named( "md5" ) private Digester md5Digest; @@ -50,53 +59,69 @@ class DigesterTest @Test void algorithm() { + assertEquals( "SHA-256", sha256Digest.getAlgorithm() ); assertEquals( "SHA-1", sha1Digest.getAlgorithm() ); assertEquals( "MD5", md5Digest.getAlgorithm() ); } @Test - void bareDigestFormat() { - File file = new File( getClass().getResource( "/test-file.txt" ).getPath() ); - - assertDoesNotThrow( () -> md5Digest.verify( file, MD5 ), "Bare format MD5 must not throw exception" ); + void md5DigestFormat() { + assertDoesNotThrow(() -> md5Digest.verify(file, MD5), "Bare format MD5 must not throw exception"); + } + @Test + void sha1DigestFormat() { assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 ), "Bare format SHA1 must not throw exception" ); + } - assertThrows( DigesterException.class, - () -> sha1Digest.verify( file, WRONG_SHA1 ), "Wrong SHA1 must throw exception" ); + @Test + void wrongSha1DigestFormat() { + assertThrows( DigesterException.class, () -> sha1Digest.verify( file, WRONG_SHA1 ), "Wrong SHA1 must throw exception" ); } @Test - void opensslDigestFormat() { - File file = new File( getClass().getResource( "/test-file.txt" ).getPath() ); + void sha256DigestFormat() { + assertDoesNotThrow( () -> sha256Digest.verify( file , SHA256 ), "Bare format SHA256 must not throw exception" ); + } + @Test + void opensslDigestMd5Format() { assertDoesNotThrow( () -> md5Digest.verify( file, "MD5(test-file.txt)= " + MD5 ), "OpenSSL MD5 format must not cause exception" ); assertDoesNotThrow( () -> md5Digest.verify( file, "MD5 (test-file.txt) = " + MD5 ), "FreeBSD MD5 format must not cause exception" ); + } - assertDoesNotThrow( () -> sha1Digest.verify( file, "SHA1(test-file.txt)= " + SHA1 ), "OpenSSL SHA1 format must not cause exception" ); - - assertDoesNotThrow( () -> sha1Digest.verify( file, "SHA1 (test-file.txt) = " + SHA1 ), "FreeBSD SHA1 format must not cause exception" ); + @Test + void opensslDigestSha1Format() { + assertDoesNotThrow( () -> sha1Digest.verify( file, "SHA1 (test-file.txt) = " + SHA1 ), "FreeBSD SHA1 format must not cause exception"); assertThrows( DigesterException.class, - () -> sha1Digest.verify( file, "SHA1 (FOO) = " + SHA1 ), "Wrong filename must throw exception" ); + () -> sha1Digest.verify( file, "SHA1 (FOO) = " + SHA1 ), "Wrong filename must throw exception"); assertThrows( DigesterException.class, () -> sha1Digest.verify( file, "SHA1 (test-file.txt) = " + WRONG_SHA1 ), "Wrong SHA1 must throw exception" ); - } @Test - void gnuDigestFormat() { - File file = new File( getClass().getResource( "/test-file.txt" ).getPath() ); + void opensslDigestSha256Format() { + assertDoesNotThrow( () -> sha256Digest.verify( file, "SHA256(test-file.txt) = " + SHA256 ), "FreeBSD SHA256 format must not cause exception" ); + assertThrows( DigesterException.class, + () -> sha256Digest.verify( file, "SHA256(FOO) = " + SHA256 ), "Wrong filename must throw exception" ); + } + + @Test + void gnuDigestMd5Format() { assertDoesNotThrow( () -> md5Digest.verify( file, MD5 + " *test-file.txt" ), "GNU format MD5 must not cause exception" ); assertDoesNotThrow( () -> md5Digest.verify( file, MD5 + " test-file.txt" ), "GNU text format MD5 must not cause exception" ); + } - assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 + " *test-file.txt" ), "GNU format SHA1 must not cause exception" ); + @Test + void gnuDigestSha1Format() { + assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 + " *test-file.txt" ), "GNU format SHA1 must not cause exception"); - assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 + " test-file.txt" ), "GNU text format SHA1 must not cause exception" ); + assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 + " test-file.txt" ), "GNU text format SHA1 must not cause exception"); assertThrows( DigesterException.class, () -> sha1Digest.verify( file, SHA1 + " FOO" ), "Wrong filename must throw exception" ); @@ -105,9 +130,15 @@ void gnuDigestFormat() { () -> sha1Digest.verify( file, WRONG_SHA1 + " test-file.txt" ), "Wrong SHA1 must throw exception" ); } + @Test + void gnuDigestSha256Format() { + assertDoesNotThrow( () -> sha256Digest.verify( file, SHA256 + " *test-file.txt" ), "GNU format SHA256 must not cause exception" ); + + assertDoesNotThrow( () -> sha256Digest.verify( file, SHA256 + " test-file.txt" ), "GNU text format SHA256 must not cause exception" ); + } + @Test void untrimmedContent() { - File file = new File( getClass().getResource( "/test-file.txt" ).getPath() ); assertDoesNotThrow( () -> sha1Digest.verify( file, SHA1 + " *test-file.txt \n" ), "GNU untrimmed SHA1 must not cause exception" ); } }