Demonstrates the use of standard Java cryptographic libraries to generate key pairs, securely exchange secrets, encrypt messages, generate/verify JSON Web Tokens (JWTs), and manage self-signed TLS (X.509) Certificates.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Copyright © 2026, Paul Wood.
Project Maintainer: paulowoody
Email: paulowoody@users.noreply.github.com
Issues: Please use the GitHub Issues page for bug reports or feature requests.
The main demonstration (net.perseity.Demo) performs the following steps to simulate a secure exchange between two parties ("Alice" and "Bob"), followed by real-world API and secure server scenarios:
Part 1: Key Pair Generation (Asymmetric)
- Alice and Bob both generate their own personal RSA key pairs.
- The generated keys are immediately saved to disk (
alice.pub/alice.keyandbob.pub/bob.key) and then reloaded to simulate a real-world persistent identity.
Part 2: Secure Key Exchange (Asymmetric + Symmetric)
- Alice creates a random, highly secure AES shared secret.
- Alice loads Bob's Public Key from the 'bob.pub' file. By using a Public-Only instance, she ensures her own private key remains separate and safe.
- Bob receives the package and decrypts it using his Private RSA key. Both parties now share the same AES secret.
Part 3: Secure Messaging & Digital Signatures (Symmetric + Asymmetric)
- Bob encrypts a secret message using the new AES shared secret (much faster for data than RSA).
- Bob signs the encrypted message using his Private RSA key to prove it came from him.
- Alice verifies the signature is valid using Bob's Public Key only.
- Alice decrypts the encrypted secret message using their shared AES secret.
Part 4: Real-World JWT Scenario (HMAC)
- A Server uses the shared secret as an HMAC key to generate a short-lived JSON Web Token (JWT) for a Client.
- The Client attaches the JWT to an API request.
- The Server verifies the token's cryptographic signature and expiration timestamp to grant access.
- A Hacker attempts to tamper with the token's payload, but the Server detects the invalid signature and rejects it.
Part 5: Real-World TLS Certificate Scenario (X.509)
- A Server (Alice) uses her RSA key pair to generate a self-signed TLS Certificate to secure an HTTPS website.
- A Client (Bob) connects and downloads the certificate.
- Bob verifies the digital signature of the certificate using Alice's trusted public key to ensure a secure, un-tampered connection.
- A Hacker (Eve) generates a forged certificate to impersonate Alice, but Bob detects the invalid signature and rejects the connection.
Part 6: Secure Email Scenario (Custom Implementation without Third-Party CMS)
Note: True S/MIME compliance requires formatting the cryptographic payloads using a complex standard called CMS (Cryptographic Message Syntax, or PKCS#7). The Java Standard Library does not have internal support for generating CMS EnvelopedData (Encryption). Therefore, to create a fully S/MIME compliant application that standard email clients can natively read, a third-party library like BouncyCastle is required. This project demonstrates the exact same cryptographic concepts (Authenticity, Integrity, and Confidentiality) using only standard Java RSA/AES.
- Alice creates a standard MimeMessage and encrypts/signs it using standard AES and RSA.
- She encrypts the message payload using AES, and encrypts the AES session key using Bob's public RSA key.
- Bob receives the encrypted message and decrypts the session key using his Private Key, and uses it to decrypt the body.
- Bob verifies the signature on the decrypted content against Alice's public key to confirm she sent it and it hasn't been tampered with.
- A Hacker (Eve) intercepts the encrypted email in transit and attempts to decrypt it, but fails because she does not possess Bob's private key.
- A Hacker (Eve) attempts to forge an email claiming to be from Alice by signing it with her own key and encrypting it for Bob. Bob decrypts it, but detects the forgery because the signature verification fails against Alice's known public key.
AsymmetricCipher: An interface defining the contract for public/private key systems (like RSA or ECC). Allows easily swapping algorithms.SymmetricCipher: An interface defining the contract for shared secret systems (like AES). Allows swapping fast encryption algorithms.TokenProvider: An interface for generating and verifying security tokens (like JWT).SecureMessageTransport: An interface for high-level secure message transport (signing and encrypting).MyKeyPair: ImplementsAsymmetricCipherto handle asymmetric cryptography using RSA. Used for key exchange and digital signatures.MyCrypt: ImplementsSymmetricCipherto handle symmetric encryption/decryption using AES-GCM. Used for encrypting actual message data securely and fast.MyJwt: ImplementsTokenProviderto handle the creation and verification of JSON Web Tokens using HMAC SHA-256 signatures.MyTLSCert: Handles the creation, signing, and verification of TLS (X.509) Certificates using internalsun.security.x509APIs.- Note: Because standard Java lacks a public API for certificate generation, this project intentionally uses internal JVM classes to avoid external dependencies. The
pom.xmlconfigures compiler arguments and jar manifest entries (Add-Exports: java.base/sun.security.x509) to bypass the Java Module System restrictions.
- Note: Because standard Java lacks a public API for certificate generation, this project intentionally uses internal JVM classes to avoid external dependencies. The
MySecureEmail: ImplementsSecureMessageTransportto demonstrate secure email concepts (signing, encrypting, decrypting, verifying) using standard Java cryptography instead of heavy third-party S/MIME libraries.Helper: Provides common Base64 (Standard and URL-Safe) encoding/decoding and PEM file operations for Keys and Certificates.
The java-crypt library is deployed to a public Cloudsmith repository. To use it in your own Maven project, add the following to your pom.xml:
<repositories>
<repository>
<id>paulowoody-java-crypt</id>
<url>https://dl.cloudsmith.io/public/paulowoody/java-crypt/maven/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories><dependency>
<groupId>net.perseity</groupId>
<artifactId>java-crypt</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>Ensure you have Java 21 and Maven 3 installed.
This project uses internal JVM APIs (sun.security.x509) for certificate generation to avoid external dependencies. As a result, the pom.xml is configured with:
-source 21and-target 21instead of--release 21, as the latter strictly enforces public API boundaries and would block access to internal classes.-Xlint:-optionsto suppress the compiler warning about not setting the system module location when using-source.--add-exportsto allow the compiler and runtime to access the necessary internal packages.
To compile, run the unit tests, and package the application, run:
mvn clean installNote: The clean goal is configured to also remove temporary cryptographic keys, certificates, and email files (.pem, .key, .eml, etc.) generated in the project root during demonstration runs.
To run the demonstration and see the narrative flow, you can either execute the built assembly JAR:
java -jar target/java-crypt-0.1.0-SNAPSHOT-assembly.jarOr use the Maven exec plugin directly (this will compile the code first if needed):
mvn compile exec:execTo run the unit tests and automatically generate a JaCoCo code coverage report (found in target/site/jacoco/index.html), run:
mvn clean testIn addition to the main library, this repository includes sample projects that demonstrate how to integrate java-crypt into your own applications.
Located in samples/repro-demo, this project shows how to:
- Configure a Maven project to depend on the
java-cryptlibrary. - Access the Cloudsmith Maven repository.
- Correctly set up the JVM export flags (
--add-exports) required for certificate generation. - Implement a full cryptographic flow using the library.
To build and run the sample:
cd samples/repro-demo
mvn clean verify
# Option 1: Run via Maven
mvn compile exec:exec
# Option 2: Run via standalone JAR
java -jar target/repro-demo-1.0-SNAPSHOT-jar-with-dependencies.jarThis project uses dependencyManagement in the pom.xml to explicitly override versions of transitive dependencies that have known security vulnerabilities.
For example, we explicitly manage versions of plexus-archiver and plexus-utils to mitigate Path Traversal and Zip‑Slip vulnerabilities (e.g., CVE‑2023‑37460) found in transitive dependencies from older Maven plugins.
This project automatically generates a CycloneDX Software Bill of Materials (SBOM) during the Maven build. The SBOM provides a complete, machine‑readable list of the libraries used by the application, which is useful for supply‑chain security, auditing, and vulnerability scanning.
The SBOM is produced during the package phase and written to:
-
target/bom.json(JSON format) -
target/bom.xml(XML format)
To generate the SBOM manually, run:
mvn clean package
After the build completes, you can inspect the SBOM files directly or feed them into external tools such as Grype, Dependency-Track, or other SBOM consumers.
CycloneDX specification and tooling details are available at:
This project is configured with the OWASP Dependency-Check Maven Plugin to identify project dependencies and check for known, publicly disclosed vulnerabilities.
The scan is bound to the verify phase. Because it requires an NVD API key, it is optional and must be invoked with the key:
mvn verify -Dnvd.api.key=YOUR_NVD_API_KEYN.B. A key may be obtained from: Request an API Key
The plugin is configured to:
- Fail the build if any vulnerabilities with a CVSS score of 7.0 or higher are found.
- Generate reports in both HTML and JSON formats in the
target/directory (e.g.,target/dependency-check-report.html).
To avoid passing the API key on the command line every time, you can add it to your global Maven configuration in ~/.m2/settings.xml.
e.g. Add the following inside the <profiles> section of your settings.xml file:
<profiles>
<profile>
<id>owasp-scanning</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<nvd.api.key>YOUR_NVD_API_KEY_HERE</nvd.api.key>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nvd-security</activeProfile>
</activeProfiles>With this configuration, you can run the scan simply by calling:
mvn verifyThis project prioritises cryptographic best practices while remaining a educational resource. Recent updates (March 2026) have addressed several key security areas:
- Entropy: Transitioned to modern
SecureRandomdefaults for high-quality entropy. - Key Strength: Upgraded default RSA key sizes to 2048-bit.
- Robustness: Fixed issues in password-based key derivation (PBKDF2) and added validation for malformed ciphertexts.
- Consistency: Enforced UTF-8 charset across all cryptographic operations to ensure cross-platform compatibility.
For a detailed technical breakdown of these fixes, see docs/SecurityUpdates.md.
The project already covers several foundational and practical applications of cryptography. To expand it with more real-world examples, we could consider the following:
-
Password Hashing & Key Derivation (KDF) While SymmetricCipher likely uses keys, demonstrating how to securely derive those keys from user passwords using industry standards like Argon2, bcrypt, or PBKDF2 is a critical real-world use case.
-
Time-based One-Time Passwords (TOTP) Implementing the algorithm behind Google Authenticator (RFC 6238). This combines HMAC with a moving factor (time) and is the standard for modern Multi-Factor Authentication (MFA).
-
Key Exchange (Diffie-Hellman / ECDH) The project has MyKeyPair, but showing how two parties can establish a shared secret over an insecure channel using Elliptic Curve Diffie-Hellman (ECDH) is fundamental to how TLS works under the hood.
-
JSON Object Encryption (JWE) You already have MyJwt (which is typically signed, i.e., a JWS). Adding JWE would demonstrate how to encrypt the payload of a JWT so that sensitive identity information isn't visible to the client or intermediaries.
-
Secure File Storage (AES-GCM) A utility for encrypting/decrypting local files. This would involve handling initialization vectors (IVs), salt management, and authenticated encryption to ensure the file hasn't been tampered with while stored.
-
Digital Signatures (Detached & CMS) Extending the asymmetric examples to show detached signatures for software updates or CMS (Cryptographic Message Syntax) for formal document signing.
- 0.1.0-SNAPSHOT
- 2026-03-17, Key Persistence & Loading:
- Updated
Demoto save generated RSA keys to disk and reload them. - Alice now explicitly loads Bob's public key from a
.pubfile for encryption. - Synchronized
samples/repro-demowith these changes.
- Updated
- 2026-03-17, Public Key Separation:
- Added explicit support for "Public-Key-Only" instances in
MyKeyPair. - Added
getPublicOnly()method to safely strip private keys before sharing. - Added constructors and
Helpermethods to load only the public key from PEM files. - Updated
Demoand documentation to follow standard public-key infrastructure patterns.
- Added explicit support for "Public-Key-Only" instances in
- 2026-03-16, Security & Robustness Improvements:
- Fixed PBKDF2 salt handling to allow consistent key re-derivation.
- Transitioned to modern
SecureRandom(replaced legacySHA1PRNG). - Increased default RSA key size from 1024-bit to 2048-bit.
- Improved robustness of symmetric decryption and signature extraction.
- Enforced UTF-8 charset consistency across all cryptographic operations.
- Added detailed documentation in docs/SecurityUpdates.md.
- 2026-03-16, Added OWASP Dependency‑Check for vulnerability scanning, security overrides for transitive dependencies, and enhanced Maven build with Javadoc and Source plugins.
- 2026-03-13, Reorganized sample code into
samples/repro-demoand aligned project structure. - 2026-03-10, Refactored to use ephemeral cryptographic keys in tests and support for Java 21+
- 2026-03-10, Added Secure Email functions with pure standard library
MySecureEmailimplementation. - 2026-03-10, Added Hacker/Eve interception and forgery scenarios to both the TLS and Secure Email examples.
- 2026-03-10, Updated
Demo.javato output secure email payloads as.emlfiles to disk for inspection. - 2026-03-09, Added TLS/X.509 self-signed certificate generation using native Java libraries (
sun.security.x509). - 2026-03-09, Added JWT/HMAC support, real-world scenario narrative, extensive Javadocs, and URL-Safe Base64 helpers.
- 2026-03-09, Update documentation with demonstration flow and build instructions.
- 2025-06-24, Added RSA/AES functionality.
- 2026-03-17, Key Persistence & Loading: