Class 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
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:
- SHA-1 -
BotanMessageDigest.SHA1- SHA-1 (20-byte output) - Not recommended for security-critical applications - SHA-224 -
BotanMessageDigest.SHA224- SHA-2 family (28-byte output) - SHA-256 -
BotanMessageDigest.SHA256- SHA-2 family (32-byte output) - SHA-384 -
BotanMessageDigest.SHA384- SHA-2 family (48-byte output) - SHA-512 -
BotanMessageDigest.SHA512- SHA-2 family (64-byte output) - SHA-3(224) -
BotanMessageDigest.SHA3_224- SHA-3 family (28-byte output) - SHA-3(256) -
BotanMessageDigest.SHA3_256- SHA-3 family (32-byte output) - SHA-3(384) -
BotanMessageDigest.SHA3_384- SHA-3 family (48-byte output) - SHA-3(512) -
BotanMessageDigest.SHA3_512- SHA-3 family (64-byte output) - Keccak-1600(224) -
BotanMessageDigest.Keccak224- Keccak (28-byte output) - Keccak-1600(256) -
BotanMessageDigest.Keccak256- Keccak (32-byte output) - Keccak-1600(384) -
BotanMessageDigest.Keccak384- Keccak (48-byte output) - Keccak-1600(512) -
BotanMessageDigest.Keccak512- Keccak (64-byte output) - Blake2b(160) -
BotanMessageDigest.Blake2b160- BLAKE2b (20-byte output) - Blake2b(256) -
BotanMessageDigest.Blake2b256- BLAKE2b (32-byte output) - Blake2b(384) -
BotanMessageDigest.Blake2b384- BLAKE2b (48-byte output) - Blake2b(512) -
BotanMessageDigest.Blake2b512- BLAKE2b (64-byte output) - MD4 -
BotanMessageDigest.MD4- MD4 (16-byte output) - Not recommended for security-critical applications - MD5 -
BotanMessageDigest.MD5- MD5 (16-byte output) - Not recommended for security-critical applications - RIPEMD-160 -
BotanMessageDigest.RipeMd160- RIPEMD-160 (20-byte output)
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:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final classstatic final class -
Method Summary
Modifier and TypeMethodDescriptionclone()protected byte[]protected intprotected voidprotected voidengineUpdate(byte input) protected voidengineUpdate(byte[] input, int offset, int len) Methods inherited from class java.security.MessageDigestSpi
engineDigest, engineUpdate
-
Method Details
-
engineGetDigestLength
protected int engineGetDigestLength()- Overrides:
engineGetDigestLengthin classMessageDigestSpi
-
engineUpdate
protected void engineUpdate(byte input) - Specified by:
engineUpdatein classMessageDigestSpi
-
engineUpdate
protected void engineUpdate(byte[] input, int offset, int len) - Specified by:
engineUpdatein classMessageDigestSpi
-
engineDigest
protected byte[] engineDigest()- Specified by:
engineDigestin classMessageDigestSpi
-
engineReset
protected void engineReset()- Specified by:
engineResetin classMessageDigestSpi
-
clone
- Overrides:
clonein classMessageDigestSpi
-