Skip to content

callibrity/dynaform-api

Repository files navigation

DynaForm API

DynaForm API is a secure, zero-knowledge dynamic form service that enables workflow engines to collect sensitive user input through encrypted form submissions. Built with Spring Boot 4.0 and Java 25, it provides end-to-end encryption using both classical (RSA-OAEP) and post-quantum (ML-KEM) cryptography.

GitHub License

Features

  • Zero-Knowledge Architecture: Service never sees plaintext data after submission
  • Envelope Encryption: AES-256-GCM for data encryption + public key encapsulation
  • Post-Quantum Ready: Support for ML-KEM (Kyber) alongside RSA-OAEP
  • Dynamic JSON Schemas: Define form structure using JSON Schema v7+
  • Cryptographically Signed Tokens: Ed25519-signed form access tokens
  • TTL-Based Lifecycle: Automatic expiration and cleanup of sensitive data
  • RFC 7807 Error Handling: Standardized ProblemDetail error responses

Technology Stack

  • Java 25
  • Spring Boot 4.0.0
  • PostgreSQL (production) / H2 (testing)
  • Liquibase for database migrations
  • Jackson 3 for JSON processing
  • Bouncy Castle for cryptographic operations
  • networknt/json-schema-validator for JSON Schema validation

Quick Start

Prerequisites

  • Java 25
  • Maven 3.9+
  • PostgreSQL 16+ (for production)

Building from Source

git clone https://github.com/callibrity/dynaform-api.git
cd dynaform-api
mvn clean install

Running the Application

mvn spring-boot:run

The application will start on port 8080 by default.

Running Tests

mvn clean test

All 32 tests should pass, covering:

  • 14 ExchangeService tests
  • 17 Ed25519TokenService tests
  • 1 Spring Boot context load test

API Endpoints

Workflow Engine Endpoints

Create Exchange

POST /exchanges
Content-Type: application/json

{
  "exchangeId": "optional-custom-id",
  "schema": { JSON Schema object },
  "instructions": "Instructions for form completion",
  "publicKey": "base64-encoded-public-key",
  "encryptionScheme": "ML_KEM_768",
  "ttl": "PT24H",
  "accessMode": "PUBLIC_LINK"
}

Response:

{
  "exchangeId": "generated-uuid",
  "formAccessToken": "signed-access-token",
  "formUrl": "/forms/generated-uuid?token=signed-access-token"
}

Retrieve Encrypted Submission

GET /exchanges/{exchangeId}/result

Response:

{
  "exchangeId": "...",
  "encryptionEnvelope": "{JSON envelope with ciphertext}",
  "submittedAt": "2025-12-07T10:30:00Z",
  "expiresAt": "2025-12-08T10:30:00Z"
}

Form UI Endpoints

Get Form Schema

GET /forms/{exchangeId}?token={formAccessToken}

Response:

{
  "exchangeId": "...",
  "schema": { JSON Schema object },
  "instructions": "Form instructions"
}

Submit Form Data

POST /forms/{exchangeId}/submit?token={formAccessToken}
Content-Type: application/json

{
  "formData": "{ user input matching schema }"
}

Response:

{
  "exchangeId": "...",
  "submittedAt": "2025-12-07T10:30:00Z"
}

Encryption Schemes

DynaForm supports multiple encryption schemes for future-proof security:

Scheme Key Size Quantum Safe Status
RSA_OAEP_4096 4096-bit ❌ No ✅ Fully Implemented
ML_KEM_768 1184 bytes ✅ Yes ⚠️ Stub (awaiting PQC library)
ML_KEM_1024 1568 bytes ✅ Yes ⚠️ Stub (awaiting PQC library)

All schemes use AES-256-GCM for symmetric data encryption.

Envelope Encryption Process

  1. Generate random AES-256 symmetric key
  2. Encrypt form data with AES-GCM (produces ciphertext + auth tag)
  3. Encrypt/encapsulate symmetric key with recipient's public key
  4. Return envelope containing:
    • ciphertext: Encrypted form data
    • encryptedKey / encapsulatedKey: Wrapped symmetric key
    • iv: Initialization vector for GCM
    • tag: Authentication tag for GCM

The service never has access to the recipient's private key and cannot decrypt submissions.

Configuration

Application Properties

# Database Configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/dynaform
spring.datasource.username=dynaform
spring.datasource.password=your-password

# Token Service
dynaform.token.signing-key=base64-encoded-ed25519-private-key
dynaform.token.ttl-default=PT24H
dynaform.token.ttl-min=PT1H
dynaform.token.ttl-max=P7D

# Encryption
dynaform.encryption.default-scheme=ML_KEM_768

Generating Ed25519 Signing Key

# Generate private key
openssl genpkey -algorithm Ed25519 -out private.pem

# Extract base64-encoded key
openssl pkey -in private.pem -outform DER | base64

Security Features

Zero-Knowledge Architecture

  • Service never stores or logs plaintext form data
  • All submissions encrypted before persistence
  • Encryption keys managed by workflow engine

Token Security

  • Ed25519 cryptographic signatures (fast, secure, battle-tested)
  • Unique token IDs prevent replay attacks
  • TTL-based automatic expiration
  • 404 responses on invalid tokens (prevents enumeration)

Data Lifecycle

  • AWAITING_INPUT: Exchange created, waiting for submission
  • COMPLETED: Form submitted and encrypted
  • EXPIRED: TTL exceeded, data eligible for cleanup

Architecture

Layers

┌─────────────────────────────────┐
│     REST Controllers            │
│  (ExchangeController,           │
│   FormController)                │
└────────────┬────────────────────┘
             │
┌────────────▼────────────────────┐
│     Service Layer               │
│  (ExchangeService,              │
│   SubmissionService,            │
│   RetrievalService)             │
└────────────┬────────────────────┘
             │
┌────────────▼────────────────────┐
│  Encryption Infrastructure      │
│  (Enum-as-Factory Pattern)      │
└────────────┬────────────────────┘
             │
┌────────────▼────────────────────┐
│     JPA Repositories            │
│  (PostgreSQL / H2)              │
└─────────────────────────────────┘

Key Design Patterns

  • Enum-as-Factory: EncryptionScheme enum instances contain encryptor implementations
  • Strategy Pattern: Pluggable EnvelopeEncryptor implementations
  • DTO Records: Immutable data transfer objects using Java records
  • ProblemDetail: RFC 7807 standard error responses

Development

Adding License Headers

This project uses the mycila license-maven-plugin to enforce Apache 2.0 license headers:

# Check for missing headers
mvn license:check

# Add headers to files
mvn license:format

Code Style

  • Minimal JPA annotations (avoid @Column unless necessary)
  • Use @Lob for large text fields
  • Record types for immutable DTOs
  • Service layer independent of controller layer

License

This project is licensed under the Apache License 2.0—see the LICENSE file for details.

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass (mvn clean test)
  2. Code includes proper license headers
  3. Follow existing code style and patterns
  4. Add tests for new functionality

Roadmap

  • Complete ML-KEM implementation with Bouncy Castle PQC
  • Add TTL enforcement cleanup jobs
  • Implement rate limiting
  • Add OpenAPI/Swagger documentation
  • Create integration tests for controllers
  • Add security headers (CORS, CSP)
  • Implement monitoring with Spring Boot Actuator

Support

For questions or issues, please open an issue on GitHub.


Built with ☕ using Java 25 and Spring Boot 4.0

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages