Skip to content

enhancement: port CryptX cryptographic toolkit #1220

Open

Description

@fglock

Summary

Port the CPAN CryptX distribution to PerlOnJava so Perl code that depends on its cryptographic APIs can run without native XS code.

Motivation

CryptX is currently a major compatibility blocker for PerlOnJava applications using JWT, OAuth, OpenID Connect, SAML, XML signatures, ACME, encrypted credentials, and related protocols.

The immediate observed case is WebService::GoogleAPI::Client 0.27. Its dependency chain includes Mojo::JWT, which directly loads CryptX for JWT signing and verification. PerlOnJava's CPAN installer reports that CryptX contains XS/C code and cannot compile it. The resulting module load failure aborts all three upstream test programs before any subtests run.

CryptX also has a substantial reverse-dependency surface. Examples include Mojo::JWT, Crypt::JWT, XML::Sig, Net::SAML2, OIDC::Client, Net::ACME2, Net::SSH::Perl, KeePass::Reader, and encryption/database modules.

Proposed scope

Implement the Perl-facing CryptX API using Java-backed cryptography while preserving the upstream module names and behavior wherever practical.

At minimum, investigate and support the APIs required by Mojo::JWT:

  • Crypt::Misc base64url helpers
  • HMAC signing and verification used by HS JWT algorithms
  • RSA signing and verification used by RS JWT algorithms
  • key and digest handling needed by the supported JWT algorithms

Then expand coverage to the rest of the distribution's public families as feasible:

  • Crypt::Digest::*
  • Crypt::Mac::*
  • Crypt::Cipher::* and Crypt::Mode::*
  • Crypt::AuthEnc::*
  • Crypt::PK::*
  • Crypt::KeyDerivation
  • Crypt::PRNG
  • Crypt::Misc
  • Crypt::ASN1

The implementation should use Java standard cryptography or existing project dependencies where they provide compatible primitives. It should not silently downgrade security or change algorithm semantics. Algorithms unavailable from the Java provider should fail explicitly and consistently with the Perl API.

Suggested approach

  1. Obtain and inspect the upstream CryptX Perl and XS/C sources, preserving license and attribution.
  2. Separate the pure-Perl wrappers and constants from the XS entry points.
  3. Implement the required XS-facing methods in Java, using existing PerlOnJava module registration patterns.
  4. Prefer standard Java cryptographic providers and well-defined encoding behavior.
  5. Add a bundled module test suite derived from the upstream tests, beginning with the JWT-required surface.
  6. Compare every new test with native system Perl before using it as a compatibility oracle.
  7. Verify both JVM and interpreter backends.
  8. Test downstream modules, especially Mojo::JWT, Mojo::JWT::Google, and WebService::GoogleAPI::Client.

Acceptance criteria

  • use CryptX, use Crypt::Misc, and the JWT-required CryptX modules load under both PerlOnJava backends.
  • Mojo::JWT can create and verify representative HS256 tokens with matching system-Perl results.
  • Supported RSA JWT operations have matching system-Perl results, including invalid-signature rejection.
  • Base64url encoding/decoding handles padding, empty values, binary data, and malformed input consistently.
  • Upstream or focused bundled tests cover success cases, malformed inputs, wrong keys, wrong algorithms, and context-sensitive return values.
  • WebService::GoogleAPI::Client no longer aborts at module load solely because CryptX is unavailable.
  • Unsupported algorithms are reported clearly rather than producing incorrect cryptographic results.
  • No native XS compilation is required for the supported port.

Related evidence

The CPAN tester failure is the WebService::GoogleAPI::Client 0.27 failure observed on 2026-09-02. Native system Perl can load CryptX and Mojo::JWT when the XS distribution is installed, while the PerlOnJava CPAN build explicitly skips CryptX's XS/C compilation.

References

Activity

  1. fglock commented on Sep 4, 2026

    @fglock
    OwnerAuthor

    Additional downstream evidence: Noise v0.0.2

    CPAN tester run 20260904-185312-10032 attempted Noise v0.0.2. The
    distribution itself is pure Perl and built successfully, but its required
    crypto modules resolve to CryptX v0.091:

    • Crypt::AuthEnc::ChaCha20Poly1305
    • Crypt::AuthEnc::GCM
    • Crypt::Mac::HMAC
    • Crypt::PK::X25519

    PerlOnJava configured and built the CryptX Perl wrapper files, but cannot load
    the native XS backend when Noise tests start:

    Can't load loadable object for module CryptX:
    no Java XS implementation available
    

    All four Noise test programs (t/00_compile.t, t/01_handshake.t,
    t/02_stream.t, and t/99_vectors.t) abort during module loading before any
    subtests run. This is additional downstream verification of the CryptX port
    blocker, not a Noise-specific failure.

    Current MetaCPAN reverse-dependency metadata lists 46 unique distributions
    referencing CryptX, including 43 unique direct runtime requirements:
    https://fastapi.metacpan.org/v1/reverse_dependencies/module/CryptX?page=1

  2. fglock commented on Oct 1, 2026

    @fglock
    OwnerAuthor

    Implementation approach and preliminary effort

    Retain upstream Perl wrappers and implement their XS entry points using the existing Bouncy Castle dependencies and PerlOnJava module registration patterns. Factor reusable RSA key parsing and signing helpers from Crypt::OpenSSL::RSA; reuse digest, cipher and random-byte infrastructure where semantics match.

    Milestone Cumulative effort
    Encoding helpers, digests, HMAC, RSA and HS/RS JWT support 8–15 working days
    ECC/ECDH, AES-GCM and HTTP::Request::Webpush support 15–25 days
    Broad coverage of common algorithms and key formats 30–50 days
    Full upstream compatibility 60–100+ days

    Estimates assume one engineer familiar with PerlOnJava and include testing and integration. Inspection of CryptX 0.091 found 125 Perl modules, 50 XS include files, approximately 450 XS entry points and 164 upstream test files.

    The main compatibility work concerns arguments, return values, padding defaults, key encodings, streaming, cloning and errors. The current SecureRandom-backed Crypt::PRNG wrapper does not reproduce each named generator's state.

    Validate supported APIs against system Perl and both PerlOnJava backends, retaining upstream tests. Include wrong-key and invalid-signature/tag cases. Target Mojo::JWT for the first milestone and all 38 HTTP::Request::Webpush tests for the second.

    HTTP::Request::Webpush 0.15 is a confirmed downstream acceptance target: in CPAN tester run 20261001-123047-11054, system Perl passed all three test programs (38/38 tests), while PerlOnJava aborted before subtests because CryptX 0.091 had no Java XS implementation.

  3. fglock commented on Oct 30, 2026

    @fglock
    OwnerAuthor

    Additional CPAN evidence: Text::Shift 1.00

    CPAN tester run 20261029-123650-2402 failed Text::Shift 1.00 at t/1.t while loading its required Crypt::Cipher dependency from CryptX 0.091:

    Can't load loadable object for module CryptX: no Java XS implementation available
    

    The archived system-Perl oracle installed the native dependency and passed the complete CryptX suite (164 files, 27,296 tests) and Text::Shift (1 file, 1 test). This confirms another downstream load failure attributable to the unsupported CryptX XS backend.

    A refreshed targeted MetaCPAN lookup via dev/tools/cpan_port_priorities.pl found 55 unique released distributions referencing CryptX. Inspecting released/latest metadata and counting only runtime.requires gives 49 unique runtime dependants, of which 29 have release dates in the last three years (cutoff 2023-10-30). Examples include Mail-DKIM2, File-SOPS, AWS-Signature-V4, Crypt-Age, Web-Authn, XML-Sig, Mojo-JWT, and Crypt-JWT. The raw lookup is available at https://fastapi.metacpan.org/v1/reverse_dependencies/module/CryptX?page=1.

  4. fglock commented on Oct 30, 2026

    @fglock
    OwnerAuthor

    State: released
    Agent/session: Codex-20261030-cryptx-java-bridge
    Scope: #1220 phase 1: CryptX bootstrap, encoding helpers, functional digest APIs, and HMAC using existing JCA/Bouncy Castle providers.
    Work: feature/cryptx-java-bridge, commit e7f9f78, draft PR #1929 (#1929)
    Checkpoint: 2026-10-30 08:32 UTC; phase 1 committed and published; draft PR is open on master.
    Evidence: native system Perl focused oracle 12/12; nice -n 19 make passed with 3,056 tests, 0 failures, 3 skipped; JPERL_TEST_FILTER=CryptX timeout 1800 nice -n 19 make test-bundled-modules passed the CryptX module test; nice -n 19 make check-links reported 0 errors. Remote branch commit and tree match local commit/tree.
    Blocked by: none
    Next: review PR #1929; continue stateful digest/MAC and RSA APIs as the next issue phase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cpan-portCPAN compatibility ports and providersenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions