Do proper class isolation
This commit is contained in:
parent
4a1e3c915d
commit
dd8a863cb3
9 changed files with 117 additions and 46 deletions
83
dependency-reduced-pom.xml
Normal file
83
dependency-reduced-pom.xml
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>ai.nomyo</groupId>
|
||||||
|
<artifactId>nomyo4J</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.13.0</version>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.44</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.5.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.6.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputFile>${project.build.directory}/${project.build.finalName}.jar</outputFile>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.44</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>5.12.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>local-repository</id>
|
||||||
|
<url>http://gamingvm.home.lan:8080/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.target>25</maven.compiler.target>
|
||||||
|
<maven.compiler.source>25</maven.compiler.source>
|
||||||
|
</properties>
|
||||||
|
</project>
|
||||||
24
pom.xml
24
pom.xml
|
|
@ -36,6 +36,13 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>local-repository</id>
|
||||||
|
<url>http://gamingvm.home.lan:8080/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
@ -57,6 +64,23 @@
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.0</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.6.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputFile>${project.build.directory}/${project.build.finalName}.jar</outputFile>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import java.util.Set;
|
||||||
/**
|
/**
|
||||||
* Protocol, crypto, and configuration constants. Immutable — used for downgrade detection.
|
* Protocol, crypto, and configuration constants. Immutable — used for downgrade detection.
|
||||||
*/
|
*/
|
||||||
public final class Constants {
|
final class Constants {
|
||||||
|
|
||||||
// ── Protocol Constants ──────────────────────────────────────────
|
// ── Protocol Constants ──────────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import lombok.Setter;
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class EncryptedRequest {
|
class EncryptedRequest {
|
||||||
|
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
private static final Gson GSON = new GsonBuilder().create();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
package ai.nomyo;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry point — loads RSA keys and validates key length.
|
|
||||||
*/
|
|
||||||
public class Main {
|
|
||||||
|
|
||||||
static void main() {
|
|
||||||
SecureChatCompletion secureChatCompletion = new SecureChatCompletion(Constants.DEFAULT_BASE_URL, "NOMYO_AI_E2EE_INFERENCE");
|
|
||||||
List<Map<String, Object>> messages = List.of(
|
|
||||||
Map.of("role", "user", "content", "Hello! How are you today?")
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, Object> kwargs = Map.of(
|
|
||||||
"security_tier", "standard",
|
|
||||||
"temperature", 0.7
|
|
||||||
);
|
|
||||||
|
|
||||||
var response = secureChatCompletion.create(
|
|
||||||
"Qwen/Qwen3-0.6B",
|
|
||||||
messages,
|
|
||||||
kwargs);
|
|
||||||
|
|
||||||
System.out.println(response.toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package ai.nomyo.util;
|
package ai.nomyo;
|
||||||
|
|
||||||
import ai.nomyo.SecureMemory;
|
|
||||||
import ai.nomyo.SecureMemory.SecureBuffer;
|
import ai.nomyo.SecureMemory.SecureBuffer;
|
||||||
import ai.nomyo.errors.SecurityError;
|
import ai.nomyo.errors.SecurityError;
|
||||||
|
|
||||||
|
|
@ -13,7 +12,6 @@ import javax.crypto.SecretKeyFactory;
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
import javax.crypto.spec.PBEKeySpec;
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
|
@ -2,7 +2,6 @@ package ai.nomyo;
|
||||||
|
|
||||||
import ai.nomyo.errors.*;
|
import ai.nomyo.errors.*;
|
||||||
import ai.nomyo.util.PEMConverter;
|
import ai.nomyo.util.PEMConverter;
|
||||||
import ai.nomyo.util.Pass2Key;
|
|
||||||
import ai.nomyo.SecureMemory.SecureBuffer;
|
import ai.nomyo.SecureMemory.SecureBuffer;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
|
@ -40,7 +39,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||||
/**
|
/**
|
||||||
* Low-level client: key management, hybrid encryption, HTTP with retry, response decryption. Used by {@link SecureChatCompletion}.
|
* Low-level client: key management, hybrid encryption, HTTP with retry, response decryption. Used by {@link SecureChatCompletion}.
|
||||||
*/
|
*/
|
||||||
public class SecureCompletionClient {
|
class SecureCompletionClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOMYO router base URL (trailing slash stripped).
|
* NOMYO router base URL (trailing slash stripped).
|
||||||
|
|
@ -405,9 +404,10 @@ public class SecureCompletionClient {
|
||||||
throw new RuntimeException(new SecurityError("RSA-OAEP key wrapping failed: " + e.getMessage(), e));
|
throw new RuntimeException(new SecurityError("RSA-OAEP key wrapping failed: " + e.getMessage(), e));
|
||||||
}
|
}
|
||||||
|
|
||||||
String encryptedAESKeyB64 = Base64.getEncoder().encodeToString(encryptedAESKey);
|
|
||||||
|
|
||||||
try (SecureBuffer secureEncryptedAESKey = SecureMemory.secureByteArray(encryptedAESKey)) {
|
try (SecureBuffer secureEncryptedAESKey = SecureMemory.secureByteArray(encryptedAESKey)) {
|
||||||
|
|
||||||
|
Arrays.fill(encryptedAESKey, (byte) 0);
|
||||||
|
|
||||||
byte[] tag = Arrays.copyOfRange(ciphertext, ciphertext.length - Constants.GCM_TAG_SIZE, ciphertext.length);
|
byte[] tag = Arrays.copyOfRange(ciphertext, ciphertext.length - Constants.GCM_TAG_SIZE, ciphertext.length);
|
||||||
|
|
||||||
byte[] actualCiphertext = Arrays.copyOf(ciphertext, ciphertext.length - Constants.GCM_TAG_SIZE);
|
byte[] actualCiphertext = Arrays.copyOf(ciphertext, ciphertext.length - Constants.GCM_TAG_SIZE);
|
||||||
|
|
@ -416,13 +416,11 @@ public class SecureCompletionClient {
|
||||||
|
|
||||||
request.setVersion(Constants.PROTOCOL_VERSION);
|
request.setVersion(Constants.PROTOCOL_VERSION);
|
||||||
request.setAlgorithm(Constants.HYBRID_ALGORITHM);
|
request.setAlgorithm(Constants.HYBRID_ALGORITHM);
|
||||||
request.setEncryptedPayload(new EncryptedRequest.EncryptedPayload(Base64.getEncoder().encodeToString(actualCiphertext), encryptedAESKeyB64, Base64.getEncoder().encodeToString(tag)));
|
request.setEncryptedPayload(new EncryptedRequest.EncryptedPayload(Base64.getEncoder().encodeToString(actualCiphertext), Base64.getEncoder().encodeToString(secureNonce.getAsByteArray()), Base64.getEncoder().encodeToString(tag)));
|
||||||
request.setEncryptedAESKey(encryptedAESKeyB64);
|
request.setEncryptedAESKey(Base64.getEncoder().encodeToString(secureEncryptedAESKey.getAsByteArray()));
|
||||||
request.setKeyAlgorithm(Constants.KEY_WRAP_ALGORITHM);
|
request.setKeyAlgorithm(Constants.KEY_WRAP_ALGORITHM);
|
||||||
request.setPayloadAlgorithm(Constants.PAYLOAD_ALGORITHM);
|
request.setPayloadAlgorithm(Constants.PAYLOAD_ALGORITHM);
|
||||||
|
|
||||||
Arrays.fill(encryptedAESKey, (byte) 0);
|
|
||||||
|
|
||||||
return request.toJson().getBytes(StandardCharsets.UTF_8);
|
return request.toJson().getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.Map;
|
||||||
* Cross-platform memory locking and secure zeroing for sensitive cryptographic buffers. Fails gracefully if unavailable.
|
* Cross-platform memory locking and secure zeroing for sensitive cryptographic buffers. Fails gracefully if unavailable.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("SameReturnValue")
|
@SuppressWarnings("SameReturnValue")
|
||||||
public final class SecureMemory {
|
final class SecureMemory {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static final boolean HAS_MEMORY_LOCKING;
|
private static final boolean HAS_MEMORY_LOCKING;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package ai.nomyo;
|
package ai.nomyo;
|
||||||
|
|
||||||
import ai.nomyo.errors.SecurityError;
|
import ai.nomyo.errors.SecurityError;
|
||||||
import ai.nomyo.util.Pass2Key;
|
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.junit.jupiter.api.parallel.Execution;
|
import org.junit.jupiter.api.parallel.Execution;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue