Class BotanMessageDigest

java.lang.Object
java.security.MessageDigestSpi
net.randombit.botan.digest.BotanMessageDigest
All Implemented Interfaces:
Cloneable
Direct Known Subclasses:
BotanMessageDigest.Blake2b160, BotanMessageDigest.Blake2b256, BotanMessageDigest.Blake2b384, BotanMessageDigest.Blake2b512, BotanMessageDigest.Keccak224, BotanMessageDigest.Keccak256, BotanMessageDigest.Keccak384, BotanMessageDigest.Keccak512, BotanMessageDigest.MD4, BotanMessageDigest.MD5, BotanMessageDigest.RipeMd160, BotanMessageDigest.SHA1, BotanMessageDigest.SHA224, BotanMessageDigest.SHA256, BotanMessageDigest.SHA3_224, BotanMessageDigest.SHA3_256, BotanMessageDigest.SHA3_384, BotanMessageDigest.SHA3_512, BotanMessageDigest.SHA384, BotanMessageDigest.SHA512

public class BotanMessageDigest extends MessageDigestSpi implements Cloneable
Message digest (cryptographic hash) implementation using the Botan cryptography library.

This class provides a JCE-compliant MessageDigest implementation that delegates hash computations to native Botan library functions via JNR-FFI. It implements automatic native resource management using the Java Cleaner API to ensure native hash objects are properly destroyed when no longer needed.

Lifecycle and Resource Management

Native Botan hash objects are created during construction and destroyed automatically by the Cleaner when the Java object becomes unreachable (garbage collection). Unlike MAC and Cipher implementations, MessageDigest objects are not re-initializable - once created, they maintain the same hash algorithm for their entire lifetime.

Thread Safety

This implementation is NOT thread-safe. Each thread should use its own MessageDigest instance. The JCE API does not require MessageDigest implementations to be thread-safe.

Cloning Support

This implementation supports cloning via clone(). When a MessageDigest is cloned, the native hash state is copied using Botan's botan_hash_copy_state function, allowing independent computation of digests from the same intermediate state. Each cloned instance maintains its own native resource that is independently managed by the Cleaner.

Usage Examples

Basic SHA-256 Hash


 // Get MessageDigest instance from the Botan provider
 MessageDigest digest = MessageDigest.getInstance("SHA-256", "Botan");

 // Update with data
 digest.update("Hello, World!".getBytes());

 // Compute the hash
 byte[] hash = digest.digest();
 

Incremental Hashing with Multiple Updates


 MessageDigest digest = MessageDigest.getInstance("SHA-256", "Botan");

 // Process data incrementally
 digest.update("Part 1 ".getBytes());
 digest.update("Part 2 ".getBytes());
 digest.update("Part 3".getBytes());

 // Finalize and get result
 byte[] hash = digest.digest();
 

Digest and Reset for Multiple Messages


 MessageDigest digest = MessageDigest.getInstance("SHA-512", "Botan");

 // Hash first message
 digest.update(message1);
 byte[] hash1 = digest.digest();  // Auto-resets after digest

 // Hash second message
 digest.update(message2);
 byte[] hash2 = digest.digest();

 // Explicit reset if needed without digest
 digest.update(message3);
 digest.reset();  // Discard partial computation
 digest.update(message4);
 byte[] hash4 = digest.digest();
 

Cloning for Branch Computation


 MessageDigest digest = MessageDigest.getInstance("SHA-256", "Botan");

 // Common prefix
 digest.update("Common prefix: ".getBytes());

 // Clone to create independent branches
 MessageDigest branch1 = (MessageDigest) digest.clone();
 MessageDigest branch2 = (MessageDigest) digest.clone();

 // Compute different hashes from same prefix
 branch1.update("branch 1 data".getBytes());
 byte[] hash1 = branch1.digest();

 branch2.update("branch 2 data".getBytes());
 byte[] hash2 = branch2.digest();

 // Original digest is unchanged
 digest.update("original continuation".getBytes());
 byte[] hash3 = digest.digest();
 

Single-Byte Processing


 MessageDigest digest = MessageDigest.getInstance("BLAKE2b-256", "Botan");

 // Process byte by byte (uses internal single-byte buffer)
 for (byte b : data) {
     digest.update(b);
 }
 byte[] result = digest.digest();
 

One-Shot Hashing


 MessageDigest digest = MessageDigest.getInstance("SHA-256", "Botan");

 // Compute hash in single call (combines update + digest)
 byte[] hash = digest.digest(data);
 

Supported Algorithms

The following hash algorithms are available through concrete subclasses:

Implementation Notes

  • Cloning Supported - Unlike MAC and Cipher, MessageDigest supports cloning via native state copy
  • Immutable Algorithm - The hash algorithm cannot be changed after construction
  • Auto-Reset After Digest - After digest(), the state is automatically reset by Botan
  • Memory Safety - Native resources are guaranteed to be freed even if explicit cleanup is not called, thanks to the Cleaner API
  • Performance - Delegates to native Botan implementation for optimal performance
Since:
0.1.0
Author:
Yasser Aziza
See Also: