Skip to main content

SOFTWARE

Changelog

Changes that affect how you use STRCrypt or what it produces, by release. Internal test and build tooling changes and documentation corrections are not listed.

0.3.1Updated 2026-09-27MIT · Linux x86_64 · Windows x64

Security notice: database install permissions fixed in 0.3.1 2026-09-27

If you installed the SQL functions in Oracle or PostgreSQL from a STRCrypt 0.3.0 or earlier database bundle, every account that can connect to the database can execute the decryption functions. Even though the key stays outside SQL, permission to decrypt means access to plaintext. The search examples in the guides used an unkeyed SHA-256 hash of national ID and card numbers, which can be reversed by hashing candidate values.

Actions

  1. Run revoke_public.sql from the 0.3.1 bundle to revoke the PUBLIC grants, then grant access only to the roles that need it. For Oracle, run revoke_public.sql or re-run install.sql; for PostgreSQL, run ALTER EXTENSION pg_strcrypt UPDATE or sql/revoke_public.sql.
  2. If you created search columns with an unkeyed hash, recompute them with the search index function strcrypt_search_index and drop the hash columns. Backups and replicas from that period still contain the hash values.
  3. MySQL and MariaDB cannot restrict UDF execution with database privileges. Restrict decryption through read access to the ciphertext tables and by limiting who gets database accounts.

Contact us through the contact form with the inquiry type "Security Vulnerability".

0.3.1 2026-09-27

Ciphertext, encrypted files, and wrapped data keys created with 0.3.0 still decrypt as before. Existing function names and arguments and the SQL functions are unchanged, and a search index function has been added. The Oracle and PostgreSQL install scripts no longer grant the encryption and decryption functions to PUBLIC, so database accounts that called them through PUBLIC on 0.3.0 or earlier installations must be granted access explicitly.

Added

  • Search index: a deterministic index (64 hex characters) for exact-match lookup on encrypted columns. SQL strcrypt_search_index (Oracle STRCRYPT_SEARCH_INDEX), Python search_index, and Node.js and Java searchIndex produce the same value. Equal values share an index, so matches and frequencies are visible
  • Wheels for each Python version from 3.9 to 3.14 (Linux and Windows)
  • PostgreSQL extension 1.1, and revoke_public.sql that revokes only the PUBLIC grants of earlier installations (Oracle and PostgreSQL)
  • Third-party license notices LICENSE-THIRD-PARTY and source archives

Changed

  • Operating mode name korean-standard added. The former name kcmvp-approved is deprecated. Code that compares error messages as strings needs to use the new name
  • Parallel batch encryption in the default mode now scales with the thread count (output format unchanged)
  • The error message for a missing key and the CLI help point to a mode 0600 key file (STRCRYPT_KEY_FILE) first
  • Node.js string arguments containing an unpaired surrogate are rejected with RangeError

Security

  • Oracle and PostgreSQL installations opened the encryption and decryption functions to PUBLIC, so every account that could connect to the database could decrypt
  • The search column examples in the install guides used an unkeyed SHA-256 hash, which lets guessable values be recovered by trying candidates. Replaced with the search index

Fixed

  • Oracle STRCRYPT_ENCRYPT and STRCRYPT_ENCRYPT_ALGO dropped everything after a NUL (CHR(0)) in the value and encrypted only the first part. They now reject it with ORA-20502
  • A child process forked while another thread was loading the key for the first time could hang

Known limitations

  • MySQL and MariaDB UDFs have no per-function execute privilege, so every account that can connect can call the encryption, decryption, and search index UDFs. Restrict access through read privileges on ciphertext tables and the scope of database accounts

0.3.0 2026-09-25

Ciphertext and encrypted files created with 0.2.0 still decrypt as before. Names, arguments, and return types of the Python, Node.js, and Java functions, and the existing C shared library functions, are unchanged. Changes to existing behavior are listed under "Changed" below; most of them concern how error cases are handled.

Added

  • Data key (DEK) management functions: per-subject data keys (per customer, user, and so on) are stored only in wrapped form under the master key. Generate with generate_wrapped_dek, rewrap for master key rotation with rewrap_dek, inspect with wrapped_dek_info. No function returns a plaintext data key
  • EncryptionContext: an object that encrypts and decrypts with a wrapped data key or a key supplied by an external key management system (KMS), including batch encryption and decryption with per-record AAD (sequential and parallel). Available in Python, Node.js, and Java (Node.js and Java use names such as generateWrappedDek)
  • Nine C shared library functions providing the same features (existing SQL functions unchanged)
  • Type stubs (.pyi, py.typed) included in the Python wheel

Changed

  • Example classes removed from the Java JAR (public API classes unchanged)
  • Native failures in Java generatePbeSalt, hardwareInfo, supportedAlgorithms, and version now throw IllegalStateException instead of StrCryptException
  • CLI option combinations where one option was ignored (-c with -q, -c with -o, a Base64 argument with -f for decrypt, and others) are now usage errors (exit code 2)
  • CLI --mode values are parsed the same way as STRCRYPT_MODE: KcmvpApproved is accepted, values with leading or trailing spaces are rejected
  • If interactive CLI input ends immediately (EOF), the CLI exits with an input error (exit code 1). Previously it encrypted an empty string and overwrote the default output file
  • The CLI is integrity-checked against the .hmac file next to the executable even when run from PATH. Replace the .hmac file whenever you replace the executable
  • The CLI writes logs to standard error when RUST_LOG is set
  • Supported platforms stated explicitly: release builds for Linux x86_64 and Windows x64, source builds for Linux aarch64, Windows arm64 not supported

Security

  • AES-256-GCM encryption plaintext limit reduced to the NIST SP 800-38D limit (2^36-32 bytes). Lengths near the old limit reused keystream. The decryption limit is unchanged
  • CLI encrypt-file and decrypt-file create output files with mode 0600. In directories with a default ACL, decrypted plaintext files could be readable by other users
  • The C shared library logged unknown algorithm names verbatim, so calling it with swapped arguments put plaintext in the log
  • Race between the key file permission check and the read, where the path could be swapped, is closed
  • Integrity checks were skipped for libraries placed in directories with certain names (such as deps)
  • Removed paths that left key file contents, file and batch decryption plaintext, and string copies in the Java and Node.js bindings in memory that was not wiped
  • Key statistics removed from the weak key warning log

Fixed

  • Parallel file encryption and decryption hung (deadlock) when another thread switched the operating mode
  • Java strings containing an unpaired surrogate were encrypted with emoji and similar characters replaced by U+FFFD. They are now rejected with StrCryptException
  • CLI decrypt -f aborted the process when it could not allocate memory for the file size. It now reports an I/O error
  • Missing return value (undefined behavior) in the Oracle bulk processing C wrapper

Known limitations

  • The global functions use only the first 16 bytes of the master key for SEED-128-GCM, LEA-128-GCM, AEGIS-128L, and ASCON-128. Generate the full 32-byte master key randomly. File encryption and wrapped data keys are not affected
  • Record ciphertext is not key-committing. Pass only keys from a trusted KMS to from_raw_key, and record a data key identifier with each record
  • Per-key usage counters live only in process memory. Totals across restarts and multiple processes must be tracked by the caller
  • The new functions in the bindings and the C shared library have not been run and tested on Windows
  • The SQL functions and global functions that encrypt every row with one master key are limited to 2^32 encryptions per key (summed across all processes and re-encryption). Rotate the key before the total reaches 2^31

0.2.0 2026-09-17

Added

  • Bulk byte batch encryption and decryption with per-record AAD in Python, Node.js, and Java. Splits work by record count and byte limits, and reports the index of the failed record
  • CLI encrypt-batch and decrypt-batch: one record per line (Base64, or data and AAD as TSV), with exit codes 0 to 4 by error type
  • C shared library bulk batch functions and return code constants
  • Oracle bulk processing package STRCRYPT_BULK: collection procedures and pipelined functions, sharing the ciphertext format of the scalar functions
  • Windows 10 and 11 x64 releases: CLI, C shared library, Python wheel, Node.js addon, and Java JNI library. No VC++ redistributable required

Changed

  • String batch decryption detects the header per element, so arrays mixing header and legacy ciphertext decrypt in one call
  • Fixed a mode mismatch when the CLI is run with STRCRYPT_MODE but no --mode. Runs with STRCRYPT_MODE=non-approved now default to AEGIS-128L, so ciphertext they create does not decrypt in a default-mode process. Existing ARIA-256-GCM ciphertext decrypts in both modes
  • CLI plaintext read from standard input keeps leading and trailing spaces (only the final line break is removed). Decrypting the same input gives a different result from earlier versions
  • CLI output format changed: banner and separator lines removed, results printed as aligned Label: value lines. Scripts that parse the output need updating
  • Exit code for unknown CLI -a, --mode, and migrate-file -t values changed from 1 to 2
  • AES-256-GCM and AES-256-GCM-SIV report oversized input as PlaintextTooLong or AadTooLong instead of an authentication failure
  • MySQL and MariaDB UDFs: key and algorithm problems now end the statement with an error (ERROR 1123) instead of returning NULL for every row. A row-level failure returns NULL for that row only. Strings containing a NUL byte return NULL
  • Oracle error numbers changed from ORA-29501 and ORA-29502 to ORA-20502 and ORA-20503. PL/SQL exception handlers catching the old numbers need updating
  • Python raises MemoryError when result allocation fails; Java rejects null list elements with NullPointerException
  • macOS support dropped

Security

  • On Unix, a forked child process could generate the same nonces as its parent
  • CLI output is written to a temporary file (mode 0600) and then swapped in, so the existing file is kept if the write fails. Decrypted plaintext files were previously created with the default umask permissions (usually 0644)
  • If a CLI output path is a symbolic link, FIFO, or device, the CLI no longer writes through it and exits with a save error (exit code 1). Usage such as -o /dev/stdout is no longer possible
  • Non-UTF-8 values of STRCRYPT_KEY_FILE or STRCRYPT_KEY were treated as unset, and another key was used for encryption. The CLI and libraries now stop with an error
  • Removed paths where the bindings and cipher code freed copies of keys, passwords, and plaintext without wiping them

Fixed

  • Parallel work in a forked child process waited forever
  • With STRCRYPT_MODE=non-approved, depending on the first function called, keys shorter than 16 bytes were rejected and all later encryption and decryption failed
  • With STRCRYPT_MODE=non-approved, authentication failed when the first call decrypted legacy AES-256-GCM ciphertext
  • MySQL and MariaDB UDFs truncated values over about 49 KB in UNION and DISTINCT queries. Truncated ciphertext cannot be decrypted
  • Reinstalling the PostgreSQL integration dropped views, column defaults, and constraints that used the extension functions
  • Declaration error that left the six SQL functions INVALID (PLS-00249, PLS-00251) on Oracle 19c, and the install SQL stopping to wait for input
  • File encryption and decryption failed for output file names longer than about 232 bytes
  • The CLI exited with a panic message when its output went to a closed pipe
  • CLI info showed the key source as "not set" when only a key file was configured
  • JNI local references accumulated during Java batch calls with large lists

Known limitations

  • No SQL batch functions for PostgreSQL, MySQL, or MariaDB. Use the CLI or a binding for bulk processing
  • Oracle bulk processing was verified on 19c Enterprise Edition single instance. RAC and other setups are not verified, and if the database character set is not AL32UTF8, a single non-ASCII record fails the whole chunk

0.1.2 2026-07-17

Security

  • Stricter policy checks for operating mode switches and cipher operations
  • A failed file decryption no longer leaves partial plaintext at the final output path
  • Stronger input validation, panic containment, and secret wiping in the bindings and the C shared library

Changed

  • Default algorithm in Python, Node.js, and Java aligned with the operating mode
  • Java release shipped as an archive bundling the JAR and per-platform JNI libraries

0.1.1 2026-04-23

Added

  • First integrated release with the Korean standard algorithms and the Python, Node.js, and Java bindings

Click the image for actual size · click outside or press Esc to close