Skip to content

feat: implement hybrid encryption and compress public key URLs (Fixes… - #15

Open
Adityakk9031 wants to merge 1 commit into
Corgea:mainfrom
Adityakk9031:#13
Open

feat: implement hybrid encryption and compress public key URLs (Fixes…#15
Adityakk9031 wants to merge 1 commit into
Corgea:mainfrom
Adityakk9031:#13

Conversation

@Adityakk9031

@Adityakk9031 Adityakk9031 commented Jul 15, 2026

Copy link
Copy Markdown

closes:#13

Summary

This PR implements hybrid encryption (RSA-OAEP + AES-GCM-256) and public key modulus minification to resolve two primary user issues:

  1. Size Limit Failures ("Unable to encrypt"): PAYLOADS larger than 190 bytes (e.g. SSH keys or long passwords) previously failed encryption because Retriever used direct RSA-OAEP-256. We now encrypt the payload symmetrically via AES-GCM-256 and encrypt the ephemeral AES key with the RSA public key.
  2. URL Truncation ("Unable to load public key"): Serializing full JWK public keys made request URLs very long (>600 characters), which chat/SMS apps often truncated. We now compress public key serialization by sharing only the public key's modulus n (reducing the URL length to under 380 characters).

Both changes are fully backward-compatible with older URLs.

Changes Made

Cryptography Layer (js/crypto.js)

  • Hybrid Encryption (encryptString / decryptString):
    • Generates an ephemeral 256-bit AES-GCM key per encryption.
    • Encrypts the secret with AES-GCM and a random 12-byte IV.
    • Encrypts the raw AES key with the RSA-OAEP public key.
    • Packs the payload: [RSA-Encrypted AES Key (256 bytes) | IV (12 bytes) | AES Ciphertext (variable)] and encodes it to Base64.
    • Backward Compatibility: decryptString checks the byte length of the decoded payload. If it is exactly 256 bytes, it automatically decrypts using the legacy RSA-only logic.
  • Public Key Modulus Serialization (serialize_key / deserialize_key):
    • serialize_key detects RSA public keys and extracts only their modulus n parameter, yielding a compact 342-character string. Private keys still serialize as full JWK JSON.
    • deserialize_key detects old JWKs by checking for the ey (Base64 JSON {) prefix. If not present, it dynamically reconstructs the JWK using the string as the modulus n and AQAB as the exponent.
  • Utility Helpers:
    • Added bufferToBase64 and base64ToBuffer to safely encode/decode binary data without call stack limit exceptions on large secrets.
  • Bug Fixes:
    • Fixed a parameter variable typo in the unused load_private_key function.

How to Test

You can run the automated test suite in Node.js, or manually verify directly in the browser:

1. Run Tests (Node.js)

Execute the testing script:

node .system_generated/scratch/test_crypto.js

@Adityakk9031

Copy link
Copy Markdown
Author

@asadeddin have a look

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant