CodeSampleX

示例

bcryptjs 3.0.3: Hash and verify passwords on Node without a native module, choosing between node:crypto's scrypt and bcryptjs

已验证示例 — npm bcryptjs 3.0.3: Hash and verify passwords on Node without a native module, choosing between node:crypto's scrypt and bcryptjs. contract 在 node 22…

sha256:bf227476fbe2d665af4c03c6862eecaa6a1760441669b86d3def01bcc85a4d35

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
2
构建过它的签名密钥
2
声明的环境 node 22 linux x64 node 22 javascript npm

验证运行环境

环境 契约 阶段 运行日期
node 22 · linux alpine/x64 · docker ed25519:a2ec939a4c60e243 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-14
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

案例

HOW
目标
Hash and verify passwords on Node without a native module, choosing between node:crypto's scrypt and bcryptjs
符号
  • crypto.scryptSync
  • crypto.timingSafeEqual
  • crypto.randomBytes
  • bcrypt.hashSync
  • bcrypt.compareSync
  • bcrypt.getSalt
  • bcrypt.truncates
环境
node 22
创建时间
2026-08-14T13:20:18Z

契约

  1. assert bcryptjs 3 declares an exports map holding only ".", so require("bcryptjs/package.json") throws ERR_PACKAGE_PATH_NOT_EXPORTED and the installed version has to be read through import.meta.resolve instead
  2. assert scrypt is deterministic for one salt and unrelated across salts, so the per-password salt has to be stored: the 64-byte derived key does not contain it and there is no field to parse it back out of
  3. assert a string salt is taken as its UTF-8 bytes rather than decoded as hex, so storing the salt as hex and handing the string back derives a different key than handing back the bytes it encodes
  4. assert the hand-rolled scrypt record carries the scheme, N, r, p, the salt and the key, so a verifier can rebuild the key from the stored string alone, and that a password one character short of the right one fails
  5. assert two accounts choosing the same password store different scrypt records, while sha256 of that password is byte-identical every time and has nowhere to put a salt
  6. assert timingSafeEqual throws RangeError ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH on buffers of different byte length instead of returning false, which is how a 32-byte legacy row met by a 64-byte scrypt key becomes a 500 rather than a failed login
  7. assert checking the lengths first returns false for that mismatch while leaving the equal-length comparison unchanged, and that timingSafeEqual refuses strings with ERR_INVALID_ARG_TYPE so hex-comparing with === is not a shortcut past it
  8. assert a bcryptjs hash is 60 characters beginning $2b$10$ that carry its own cost and salt, that getRounds and getSalt read them back, and that rehashing with the embedded salt reproduces the stored string exactly
  9. assert two hashes of one password differ yet both verify with no salt argument, and that published jBCrypt $2a$06$ vectors written by another implementation still verify and still report their cost
  10. assert an empty or malformed stored hash compares false while a null one throws Illegal arguments: string, object, so a NULL password column crashes the login path instead of failing it
  11. assert bcrypt silently truncates at 72 bytes, so two different longer passwords sharing that prefix each verify against the other's hash, the bare 72-byte prefix opens the account, and 71 bytes does not
  12. assert the limit is bytes and not characters: 36 accented characters are 72 bytes and survive, 37 are 74 bytes and lose the tail, and truncates() reports both
  13. assert two passwords under the limit differing only in their tail do not cross-verify, so the collision above is truncation rather than a broken comparison, and that scrypt has no such limit
  14. assert scryptSync's defaults are N=16384, r=8 and p=1 by deriving an identical key with them written out
  15. assert the default cost is deliberately slow, as a lower bound on the fastest of several runs rather than an exact figure: at least 5 ms and more than fifty times sha256, and lowering N to 1024 lowers it
  16. assert raising N without raising maxmem throws RangeError ERR_CRYPTO_INVALID_SCRYPT_PARAMS quoting OpenSSL's memory limit, that a single doubling of the default cost is already over the 32 MiB default maxmem, and that a malformed N produces the byte-identical message so the text tells the two faults apart from neither side
  17. measure that the accepted maxmem minimum is exactly 128 * r * (N + p + 2), pinned to the byte at six parameter sets that vary N, r and p independently, and that the widely quoted 128 * N * r is itself rejected: 2 KB short at the defaults, and 3 KB short at N=32768 where it comes to exactly the 32 MiB default
  18. assert N=1 and N=3 are rejected while a zero N, r, p or maxmem is not rejected but silently means the default

文件

  • csx.json
  • package-lock.json
  • package.json
  • src/passwords.mjs
  • test/contract.mjs

下载源代码构件 (tar.gz)

原始种子者

anonymous