JNI: wrap native SHA-3 support in com.wolfssl.wolfcrypt.Sha3 class

pull/103/head
Chris Conlon 2025-02-21 17:06:11 -07:00
parent 613e4f4914
commit 00f2b1c318
9 changed files with 1226 additions and 63 deletions

View File

@ -55,6 +55,14 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Sha384Enable
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Sha512Enabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_FeatureDetect
* Method: Sha3Enabled
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Sha3Enabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_FeatureDetect
* Method: AesEnabled

View File

@ -0,0 +1,87 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_wolfssl_wolfcrypt_Sha3 */
#ifndef _Included_com_wolfssl_wolfcrypt_Sha3
#define _Included_com_wolfssl_wolfcrypt_Sha3
#ifdef __cplusplus
extern "C" {
#endif
#undef com_wolfssl_wolfcrypt_Sha3_NULL
#define com_wolfssl_wolfcrypt_Sha3_NULL 0LL
#undef com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_224
#define com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_224 10L
#undef com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_256
#define com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_256 11L
#undef com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_384
#define com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_384 12L
#undef com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_512
#define com_wolfssl_wolfcrypt_Sha3_TYPE_SHA3_512 13L
#undef com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_224
#define com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_224 28L
#undef com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_256
#define com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_256 32L
#undef com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_384
#define com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_384 48L
#undef com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_512
#define com_wolfssl_wolfcrypt_Sha3_DIGEST_SIZE_512 64L
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: mallocNativeStruct_internal
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Sha3_mallocNativeStruct_1internal
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_init_internal
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1init_1internal
(JNIEnv *, jobject, jint);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_copy_internal
* Signature: (Lcom/wolfssl/wolfcrypt/Sha3;I)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1copy_1internal
(JNIEnv *, jobject, jobject, jint);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_update_internal
* Signature: (Ljava/nio/ByteBuffer;III)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal__Ljava_nio_ByteBuffer_2III
(JNIEnv *, jobject, jobject, jint, jint, jint);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_update_internal
* Signature: ([BIII)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal___3BIII
(JNIEnv *, jobject, jbyteArray, jint, jint, jint);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_final_internal
* Signature: (Ljava/nio/ByteBuffer;II)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal__Ljava_nio_ByteBuffer_2II
(JNIEnv *, jobject, jobject, jint, jint);
/*
* Class: com_wolfssl_wolfcrypt_Sha3
* Method: native_final_internal
* Signature: ([BI)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal___3BI
(JNIEnv *, jobject, jbyteArray, jint);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -100,6 +100,18 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Sha512Enable
#endif
}
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Sha3Enabled
(JNIEnv* env, jclass jcl)
{
(void)env;
(void)jcl;
#ifdef WOLFSSL_SHA3
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_AesEnabled
(JNIEnv* env, jclass jcl)
{

View File

@ -30,6 +30,7 @@
#include <wolfssl/wolfcrypt/sha.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/sha512.h>
#include <wolfssl/wolfcrypt/sha3.h>
#include <com_wolfssl_wolfcrypt_Sha.h>
#include <com_wolfssl_wolfcrypt_Sha224.h>
@ -395,6 +396,237 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1final_1internal___3B(
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1init_1internal
(JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
if (sha == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_InitSha224(sha);
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
#else
(void)env;
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1copy_1internal
(JNIEnv* env, jobject this, jobject toBeCopied)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = NULL;
Sha224* tbc = NULL; /* tbc = to be copied */
if (this == NULL || toBeCopied == NULL) {
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
return;
}
sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
tbc = (Sha224*) getNativeStruct(env, toBeCopied);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
ret = wc_Sha224Copy(tbc, sha);
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
#else
(void)env;
(void)this;
(void)toBeCopied;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal__Ljava_nio_ByteBuffer_2II
(JNIEnv* env, jobject this, jobject data_buffer, jint position, jint len)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = NULL;
byte* data = NULL;
sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
data = getDirectBufferAddress(env, data_buffer);
if (sha == NULL || data == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Update(sha, data + position, len);
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("data[%u]: [%p]\n", (word32)len, data);
LogHex(data, 0, len);
#else
(void)env;
(void)this;
(void)data_buffer;
(void)position;
(void)len;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal___3BII
(JNIEnv* env, jobject this, jbyteArray data_buffer, jint offset, jint len)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = NULL;
byte* data = NULL;
word32 dataSz = 0;
sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Update(sha, data + offset, len);
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("data[%u]: [%p]\n", (word32)len, data + offset);
LogHex(data, offset, len);
releaseByteArray(env, data_buffer, data, JNI_ABORT);
#else
(void)env;
(void)this;
(void)data_buffer;
(void)offset;
(void)len;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal__Ljava_nio_ByteBuffer_2I
(JNIEnv* env, jobject this, jobject hash_buffer, jint position)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = NULL;
byte* hash = NULL;
sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
hash = getDirectBufferAddress(env, hash_buffer);
if (sha == NULL || hash == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Final(sha, hash + position);
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret);
LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA224_DIGEST_SIZE);
#else
(void)env;
(void)this;
(void)hash_buffer;
(void)position;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal___3B
(JNIEnv* env, jobject this, jbyteArray hash_buffer)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = NULL;
byte* hash = NULL;
sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
hash = getByteArray(env, hash_buffer);
if (sha == NULL || hash == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Final(sha, hash);
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret);
LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA224_DIGEST_SIZE);
releaseByteArray(env, hash_buffer, hash, ret);
#else
(void)env;
(void)this;
(void)hash_buffer;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Sha256_native_1init_1internal(
JNIEnv* env, jobject this)
@ -982,22 +1214,62 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1final_1internal___3B(
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1init_1internal
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Sha3_mallocNativeStruct_1internal
(JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA224
int ret = 0;
Sha224* sha = (Sha224*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
#ifdef WOLFSSL_SHA3
wc_Sha3* sha = NULL;
sha = (wc_Sha3*) XMALLOC(sizeof(wc_Sha3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (sha == NULL) {
throwOutOfMemoryException(env, "Failed to allocate wc_Sha3 object");
}
else {
XMEMSET(sha, 0, sizeof(wc_Sha3));
}
LogStr("new wc_Sha3 = %p\n", sha);
return (jlong)(uintptr_t)sha;
#else
(void)env;
(void)this;
throwNotCompiledInException(env);
return (jlong)0;
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1init_1internal
(JNIEnv* env, jobject this, jint hashType)
{
#ifdef WOLFSSL_SHA3
int ret = 0;
wc_Sha3* sha = NULL;
sha = (wc_Sha3*) getNativeStruct(env, this);
if (sha == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_InitSha224(sha);
if (ret == 0) {
switch (hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_InitSha3_224(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_InitSha3_256(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_InitSha3_384(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_InitSha3_512(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
}
if (ret != 0) {
@ -1006,55 +1278,75 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1init_1internal
#else
(void)env;
(void)this;
(void)hashType;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1copy_1internal
(JNIEnv* env, jobject this, jobject toBeCopied)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1copy_1internal
(JNIEnv* env, jobject this, jobject toBeCopied, jint hashType)
{
#ifdef WOLFSSL_SHA224
#ifdef WOLFSSL_SHA3
int ret = 0;
Sha224* sha = NULL;
Sha224* tbc = NULL; /* tbc = to be copied */
wc_Sha3* sha = NULL;
wc_Sha3* tbc = NULL; /* tbc = to be copied */
if (this == NULL || toBeCopied == NULL) {
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
return;
}
sha = (Sha224*) getNativeStruct(env, this);
sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
tbc = (Sha224*) getNativeStruct(env, toBeCopied);
tbc = (wc_Sha3*) getNativeStruct(env, toBeCopied);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
}
ret = wc_Sha224Copy(tbc, sha);
switch (hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Copy(tbc, sha);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Copy(tbc, sha);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Copy(tbc, sha);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Copy(tbc, sha);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
if (ret != 0) {
throwWolfCryptExceptionFromError(env, ret);
}
#else
(void)env;
(void)this;
(void)toBeCopied;
(void)hashType;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal__Ljava_nio_ByteBuffer_2II
(JNIEnv* env, jobject this, jobject data_buffer, jint position, jint len)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal__Ljava_nio_ByteBuffer_2III
(JNIEnv* env, jobject this, jobject data_buffer, jint offset, jint len, jint hashType)
{
#ifdef WOLFSSL_SHA224
#ifdef WOLFSSL_SHA3
int ret = 0;
Sha224* sha = NULL;
byte* data = NULL;
byte* data = NULL;
wc_Sha3* sha = NULL;
sha = (Sha224*) getNativeStruct(env, this);
sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
@ -1065,37 +1357,55 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna
if (sha == NULL || data == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Update(sha, data + position, len);
if (ret == 0) {
switch (hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Update(sha, data + offset, len);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
}
if (ret != 0) {
if (ret < 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("wc_Sha3_Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("data[%u]: [%p]\n", (word32)len, data);
LogHex(data, 0, len);
#else
(void)env;
(void)this;
(void)data_buffer;
(void)position;
(void)offset;
(void)len;
(void)hashType;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal___3BII
(JNIEnv* env, jobject this, jbyteArray data_buffer, jint offset, jint len)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal___3BIII
(JNIEnv* env, jobject this, jbyteArray data_buffer, jint offset, jint len, jint hashType)
{
#ifdef WOLFSSL_SHA224
#ifdef WOLFSSL_SHA3
int ret = 0;
Sha224* sha = NULL;
byte* data = NULL;
wc_Sha3* sha = NULL;
byte* data = NULL;
word32 dataSz = 0;
sha = (Sha224*) getNativeStruct(env, this);
sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
@ -1108,16 +1418,33 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Update(sha, data + offset, len);
if (ret == 0) {
switch(hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Update(sha, data + offset, len);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Update(sha, data + offset, len);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
}
if (ret != 0) {
if (ret < 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("data[%u]: [%p]\n", (word32)len, data + offset);
LogStr("wc_Sha3_Update(sha=%p, data, len) = %d\n", sha, ret);
LogStr("data[%u]: [%p]\n", (word32)len, data);
LogHex(data, offset, len);
releaseByteArray(env, data_buffer, data, JNI_ABORT);
@ -1127,19 +1454,20 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna
(void)data_buffer;
(void)offset;
(void)len;
(void)hashType;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal__Ljava_nio_ByteBuffer_2I
(JNIEnv* env, jobject this, jobject hash_buffer, jint position)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal__Ljava_nio_ByteBuffer_2II
(JNIEnv* env, jobject this, jobject hash_buffer, jint position, jint hashType)
{
#ifdef WOLFSSL_SHA224
#ifdef WOLFSSL_SHA3
int ret = 0;
Sha224* sha = NULL;
byte* hash = NULL;
wc_Sha3* sha = NULL;
byte* hash = NULL;
sha = (Sha224*) getNativeStruct(env, this);
sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
@ -1150,35 +1478,51 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal
if (sha == NULL || hash == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Final(sha, hash + position);
if (ret == 0) {
switch(hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Final(sha, hash + position);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Final(sha, hash + position);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Final(sha, hash + position);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Final(sha, hash + position);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
}
if (ret != 0) {
if (ret < 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret);
LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA224_DIGEST_SIZE);
LogStr("wc_Sha3_Final(sha=%p, hash) = %d\n", sha, ret);
#else
(void)env;
(void)this;
(void)hash_buffer;
(void)position;
(void)hashType;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal___3B
(JNIEnv* env, jobject this, jbyteArray hash_buffer)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal___3BI
(JNIEnv* env, jobject this, jbyteArray hash_buffer, jint hashType)
{
#ifdef WOLFSSL_SHA224
#ifdef WOLFSSL_SHA3
int ret = 0;
Sha224* sha = NULL;
byte* hash = NULL;
wc_Sha3* sha = NULL;
byte* hash = NULL;
sha = (Sha224*) getNativeStruct(env, this);
sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
return;
@ -1189,23 +1533,40 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal
if (sha == NULL || hash == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha224Final(sha, hash);
if (ret == 0) {
switch(hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Final(sha, hash);
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Final(sha, hash);
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Final(sha, hash);
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Final(sha, hash);
break;
default:
ret = BAD_FUNC_ARG;
break;
}
}
if (ret != 0) {
if (ret < 0) {
throwWolfCryptExceptionFromError(env, ret);
}
LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret);
LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA224_DIGEST_SIZE);
LogStr("wc_Sha3_Final(sha=%p, hash) = %d\n", sha, ret);
releaseByteArray(env, hash_buffer, hash, ret);
#else
(void)env;
(void)this;
(void)hash_buffer;
(void)hashType;
throwNotCompiledInException(env);
#endif
}

View File

@ -57,6 +57,7 @@ infer --fail-on-issue run -- javac \
src/main/java/com/wolfssl/wolfcrypt/Sha256.java \
src/main/java/com/wolfssl/wolfcrypt/Sha384.java \
src/main/java/com/wolfssl/wolfcrypt/Sha512.java \
src/main/java/com/wolfssl/wolfcrypt/Sha3.java \
src/main/java/com/wolfssl/wolfcrypt/WolfCrypt.java \
src/main/java/com/wolfssl/wolfcrypt/WolfCryptError.java \
src/main/java/com/wolfssl/wolfcrypt/WolfCryptException.java \

View File

@ -69,6 +69,13 @@ public class FeatureDetect {
*/
public static native boolean Sha512Enabled();
/**
* Tests if SHA3 is compiled into the native wolfSSL library.
*
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean Sha3Enabled();
/**
* Tests if AES is compiled into the native wolfSSL library.
*

View File

@ -0,0 +1,309 @@
/* Sha3.java
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
package com.wolfssl.wolfcrypt;
import java.nio.ByteBuffer;
/**
* Wrapper for the native WolfCrypt SHA3 implementation
*/
public class Sha3 extends MessageDigest implements Cloneable {
/** SHA3-224 hash type */
public static final int TYPE_SHA3_224 = 10;
/** SHA3-256 hash type */
public static final int TYPE_SHA3_256 = 11;
/** SHA3-384 hash type */
public static final int TYPE_SHA3_384 = 12;
/** SHA3-512 hash type */
public static final int TYPE_SHA3_512 = 13;
/** SHA3-224 digest size */
public static final int DIGEST_SIZE_224 = 28;
/** SHA3-256 digest size */
public static final int DIGEST_SIZE_256 = 32;
/** SHA3-384 digest size */
public static final int DIGEST_SIZE_384 = 48;
/** SHA3-512 digest size */
public static final int DIGEST_SIZE_512 = 64;
/** Array to init Sha3 with, will be reset to null once initialized */
private byte[] initialData = null;
/** Hash type of this current object */
private int hashType = 0;
/** Digest size of this current object */
private int digestSize = 0;
/* Native JNI methods, internally reach back and grab/use pointer
* from NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native long mallocNativeStruct_internal()
throws OutOfMemoryError;
private native void native_init_internal(int hashType);
private native void native_copy_internal(Sha3 toBeCopied, int hashType);
private native void native_update_internal(ByteBuffer data, int offset,
int len, int hashType);
private native void native_update_internal(byte[] data, int offset,
int len, int hashType);
private native void native_final_internal(ByteBuffer hash, int offset,
int hashType);
private native void native_final_internal(byte[] hash, int hashType);
/**
* Get the hash type of this Sha3 object
*
* @return the hash type of this Sha3 object. One of TYPE_SHA3_224,
* TYPE_SHA3_256, TYPE_SHA3_384, or TYPE_SHA3_512.
*/
public int getHashType() {
return this.hashType;
}
/**
* Sanitize and set the hash type of this Sha3 object.
*
* @param hashType hash type of the Sha3 object
*
* @throws WolfCryptException if the hash type is invalid
*/
private void sanitizeAndSetHashType(int hashType) {
if (hashType != TYPE_SHA3_224 && hashType != TYPE_SHA3_256 &&
hashType != TYPE_SHA3_384 && hashType != TYPE_SHA3_512) {
throw new WolfCryptException(
"Invalid hash type: " + hashType + ". " +
"Must be one of TYPE_SHA3_224, TYPE_SHA3_256, " +
"TYPE_SHA3_384, or TYPE_SHA3_512.");
}
this.hashType = hashType;
switch (hashType) {
case TYPE_SHA3_224:
this.digestSize = DIGEST_SIZE_224;
break;
case TYPE_SHA3_256:
this.digestSize = DIGEST_SIZE_256;
break;
case TYPE_SHA3_384:
this.digestSize = DIGEST_SIZE_384;
break;
case TYPE_SHA3_512:
this.digestSize = DIGEST_SIZE_512;
break;
}
}
/**
* Malloc native JNI Sha3 structure
*
* @return native allocated pointer
*
* @throws OutOfMemoryError when malloc fails with memory error
*/
protected long mallocNativeStruct()
throws OutOfMemoryError {
synchronized (pointerLock) {
return mallocNativeStruct_internal();
}
}
/**
* Initialize Sha3 object
*
* @throws WolfCryptException if native operation fails
*/
protected void native_init()
throws WolfCryptException {
synchronized (pointerLock) {
native_init_internal(this.hashType);
/* Check if we need to init with passed in data */
if (this.initialData != null) {
update(this.initialData);
this.initialData = null;
}
}
}
/**
* Copy existing native wc_Sha3 struct (Sha3 object) into this one.
* Copies structure state using wc_Sha3_XXX_Copy().
*
* @param toBeCopied initialized Sha3 object to be copied.
*
* @throws WolfCryptException if native operation fails
*/
protected void native_copy(Sha3 toBeCopied)
throws WolfCryptException {
synchronized (pointerLock) {
native_copy_internal(toBeCopied, toBeCopied.getHashType());
}
}
/**
* Native SHA-3 update
*
* @param data input data
* @param offset offset into input data
* @param len length of input data
*
* @throws WolfCryptException if native operation fails
*/
protected void native_update(ByteBuffer data, int offset, int len)
throws WolfCryptException {
synchronized (pointerLock) {
native_update_internal(data, offset, len, this.hashType);
}
}
/**
* Native SHA-3 update
*
* @param data input data
* @param offset offset into input data
* @param len length of input data
*
* @throws WolfCryptException if native operation fails
*/
protected void native_update(byte[] data, int offset, int len)
throws WolfCryptException {
synchronized (pointerLock) {
native_update_internal(data, offset, len, this.hashType);
}
}
/**
* Native SHA-3 final, calculate final digest
*
* @param hash output buffer to place digest
* @param offset offset into output buffer to write digest
*
* @throws WolfCryptException if native operation fails
*/
protected void native_final(ByteBuffer hash, int offset)
throws WolfCryptException {
synchronized (pointerLock) {
native_final_internal(hash, offset, this.hashType);
}
}
/**
* Native SHA-3 final, calculate final digest
*
* @param hash output buffer to place digest
*
* @throws WolfCryptException if native operation fails
*/
protected void native_final(byte[] hash)
throws WolfCryptException {
synchronized (pointerLock) {
native_final_internal(hash, this.hashType);
}
}
/**
* Create new Sha3 object.
*
* @param hashType SHA3 hash type: one of TYPE_SHA3_224, TYPE_SHA3_256,
* TYPE_SHA3_384, or TYPE_SHA3_512.
*
* @throws WolfCryptException if SHA-3 has not been compiled into native
* wolfCrypt library.
*/
public Sha3(int hashType) {
if (!FeatureDetect.Sha3Enabled()) {
throw new WolfCryptException(
WolfCryptError.NOT_COMPILED_IN.getCode());
}
/* Internal state is initialized on first use */
sanitizeAndSetHashType(hashType);
}
/**
* Create new Sha3 object by making a copy of the one given.
*
* @param sha3 Initialized/created Sha3 object to be copied
*
* @throws WolfCryptException to indicate this constructor has been
* deprecated, along with instructions on what API to call
*
* @deprecated This constructor has been deprecated to avoid storage
* of a second Sha3 object inside this Sha3 object, and to
* avoid potential incomplete object creation issues between
* subclass/superclasses. Please refactor existing code to
* call Sha3.clone() to get a copy of an existing Sha3
* object.
*/
@Deprecated
public Sha3(Sha3 sha3) {
throw new WolfCryptException(
"Constructor deprecated, use Sha3.clone() to duplicate " +
"Sha3 object");
}
/**
* Create new Sha3 object.
*
* @param data input data to hash
* @param hashType hash type of the Sha3 object
*
* @throws WolfCryptException if SHA-3 has not been compiled into native
* wolfCrypt library.
*/
public Sha3(byte[] data, int hashType) {
if (!FeatureDetect.Sha3Enabled()) {
throw new WolfCryptException(
WolfCryptError.NOT_COMPILED_IN.getCode());
}
/* Internal state is initialized on first use */
this.initialData = data.clone();
sanitizeAndSetHashType(hashType);
}
/**
* Get SHA3 digest size
*
* @return SHA3 digest size
*/
public int digestSize() {
return this.digestSize;
}
@Override
public Object clone() {
Sha3 shaCopy = new Sha3(this.hashType);
/* Initialize NativeStruct, since is done on first use */
shaCopy.checkStateAndInitialize();
shaCopy.native_copy(this);
return shaCopy;
}
}

View File

@ -0,0 +1,377 @@
/* Sha3Test.java
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
package com.wolfssl.wolfcrypt.test;
import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import org.junit.Test;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import com.wolfssl.wolfcrypt.Sha3;
import com.wolfssl.wolfcrypt.NativeStruct;
import com.wolfssl.wolfcrypt.WolfCryptException;
import com.wolfssl.wolfcrypt.WolfCryptError;
public class Sha3Test {
private ByteBuffer data = ByteBuffer.allocateDirect(32);
private ByteBuffer result = ByteBuffer.allocateDirect(Sha3.DIGEST_SIZE_512);
private ByteBuffer expected = ByteBuffer.allocateDirect(Sha3.DIGEST_SIZE_512);
@Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description desc) {
System.out.println("\t" + desc.getMethodName());
}
};
@BeforeClass
public static void checkSha3IsAvailable() {
try {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
System.out.println("JNI Sha3 Class");
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("Sha3Test skipped: " + e.getError());
Assume.assumeTrue(false);
}
}
}
@Test
public void constructorShouldNotInitializeNativeStruct() {
assertEquals(NativeStruct.NULL,
new Sha3(Sha3.TYPE_SHA3_256).getNativeStruct());
}
@Test
public void sha3_256HashShouldMatchUsingByteArray() {
/* Test vectors from NIST FIPS 202 - SHA-3 Standard */
String[] dataVector = new String[] {
"", /* empty string */
"616263", /* "abc" */
/* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
"6162636462636465636465666465666765666768666768696768696A68696A6B" +
"696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"
};
String[] hashVector = new String[] {
/* NIST FIPS 202 A.1 - SHA3-256 Empty Test Vector */
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
/* NIST FIPS 202 A.1 - SHA3-256 abc Test Vector */
"3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
/* NIST FIPS 202 A.1 - SHA3-256 Long Test Vector */
"41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"
};
for (int i = 0; i < dataVector.length; i++) {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
byte[] data = Util.h2b(dataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
sha.update(data);
byte[] result = sha.digest();
assertArrayEquals(expected, result);
}
}
@Test
public void sha3_224HashShouldMatchUsingByteArray() {
/* Test vectors from NIST FIPS 202 - SHA-3 Standard */
String[] dataVector = new String[] {
"", /* empty string */
"616263", /* "abc" */
/* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
"6162636462636465636465666465666765666768666768696768696A68696A6B" +
"696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"
};
String[] hashVector = new String[] {
/* NIST FIPS 202 A.1 - SHA3-224 Empty Test Vector */
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7",
/* NIST FIPS 202 A.1 - SHA3-224 abc Test Vector */
"e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf",
/* NIST FIPS 202 A.1 - SHA3-224 Long Test Vector */
"8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33"
};
for (int i = 0; i < dataVector.length; i++) {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_224);
byte[] data = Util.h2b(dataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
sha.update(data);
byte[] result = sha.digest();
assertArrayEquals(expected, result);
}
}
@Test
public void sha3_384HashShouldMatchUsingByteArray() {
/* Test vectors from NIST FIPS 202 - SHA-3 Standard */
String[] dataVector = new String[] {
"", /* empty string */
"616263", /* "abc" */
/* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
"6162636462636465636465666465666765666768666768696768696A68696A6B" +
"696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"
};
String[] hashVector = new String[] {
/* NIST FIPS 202 A.1 - SHA3-384 Empty Test Vector */
"0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a" +
"c3713831264adb47fb6bd1e058d5f004",
/* NIST FIPS 202 A.1 - SHA3-384 abc Test Vector */
"ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b2" +
"98d88cea927ac7f539f1edf228376d25",
/* NIST FIPS 202 A.1 - SHA3-384 Long Test Vector */
"991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5a" +
"a04a1f076e62fea19eef51acd0657c22"
};
for (int i = 0; i < dataVector.length; i++) {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_384);
byte[] data = Util.h2b(dataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
sha.update(data);
byte[] result = sha.digest();
assertArrayEquals(expected, result);
}
}
@Test
public void sha3_512HashShouldMatchUsingByteArray() {
/* Test vectors from NIST FIPS 202 - SHA-3 Standard */
String[] dataVector = new String[] {
"", /* empty string */
"616263", /* "abc" */
/* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */
"6162636462636465636465666465666765666768666768696768696A68696A6B" +
"696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071"
};
String[] hashVector = new String[] {
/* NIST FIPS 202 A.1 - SHA3-512 Empty Test Vector */
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6" +
"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
/* NIST FIPS 202 A.1 - SHA3-512 abc Test Vector */
"b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e" +
"10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0",
/* NIST FIPS 202 A.1 - SHA3-512 Long Test Vector */
"04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636d" +
"ee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e"
};
for (int i = 0; i < dataVector.length; i++) {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_512);
byte[] data = Util.h2b(dataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
sha.update(data);
byte[] result = sha.digest();
assertArrayEquals(expected, result);
}
}
@Test
public void reuseObject() {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
byte[] data = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 };
byte[] data2 = new byte[] { 0x05, 0x06, 0x07, 0x08, 0x09 };
sha.update(data);
byte[] result = sha.digest();
/* test reusing existing object after a call to digest() */
sha.update(data2);
byte[] result2 = sha.digest();
assertNotNull(result);
assertNotNull(result2);
assertFalse(Arrays.equals(result, result2));
sha.releaseNativeStruct();
}
@Test
public void copyObject() {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
byte[] data = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 };
sha.update(data);
/* test making copy of Sha3, should retain same state */
Sha3 shaCopy = (Sha3)sha.clone();
byte[] result = sha.digest();
byte[] result2 = shaCopy.digest();
assertArrayEquals(result, result2);
sha.releaseNativeStruct();
shaCopy.releaseNativeStruct();
}
@Test
public void threadedHashTest() throws InterruptedException {
int numThreads = 100;
ExecutorService service = Executors.newFixedThreadPool(numThreads);
final CountDownLatch latch = new CountDownLatch(numThreads);
final LinkedBlockingQueue<byte[]> results = new LinkedBlockingQueue<>();
final byte[] rand10kBuf = new byte[10240];
/* fill large input buffer with random bytes */
new Random().nextBytes(rand10kBuf);
/* generate hash over input data concurrently across numThreads */
for (int i = 0; i < numThreads; i++) {
service.submit(new Runnable() {
@Override public void run() {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
/* process/update in 1024-byte chunks */
for (int j = 0; j < rand10kBuf.length; j+= 1024) {
sha.update(rand10kBuf, j, 1024);
}
/* get final hash */
byte[] hash = sha.digest();
results.add(hash.clone());
sha.releaseNativeStruct();
latch.countDown();
}
});
}
/* wait for all threads to complete */
latch.await();
/* compare all digests, all should be the same across threads */
Iterator<byte[]> listIterator = results.iterator();
byte[] current = listIterator.next();
while (listIterator.hasNext()) {
byte[] next = listIterator.next();
if (!Arrays.equals(current, next)) {
fail("Found two non-identical digests in thread test");
}
if (listIterator.hasNext()) {
current = listIterator.next();
}
}
}
@Test
public void blockSizeEdgeCases() {
/* Test vectors for block size edge cases */
int[] sizes = {
136, /* SHA3-224 block size */
104, /* SHA3-256 block size */
72, /* SHA3-384 block size */
72 /* SHA3-512 block size */
};
int[] types = {
Sha3.TYPE_SHA3_224,
Sha3.TYPE_SHA3_256,
Sha3.TYPE_SHA3_384,
Sha3.TYPE_SHA3_512
};
for (int i = 0; i < sizes.length; i++) {
/* Test exactly block size */
byte[] blockData = new byte[sizes[i]];
Arrays.fill(blockData, (byte)0x61); /* fill with 'a' */
Sha3 sha = new Sha3(types[i]);
sha.update(blockData);
byte[] result1 = sha.digest();
/* Test one byte less than block size */
byte[] underData = new byte[sizes[i] - 1];
Arrays.fill(underData, (byte)0x61);
sha = new Sha3(types[i]);
sha.update(underData);
byte[] result2 = sha.digest();
/* Test one byte more than block size */
byte[] overData = new byte[sizes[i] + 1];
Arrays.fill(overData, (byte)0x61);
sha = new Sha3(types[i]);
sha.update(overData);
byte[] result3 = sha.digest();
/* Results should all be different */
assertFalse(Arrays.equals(result1, result2));
assertFalse(Arrays.equals(result2, result3));
assertFalse(Arrays.equals(result1, result3));
}
}
@Test
public void streamingUpdates() {
/* Test streaming updates with known test vector */
String input =
"6162636462636465636465666465666765666768666768696768696A68696A6B" +
"696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071";
String expected =
"41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376";
byte[] data = Util.h2b(input);
/* Test different chunk sizes */
int[] chunks = {1, 3, 7, 13, 17, 32, 64};
for (int chunkSize : chunks) {
Sha3 sha = new Sha3(Sha3.TYPE_SHA3_256);
/* Update in chunks */
for (int i = 0; i < data.length; i += chunkSize) {
int len = Math.min(chunkSize, data.length - i);
sha.update(data, i, len);
}
byte[] result = sha.digest();
assertArrayEquals(Util.h2b(expected), result);
}
}
}

View File

@ -37,6 +37,7 @@ import org.junit.runners.Suite.SuiteClasses;
Sha256Test.class,
Sha384Test.class,
Sha512Test.class,
Sha3Test.class,
HmacTest.class,
RngTest.class,
RsaTest.class,