Summary
Perry supports many node:crypto method-style operations (hash.update().digest(), cipher.update()/final(), sign.update().sign(), etc.), but the returned crypto handles are not real Node stream objects. Node packages can use Hash, Hmac, Cipher, Decipher, Sign, and Verify objects in stream pipelines; those workloads currently lack compatible write/end/pipe/event behavior in Perry.
Affected API families include stream-backed behavior for:
crypto.createHash() / crypto.Hash
crypto.createHmac() / crypto.Hmac
crypto.createCipheriv() / crypto.Cipheriv
crypto.createDecipheriv() / crypto.Decipheriv
crypto.createSign() / crypto.Sign
crypto.createVerify() / crypto.Verify
Evidence
The crypto parity suite documents this as a deliberate follow-up:
test-parity/node-suite/crypto/README.md says current coverage includes hash/HMAC/cipher/sign method-style handles, but lists “Full Node stream-backed crypto transform semantics” under known gaps.
- Existing crypto parity fixtures under
test-parity/node-suite/crypto/hash, hmac, cipher, and asymmetric exercise update(), digest(), final(), sign(), and verify(), but do not cover write(), end(), pipe(), data, readable, finish, error, or backpressure.
Runtime/source shape also points to method-only handles:
crates/perry-stdlib/src/crypto/hash_handles.rs registers Hash/Hmac handles and dispatches methods such as update, digest, and copy.
- Hash property reads bind only
update, digest, and copy.
crates/perry-stdlib/src/crypto/cipher.rs dispatches Cipher/Decipher methods such as update, final, setAAD, getAuthTag, setAuthTag, and setAutoPadding, but there is no stream/EventEmitter method surface.
crates/perry-stdlib/src/crypto/ecdh.rs implements Sign/Verify as data-accumulating handles with method dispatch, not writable stream behavior.
Expected Node behavior
Node crypto handles are stream-compatible. For example:
import { Readable } from "node:stream";
import { createHash, createCipheriv, randomBytes } from "node:crypto";
const hash = createHash("sha256");
hash.setEncoding("hex");
Readable.from(["abc", "def"]).pipe(hash).on("data", (digest) => {
console.log("digest:", digest);
});
const key = Buffer.alloc(32, 1);
const iv = Buffer.alloc(16, 2);
const cipher = createCipheriv("aes-256-cbc", key, iv);
Readable.from([Buffer.from("0123456789abcdef")])
.pipe(cipher)
.on("data", (chunk) => console.log(chunk.length));
Hash/Hmac should act as transform streams that consume written chunks and emit the digest at the end. Cipher/Decipher should transform chunks through the stream interface and participate in normal stream lifecycle/backpressure/error behavior. Sign/Verify should accept streamed writes before sign()/verify() or stream finalization.
Current Perry behavior
The crypto objects work for direct method calls, but they are handle values with method dispatch for crypto-specific methods only. Stream-oriented calls such as .pipe(...), .write(...), .end(...), .on("data", ...), or Readable.from(...).pipe(createHash(...)) are not modeled, so packages that compose crypto with Node streams cannot run against Perry's current crypto compatibility layer.
Suggested test surface
Add focused parity cases under test-parity/node-suite/crypto/ for:
- Hash/Hmac as writable/transform streams:
write, end, setEncoding, data, finish.
Readable.from([...]).pipe(createHash("sha256")) digest output.
- Cipher/Decipher streaming round-trips through
pipe() with multiple chunks.
- Error propagation for bad keys/tags during streamed cipher/decipher finalization.
- Backpressure/lifecycle basics once the stream integration is wired.
Scope / non-goals
This issue is about Node stream semantics for already-supported crypto algorithms and handles. It does not require expanding algorithm coverage, exact OpenSSL error text, or encrypted DER/PEM import/export variants.
Summary
Perry supports many
node:cryptomethod-style operations (hash.update().digest(),cipher.update()/final(),sign.update().sign(), etc.), but the returned crypto handles are not real Node stream objects. Node packages can use Hash, Hmac, Cipher, Decipher, Sign, and Verify objects in stream pipelines; those workloads currently lack compatiblewrite/end/pipe/event behavior in Perry.Affected API families include stream-backed behavior for:
crypto.createHash()/crypto.Hashcrypto.createHmac()/crypto.Hmaccrypto.createCipheriv()/crypto.Cipherivcrypto.createDecipheriv()/crypto.Decipherivcrypto.createSign()/crypto.Signcrypto.createVerify()/crypto.VerifyEvidence
The crypto parity suite documents this as a deliberate follow-up:
test-parity/node-suite/crypto/README.mdsays current coverage includes hash/HMAC/cipher/sign method-style handles, but lists “Full Node stream-backed crypto transform semantics” under known gaps.test-parity/node-suite/crypto/hash,hmac,cipher, andasymmetricexerciseupdate(),digest(),final(),sign(), andverify(), but do not coverwrite(),end(),pipe(),data,readable,finish,error, or backpressure.Runtime/source shape also points to method-only handles:
crates/perry-stdlib/src/crypto/hash_handles.rsregisters Hash/Hmac handles and dispatches methods such asupdate,digest, andcopy.update,digest, andcopy.crates/perry-stdlib/src/crypto/cipher.rsdispatches Cipher/Decipher methods such asupdate,final,setAAD,getAuthTag,setAuthTag, andsetAutoPadding, but there is no stream/EventEmitter method surface.crates/perry-stdlib/src/crypto/ecdh.rsimplements Sign/Verify as data-accumulating handles with method dispatch, not writable stream behavior.Expected Node behavior
Node crypto handles are stream-compatible. For example:
Hash/Hmac should act as transform streams that consume written chunks and emit the digest at the end. Cipher/Decipher should transform chunks through the stream interface and participate in normal stream lifecycle/backpressure/error behavior. Sign/Verify should accept streamed writes before
sign()/verify()or stream finalization.Current Perry behavior
The crypto objects work for direct method calls, but they are handle values with method dispatch for crypto-specific methods only. Stream-oriented calls such as
.pipe(...),.write(...),.end(...),.on("data", ...), orReadable.from(...).pipe(createHash(...))are not modeled, so packages that compose crypto with Node streams cannot run against Perry's current crypto compatibility layer.Suggested test surface
Add focused parity cases under
test-parity/node-suite/crypto/for:write,end,setEncoding,data,finish.Readable.from([...]).pipe(createHash("sha256"))digest output.pipe()with multiple chunks.Scope / non-goals
This issue is about Node stream semantics for already-supported crypto algorithms and handles. It does not require expanding algorithm coverage, exact OpenSSL error text, or encrypted DER/PEM import/export variants.