Browse Source

Added SHA-256 file digest utility methods.

These read the file in small chunks, to reduce memory.
v2.0-beta
CalDescent 3 years ago
parent
commit
a78af8f248
  1. 69
      src/main/java/org/qortal/crypto/Crypto.java
  2. 36
      src/test/java/org/qortal/test/CryptoTests.java

69
src/main/java/org/qortal/crypto/Crypto.java

@ -1,5 +1,8 @@
package org.qortal.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -75,12 +78,74 @@ public abstract class Crypto {
return digest(digest(input));
}
/**
* Returns 32-byte SHA-256 digest of file passed in input.
*
* @param file
* file in which to perform digest
* @return byte[32] digest, or null if SHA-256 algorithm can't be accessed
*
* @throws IOException if the file cannot be read
*/
public static byte[] digest(File file) throws IOException {
return Crypto.digest(file, 8192);
}
/**
* Returns 32-byte SHA-256 digest of file passed in input, in hex format
*
* @param file
* file in which to perform digest
* @return String digest as a hexadecimal string, or null if SHA-256 algorithm can't be accessed
*
* @throws IOException if the file cannot be read
*/
public static String digestHexString(File file, int bufferSize) throws IOException {
byte[] digest = Crypto.digest(file, bufferSize);
// Convert to hex
StringBuilder stringBuilder = new StringBuilder();
for (byte b : digest) {
stringBuilder.append(String.format("%02x", b));
}
return stringBuilder.toString();
}
/**
* Returns 32-byte SHA-256 digest of file passed in input.
*
* @param file
* file in which to perform digest
* @param bufferSize
* the number of bytes to load into memory
* @return byte[32] digest, or null if SHA-256 algorithm can't be accessed
*
* @throws IOException if the file cannot be read
*/
public static byte[] digest(File file, int bufferSize) throws IOException {
try {
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[bufferSize];
int count;
while ((count = fileInputStream.read(bytes)) != -1) {
sha256.update(bytes, 0, count);
}
fileInputStream.close();
return sha256.digest();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-256 message digest not available");
}
}
/**
* Returns 64-byte duplicated digest of message passed in input.
* <p>
* Effectively <tt>Bytes.concat(digest(input), digest(input)).
*
* @param addressVersion
*
* @param input
*/
public static byte[] dupDigest(byte[] input) {

36
src/test/java/org/qortal/test/CryptoTests.java

@ -10,7 +10,12 @@ import org.qortal.utils.Base58;
import static org.junit.Assert.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.security.SecureRandom;
import java.util.Random;
import org.bouncycastle.crypto.agreement.X25519Agreement;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
@ -40,6 +45,37 @@ public class CryptoTests extends Common {
assertArrayEquals(expected, digest);
}
@Test
public void testFileDigest() throws IOException {
byte[] input = HashCode.fromString("00").asBytes();
Path tempPath = Files.createTempFile("", ".tmp");
Files.write(tempPath, input, StandardOpenOption.CREATE);
byte[] digest = Crypto.digest(tempPath.toFile());
byte[] expected = HashCode.fromString("6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d").asBytes();
assertArrayEquals(expected, digest);
Files.delete(tempPath);
}
@Test
public void testFileDigestWithRandomData() throws IOException {
byte[] input = new byte[128];
new Random().nextBytes(input);
Path tempPath = Files.createTempFile("", ".tmp");
Files.write(tempPath, input, StandardOpenOption.CREATE);
byte[] fileDigest = Crypto.digest(tempPath.toFile());
byte[] memoryDigest = Crypto.digest(input);
assertArrayEquals(fileDigest, memoryDigest);
Files.delete(tempPath);
}
@Test
public void testPublicKeyToAddress() {
byte[] publicKey = HashCode.fromString("775ada64a48a30b3bfc4f1db16bca512d4088704975a62bde78781ce0cba90d6").asBytes();

Loading…
Cancel
Save