Skip to content

Commit

Permalink
file digesters
Browse files Browse the repository at this point in the history
  • Loading branch information
mcaserta committed Jan 19, 2022
1 parent 38fe71b commit 6d43828
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 0 deletions.
67 changes: 67 additions & 0 deletions src/main/java/com/mirkocaserta/bruce/Bruce.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.mirkocaserta.bruce.cipher.symmetric.EncodingCipherByKey;
import com.mirkocaserta.bruce.digest.Digester;
import com.mirkocaserta.bruce.digest.EncodingDigester;
import com.mirkocaserta.bruce.digest.FileDigester;
import com.mirkocaserta.bruce.mac.EncodingMac;
import com.mirkocaserta.bruce.mac.Mac;
import com.mirkocaserta.bruce.signature.Signer;
Expand All @@ -19,6 +20,8 @@
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
Expand Down Expand Up @@ -427,6 +430,70 @@ public static EncodingDigester digester(String algorithm, String provider, Encod
return message -> encode(encoding, rawDigester.digest(message.getBytes(charset)));
}

/**
* Returns an encoding file digester for the given algorithm.
*
* @param algorithm the algorithm (ex: <code>SHA1</code>, <code>MD5</code>, etc)
* @param encoding the encoding
* @return an encoding file digester
* @throws BruceException on no such algorithm or provider exceptions
*/
public static FileDigester fileDigester(String algorithm, Encoding encoding) {
return fileDigester(algorithm, BLANK, encoding);
}

/**
* Returns an encoding file digester for the given algorithm and provider.
*
* @param algorithm the algorithm (ex: <code>SHA1</code>, <code>MD5</code>, etc)
* @param provider the provider (hint: Bouncy Castle is <code>BC</code>)
* @param encoding the encoding
* @return an encoding file digester
* @throws BruceException on no such algorithm or provider exceptions
*/
public static FileDigester fileDigester(String algorithm, String provider, Encoding encoding) {
if (encoding == null) {
throw new BruceException(INVALID_ENCODING_NULL);
}

try { // fail fast
if (provider == null || provider.isBlank()) {
MessageDigest.getInstance(algorithm);
} else {
MessageDigest.getInstance(algorithm, provider);
}
} catch (NoSuchAlgorithmException e) {
throw new BruceException(String.format("No such algorithm: %s", algorithm), e);
} catch (NoSuchProviderException e) {
throw new BruceException(String.format("No such provider: %s", provider), e);
}

return file -> {
try {
var digest = provider == null || provider.isBlank()
? MessageDigest.getInstance(algorithm)
: MessageDigest.getInstance(algorithm, provider);
var inputStream = new FileInputStream(file);
var buffer = new byte[8192];
int read;

while ((read = inputStream.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}

return encode(encoding, digest.digest());
} catch (NoSuchAlgorithmException e) {
throw new BruceException(String.format("No such algorithm: %s", algorithm), e);
} catch (NoSuchProviderException e) {
throw new BruceException(String.format("No such provider: %s", provider), e);
} catch (FileNotFoundException e) {
throw new BruceException(String.format("No such file: %s", file), e);
} catch (IOException e) {
throw new BruceException(String.format("I/O error reading file: %s", file), e);
}
};
}

/**
* Returns a raw byte array message digester for the given algorithm and provider.
*
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/mirkocaserta/bruce/digest/FileDigester.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.mirkocaserta.bruce.digest;

import com.mirkocaserta.bruce.BruceException;

import java.io.File;

/**
* Generic interface for getting file digests
* in an encoded format such as hexadecimal or base64.
*
* @author Mirko Caserta ([email protected])
*/
public interface FileDigester {

/**
* Returns the file digest in encoded format.
*
* @param file the file to digest
* @return the file digest in encoded format
* @throws BruceException on digesting errors
*/
String digest(File file);

}
44 changes: 44 additions & 0 deletions src/test/java/com/mirkocaserta/bruce/digest/FileDigesterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.mirkocaserta.bruce.digest;

import com.mirkocaserta.bruce.Bruce;
import com.mirkocaserta.bruce.BruceException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.File;

import static com.mirkocaserta.bruce.Bruce.digester;
import static com.mirkocaserta.bruce.Bruce.fileDigester;
import static org.junit.jupiter.api.Assertions.assertEquals;

@DisplayName("File digester tests")
class FileDigesterTest {

@Test
@DisplayName("Hexadecimal file digester for the SHA1 algorithm")
void sha1Hex() {
var digester = fileDigester("SHA1", Bruce.Encoding.HEX);
assertEquals("4e1243bd22c66e76c2ba9eddc1f91394e57f9f83", digester.digest(new File("src/test/resources/test-file-1")), "1st sha1");
assertEquals("9054fbe0b622c638224d50d20824d2ff6782e308", digester.digest(new File("src/test/resources/test-file-2")), "2nd sha1");
}

@Test
@DisplayName("Base64 file digester for the SHA1 algorithm")
void sha1Base64() {
var digester = fileDigester("SHA1", Bruce.Encoding.BASE64);
assertEquals("ThJDvSLGbnbCup7dwfkTlOV/n4M=", digester.digest(new File("src/test/resources/test-file-1")), "1st sha1");
assertEquals("kFT74LYixjgiTVDSCCTS/2eC4wg=", digester.digest(new File("src/test/resources/test-file-2")), "2nd sha1");
}

@Test
@DisplayName("Digester for an invalid algorithm should throw a DigesterException")
void invalidAlgorithm1() {
Assertions.assertThrows(
BruceException.class,
() -> fileDigester("foo", Bruce.Encoding.HEX),
"No such algorithm: foo"
);
}

}
1 change: 1 addition & 0 deletions src/test/resources/test-file-1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
1 change: 1 addition & 0 deletions src/test/resources/test-file-2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test2

0 comments on commit 6d43828

Please sign in to comment.