I have created one project in spring boot in which i have integrated one library which is used to generate keys, encrypt and decrypt so i have deleveloped rest apis which will do these 3 functionalities but i am not getting correct encrypt and decrypt msg if i pass the samecipher text to decrypt i am not getting original plain text please review the code and tell me what is wrong



--- Entry 1 ---
Filename: com_kyber_quantum_QuantumWrapper.cpp
Path: cpp\com_kyber_quantum_QuantumWrapper.cpp
Content:
#include "com_kyber_quantum_QuantumWrapper.h"
#include <iostream>
#include <cstring>
#include <cstdint>
#include <windows.h>
#include "kyber_API.h"  // Kyber API header

// Rename function pointers to avoid conflict with kyber_API.h
typedef void (*keygen_fn_ptr)(uint8_t*, uint8_t*);
typedef void (*encrypt_fn_ptr)(uint8_t*, uint8_t*, uint16_t*);
typedef void (*decrypt_fn_ptr)(uint8_t*, uint8_t*, uint16_t*);

// Global function pointers with new names
keygen_fn_ptr keygeneration_ptr = nullptr;
encrypt_fn_ptr encryption_ptr = nullptr;
decrypt_fn_ptr decryption_ptr = nullptr;

// Handle for the dynamically loaded library
HMODULE handle = nullptr;

// JNI_OnLoad: Called when the native library is loaded
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    printf("JNI_OnLoad called: Loading the library...\n");

    // Load the lib_kyber library
//    char* projectRoot = getenv("PROJECT_ROOT");  // Set PROJECT_ROOT as your project root
//    if (projectRoot == nullptr) {
//        fprintf(stderr, "Error: PROJECT_ROOT environment variable is not set.\n");
//        return JNI_ERR;  // Return error code
//    }

    // Construct the path to the Kyber .so file
    char soPath[1024] = "";
      // Start with the project root
    strcat(soPath, "C:/Quantam/spring/Quantum/src/main/resources/libs/lib_kyber.dll");  // Change .so to .dll

    // Load the Kyber .dll file
    handle = LoadLibraryA(soPath);
    if (!handle) {
        // Print the error and the shared library path
        fprintf(stderr, "Error loading Kyber library. Path: %s. Error: %lu\n", soPath, GetLastError());
        return JNI_ERR;  // Return error code
    } else {
        printf("kyber_lib loaded\n");
    }

    // Resolve the symbols for the Kyber functions
    keygeneration_ptr = (keygen_fn_ptr)GetProcAddress(handle, "keygeneration");
    encryption_ptr = (encrypt_fn_ptr)GetProcAddress(handle, "encryption");
    decryption_ptr = (decrypt_fn_ptr)GetProcAddress(handle, "decryption");

    if (!keygeneration_ptr || !encryption_ptr || !decryption_ptr) {
        std::cerr << "Failed to load Kyber function symbols." << std::endl;
        FreeLibrary(handle);  // Clean up in case of failure
        return JNI_ERR;  // Return error code
    }

    printf("Library and function pointers loaded successfully.\n");
    return JNI_VERSION_1_6;  // Return the JNI version
}

// JNI_OnUnload: Called when the native library is unloaded
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
    printf("JNI_OnUnload called: Unloading the library...\n");

    // Free the dynamically loaded library
    if (handle) {
        FreeLibrary(handle);
        handle = nullptr;
        keygeneration_ptr = nullptr;
        encryption_ptr = nullptr;
        decryption_ptr = nullptr;
    }
}

// JNI wrapper for the keygeneration function
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_keygeneration(JNIEnv *env, jclass clazz, jobject pubKeyBuffer, jobject privKeyBuffer) {
    printf("Key Generation called\n");

    // Create buffers for public and private keys
    uint8_t pubKey[1568];
    uint8_t privKey[1536];

    // Call the Kyber API keygeneration function
    keygeneration_ptr(pubKey, privKey);

    // Copy public key into ByteBuffer
    uint8_t* pubKeyPtr = (uint8_t*)env->GetDirectBufferAddress(pubKeyBuffer);
    if (pubKeyPtr == nullptr) {
        std::cerr << "Error accessing public key ByteBuffer memory." << std::endl;
        return;
    }
    std::memcpy(pubKeyPtr, pubKey, sizeof(pubKey));

    // Copy private key into ByteBuffer
    uint8_t* privKeyPtr = (uint8_t*)env->GetDirectBufferAddress(privKeyBuffer);
    if (privKeyPtr == nullptr) {
        std::cerr << "Error accessing private key ByteBuffer memory." << std::endl;
        return;
    }
    std::memcpy(privKeyPtr, privKey, sizeof(privKey));
}

// JNI wrapper for the encryption function
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_encryption(JNIEnv *env, jclass clazz, jbyteArray pubKey, jobject cipherBuffer, jbyteArray message) {
    printf("Encryption called\n");

    // Get the public key array from Java
    jbyte* pubKeyPtr = env->GetByteArrayElements(pubKey, NULL);
    if (pubKeyPtr == nullptr) {
        std::cerr << "Error accessing public key array." << std::endl;
        return;
    }

    // Get the cipher buffer from Java
    uint8_t* cipherPtr = (uint8_t*)env->GetDirectBufferAddress(cipherBuffer);
    if (cipherPtr == nullptr) {
        std::cerr << "Error accessing cipher ByteBuffer memory." << std::endl;
        return;
    }

    // Get the message array from Java (should be passed as a byte array)
    jbyte* messagePtr = env->GetByteArrayElements(message, NULL);
    if (messagePtr == nullptr) {
        std::cerr << "Error accessing message array." << std::endl;
        return;
    }

    // Call the Kyber API encryption function
    encryption_ptr((uint8_t*)pubKeyPtr, cipherPtr, (uint16_t*)messagePtr);

    // Release JNI arrays
    env->ReleaseByteArrayElements(pubKey, pubKeyPtr, 0);
    env->ReleaseByteArrayElements(message, messagePtr, 0);
}

// JNI wrapper for the decryption function
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_decryption(JNIEnv *env, jclass clazz, jbyteArray privKey, jbyteArray cipher, jobject messageBuffer) {
    printf("Decryption called\n");

    // Get the private key array from Java
    jbyte* privKeyPtr = env->GetByteArrayElements(privKey, NULL);
    if (privKeyPtr == nullptr) {
        std::cerr << "Error accessing private key array." << std::endl;
        return;
    }

    // Get the cipher array from Java
    jbyte* cipherPtr = env->GetByteArrayElements(cipher, NULL);
    if (cipherPtr == nullptr) {
        std::cerr << "Error accessing cipher array." << std::endl;
        return;
    }

    // Get the message buffer from Java (should be passed as a direct ByteBuffer)
    uint16_t* messagePtr = (uint16_t*)env->GetDirectBufferAddress(messageBuffer);
    if (messagePtr == nullptr) {
        std::cerr << "Error accessing message ByteBuffer memory." << std::endl;
        return;
    }

    // Call the Kyber API decryption function
    decryption_ptr((uint8_t*)privKeyPtr, (uint8_t*)cipherPtr, messagePtr);

    // Release JNI arrays
    env->ReleaseByteArrayElements(privKey, privKeyPtr, 0);
    env->ReleaseByteArrayElements(cipher, cipherPtr, 0);
}

--- Entry 2 ---
Filename: com_kyber_quantum_QuantumWrapper.h
Path: cpp\com_kyber_quantum_QuantumWrapper.h
Content:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_kyber_quantum_QuantumWrapper */

#ifndef _Included_com_kyber_quantum_QuantumWrapper
#define _Included_com_kyber_quantum_QuantumWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_kyber_quantum_QuantumWrapper
 * Method:    keygeneration
 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)V
 */
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_keygeneration
  (JNIEnv *, jclass, jobject, jobject);

/*
 * Class:     com_kyber_quantum_QuantumWrapper
 * Method:    encryption
 * Signature: ([BLjava/nio/ByteBuffer;[B)V
 */
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_encryption
  (JNIEnv *, jclass, jbyteArray, jobject, jbyteArray);

/*
 * Class:     com_kyber_quantum_QuantumWrapper
 * Method:    decryption
 * Signature: ([B[BLjava/nio/ByteBuffer;)V
 */
JNIEXPORT void JNICALL Java_com_kyber_quantum_QuantumWrapper_decryption
  (JNIEnv *, jclass, jbyteArray, jbyteArray, jobject);

#ifdef __cplusplus
}
#endif
#endif


--- Entry 3 ---
Filename: kyber_API.h
Path: cpp\kyber_API.h
Content:
uint8_t ekpke[1568];
uint8_t dkpke[1536];
uint8_t c[1568];



void keygeneration(uint8_t ekpke[],uint8_t dkpke[]);

void encryption(uint8_t ekpke[],uint8_t c[],uint16_t messg[]);

void decryption(uint8_t dkpke[],uint8_t c[],uint16_t messg[]);
	




--- Entry 4 ---
Filename: QuantumApplication.java
Path: java\com\kyber\quantum\QuantumApplication.java
Content:
package com.kyber.quantum;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class QuantumApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuantumApplication.class, args);
    }

}


--- Entry 5 ---
Filename: QuantumWrapper.java
Path: java\com\kyber\quantum\QuantumWrapper.java
Content:
package com.kyber.quantum;

import com.kyber.quantum.model.Crypto;
import org.springframework.stereotype.Service;

import java.nio.ByteBuffer;

@Service
public class QuantumWrapper {
    private static Crypto crypt = Crypto.getInstance(); // Initialize once at the start

    static {
        try {
            System.load("C:\\Quantam\\spring\\Quantum\\src\\main\\resources\\libs\\quantumlib.dll");
            System.out.println("Library loaded successfully.");
        } catch (UnsatisfiedLinkError | SecurityException e) {
            throw new RuntimeException("Failed to load the library: " + e.getMessage());
        }
    }

    // Declare the native method
    public static native void keygeneration(ByteBuffer pubKeyBuffer, ByteBuffer privKeyBuffer);
    public static native void encryption(byte[] privKey, ByteBuffer ciphertext, byte[] message);
    public static native void decryption(byte[] pubKey, byte[] ciphertext, ByteBuffer message);

    // Method to generate keys if not already generated
    private void ensureKeysGenerated() {
        if (crypt.getPubKey() == null || crypt.getPrivKey() == null) {
            getKeys();
        }
    }

    public void getKeys() {
        // Allocate direct memory for public and private keys
        ByteBuffer pubKeyBuffer = ByteBuffer.allocateDirect(1568);  // Size of pubKey
        ByteBuffer privKeyBuffer = ByteBuffer.allocateDirect(1536); // Size of privKey

        try {
            System.out.println("Calling native method for key generation.");
            keygeneration(pubKeyBuffer, privKeyBuffer);
            System.out.println("Key generation completed.");
        } catch (RuntimeException e) {
            throw new RuntimeException("Error during key generation: " + e.getMessage());
        }

        byte[] pubKey = new byte[1568];
        byte[] privKey = new byte[1536];

        // Transfer data from ByteBuffer to byte arrays
        pubKeyBuffer.get(pubKey);
        privKeyBuffer.get(privKey);

        crypt.setPubKey(pubKey);
        crypt.setPrivKey(privKey);

        // Print keys in hex format
        printKey(pubKey, "Public Key");
        printKey(privKey, "Private Key");
    }

    // Helper method to print keys in hexadecimal format
    private void printKey(byte[] key, String keyType) {
        System.out.println(keyType + ":");
        for (int i = 0; i < key.length; i++) {
            System.out.printf("%02X ", key[i]);
            if ((i + 1) % 16 == 0) System.out.println();  // Print new line after every 16 bytes
        }
        System.out.println();  // New line at the end for readability
    }

    public ByteBuffer encrypt(ByteBuffer cipherText, byte[] message) {
        ensureKeysGenerated();  // Ensure that the keys are generated before encryption
        try {
            encryption(crypt.getPubKey(), cipherText, message);
            System.out.println("Encryption completed.");
            return cipherText;
        } catch (Exception e) {
            throw new RuntimeException("Encryption failed: " + e.getMessage());
        }
    }

    public ByteBuffer decrypt(byte[] cipher, ByteBuffer message) {
        ensureKeysGenerated();  // Ensure that the keys are generated before decryption
        try {
            decryption(crypt.getPrivKey(), cipher, message);
            System.out.println("Decryption completed.");
            return message;
        } catch (Exception e) {
            throw new RuntimeException("Decryption failed: " + e.getMessage());
        }
    }
}


--- Entry 6 ---
Filename: QuantumController.java
Path: java\com\kyber\quantum\controller\QuantumController.java
Content:
package com.kyber.quantum.controller;

import com.kyber.quantum.model.Crypto;
import com.kyber.quantum.services.QuantumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.RequestBody;

import java.security.NoSuchAlgorithmException;
import java.util.Base64;

@RestController
@RequestMapping("/crypto")
public class QuantumController {

    @Autowired
    private QuantumService quantumService;

    @Autowired
    private Crypto crypto;

    static byte[] cipherText=new byte[1568];

    static byte[] plainText=new byte[1568];



    @GetMapping("/test")
    public Object generateKeys() {
        crypto=Crypto.getInstance();
        quantumService.getKeys();
        return ResponseEntity.ok(crypto);
    }

    @GetMapping("/encrypt")
    public Object encryptAES(@RequestBody String requestBody) {
        try {
            // Parse JSON and extract the 'AESKey' field
            JSONObject json = new JSONObject(requestBody);
            String AESKey = json.getString("AESKey");

            // Convert AESKey to byte array
            byte[] message = AESKey.getBytes();

            // Perform encryption
            cipherText = quantumService.encrypt(message);
            return ResponseEntity.ok(Base64.getEncoder().encodeToString(cipherText));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/decrypt")
    public Object decryptAES(@RequestBody String requestBody) {
        try{

            JSONObject json = new JSONObject(requestBody);
            byte[] cipher = json.getString("decrypt").getBytes();
            plainText = quantumService.decrypt(cipher);
            return ResponseEntity.ok(Base64.getEncoder().encodeToString(plainText));
        }
        catch(Exception e)
        {
            throw new RuntimeException(e);
        }

    }
}


--- Entry 7 ---
Filename: Crypto.java
Path: java\com\kyber\quantum\model\Crypto.java
Content:
package com.kyber.quantum.model;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class Crypto {

    private byte[] pubKey;
    private byte[] privKey;
    private byte[] cipherText;
    private byte[] message;

    private static Crypto crypto = null;

    private Crypto() {
        this.pubKey = new byte[1568];
        this.privKey = new byte[1536];
        this.cipherText = new byte[1568];
        this.message = new byte[32];
    }

    private Crypto(byte[] pubKey, byte[] privKey, byte[] cipherText, byte[] message) {
        this.pubKey = pubKey;
        this.privKey = privKey;
        this.cipherText = cipherText;
        this.message = message;
    }

    public static Crypto getInstance() {
        if (crypto == null) {
            crypto = new Crypto();
        }
        return crypto;
    }

    public byte[] getPubKey() {
        return pubKey;
    }

    public void setPubKey(byte[] pubKey) {
        this.pubKey = pubKey;
    }

    public byte[] getPrivKey() {
        return privKey;
    }

    public void setPrivKey(byte[] privKey) {
        this.privKey = privKey;
    }

    public byte[] getCipherText() {
        return cipherText;
    }

    public void setCipherText(byte[] cipherText) {
        this.cipherText = cipherText;
    }

    public byte[] getMessage() {
        return message;
    }

    public void setMessage(byte[] message) {
        this.message = message;
    }

}


--- Entry 8 ---
Filename: QuantumService.java
Path: java\com\kyber\quantum\services\QuantumService.java
Content:
package com.kyber.quantum.services;

import com.kyber.quantum.QuantumWrapper;
import com.kyber.quantum.model.Crypto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;

@Service
public class QuantumService {

    @Autowired
    private QuantumWrapper wrapper;

    public Crypto getKeys()
    {
        Crypto crypt=Crypto.getInstance();
        wrapper.getKeys();
        System.out.println(crypt.toString());
        return crypt;
    }


    public byte[] encrypt(byte[] message) throws NoSuchAlgorithmException {

        try{
            ByteBuffer ciphertext=ByteBuffer.allocateDirect(1568);

            wrapper.encrypt(ciphertext,message);
            byte[] cipher=new byte[ciphertext.capacity()];
            ciphertext.get(cipher);
            for(byte b:cipher)
            {
                System.out.print(b);
            }
            return cipher;
        }
        catch(Exception e){
            throw new RuntimeException(e.getMessage());
        }



    }


    public byte[] decrypt(byte[] cipher) throws NoSuchAlgorithmException {
        try{
            ByteBuffer message=ByteBuffer.allocateDirect(32);
            message=wrapper.decrypt(cipher,message);
            byte[] decryptedText=new byte[32];
            message.get(decryptedText);
            for(byte b:decryptedText)
            {
                System.out.print(b);
            }
            return decryptedText;
        }
        catch(Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }
}