BoxLang 🚀 A New JVM Dynamic Language Learn More...
A single bundled JAR plus a ColdFusion CFC that backports the
ColdFusion 2025 passwordHashGenerate /
passwordHashVerify password-hashing API to CF2016-CF2025,
Lucee 5/6/7, and BoxLang. Drop in the JAR, call the same function
names you will use on CF2025, and a future engine upgrade needs no
code changes and no data migration.
ColdFusion 2025 introduced a unified password-hashing API covering Argon2, BCrypt, and SCrypt. That API is stranded on CF2025 alone. If your application runs on an older Adobe CF version, Lucee, or BoxLang, you previously had no standard way to produce or verify those hashes. This library gives you the identical call signatures and byte-for-byte compatible hash output on older engines, so upgrading to CF2025 later is a no-op at both the code and the database layer.
All eleven configurations below pass the full no-TestBox test suite:
| Engine | Tested version |
|---|---|
| Adobe CF | 2016, 2018, 2021, 2023, 2025 |
| Lucee | 5, 6, 7 |
| BoxLang | latest (native, adobe-compat, lucee-compat) |
On BoxLang the library needs the bx-compat-cfml module
so that createObject("java", ...) and the CFC
behave the way they do on Adobe CF and Lucee. The bundled BoxLang
server configs install it on first run.
$pbkdf2-sha256$i=ITERATIONS$SALT$HASH. It also verifies
legacy colon-delimited iterations:salt: hash (SHA1)
hashes so you can migrate existing records without a bulk rehash.Choose exactly one of these two methods. Using both at the same time double-loads the JAR and causes class conflicts.
Copy lib/cf-passwordhash-1.0.0.jar into a folder that is
declared as libDirs in your server.json:
{
"app": {
"libDirs": "./lib"
}
}
Restart the server. The JAR is on the classpath automatically.
Copy lib/cf-passwordhash-1.0.0.jar into a
lib/ folder next to your Application.cfc,
then add:
this.javaSettings = [
"loadPaths": [ expandPath("./lib") ],
"loadColdFusionClassPath": false,
"reloadOnChange": false
];
Copy PasswordHash.cfc into your project root (or any
mapped folder). Then:
svc = new PasswordHash();
// Generate a hash using the default algorithm (Argon2)
hash = svc.passwordHashGenerate( password );
// Verify a password against a stored hash (algorithm auto-detected from the hash prefix)
ok = svc.passwordHashVerify( password, hash );
// Specify an algorithm explicitly
hash = svc.passwordHashGenerate( password, "BCrypt" );
ok = svc.passwordHashVerify( password, hash, "BCrypt" );
// Pass custom options (ordered struct literal)
hash = svc.passwordHashGenerate( password, "Argon2", [ "MEMORYCOST": 19456, "CPUCOST": 2 ] );
// Inspect a stored hash
info = svc.passwordHashInfo( hash );
// returns a map describing the hash. Keys are uppercase and vary by algorithm
// (for example ALGORITHM, plus the cost parameters embedded in the hash).
// Read keys with bracket access and the exact uppercase name so it works the
// same on Adobe CF, Lucee, and BoxLang:
alg = info[ "ALGORITHM" ];
On any engine that does NOT have the native CF2025 functions, include
the shim once - either in Application.cfc or at the top
of each template that needs it:
<cfinclude template="/path/to/include/PasswordHashFunctions.cfm">
After that, call the functions exactly as you would on CF2025:
hash = passwordHashGenerate( password );
ok = passwordHashVerify( password, hash );
info = passwordHashInfo( hash );
Important: do NOT include the shim on CF2025. The shim declares functions with the same names as the built-ins, which causes a name collision. On CF2025 the native functions are already available - just call them directly or use the CFC wrapper.
| Option | Default | Notes |
|---|---|---|
| SALTLENGTH | 16 | bytes |
| HASHLENGTH | 32 | bytes of derived key |
| PARALLEL | 1 | parallelism factor |
| MEMORYCOST | 4096 | kilobytes of memory |
| CPUCOST | 3 | time-cost iterations |
| Option | Default | Notes |
|---|---|---|
| ROUNDS | 10 | log2 cost factor (4-31) |
| VERSION | $2a | BCrypt version string |
| Option | Default | Notes |
|---|---|---|
| SALTLENGTH | 16 | bytes |
| KEYLENGTH | 32 | bytes of derived key |
| PARALLEL | 1 | parallelism factor |
| MEMORYCOST | 8 | block size parameter (r) |
| CPUCOST | 16384 | CPU/memory cost (N), must be power of 2 |
| Option | Default | Notes |
|---|---|---|
| CPUCOST | 210000 | iteration count (time cost) |
| SALTLENGTH | 16 | bytes |
| KEYLENGTH | 32 | bytes of derived key |
A prebuilt JAR is committed to lib/ so you do not need
to build. If you want to build from source:
On Windows:
pwsh ./build.ps1
On macOS/Linux:
./build.sh
The build scripts download Bouncy Castle
(bcprov-jdk18on-1.78.1.jar) from Maven Central, compile
the Java source with javac --release 8, assemble a fat
shaded JAR, and copy it to both dist/ and lib/.
Start a server for any engine:
box server start serverConfigFile=server.cf2025.json
Then open http://localhost:8925/tests/runner.cfm in a
browser (replace the port with the one for the engine you started).
The runner executes all test files and reports pass/fail counts.
Server config files are provided for all eleven tested configurations. Port assignments:
| File | Engine | Port |
|---|---|---|
| server.cf2016.json | Adobe CF 2016 | 8916 |
| server.cf2018.json | Adobe CF 2018 | 8918 |
| server.cf2021.json | Adobe CF 2021 | 8921 |
| server.cf2023.json | Adobe CF 2023 | 8923 |
| server.cf2025.json | Adobe CF 2025 | 8925 |
| server.lucee5.json | Lucee 5 | 8935 |
| server.lucee6.json | Lucee 6 | 8936 |
| server.lucee7.json | Lucee 7 | 8937 |
| server.boxlang.json | BoxLang | 8940 |
| server.boxlang-adobe.json | BoxLang (Adobe) | 8941 |
| server.boxlang-lucee.json | BoxLang (Lucee) | 8942 |
cf-passwordhash/
lib/
cf-passwordhash-1.0.0.jar prebuilt fat JAR (Bouncy Castle bundled)
include/
PasswordHashFunctions.cfm optional global-shim UDFs
tests/
runner.cfm test runner (no TestBox required)
test-argon2.cfm
test-bcrypt.cfm
test-scrypt.cfm
test-pbkdf2.cfm
test-cfc.cfm
test-shim.cfm
test-native-2025.cfm parity test against CF2025 built-ins
...
PasswordHash.cfc CFC wrapper
Application.cfc dev application component
index.cfm quick-start demo
box.json
build.ps1
build.sh
MIT - see LICENSE.
This library bundles Bouncy Castle (bcprov-jdk18on
1.78.1). See THIRD-PARTY-NOTICES.txt for the
Bouncy Castle licence text.
$
box install cf-passwordhash