Merge pull request #103 from cconlon/sha3

Add SHA-3 support to `MessageDigest`, `Mac`, and `Signature` services
pull/105/head
JacobBarthelmeh 2025-03-05 16:02:20 -07:00 committed by GitHub
commit ced95bac53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 3090 additions and 124 deletions

View File

@ -92,6 +92,10 @@ The JCE provider currently supports the following algorithms:
SHA-256
SHA-384
SHA-512
SHA3-224
SHA3-256
SHA3-384
SHA3-512
SecureRandom Class
DEFAULT (maps to HashDRBG)
@ -112,6 +116,10 @@ The JCE provider currently supports the following algorithms:
HmacSHA256
HmacSHA384
HmacSHA512
HmacSHA3-224
HmacSHA3-256
HmacSHA3-384
HmacSHA3-512
Signature Class
MD5withRSA
@ -120,11 +128,19 @@ The JCE provider currently supports the following algorithms:
SHA256withRSA
SHA384withRSA
SHA512withRSA
SHA3-224withRSA
SHA3-256withRSA
SHA3-384withRSA
SHA3-512withRSA
SHA1withECDSA
SHA224withECDSA
SHA256withECDSA
SHA384withECDSA
SHA512withECDSA
SHA3-224withECDSA
SHA3-256withECDSA
SHA3-384withECDSA
SHA3-512withECDSA
KeyAgreement Class
DiffieHellman

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

@ -113,6 +113,38 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha512
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeBlake2b
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha3_224
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1224
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha3_256
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1256
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha3_384
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1384
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: getCodeSha3_512
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1512
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Hmac
* Method: mallocNativeStruct

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

@ -65,7 +65,9 @@
static WC_INLINE int GetHashSizeByType(int type)
{
if (!(type == WC_MD5 || type == WC_SHA || type == WC_SHA224
|| type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512)) {
|| type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512
|| type == WC_SHA3_224 || type == WC_SHA3_256 || type == WC_SHA3_384
|| type == WC_SHA3_512)) {
return BAD_FUNC_ARG;
}
@ -100,14 +102,27 @@ static WC_INLINE int GetHashSizeByType(int type)
return SHA512_DIGEST_SIZE;
#endif
#if defined(WOLFSSL_SHA3)
case WC_SHA3_224:
return WC_SHA3_224_DIGEST_SIZE;
case WC_SHA3_256:
return WC_SHA3_256_DIGEST_SIZE;
case WC_SHA3_384:
return WC_SHA3_384_DIGEST_SIZE;
case WC_SHA3_512:
return WC_SHA3_512_DIGEST_SIZE;
#endif
default:
return BAD_FUNC_ARG;
}
}
JNIEXPORT jlong JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_mallocNativeStruct(
JNIEnv* env, jobject this)
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Hmac_mallocNativeStruct
(JNIEnv* env, jobject this)
{
#ifndef NO_HMAC
Hmac* hmac = NULL;
@ -131,9 +146,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_mallocNativeStruct(
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSetKey(
JNIEnv* env, jobject this, jint type, jbyteArray key_object)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSetKey
(JNIEnv* env, jobject this, jint type, jbyteArray key_object)
{
#ifndef NO_HMAC
int ret = 0;
@ -165,9 +179,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSetKey(
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__B(
JNIEnv* env, jobject this, jbyte data)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__B
(JNIEnv* env, jobject this, jbyte data)
{
#ifndef NO_HMAC
int ret = 0;
@ -191,9 +204,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__B(
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate___3BII(
JNIEnv* env, jobject this, jbyteArray data_object, jint offset, jint length)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate___3BII
(JNIEnv* env, jobject this, jbyteArray data_object, jint offset, jint length)
{
#ifndef NO_HMAC
int ret = 0;
@ -225,9 +237,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate___3BII(
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__Ljava_nio_ByteBuffer_2II(
JNIEnv* env, jobject this, jobject data_object, jint offset, jint length)
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__Ljava_nio_ByteBuffer_2II
(JNIEnv* env, jobject this, jobject data_object, jint offset, jint length)
{
#ifndef NO_HMAC
int ret = 0;
@ -257,9 +268,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__Ljava_nio_ByteBuffer_2II(
#endif
}
JNIEXPORT jbyteArray JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacFinal(
JNIEnv* env, jobject this)
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacFinal
(JNIEnv* env, jobject this)
{
jbyteArray result = NULL;
@ -308,9 +318,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacFinal(
return result;
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSizeByType(
JNIEnv* env, jobject this, jint type)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSizeByType
(JNIEnv* env, jobject this, jint type)
{
jint result = 0;
@ -330,9 +339,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSizeByType(
return result;
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeMd5(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeMd5
(JNIEnv* env, jobject this)
{
#ifndef NO_MD5
jint result = WC_MD5;
@ -344,9 +352,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeMd5(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha
(JNIEnv* env, jobject this)
{
#ifndef NO_SHA
jint result = WC_SHA;
@ -358,9 +365,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha224(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha224
(JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA224
jint result = WC_SHA224;
@ -372,9 +378,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha224(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha256(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha256
(JNIEnv* env, jobject this)
{
#ifndef NO_SHA256
jint result = WC_SHA256;
@ -386,9 +391,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha256(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha384(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha384
(JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA384
jint result = WC_SHA384;
@ -400,9 +404,8 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha384(
#endif
}
JNIEXPORT jint JNICALL
Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha512(
JNIEnv* env, jobject this)
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha512
(JNIEnv* env, jobject this)
{
#ifdef WOLFSSL_SHA512
jint result = WC_SHA512;
@ -414,3 +417,55 @@ Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha512(
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1224
(JNIEnv* env, jclass this)
{
#ifdef WOLFSSL_SHA3
jint result = WC_SHA3_224;
LogStr("WC_SHA3_224 = %d\n", result);
return result;
#else
/* not compiled in */
return (jint) -1;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1256
(JNIEnv* env, jclass this)
{
#ifdef WOLFSSL_SHA3
jint result = WC_SHA3_256;
LogStr("WC_SHA3_256 = %d\n", result);
return result;
#else
/* not compiled in */
return (jint) -1;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1384
(JNIEnv* env, jclass this)
{
#ifdef WOLFSSL_SHA3
jint result = WC_SHA3_384;
LogStr("WC_SHA3_384 = %d\n", result);
return result;
#else
/* not compiled in */
return (jint) -1;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1512
(JNIEnv* env, jclass this)
{
#ifdef WOLFSSL_SHA3
jint result = WC_SHA3_512;
LogStr("WC_SHA3_512 = %d\n", result);
return result;
#else
/* not compiled in */
return (jint) -1;
#endif
}

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>
@ -308,7 +309,7 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1update_1internal___3BII(
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
@ -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 || offset < 0 || len < 0 ||
(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)
@ -503,7 +735,7 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1update_1internal___3BII(
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
@ -698,7 +930,7 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1update_1internal___3BII(
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
@ -894,7 +1126,7 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1update_1internal___3BII(
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(word32)(offset + len) > dataSz) {
ret = BAD_FUNC_ARG;
}
@ -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;
@ -1104,20 +1414,37 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna
data = getByteArray(env, data_buffer);
dataSz = getByteArrayLength(env, data_buffer);
if (sha == NULL || data == NULL ||
if (sha == NULL || data == NULL || offset < 0 || len < 0 ||
(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

@ -35,6 +35,7 @@ import com.wolfssl.wolfcrypt.Sha224;
import com.wolfssl.wolfcrypt.Sha256;
import com.wolfssl.wolfcrypt.Sha384;
import com.wolfssl.wolfcrypt.Sha512;
import com.wolfssl.wolfcrypt.Sha3;
import com.wolfssl.wolfcrypt.Hmac;
/**
@ -48,7 +49,11 @@ public class WolfCryptMac extends MacSpi {
WC_HMAC_SHA224,
WC_HMAC_SHA256,
WC_HMAC_SHA384,
WC_HMAC_SHA512
WC_HMAC_SHA512,
WC_HMAC_SHA3_224,
WC_HMAC_SHA3_256,
WC_HMAC_SHA3_384,
WC_HMAC_SHA3_512
}
private Hmac hmac = null;
@ -94,6 +99,26 @@ public class WolfCryptMac extends MacSpi {
this.nativeHmacType = Hmac.SHA512;
break;
case WC_HMAC_SHA3_224:
this.digestSize = Sha3.DIGEST_SIZE_224;
this.nativeHmacType = Hmac.SHA3_224;
break;
case WC_HMAC_SHA3_256:
this.digestSize = Sha3.DIGEST_SIZE_256;
this.nativeHmacType = Hmac.SHA3_256;
break;
case WC_HMAC_SHA3_384:
this.digestSize = Sha3.DIGEST_SIZE_384;
this.nativeHmacType = Hmac.SHA3_384;
break;
case WC_HMAC_SHA3_512:
this.digestSize = Sha3.DIGEST_SIZE_512;
this.nativeHmacType = Hmac.SHA3_512;
break;
default:
throw new NoSuchAlgorithmException(
"Unsupported HMAC type");
@ -178,6 +203,12 @@ public class WolfCryptMac extends MacSpi {
return "SHA384";
case WC_HMAC_SHA512:
return "SHA512";
case WC_HMAC_SHA3_224:
return "SHA3-224";
case WC_HMAC_SHA3_256:
return "SHA3-256";
case WC_HMAC_SHA3_384:
return "SHA3-384";
default:
return "None";
}
@ -287,5 +318,64 @@ public class WolfCryptMac extends MacSpi {
super(HmacType.WC_HMAC_SHA512);
}
}
}
/**
* wolfJCE HMAC-SHA3-224 class
*/
public static final class wcHmacSHA3_224 extends WolfCryptMac {
/**
* Create new wcHmacSHA3_224 object
*
* @throws NoSuchAlgorithmException if HMAC-SHA3-224 is not available at
* native wolfCrypt level.
*/
public wcHmacSHA3_224() throws NoSuchAlgorithmException {
super(HmacType.WC_HMAC_SHA3_224);
}
}
/**
* wolfJCE HMAC-SHA3-256 class
*/
public static final class wcHmacSHA3_256 extends WolfCryptMac {
/**
* Create new wcHmacSHA3_256 object
*
* @throws NoSuchAlgorithmException if HMAC-SHA3-256 is not available at
* native wolfCrypt level.
*/
public wcHmacSHA3_256() throws NoSuchAlgorithmException {
super(HmacType.WC_HMAC_SHA3_256);
}
}
/**
* wolfJCE HMAC-SHA3-384 class
*/
public static final class wcHmacSHA3_384 extends WolfCryptMac {
/**
* Create new wcHmacSHA3_384 object
*
* @throws NoSuchAlgorithmException if HMAC-SHA3-384 is not available at
* native wolfCrypt level.
*/
public wcHmacSHA3_384() throws NoSuchAlgorithmException {
super(HmacType.WC_HMAC_SHA3_384);
}
}
/**
* wolfJCE HMAC-SHA3-512 class
*/
public static final class wcHmacSHA3_512 extends WolfCryptMac {
/**
* Create new wcHmacSHA3_512 object
*
* @throws NoSuchAlgorithmException if HMAC-SHA3-512 is not available at
* native wolfCrypt level.
*/
public wcHmacSHA3_512() throws NoSuchAlgorithmException {
super(HmacType.WC_HMAC_SHA3_512);
}
}
}

View File

@ -0,0 +1,199 @@
/* WolfCryptMessageDigestSha3.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.provider.jce;
import java.security.MessageDigestSpi;
import java.security.NoSuchAlgorithmException;
import javax.crypto.ShortBufferException;
import com.wolfssl.wolfcrypt.Sha3;
import com.wolfssl.wolfcrypt.WolfCryptException;
/**
* wolfCrypt JCE SHA-3 MessageDigest wrapper
*/
public class WolfCryptMessageDigestSha3
extends MessageDigestSpi implements Cloneable {
/* internal reference to wolfCrypt JNI Sha object */
private Sha3 sha;
/**
* Create new WolfCryptMessageDigestSha3 object
*
* @param hashType hash type to be used with this MessageDigest
* @throws NoSuchAlgorithmException if digest type is not
* available in native wolfCrypt library
*/
public WolfCryptMessageDigestSha3(int hashType)
throws NoSuchAlgorithmException {
try {
sha = new Sha3(hashType);
sha.init();
} catch (WolfCryptException e) {
throw new NoSuchAlgorithmException(e.getMessage());
}
}
/**
* Create new WolfCryptMessageDigestSha3 based on existing Sha3 object.
* Existing object should already be initialized.
*
* @param sha initialized Sha3 object to be used with this MessageDigest
*/
private WolfCryptMessageDigestSha3(Sha3 sha) {
this.sha = sha;
}
@Override
protected byte[] engineDigest() {
byte[] digest = new byte[sha.digestSize()];
try {
this.sha.digest(digest);
} catch (ShortBufferException e) {
throw new RuntimeException(e.getMessage());
}
log("generated final digest, len: " + digest.length);
return digest;
}
@Override
protected void engineReset() {
this.sha.init();
log("engine reset");
}
@Override
protected void engineUpdate(byte input) {
byte[] tmp = new byte[1];
tmp[0] = input;
this.sha.update(tmp, 1);
log("update with single byte");
}
@Override
protected void engineUpdate(byte[] input, int offset, int len) {
this.sha.update(input, offset, len);
log("update, offset: " + offset + ", len: " + len);
}
@Override
protected int engineGetDigestLength() {
return this.sha.digestSize();
}
private void log(String msg) {
WolfCryptDebug.print("[MessageDigest, SHA-3] " + msg);
}
@Override
public Object clone() {
Sha3 shaCopy = (Sha3)this.sha.clone();
return new WolfCryptMessageDigestSha3(shaCopy);
}
@SuppressWarnings("deprecation")
@Override
protected void finalize() throws Throwable {
try {
if (this.sha != null)
this.sha.releaseNativeStruct();
} finally {
super.finalize();
}
}
/**
* wolfJCE SHA1wECDSA message digest class
*/
public static final class wcSHA3_224 extends WolfCryptMessageDigestSha3 {
/**
* Create new wcSHA3_224 object
*
* @throws NoSuchAlgorithmException if digest type is not
* available in native wolfCrypt library
*/
public wcSHA3_224() throws NoSuchAlgorithmException {
super(Sha3.TYPE_SHA3_224);
}
}
/**
* wolfJCE SHA3-256 message digest class
*/
public static final class wcSHA3_256 extends WolfCryptMessageDigestSha3 {
/**
* Create new wcSHA3_256 object
*
* @throws NoSuchAlgorithmException if digest type is not
* available in native wolfCrypt library
*/
public wcSHA3_256() throws NoSuchAlgorithmException {
super(Sha3.TYPE_SHA3_256);
}
}
/**
* wolfJCE SHA3-384 message digest class
*/
public static final class wcSHA3_384 extends WolfCryptMessageDigestSha3 {
/**
* Create new wcSHA3_384 object
*
* @throws NoSuchAlgorithmException if digest type is not
* available in native wolfCrypt library
*/
public wcSHA3_384() throws NoSuchAlgorithmException {
super(Sha3.TYPE_SHA3_384);
}
}
/**
* wolfJCE SHA3-512 message digest class
*/
public static final class wcSHA3_512 extends WolfCryptMessageDigestSha3 {
/**
* Create new wcSHA3_512 object
*
* @throws NoSuchAlgorithmException if digest type is not
* available in native wolfCrypt library
*/
public wcSHA3_512() throws NoSuchAlgorithmException {
super(Sha3.TYPE_SHA3_512);
}
}
}

View File

@ -94,6 +94,16 @@ public final class WolfCryptProvider extends Provider {
put("MessageDigest.SHA-512",
"com.wolfssl.provider.jce.WolfCryptMessageDigestSha512");
}
if (FeatureDetect.Sha3Enabled()) {
put("MessageDigest.SHA3-224",
"com.wolfssl.provider.jce.WolfCryptMessageDigestSha3$wcSHA3_224");
put("MessageDigest.SHA3-256",
"com.wolfssl.provider.jce.WolfCryptMessageDigestSha3$wcSHA3_256");
put("MessageDigest.SHA3-384",
"com.wolfssl.provider.jce.WolfCryptMessageDigestSha3$wcSHA3_384");
put("MessageDigest.SHA3-512",
"com.wolfssl.provider.jce.WolfCryptMessageDigestSha3$wcSHA3_512");
}
/* SecureRandom */
/* TODO: May need to add "SHA1PRNG" alias, other JCA consumemrs may
@ -138,6 +148,25 @@ public final class WolfCryptProvider extends Provider {
put("Signature.SHA512withECDSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA512wECDSA");
}
if (FeatureDetect.Sha3Enabled()) {
put("Signature.SHA3-224withRSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_224wRSA");
put("Signature.SHA3-256withRSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_256wRSA");
put("Signature.SHA3-384withRSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_384wRSA");
put("Signature.SHA3-512withRSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_512wRSA");
put("Signature.SHA3-224withECDSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_224wECDSA");
put("Signature.SHA3-256withECDSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_256wECDSA");
put("Signature.SHA3-384withECDSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_384wECDSA");
put("Signature.SHA3-512withECDSA",
"com.wolfssl.provider.jce.WolfCryptSignature$wcSHA3_512wECDSA");
}
/* Mac */
if (FeatureDetect.HmacMd5Enabled()) {
@ -164,6 +193,22 @@ public final class WolfCryptProvider extends Provider {
put("Mac.HmacSHA512",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA512");
}
if (FeatureDetect.HmacSha3_224Enabled()) {
put("Mac.HmacSHA3-224",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA3_224");
}
if (FeatureDetect.HmacSha3_256Enabled()) {
put("Mac.HmacSHA3-256",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA3_256");
}
if (FeatureDetect.HmacSha3_384Enabled()) {
put("Mac.HmacSHA3-384",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA3_384");
}
if (FeatureDetect.HmacSha3_512Enabled()) {
put("Mac.HmacSHA3-512",
"com.wolfssl.provider.jce.WolfCryptMac$wcHmacSHA3_512");
}
/* Cipher */
if (FeatureDetect.AesCbcEnabled()) {

View File

@ -43,6 +43,7 @@ import com.wolfssl.wolfcrypt.Sha224;
import com.wolfssl.wolfcrypt.Sha256;
import com.wolfssl.wolfcrypt.Sha384;
import com.wolfssl.wolfcrypt.Sha512;
import com.wolfssl.wolfcrypt.Sha3;
import com.wolfssl.wolfcrypt.Rsa;
import com.wolfssl.wolfcrypt.Ecc;
import com.wolfssl.wolfcrypt.Rng;
@ -64,7 +65,11 @@ public class WolfCryptSignature extends SignatureSpi {
WC_SHA224,
WC_SHA256,
WC_SHA384,
WC_SHA512
WC_SHA512,
WC_SHA3_224,
WC_SHA3_256,
WC_SHA3_384,
WC_SHA3_512
}
/* internal hash type sums (asn.h) */
@ -74,6 +79,10 @@ public class WolfCryptSignature extends SignatureSpi {
private int SHA256h = 414;
private int SHA384h = 415;
private int SHA512h = 416;
private int SHA3_224h = 420;
private int SHA3_256h = 421;
private int SHA3_384h = 422;
private int SHA3_512h = 423;
/* internal key objects */
private Rsa rsa = null;
@ -86,6 +95,7 @@ public class WolfCryptSignature extends SignatureSpi {
private Sha256 sha256 = null;
private Sha384 sha384 = null;
private Sha512 sha512 = null;
private Sha3 sha3 = null;
private KeyType keyType; /* active key type, from KeyType */
private DigestType digestType; /* active digest type, from DigestType */
@ -155,6 +165,30 @@ public class WolfCryptSignature extends SignatureSpi {
this.internalHashSum = SHA512h;
break;
case WC_SHA3_224:
this.sha3 = new Sha3(Sha3.TYPE_SHA3_224);
this.digestSz = Sha3.DIGEST_SIZE_224;
this.internalHashSum = SHA3_224h;
break;
case WC_SHA3_256:
this.sha3 = new Sha3(Sha3.TYPE_SHA3_256);
this.digestSz = Sha3.DIGEST_SIZE_256;
this.internalHashSum = SHA3_256h;
break;
case WC_SHA3_384:
this.sha3 = new Sha3(Sha3.TYPE_SHA3_384);
this.digestSz = Sha3.DIGEST_SIZE_384;
this.internalHashSum = SHA3_384h;
break;
case WC_SHA3_512:
this.sha3 = new Sha3(Sha3.TYPE_SHA3_512);
this.digestSz = Sha3.DIGEST_SIZE_512;
this.internalHashSum = SHA3_512h;
break;
default:
throw new NoSuchAlgorithmException(
"Unsupported signature algorithm digest type");
@ -280,6 +314,13 @@ public class WolfCryptSignature extends SignatureSpi {
case WC_SHA512:
this.sha512.init();
break;
case WC_SHA3_224:
case WC_SHA3_256:
case WC_SHA3_384:
case WC_SHA3_512:
this.sha3.init();
break;
}
log("init sign with PrivateKey");
@ -350,6 +391,12 @@ public class WolfCryptSignature extends SignatureSpi {
case WC_SHA512:
this.sha512.init();
break;
case WC_SHA3_224:
case WC_SHA3_256:
case WC_SHA3_384:
case WC_SHA3_512:
this.sha3.init();
}
log("init verify with PublicKey");
@ -399,8 +446,14 @@ public class WolfCryptSignature extends SignatureSpi {
case WC_SHA512:
this.sha512.digest(digest);
break;
}
case WC_SHA3_224:
case WC_SHA3_256:
case WC_SHA3_384:
case WC_SHA3_512:
this.sha3.digest(digest);
break;
}
} catch (ShortBufferException e) {
throw new SignatureException(e.getMessage());
}
@ -489,6 +542,12 @@ public class WolfCryptSignature extends SignatureSpi {
case WC_SHA512:
this.sha512.update(b, off, len);
break;
case WC_SHA3_224:
case WC_SHA3_256:
case WC_SHA3_384:
case WC_SHA3_512:
this.sha3.update(b, off, len);
}
log("update, offset: " + off + ", len: " + len);
@ -531,6 +590,13 @@ public class WolfCryptSignature extends SignatureSpi {
case WC_SHA512:
this.sha512.digest(digest);
break;
case WC_SHA3_224:
case WC_SHA3_256:
case WC_SHA3_384:
case WC_SHA3_512:
this.sha3.digest(digest);
break;
}
} catch (ShortBufferException e) {
@ -619,6 +685,14 @@ public class WolfCryptSignature extends SignatureSpi {
return "SHA384";
case WC_SHA512:
return "SHA512";
case WC_SHA3_224:
return "SHA3-224";
case WC_SHA3_256:
return "SHA3-256";
case WC_SHA3_384:
return "SHA3-384";
case WC_SHA3_512:
return "SHA3-512";
default:
return "None";
}
@ -652,6 +726,9 @@ public class WolfCryptSignature extends SignatureSpi {
if (this.sha512 != null)
this.sha512.releaseNativeStruct();
if (this.sha3 != null)
this.sha3.releaseNativeStruct();
/* free native key objects */
if (this.rsa != null)
this.rsa.releaseNativeStruct();
@ -763,6 +840,66 @@ public class WolfCryptSignature extends SignatureSpi {
}
}
/**
* wolfJCE SHA3-224wRSA signature class
*/
public static final class wcSHA3_224wRSA extends WolfCryptSignature {
/**
* Create new wcSHA3_224wRSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_224wRSA() throws NoSuchAlgorithmException {
super(KeyType.WC_RSA, DigestType.WC_SHA3_224);
}
}
/**
* wolfJCE SHA3-256wRSA signature class
*/
public static final class wcSHA3_256wRSA extends WolfCryptSignature {
/**
* Create new wcSHA3_256wRSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_256wRSA() throws NoSuchAlgorithmException {
super(KeyType.WC_RSA, DigestType.WC_SHA3_256);
}
}
/**
* wolfJCE SHA3-384wRSA signature class
*/
public static final class wcSHA3_384wRSA extends WolfCryptSignature {
/**
* Create new wcSHA3_384wRSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_384wRSA() throws NoSuchAlgorithmException {
super(KeyType.WC_RSA, DigestType.WC_SHA3_384);
}
}
/**
* wolfJCE SHA3-512wRSA signature class
*/
public static final class wcSHA3_512wRSA extends WolfCryptSignature {
/**
* Create new wcSHA3_512wRSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_512wRSA() throws NoSuchAlgorithmException {
super(KeyType.WC_RSA, DigestType.WC_SHA3_512);
}
}
/**
* wolfJCE SHA1wECDSA signature class
*/
@ -837,5 +974,64 @@ public class WolfCryptSignature extends SignatureSpi {
super(KeyType.WC_ECDSA, DigestType.WC_SHA512);
}
}
}
/**
* wolfJCE SHA3-224wECDSA signature class
*/
public static final class wcSHA3_224wECDSA extends WolfCryptSignature {
/**
* Create new wcSHA3_224wECDSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_224wECDSA() throws NoSuchAlgorithmException {
super(KeyType.WC_ECDSA, DigestType.WC_SHA3_224);
}
}
/**
* wolfJCE SHA3-256wECDSA signature class
*/
public static final class wcSHA3_256wECDSA extends WolfCryptSignature {
/**
* Create new wcSHA3_256wECDSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_256wECDSA() throws NoSuchAlgorithmException {
super(KeyType.WC_ECDSA, DigestType.WC_SHA3_256);
}
}
/**
* wolfJCE SHA3-384wECDSA signature class
*/
public static final class wcSHA3_384wECDSA extends WolfCryptSignature {
/**
* Create new wcSHA3_384wECDSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_384wECDSA() throws NoSuchAlgorithmException {
super(KeyType.WC_ECDSA, DigestType.WC_SHA3_384);
}
}
/**
* wolfJCE SHA3-512wECDSA signature class
*/
public static final class wcSHA3_512wECDSA extends WolfCryptSignature {
/**
* Create new wcSHA3_512wECDSA object
*
* @throws NoSuchAlgorithmException if signature type is not
* available in native wolfCrypt library
*/
public wcSHA3_512wECDSA() throws NoSuchAlgorithmException {
super(KeyType.WC_ECDSA, DigestType.WC_SHA3_512);
}
}
}

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

@ -29,7 +29,8 @@ import java.nio.ByteBuffer;
public class Hmac extends NativeStruct {
private enum hashType {
typeMD5, typeSHA, typeSHA224, typeSHA256, typeSHA384, typeSHA512;
typeMD5, typeSHA, typeSHA224, typeSHA256, typeSHA384, typeSHA512,
typeSHA3_224, typeSHA3_256, typeSHA3_384, typeSHA3_512;
}
/* types may be -1 if not compiled in at native level */
@ -45,6 +46,14 @@ public class Hmac extends NativeStruct {
public static final int SHA384 = getHashCode(hashType.typeSHA384);
/** HMAC-SHA2-512 type */
public static final int SHA512 = getHashCode(hashType.typeSHA512);
/** HMAC-SHA3-224 type */
public static final int SHA3_224 = getHashCode(hashType.typeSHA3_224);
/** HMAC-SHA3-256 type */
public static final int SHA3_256 = getHashCode(hashType.typeSHA3_256);
/** HMAC-SHA3-384 type */
public static final int SHA3_384 = getHashCode(hashType.typeSHA3_384);
/** HMAC-SHA3-512 type */
public static final int SHA3_512 = getHashCode(hashType.typeSHA3_512);
private WolfCryptState state = WolfCryptState.UNINITIALIZED;
private int type = -1;
@ -102,6 +111,10 @@ public class Hmac extends NativeStruct {
private native static int getCodeSha384();
private native static int getCodeSha512();
private native static int getCodeBlake2b();
private native static int getCodeSha3_224();
private native static int getCodeSha3_256();
private native static int getCodeSha3_384();
private native static int getCodeSha3_512();
/**
* Malloc native JNI Hmac structure
@ -333,6 +346,18 @@ public class Hmac extends NativeStruct {
else if (type == SHA512) {
return "HmacSHA512";
}
else if (type == SHA3_224) {
return "HmacSHA3-224";
}
else if (type == SHA3_256) {
return "HmacSHA3-256";
}
else if (type == SHA3_384) {
return "HmacSHA3-384";
}
else if (type == SHA3_512) {
return "HmacSHA3-512";
}
else {
return "";
}
@ -373,6 +398,14 @@ public class Hmac extends NativeStruct {
return getCodeSha384();
case typeSHA512:
return getCodeSha512();
case typeSHA3_224:
return getCodeSha3_224();
case typeSHA3_256:
return getCodeSha3_256();
case typeSHA3_384:
return getCodeSha3_384();
case typeSHA3_512:
return getCodeSha3_512();
default:
return WolfCrypt.FAILURE;
}

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

@ -49,6 +49,7 @@ import java.security.InvalidKeyException;
import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.provider.jce.WolfCryptProvider;
import com.wolfssl.wolfcrypt.test.Util;
public class WolfCryptMacTest {
@ -58,7 +59,11 @@ public class WolfCryptMacTest {
"HmacSHA224",
"HmacSHA256",
"HmacSHA384",
"HmacSHA512"
"HmacSHA512",
"HmacSHA3-224",
"HmacSHA3-256",
"HmacSHA3-384",
"HmacSHA3-512"
};
private static ArrayList<String> enabledAlgos =
@ -71,6 +76,10 @@ public class WolfCryptMacTest {
28,
32,
48,
64,
28,
32,
48,
64
};
@ -88,8 +97,6 @@ public class WolfCryptMacTest {
public static void testProviderInstallationAtRuntime()
throws NoSuchProviderException {
Mac mac;
System.out.println("JCE WolfCryptMac Class");
/* install wolfJCE provider at runtime */
@ -102,7 +109,7 @@ public class WolfCryptMacTest {
* compiled out */
for (int i = 0; i < wolfJCEAlgos.length; i++) {
try {
mac = Mac.getInstance(wolfJCEAlgos[i], "wolfJCE");
Mac mac = Mac.getInstance(wolfJCEAlgos[i], "wolfJCE");
assertNotNull(mac);
enabledAlgos.add(wolfJCEAlgos[i]);
enabledAlgoLengths.add(wolfJCEMacLengths[i]);
@ -116,17 +123,15 @@ public class WolfCryptMacTest {
public void testGetMacFromProvider()
throws NoSuchProviderException, NoSuchAlgorithmException {
Mac mac;
/* try to get all available options we expect to have */
for (int i = 0; i < enabledAlgos.size(); i++) {
mac = Mac.getInstance(enabledAlgos.get(i), "wolfJCE");
Mac mac = Mac.getInstance(enabledAlgos.get(i), "wolfJCE");
assertNotNull(mac);
}
/* getting a garbage algorithm should throw an exception */
try {
mac = Mac.getInstance("NotValid", "wolfJCE");
Mac.getInstance("NotValid", "wolfJCE");
fail("Mac.getInstance should throw NoSuchAlgorithmException " +
"when given bad algorithm value");
@ -820,7 +825,8 @@ public class WolfCryptMacTest {
new SecretKeySpec(vectors[i].getKey(), "SHA512");
try {
Mac mac = Mac.getInstance("HmacSHA512", "wolfJCE");
Mac mac =
Mac.getInstance("HmacSHA512", "wolfJCE");
mac.init(keyspec);
mac.update(vectors[i].getInput());
@ -836,6 +842,201 @@ public class WolfCryptMacTest {
}
}
/**
* Shared SHA-3 test key and data vectors.
*/
static final String[] sha3KeyVector = new String[] {
"4A656665", /* Jefe */
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708"
};
static final String[] sha3DataVector = new String[] {
/* what do ya want for nothing? */
"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
/* Hi There */
"4869205468657265",
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd",
/* Big Key Input */
"426967204b657920496e707574"
};
@Test
public void testMacSha3_224SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException {
String[] hashVector = new String[] {
"7fdb8dd88bd2f60d1b798634ad386811" +
"c2cfc85bfaf5d52bbace5e66",
"3b16546bbc7be2706a031dcafd56373d" +
"9884367641d8c59af3c860f7",
"676cfc7d16153638780390692be142d2" +
"df7ce924b909c0c08dbfdc1a",
"29e05e46c4a45e4674bfd72d1ad866db" +
"2d0d104e2bfaad537d15698b"
};
if (!enabledAlgos.contains("HmacSHA3-224")) {
return;
}
Mac mac = Mac.getInstance("HmacSHA3-224", "wolfJCE");
for (int i = 0; i < hashVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
SecretKeySpec key = new SecretKeySpec(
Util.h2b(sha3KeyVector[i]), "HmacSHA3-224");
mac.init(key);
mac.update(Util.h2b(sha3DataVector[i]));
byte[] result = mac.doFinal();
assertArrayEquals(Util.h2b(hashVector[i]), result);
}
}
@Test
public void testMacSha3_256SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException {
String[] hashVector = new String[] {
"c7d4072e788877ae3596bbb0da73b887" +
"c9171f93095b294ae857fbe2645e1ba5",
"ba85192310dffa96e2a3a40e69774351" +
"140bb7185e1202cdcc917589f95e16bb",
"84ec79124a27107865cedd8bd82da996" +
"5e5ed8c37b0ac98005a7f39ed58a4207",
"b55b8d64b69c21d0bf205ca2f7b9b14e" +
"8821612c66c391ae6c95168583e6f49b"
};
if (!enabledAlgos.contains("HmacSHA3-256")) {
return;
}
Mac mac = Mac.getInstance("HmacSHA3-256", "wolfJCE");
for (int i = 0; i < hashVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
SecretKeySpec key = new SecretKeySpec(
Util.h2b(sha3KeyVector[i]), "HmacSHA3-256");
mac.init(key);
mac.update(Util.h2b(sha3DataVector[i]));
byte[] result = mac.doFinal();
assertArrayEquals(Util.h2b(hashVector[i]), result);
}
}
@Test
public void testMacSha3_384SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException {
String[] hashVector = new String[] {
"f1101f8cbf9766fd6764d2ed61903f21" +
"ca9b18f57cf3e1a23ca13508a93243ce" +
"48c045dc007f26a21b3f5e0e9df4c20a",
"68d2dcf7fd4ddd0a2240c8a437305f61" +
"fb7334cfb5d0226e1bc27dc10a2e723a" +
"20d370b47743130e26ac7e3d532886bd",
"275cd0e661bb8b151c64d288f1f782fb" +
"91a8abd56858d72babb2d476f0458373" +
"b41b6ab5bf174bec422e53fc3135ac6e",
"aa91b3a62f56a1be8c3e7438db58d9d3" +
"34dea0606d8d46e0eca9f6063514e6ed" +
"83e67c77246c11b59082b575da7b832d"
};
if (!enabledAlgos.contains("HmacSHA3-384")) {
return;
}
Mac mac = Mac.getInstance("HmacSHA3-384", "wolfJCE");
for (int i = 0; i < hashVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
SecretKeySpec key = new SecretKeySpec(
Util.h2b(sha3KeyVector[i]), "HmacSHA3-384");
mac.init(key);
mac.update(Util.h2b(sha3DataVector[i]));
byte[] result = mac.doFinal();
assertArrayEquals(Util.h2b(hashVector[i]), result);
}
}
@Test
public void testMacSha3_512SingleUpdate()
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException {
String[] hashVector = new String[] {
"5a4bfeab6166427c7a3647b747292b83" +
"84537cdb89afb3bf5665e4c5e709350b" +
"287baec921fd7ca0ee7a0c31d022a95e" +
"1fc92ba9d77df883960275beb4e62024",
"eb3fbd4b2eaab8f5c504bd3a41465aac" +
"ec15770a7cabac531e482f860b5ec7ba" +
"47ccb2c6f2afce8f88d22b6dc61380f2" +
"3a668fd3888bb80537c0a0b86407689e",
"309e99f9ec075ec6c6d475eda1180687" +
"fcf1531195802a99b5677449a8625182" +
"851cb332afb6a89c411325fbcbcd42af" +
"cb7b6e5aab7ea42c660f97fd8584bf03",
"1cc3a9244a4a3fbdc72000169b794703" +
"78752cb5f12e627cbeef4e8f0b112b32" +
"a0eec9d04d64640b37f4dd66f78bb3ad" +
"52526b6512de0d7cc08b60016c37d7a8"
};
if (!enabledAlgos.contains("HmacSHA3-512")) {
return;
}
Mac mac = Mac.getInstance("HmacSHA3-512", "wolfJCE");
for (int i = 0; i < hashVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
SecretKeySpec key = new SecretKeySpec(
Util.h2b(sha3KeyVector[i]), "HmacSHA3-512");
mac.init(key);
mac.update(Util.h2b(sha3DataVector[i]));
byte[] result = mac.doFinal();
assertArrayEquals(Util.h2b(hashVector[i]), result);
}
}
private void threadRunnerMacTest(String hmacAlgo, String digest,
HmacVector vector) throws InterruptedException {
@ -1140,6 +1341,50 @@ public class WolfCryptMacTest {
if (enabledAlgos.contains("HmacSHA512")) {
threadRunnerMacTest("HmacSHA512", "SHA512", sha512Vector);
}
if (enabledAlgos.contains("HmacSHA3-224")) {
HmacVector sha3_224Vector = new HmacVector(
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
Util.h2b("4869205468657265"),
Util.h2b("3b16546bbc7be2706a031dcafd56373d" +
"9884367641d8c59af3c860f7")
);
threadRunnerMacTest("HmacSHA3-224", "SHA3-224", sha3_224Vector);
}
if (enabledAlgos.contains("HmacSHA3-256")) {
HmacVector sha3_256Vector = new HmacVector(
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
Util.h2b("4869205468657265"),
Util.h2b("ba85192310dffa96e2a3a40e69774351" +
"140bb7185e1202cdcc917589f95e16bb")
);
threadRunnerMacTest("HmacSHA3-256", "SHA3-256", sha3_256Vector);
}
if (enabledAlgos.contains("HmacSHA3-384")) {
HmacVector sha3_384Vector = new HmacVector(
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
Util.h2b("4869205468657265"),
Util.h2b("68d2dcf7fd4ddd0a2240c8a437305f61" +
"fb7334cfb5d0226e1bc27dc10a2e723a" +
"20d370b47743130e26ac7e3d532886bd")
);
threadRunnerMacTest("HmacSHA3-384", "SHA3-384", sha3_384Vector);
}
if (enabledAlgos.contains("HmacSHA3-512")) {
HmacVector sha3_512Vector = new HmacVector(
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
Util.h2b("4869205468657265"),
Util.h2b("eb3fbd4b2eaab8f5c504bd3a41465aac" +
"ec15770a7cabac531e482f860b5ec7ba" +
"47ccb2c6f2afce8f88d22b6dc61380f2" +
"3a668fd3888bb80537c0a0b86407689e")
);
threadRunnerMacTest("HmacSHA3-512", "SHA3-512", sha3_512Vector);
}
}
private class HmacVector {

View File

@ -0,0 +1,654 @@
/* WolfCryptMessageDigestSha3Test.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.provider.jce.test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.Test;
import org.junit.Assume;
import org.junit.BeforeClass;
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 java.security.Security;
import java.security.Provider;
import java.security.MessageDigest;
import java.security.NoSuchProviderException;
import java.security.NoSuchAlgorithmException;
import com.wolfssl.wolfcrypt.Sha3;
import com.wolfssl.provider.jce.WolfCryptProvider;
import com.wolfssl.wolfcrypt.FeatureDetect;
public class WolfCryptMessageDigestSha3Test {
@Rule
public TestRule watcher = new TestWatcher() {
protected void starting(Description description) {
System.out.println("\t" + description.getMethodName());
}
};
@BeforeClass
public static void testProviderInstallationAtRuntime()
throws NoSuchProviderException {
System.out.println("JCE WolfCryptMessageDigestSha3 Class");
/* Install wolfJCE provider at runtime */
Security.insertProviderAt(new WolfCryptProvider(), 1);
Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
try {
MessageDigest.getInstance("SHA3-256", "wolfJCE");
} catch (NoSuchAlgorithmException e) {
/* If algo is compiled out, skip tests */
if (FeatureDetect.Sha3Enabled() == false) {
System.out.println("wolfJCE SHA3 Test skipped");
Assume.assumeTrue(false);
}
}
}
@Test
public void testSha3_224SingleUpdate()
throws NoSuchProviderException, NoSuchAlgorithmException {
DigestVector vectors[] = new DigestVector[] {
/* NIST FIPS 202 test vector */
new DigestVector(
new String("abc").getBytes(),
new byte[] {
(byte)0xe6, (byte)0x42, (byte)0x82, (byte)0x4c,
(byte)0x3f, (byte)0x8c, (byte)0xf2, (byte)0x4a,
(byte)0xd0, (byte)0x92, (byte)0x34, (byte)0xee,
(byte)0x7d, (byte)0x3c, (byte)0x76, (byte)0x6f,
(byte)0xc9, (byte)0xa3, (byte)0xa5, (byte)0x16,
(byte)0x8d, (byte)0x0c, (byte)0x94, (byte)0xad,
(byte)0x73, (byte)0xb4, (byte)0x6f, (byte)0xdf
}
),
};
byte[] output;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-224", "wolfJCE");
for (int i = 0; i < vectors.length; i++) {
sha3.update(vectors[i].getInput());
output = sha3.digest();
assertEquals(vectors[i].getOutput().length, output.length);
assertArrayEquals(vectors[i].getOutput(), output);
}
}
@Test
public void testSha3_256SingleUpdate()
throws NoSuchProviderException, NoSuchAlgorithmException {
DigestVector vectors[] = new DigestVector[] {
/* NIST FIPS 202 test vector */
new DigestVector(
new String("abc").getBytes(),
new byte[] {
(byte)0x3a, (byte)0x98, (byte)0x5d, (byte)0xa7,
(byte)0x4f, (byte)0xe2, (byte)0x25, (byte)0xb2,
(byte)0x04, (byte)0x5c, (byte)0x17, (byte)0x2d,
(byte)0x6b, (byte)0xd3, (byte)0x90, (byte)0xbd,
(byte)0x85, (byte)0x5f, (byte)0x08, (byte)0x6e,
(byte)0x3e, (byte)0x9d, (byte)0x52, (byte)0x5b,
(byte)0x46, (byte)0xbf, (byte)0xe2, (byte)0x45,
(byte)0x11, (byte)0x43, (byte)0x15, (byte)0x32
}
),
};
byte[] output;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
for (int i = 0; i < vectors.length; i++) {
sha3.update(vectors[i].getInput());
output = sha3.digest();
assertEquals(vectors[i].getOutput().length, output.length);
assertArrayEquals(vectors[i].getOutput(), output);
}
}
@Test
public void testSha3_384SingleUpdate()
throws NoSuchProviderException, NoSuchAlgorithmException {
DigestVector vectors[] = new DigestVector[] {
/* NIST FIPS 202 test vector */
new DigestVector(
new String("abc").getBytes(),
new byte[] {
(byte)0xec, (byte)0x01, (byte)0x49, (byte)0x82,
(byte)0x88, (byte)0x51, (byte)0x6f, (byte)0xc9,
(byte)0x26, (byte)0x45, (byte)0x9f, (byte)0x58,
(byte)0xe2, (byte)0xc6, (byte)0xad, (byte)0x8d,
(byte)0xf9, (byte)0xb4, (byte)0x73, (byte)0xcb,
(byte)0x0f, (byte)0xc0, (byte)0x8c, (byte)0x25,
(byte)0x96, (byte)0xda, (byte)0x7c, (byte)0xf0,
(byte)0xe4, (byte)0x9b, (byte)0xe4, (byte)0xb2,
(byte)0x98, (byte)0xd8, (byte)0x8c, (byte)0xea,
(byte)0x92, (byte)0x7a, (byte)0xc7, (byte)0xf5,
(byte)0x39, (byte)0xf1, (byte)0xed, (byte)0xf2,
(byte)0x28, (byte)0x37, (byte)0x6d, (byte)0x25
}
),
};
byte[] output;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-384", "wolfJCE");
for (int i = 0; i < vectors.length; i++) {
sha3.update(vectors[i].getInput());
output = sha3.digest();
assertEquals(vectors[i].getOutput().length, output.length);
assertArrayEquals(vectors[i].getOutput(), output);
}
}
@Test
public void testSha3_512SingleUpdate()
throws NoSuchProviderException, NoSuchAlgorithmException {
DigestVector vectors[] = new DigestVector[] {
/* NIST FIPS 202 test vector */
new DigestVector(
new String("abc").getBytes(),
new byte[] {
(byte)0xb7, (byte)0x51, (byte)0x85, (byte)0x0b,
(byte)0x1a, (byte)0x57, (byte)0x16, (byte)0x8a,
(byte)0x56, (byte)0x93, (byte)0xcd, (byte)0x92,
(byte)0x4b, (byte)0x6b, (byte)0x09, (byte)0x6e,
(byte)0x08, (byte)0xf6, (byte)0x21, (byte)0x82,
(byte)0x74, (byte)0x44, (byte)0xf7, (byte)0x0d,
(byte)0x88, (byte)0x4f, (byte)0x5d, (byte)0x02,
(byte)0x40, (byte)0xd2, (byte)0x71, (byte)0x2e,
(byte)0x10, (byte)0xe1, (byte)0x16, (byte)0xe9,
(byte)0x19, (byte)0x2a, (byte)0xf3, (byte)0xc9,
(byte)0x1a, (byte)0x7e, (byte)0xc5, (byte)0x76,
(byte)0x47, (byte)0xe3, (byte)0x93, (byte)0x40,
(byte)0x57, (byte)0x34, (byte)0x0b, (byte)0x4c,
(byte)0xf4, (byte)0x08, (byte)0xd5, (byte)0xa5,
(byte)0x65, (byte)0x92, (byte)0xf8, (byte)0x27,
(byte)0x4e, (byte)0xec, (byte)0x53, (byte)0xf0
}
),
};
byte[] output;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-512", "wolfJCE");
for (int i = 0; i < vectors.length; i++) {
sha3.update(vectors[i].getInput());
output = sha3.digest();
assertEquals(vectors[i].getOutput().length, output.length);
assertArrayEquals(vectors[i].getOutput(), output);
}
}
@Test
public void testSha3Reset()
throws NoSuchProviderException, NoSuchAlgorithmException {
String input = "abc";
byte[] inArray = input.getBytes();
final byte expected[] = new byte[] {
(byte)0x3a, (byte)0x98, (byte)0x5d, (byte)0xa7,
(byte)0x4f, (byte)0xe2, (byte)0x25, (byte)0xb2,
(byte)0x04, (byte)0x5c, (byte)0x17, (byte)0x2d,
(byte)0x6b, (byte)0xd3, (byte)0x90, (byte)0xbd,
(byte)0x85, (byte)0x5f, (byte)0x08, (byte)0x6e,
(byte)0x3e, (byte)0x9d, (byte)0x52, (byte)0x5b,
(byte)0x46, (byte)0xbf, (byte)0xe2, (byte)0x45,
(byte)0x11, (byte)0x43, (byte)0x15, (byte)0x32
};
byte[] output;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
for (int i = 0; i < inArray.length; i++) {
sha3.update(inArray[i]);
}
sha3.reset();
for (int i = 0; i < inArray.length; i++) {
sha3.update(inArray[i]);
}
output = sha3.digest();
assertEquals(expected.length, output.length);
assertArrayEquals(expected, output);
}
@Test
public void testSha3Clone()
throws NoSuchProviderException, NoSuchAlgorithmException,
CloneNotSupportedException {
String input = "abc";
byte[] inArray = input.getBytes();
final byte expected[] = new byte[] {
(byte)0x3a, (byte)0x98, (byte)0x5d, (byte)0xa7,
(byte)0x4f, (byte)0xe2, (byte)0x25, (byte)0xb2,
(byte)0x04, (byte)0x5c, (byte)0x17, (byte)0x2d,
(byte)0x6b, (byte)0xd3, (byte)0x90, (byte)0xbd,
(byte)0x85, (byte)0x5f, (byte)0x08, (byte)0x6e,
(byte)0x3e, (byte)0x9d, (byte)0x52, (byte)0x5b,
(byte)0x46, (byte)0xbf, (byte)0xe2, (byte)0x45,
(byte)0x11, (byte)0x43, (byte)0x15, (byte)0x32
};
byte[] output;
byte[] output2;
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
for (int i = 0; i < inArray.length; i++) {
sha3.update(inArray[i]);
}
/* Try to clone existing MessageDigest, should copy over same state */
MessageDigest sha3Copy = (MessageDigest)sha3.clone();
output = sha3.digest();
output2 = sha3Copy.digest();
assertEquals(expected.length, output.length);
assertEquals(expected.length, output2.length);
assertArrayEquals(expected, output);
assertArrayEquals(expected, output2);
}
@Test
public void testSha3GetDigestLength()
throws NoSuchProviderException, NoSuchAlgorithmException {
MessageDigest sha3_224 =
MessageDigest.getInstance("SHA3-224", "wolfJCE");
assertEquals(Sha3.DIGEST_SIZE_224, sha3_224.getDigestLength());
MessageDigest sha3_256 =
MessageDigest.getInstance("SHA3-256", "wolfJCE");
assertEquals(Sha3.DIGEST_SIZE_256, sha3_256.getDigestLength());
MessageDigest sha3_384 =
MessageDigest.getInstance("SHA3-384", "wolfJCE");
assertEquals(Sha3.DIGEST_SIZE_384, sha3_384.getDigestLength());
MessageDigest sha3_512 =
MessageDigest.getInstance("SHA3-512", "wolfJCE");
assertEquals(Sha3.DIGEST_SIZE_512, sha3_512.getDigestLength());
}
@Test
public void testSha3Threaded()
throws NoSuchProviderException, NoSuchAlgorithmException,
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() {
MessageDigest sha3 = null;
try {
sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
} catch (NoSuchAlgorithmException |
NoSuchProviderException e) {
/* Add empty array on failure, will error out below */
results.add(new byte[] {0});
}
/* Process/update in 1024-byte chunks */
for (int j = 0; j < rand10kBuf.length; j+= 1024) {
sha3.update(rand10kBuf, j, 1024);
}
/* Get final hash */
byte[] hash = sha3.digest();
results.add(hash.clone());
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 testSha3EmptyInput()
throws NoSuchProviderException, NoSuchAlgorithmException {
/* NIST FIPS 202 test vectors for empty input */
byte[] empty224 = new byte[] {
(byte)0x6b, (byte)0x4e, (byte)0x03, (byte)0x42,
(byte)0x36, (byte)0x67, (byte)0xdb, (byte)0xb7,
(byte)0x3b, (byte)0x6e, (byte)0x15, (byte)0x45,
(byte)0x4f, (byte)0x0e, (byte)0xb1, (byte)0xab,
(byte)0xd4, (byte)0x59, (byte)0x7f, (byte)0x9a,
(byte)0x1b, (byte)0x07, (byte)0x8e, (byte)0x3f,
(byte)0x5b, (byte)0x5a, (byte)0x6b, (byte)0xc7
};
byte[] empty256 = new byte[] {
(byte)0xa7, (byte)0xff, (byte)0xc6, (byte)0xf8,
(byte)0xbf, (byte)0x1e, (byte)0xd7, (byte)0x66,
(byte)0x51, (byte)0xc1, (byte)0x47, (byte)0x56,
(byte)0xa0, (byte)0x61, (byte)0xd6, (byte)0x62,
(byte)0xf5, (byte)0x80, (byte)0xff, (byte)0x4d,
(byte)0xe4, (byte)0x3b, (byte)0x49, (byte)0xfa,
(byte)0x82, (byte)0xd8, (byte)0x0a, (byte)0x4b,
(byte)0x80, (byte)0xf8, (byte)0x43, (byte)0x4a
};
byte[] empty384 = new byte[] {
(byte)0x0c, (byte)0x63, (byte)0xa7, (byte)0x5b,
(byte)0x84, (byte)0x5e, (byte)0x4f, (byte)0x7d,
(byte)0x01, (byte)0x10, (byte)0x7d, (byte)0x85,
(byte)0x2e, (byte)0x4c, (byte)0x24, (byte)0x85,
(byte)0xc5, (byte)0x1a, (byte)0x50, (byte)0xaa,
(byte)0xaa, (byte)0x94, (byte)0xfc, (byte)0x61,
(byte)0x99, (byte)0x5e, (byte)0x71, (byte)0xbb,
(byte)0xee, (byte)0x98, (byte)0x3a, (byte)0x2a,
(byte)0xc3, (byte)0x71, (byte)0x38, (byte)0x31,
(byte)0x26, (byte)0x4a, (byte)0xdb, (byte)0x47,
(byte)0xfb, (byte)0x6b, (byte)0xd1, (byte)0xe0,
(byte)0x58, (byte)0xd5, (byte)0xf0, (byte)0x04
};
byte[] empty512 = new byte[] {
(byte)0xa6, (byte)0x9f, (byte)0x73, (byte)0xcc,
(byte)0xa2, (byte)0x3a, (byte)0x9a, (byte)0xc5,
(byte)0xc8, (byte)0xb5, (byte)0x67, (byte)0xdc,
(byte)0x18, (byte)0x5a, (byte)0x75, (byte)0x6e,
(byte)0x97, (byte)0xc9, (byte)0x82, (byte)0x16,
(byte)0x4f, (byte)0xe2, (byte)0x58, (byte)0x59,
(byte)0xe0, (byte)0xd1, (byte)0xdc, (byte)0xc1,
(byte)0x47, (byte)0x5c, (byte)0x80, (byte)0xa6,
(byte)0x15, (byte)0xb2, (byte)0x12, (byte)0x3a,
(byte)0xf1, (byte)0xf5, (byte)0xf9, (byte)0x4c,
(byte)0x11, (byte)0xe3, (byte)0xe9, (byte)0x40,
(byte)0x2c, (byte)0x3a, (byte)0xc5, (byte)0x58,
(byte)0xf5, (byte)0x00, (byte)0x19, (byte)0x9d,
(byte)0x95, (byte)0xb6, (byte)0xd3, (byte)0xe3,
(byte)0x01, (byte)0x75, (byte)0x85, (byte)0x86,
(byte)0x28, (byte)0x1d, (byte)0xcd, (byte)0x26
};
byte[] output;
/* Test SHA3-224 empty input */
MessageDigest sha3 = MessageDigest.getInstance("SHA3-224", "wolfJCE");
output = sha3.digest();
assertEquals(empty224.length, output.length);
assertArrayEquals(empty224, output);
/* Test SHA3-256 empty input */
sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
output = sha3.digest();
assertEquals(empty256.length, output.length);
assertArrayEquals(empty256, output);
/* Test SHA3-384 empty input */
sha3 = MessageDigest.getInstance("SHA3-384", "wolfJCE");
output = sha3.digest();
assertEquals(empty384.length, output.length);
assertArrayEquals(empty384, output);
/* Test SHA3-512 empty input */
sha3 = MessageDigest.getInstance("SHA3-512", "wolfJCE");
output = sha3.digest();
assertEquals(empty512.length, output.length);
assertArrayEquals(empty512, output);
}
@Test
public void testSha3ByteByByteUpdate()
throws NoSuchProviderException, NoSuchAlgorithmException {
String input =
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
byte[] inArray = input.getBytes();
final byte expected[] = new byte[] {
/* NIST FIPS 202 test vector for above input with SHA3-256 */
(byte)0x41, (byte)0xc0, (byte)0xdb, (byte)0xa2,
(byte)0xa9, (byte)0xd6, (byte)0x24, (byte)0x08,
(byte)0x49, (byte)0x10, (byte)0x03, (byte)0x76,
(byte)0xa8, (byte)0x23, (byte)0x5e, (byte)0x2c,
(byte)0x82, (byte)0xe1, (byte)0xb9, (byte)0x99,
(byte)0x8a, (byte)0x99, (byte)0x9e, (byte)0x21,
(byte)0xdb, (byte)0x32, (byte)0xdd, (byte)0x97,
(byte)0x49, (byte)0x6d, (byte)0x33, (byte)0x76
};
byte[] output;
byte[] output2;
MessageDigest sha3 =
MessageDigest.getInstance("SHA3-256", "wolfJCE");
MessageDigest sha3Bulk =
MessageDigest.getInstance("SHA3-256", "wolfJCE");
/* Update one byte at a time */
for (int i = 0; i < inArray.length; i++) {
sha3.update(inArray[i]);
}
/* Update all at once */
sha3Bulk.update(inArray);
output = sha3.digest();
output2 = sha3Bulk.digest();
/* Both methods should produce same digest */
assertEquals(expected.length, output.length);
assertEquals(expected.length, output2.length);
assertArrayEquals(expected, output);
assertArrayEquals(expected, output2);
assertArrayEquals(output, output2);
}
@Test
public void testSha3LargeInput()
throws NoSuchProviderException, NoSuchAlgorithmException {
/* Test with 1MB of random data */
byte[] largeInput = new byte[1024 * 1024];
new Random().nextBytes(largeInput);
MessageDigest sha3_224 =
MessageDigest.getInstance("SHA3-224", "wolfJCE");
MessageDigest sha3_256 =
MessageDigest.getInstance("SHA3-256", "wolfJCE");
MessageDigest sha3_384 =
MessageDigest.getInstance("SHA3-384", "wolfJCE");
MessageDigest sha3_512 =
MessageDigest.getInstance("SHA3-512", "wolfJCE");
/* Hash same input with all SHA-3 variants */
byte[] hash224 = sha3_224.digest(largeInput);
byte[] hash256 = sha3_256.digest(largeInput);
byte[] hash384 = sha3_384.digest(largeInput);
byte[] hash512 = sha3_512.digest(largeInput);
/* Verify expected digest sizes */
assertEquals(Sha3.DIGEST_SIZE_224, hash224.length);
assertEquals(Sha3.DIGEST_SIZE_256, hash256.length);
assertEquals(Sha3.DIGEST_SIZE_384, hash384.length);
assertEquals(Sha3.DIGEST_SIZE_512, hash512.length);
/* Verify digests are different */
assertFalse(Arrays.equals(hash224, hash256));
assertFalse(Arrays.equals(hash224, hash384));
assertFalse(Arrays.equals(hash224, hash512));
assertFalse(Arrays.equals(hash256, hash384));
assertFalse(Arrays.equals(hash256, hash512));
assertFalse(Arrays.equals(hash384, hash512));
}
@Test
public void testSha3Interop()
throws NoSuchProviderException, NoSuchAlgorithmException {
String input = "Bozeman, MT";
String input2 = "wolfSSL is an Open Source Internet security " +
"company, focused primarily on SSL/TLS and " +
"cryptography. Main products include the wolfSSL " +
"embedded SSL/TLS library, wolfCrypt cryptography " +
"library, wolfMQTT, and wolfSSH. Products are " +
"dual licensed under both GPLv2 and a commercial" +
"license.";
byte[] wolfOutput;
byte[] interopOutput;
/* Get SUN SHA3 implementation */
MessageDigest sunSha3 = null;
try {
sunSha3 = MessageDigest.getInstance("SHA3-256", "SUN");
Provider provider = sunSha3.getProvider();
if (!provider.getName().equals("SUN")) {
/* Skip test if SUN SHA3-256 provider name mismatch */
return;
}
} catch (NoSuchAlgorithmException e) {
/* Skip test if SUN SHA3-256 provider available */
return;
}
MessageDigest wolfSha3 =
MessageDigest.getInstance("SHA3-256", "wolfJCE");
/* short message */
sunSha3.update(input.getBytes());
interopOutput = sunSha3.digest();
wolfSha3.update(input.getBytes());
wolfOutput = wolfSha3.digest();
assertArrayEquals(wolfOutput, interopOutput);
/* long message */
sunSha3.update(input2.getBytes());
interopOutput = sunSha3.digest();
wolfSha3.update(input2.getBytes());
wolfOutput = wolfSha3.digest();
assertArrayEquals(wolfOutput, interopOutput);
}
@Test
public void testSha3DigestAfterDigest()
throws NoSuchProviderException, NoSuchAlgorithmException {
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
sha3.update((byte)0x00);
sha3.digest();
/* Try to digest again without update, should return empty hash */
byte[] emptyHash = sha3.digest();
byte[] expectedEmptyHash = new byte[] {
(byte)0xa7, (byte)0xff, (byte)0xc6, (byte)0xf8,
(byte)0xbf, (byte)0x1e, (byte)0xd7, (byte)0x66,
(byte)0x51, (byte)0xc1, (byte)0x47, (byte)0x56,
(byte)0xa0, (byte)0x61, (byte)0xd6, (byte)0x62,
(byte)0xf5, (byte)0x80, (byte)0xff, (byte)0x4d,
(byte)0xe4, (byte)0x3b, (byte)0x49, (byte)0xfa,
(byte)0x82, (byte)0xd8, (byte)0x0a, (byte)0x4b,
(byte)0x80, (byte)0xf8, (byte)0x43, (byte)0x4a
};
assertArrayEquals(expectedEmptyHash, emptyHash);
}
@Test
public void testSha3UpdateAfterDigest()
throws NoSuchProviderException, NoSuchAlgorithmException {
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256", "wolfJCE");
sha3.update((byte)0x00);
sha3.digest();
/* Try to update after digest, should implicitly reset */
sha3.update((byte)0x00);
byte[] output = sha3.digest();
/* Verify we get expected output for single 0x00 byte */
byte[] expected = new byte[] {
(byte)0x5d, (byte)0x53, (byte)0x46, (byte)0x9f,
(byte)0x20, (byte)0xfe, (byte)0xf4, (byte)0xf8,
(byte)0xea, (byte)0xb5, (byte)0x2b, (byte)0x88,
(byte)0x04, (byte)0x4e, (byte)0xde, (byte)0x69,
(byte)0xc7, (byte)0x7a, (byte)0x6a, (byte)0x68,
(byte)0xa6, (byte)0x07, (byte)0x28, (byte)0x60,
(byte)0x9f, (byte)0xc4, (byte)0xa6, (byte)0x5f,
(byte)0xf5, (byte)0x31, (byte)0xe7, (byte)0xd0
};
assertArrayEquals(expected, output);
}
}

View File

@ -62,11 +62,19 @@ public class WolfCryptSignatureTest {
"SHA256withRSA",
"SHA384withRSA",
"SHA512withRSA",
"SHA3-224withRSA",
"SHA3-256withRSA",
"SHA3-384withRSA",
"SHA3-512withRSA",
"SHA1withECDSA",
"SHA224withECDSA",
"SHA256withECDSA",
"SHA384withECDSA",
"SHA512withECDSA"
"SHA512withECDSA",
"SHA3-224withECDSA",
"SHA3-256withECDSA",
"SHA3-384withECDSA",
"SHA3-512withECDSA"
};
private static ArrayList<String> enabledAlgos =

View File

@ -33,6 +33,7 @@ import org.junit.runners.Suite.SuiteClasses;
WolfCryptMessageDigestSha256Test.class,
WolfCryptMessageDigestSha384Test.class,
WolfCryptMessageDigestSha512Test.class,
WolfCryptMessageDigestSha3Test.class,
WolfCryptRandomTest.class,
WolfCryptSecretKeyFactoryTest.class,
WolfCryptSignatureTest.class,

View File

@ -40,6 +40,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.wolfcrypt.Hmac;
import com.wolfssl.wolfcrypt.NativeStruct;
import com.wolfssl.wolfcrypt.WolfCryptError;
@ -274,6 +275,197 @@ public class HmacTest {
}
}
static final String[] sha3KeyVector = new String[] {
"4A656665", /* Jefe */
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708" +
"0102030405060708010203040506070801020304050607080102030405060708"
};
static final String[] sha3DataVector = new String[] {
/* what do ya want for nothing? */
"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
/* Hi There */
"4869205468657265",
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd" +
"dddddddddddddddddddd",
/* Big Key Input */
"426967204b657920496e707574"
};
@Test
public void sha3_224HmacShouldMatch() {
String[] hashVector = new String[] {
"7fdb8dd88bd2f60d1b798634ad386811c2cfc85bfaf5d52bbace5e66",
"3b16546bbc7be2706a031dcafd56373d9884367641d8c59af3c860f7",
"676cfc7d16153638780390692be142d2df7ce924b909c0c08dbfdc1a",
"29e05e46c4a45e4674bfd72d1ad866db2d0d104e2bfaad537d15698b"
};
for (int i = 0; i < sha3DataVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
try {
Hmac hmac = new Hmac();
byte[] key = Util.h2b(sha3KeyVector[i]);
byte[] data = Util.h2b(sha3DataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
hmac.setKey(Hmac.SHA3_224, key);
hmac.update(data);
assertArrayEquals(expected, hmac.doFinal());
hmac.reset();
assertArrayEquals(expected, hmac.doFinal(data));
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("Hmac SHA3-224 test skipped: " +
e.getError());
} else {
throw e;
}
}
}
}
@Test
public void sha3_256HmacShouldMatch() {
String[] hashVector = new String[] {
"c7d4072e788877ae3596bbb0da73b887c9171f93095b294ae857fbe2645e1ba5",
"ba85192310dffa96e2a3a40e69774351140bb7185e1202cdcc917589f95e16bb",
"84ec79124a27107865cedd8bd82da9965e5ed8c37b0ac98005a7f39ed58a4207",
"b55b8d64b69c21d0bf205ca2f7b9b14e8821612c66c391ae6c95168583e6f49b"
};
for (int i = 0; i < sha3DataVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
try {
Hmac hmac = new Hmac();
byte[] key = Util.h2b(sha3KeyVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
byte[] data = Util.h2b(sha3DataVector[i]);
hmac.setKey(Hmac.SHA3_256, key);
hmac.update(data);
assertArrayEquals(expected, hmac.doFinal());
hmac.reset();
assertArrayEquals(expected, hmac.doFinal(data));
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("Hmac SHA3-256 test skipped: " +
e.getError());
} else {
throw e;
}
}
}
}
@Test
public void sha3_384HmacShouldMatch() {
String[] hashVector = new String[] {
"f1101f8cbf9766fd6764d2ed61903f21ca9b18f57cf3e1a23ca13508a93243ce48c045dc007f26a21b3f5e0e9df4c20a",
"68d2dcf7fd4ddd0a2240c8a437305f61fb7334cfb5d0226e1bc27dc10a2e723a20d370b47743130e26ac7e3d532886bd",
"275cd0e661bb8b151c64d288f1f782fb91a8abd56858d72babb2d476f0458373b41b6ab5bf174bec422e53fc3135ac6e",
"aa91b3a62f56a1be8c3e7438db58d9d334dea0606d8d46e0eca9f6063514e6ed83e67c77246c11b59082b575da7b832d"
};
for (int i = 0; i < sha3DataVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
try {
Hmac hmac = new Hmac();
byte[] key = Util.h2b(sha3KeyVector[i]);
byte[] data = Util.h2b(sha3DataVector[i]);
byte[] expected = Util.h2b(hashVector[i]);
hmac.setKey(Hmac.SHA3_384, key);
hmac.update(data);
assertArrayEquals(expected, hmac.doFinal());
hmac.reset();
assertArrayEquals(expected, hmac.doFinal(data));
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("Hmac SHA3-384 test skipped: " +
e.getError());
} else {
throw e;
}
}
}
}
@Test
public void sha3_512HmacShouldMatch() {
String[] hashVector = new String[] {
"5a4bfeab6166427c7a3647b747292b8384537cdb89afb3bf5665e4c5e709350b287baec921fd7ca0ee7a0c31d022a95e1fc92ba9d77df883960275beb4e62024",
"eb3fbd4b2eaab8f5c504bd3a41465aacec15770a7cabac531e482f860b5ec7ba47ccb2c6f2afce8f88d22b6dc61380f23a668fd3888bb80537c0a0b86407689e",
"309e99f9ec075ec6c6d475eda1180687fcf1531195802a99b5677449a8625182851cb332afb6a89c411325fbcbcd42afcb7b6e5aab7ea42c660f97fd8584bf03",
"1cc3a9244a4a3fbdc72000169b79470378752cb5f12e627cbeef4e8f0b112b32a0eec9d04d64640b37f4dd66f78bb3ad52526b6512de0d7cc08b60016c37d7a8"
};
for (int i = 0; i < sha3DataVector.length; i++) {
if ((i == 0) && Fips.enabled) {
/* FIPS doesn't allow short key lengths */
continue;
}
try {
Hmac hmac = new Hmac();
byte[] expected = Util.h2b(hashVector[i]);
byte[] data = Util.h2b(sha3DataVector[i]);
hmac.setKey(Hmac.SHA3_512, Util.h2b(sha3KeyVector[i]));
hmac.update(data);
assertArrayEquals(expected, hmac.doFinal());
hmac.reset();
assertArrayEquals(expected, hmac.doFinal(data));
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("Hmac SHA3-512 test skipped: " +
e.getError());
} else {
throw e;
}
}
}
}
private void threadRunnerHmacTest(int hmacType, byte[] inKey,
byte[] inData, byte[] inExpected)
throws InterruptedException {
@ -421,5 +613,42 @@ public class HmacTest {
"952ac4b7da7131f0")
);
}
if (Hmac.SHA3_224 != -1) {
threadRunnerHmacTest(Hmac.SHA3_224,
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), /* key */
Util.h2b("4869205468657265"), /* data */
Util.h2b("3b16546bbc7be2706a031dcafd56373d" +
"9884367641d8c59af3c860f7")
);
}
if (Hmac.SHA3_256 != -1) {
threadRunnerHmacTest(Hmac.SHA3_256,
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), /* key */
Util.h2b("4869205468657265"), /* data */
Util.h2b("ba85192310dffa96e2a3a40e697743" +
"51140bb7185e1202cdcc917589f95e" +
"16bb")
);
}
if (Hmac.SHA3_384 != -1) {
threadRunnerHmacTest(Hmac.SHA3_384,
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), /* key */
Util.h2b("4869205468657265"), /* data */
Util.h2b("68d2dcf7fd4ddd0a2240c8a437305f61" +
"fb7334cfb5d0226e1bc27dc10a2e723a" +
"20d370b47743130e26ac7e3d532886bd")
);
}
if (Hmac.SHA3_512 != -1) {
threadRunnerHmacTest(Hmac.SHA3_512,
Util.h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), /* key */
Util.h2b("4869205468657265"), /* data */
Util.h2b("eb3fbd4b2eaab8f5c504bd3a41465aac" +
"ec15770a7cabac531e482f860b5ec7ba" +
"47ccb2c6f2afce8f88d22b6dc61380f2" +
"3a668fd3888bb80537c0a0b86407689e")
);
}
}
}

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,