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. node 22 · linux…

sha256:bf227476fbe2d665af4c03c6862eecaa6a1760441669b86d3def01bcc85a4d35

이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다. 통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다. 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