Skip to main content

Security

In fact, this document can be considered the most core of all documents.

The Quant team treats security issues very deeply and sensitively. User activity must not be perceived by the provider side as well as external parties. Sensitive data generated internally or assigned by user input in all Quant projects must be automatically wiped, and even when creating files, the implementation details must be thoroughly analyzed for potential security vulnerabilities and preventive measures must be applied.

When sensitive data must be utilized, pass a copy to prevent forced destruction of the original while managing the data safely. This requires technically somewhat complex implementation, but only by recognizing such heavy responsibility can we take a step closer to Quant's core goal, security. Please review security-related documents, including this one, closely and comply with your obligations.

note

This document is written to inform Quant team members how to maintain and manage client or their own secrets within their projects or within projects (i.e., applications).

To Improve Project Security

As mentioned earlier, it is important that sensitive data assigned by user input be automatically zero-wiped and that a copy of the data be passed. When implementing specific features in a project, and if that implementation requires processing user data, do not store that data in global (or local) variables.

Technically, we all know that data is stored in the Stack or Heap. And if it is stored in this memory area, and if you are a security professional, you know how stupid the Garbage Collector is.

Why the Garbage Collector (GC) is called stupid

First of all, information about GC is organized in 'Deep Blue', a past Java lecture document of the Quant team. As stated in Deep Blue, GC plays a key role in Java's memory management system, literally a memory cleaner.

It helps the program run smoothly by automatically finding and reclaiming objects that are no longer in use from memory, without the programmer having to manage memory deallocation directly.

It actually does a lot of useful work.

However, GC shows laziness by not immediately releasing memory when an object is no longer referenced, but collecting it later. During this process, sensitive data such as passwords, encryption keys, and personal information remain in memory for a considerable period, exposing them to risks such as heap dump attacks.

And even if an object is removed from memory, the memory space may not be immediately wiped with 0, so residual data may remain until reallocation.

So what can be done 'to improve project security'? In fact, the safest way is to use the Sensitive Data Container of EntanglementLib, but we will focus on enabling developers to build high-security workspaces themselves.

In accordance with the provided document style, we write a specific guide to technically strengthen the security of the project.

Beware of Immutable Objects

In Java, String is a representative immutable object. While this is advantageous for ensuring thread-safety and optimizing performance in general application development, it is the worst enemy from a security perspective.

If you create a password or encryption key with a string literal or String object, that data is stored in the String Constant Pool. Even if the developer directly assigns null to the variable, the actual data remains in the heap memory in plaintext form until the GC runs to clean up and overwrite that memory area.

Therefore, sensitive data must use mutable primitive arrays. Use char[] or byte[] instead of String for passwords or key data.

Password Declaration: Good and Bad Examples
// [Bad] Strings are immutable, so they cannot be immediately erased from memory
String password = "super_secret_password";

// [Good] Arrays are mutable, so data can be overwritten after use
char[] password = {'s', 'u', 'p', 'e', 'r', '_', 's', 'e', 'c', 'r', 'e', 't'};

Explicit Erasure

If you used an array, you must overwrite that memory space with meaningless data (usually 0) immediately after use. This is called 'zeroize'. The Quant team strongly recommends performing this process in the finally block of all sensitive data processing logic.

import java.util.Arrays;

public void handleSensitiveData(char[] rawPassword) {
try {
// do cryptographic operations...
// Perform encryption logic using sensitive data
} finally {
// Immediate memory erasure after use
if (rawPassword != null) {
Arrays.fill(rawPassword, '\0');
}
}
}

warning

Simply filling an array with 0 may result in the code being removed by compiler optimization or the JIT (Just-In-Time) compiler. EntanglementLib uses native-level memory fences and erasure logic via the FFM API to prevent this, but in a pure Java environment, you must force the compiler not to ignore the code by overwriting with SecureRandom or using loops.

Get Out of the Heap

The FFM (Foreign Function & Memory) API, officially introduced in Java 22, is the core of the high-performance and high-security system pursued by the Quant team. Heap memory is under the management of the GC, making it difficult to predict the movement and lifecycle of data. On the other hand, using the FFM API allows direct allocation and control of native memory outside the heap (Off-heap).

Allocate sensitive data to native memory via java.lang.foreign.Arena instead of the heap, and manage it with java.lang.foreign.MemorySegment. This method is easy to combine with system calls that prevent memory pages from being swapped at the OS level, and allows memory to be released exactly when desired without GC interference.

Using FFM API
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueChangedLayout;

public void processKeyOffHeap(byte[] keyData) {
// confined arena: When the try-with-resources block ends,
// memory is deterministically released
try (Arena arena = Arena.ofConfined()) {
// Native memory allocation (outside heap)
MemorySegment segment = arena.allocate(keyData.length);

// Copy data
// copy data from heap to off-heap
for (int i = 0; i < keyData.length; i++) {
segment.set(ValueChangedLayout.JAVA_BYTE, i, keyData[i]);
}

// ... perform secure operations ...

// Manual erasure (overwrite before release)
for (long i = 0; i < segment.byteSize(); i++) {
segment.set(ValueChangedLayout.JAVA_BYTE, i, (byte) 0);
}
}
// Arena closes and memory is immediately returned to the OS
}

This pattern can be cumbersome for developers. But remember. Security and convenience are in a trade-off relationship. As developers of the Quant team, we pursue perfect security at the expense of convenience.