-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deno crashes at createDecipheriv
#25279
Comments
I haven't had time to track down why, but when I run some tests against this same method, I get a different crash, later in the method: ============================================================
Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.
Platform: macos aarch64
Version: 1.45.5
Args: ["/opt/homebrew/bin/deno", "test", "--fail-fast", "--coverage", "--clean", "--allow-env", "--allow-read", "src/index.test.ts"]
thread 'tokio-runtime-worker' panicked at ext/node/ops/crypto/cipher.rs:399:9:
assertion failed: input.len() == 16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace The crash is at line: |
With the original issue, the problem seems to be using a secret that is 11 chars long, not the expected 32 chars. ...
assertion `left == right` failed
left: 11
right: 32
... However, it seems even with the correct length secret, the decryption does not work (or at least one of the two encrypt or decrypt do not work). Here's a more complete script: import { NonEmptyArray } from "https://deno.land/x/fun@v2.0.0/array.ts";
import { Buffer } from "node:buffer";
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
import { string } from "https://deno.land/x/fun@v2.0.0/mod.ts";
const ALGORITHM = "aes-256-cbc";
const IV_LENGTH = 16; // For AES, this is always 16
const split = string.split(":");
const secret = "a test secret.. that is 16 x 2..";
function ensureSecret(secret: string) {
if (secret.length !== 32) {
throw new Error(
"secret must be a 32 char string, length: " + secret.length,
);
}
}
function encrypt(json: string, secret: string): string {
ensureSecret(secret);
const iv = randomBytes(IV_LENGTH);
const cipher = createCipheriv(ALGORITHM, Buffer.from(secret), iv);
let encrypted = cipher.update(JSON.stringify(json));
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString("hex") + ":" + encrypted.toString("hex");
}
function decrypt(encryptedString: string, secret: string): string {
ensureSecret(secret);
const pieces: NonEmptyArray<string> = split(encryptedString);
const firstElement = pieces[0];
const restElements = pieces.slice(1);
const iv = Buffer.from(firstElement, "hex");
const encryptedText = Buffer.from(restElements.join(":"), "hex");
const decipher = createDecipheriv(ALGORITHM, Buffer.from(secret), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
const encString = encrypt("foo bar baz", secret);
console.log("decrypted: ", decrypt(encString, secret)); This is based on an original implementation that has been working fine in node, modified for Deno and simplified for the purposes of this example. |
Encrypting part looks wrong in Deno. The below snippet: import { Buffer } from "node:buffer";
import { createCipheriv, createDecipheriv } from "node:crypto";
const secret = Buffer.from("a test secret.. that is 16 x 2..");
const iv = Buffer.from("e75f3621f41df73a47efa67cac1053bd", "hex");
const cipher = createCipheriv("aes-256-cbc", secret, iv);
const x = Buffer.concat([cipher.update("foo bar baz"), cipher.final()]);
console.log(x.toString("hex"));
const decipher = createDecipheriv("aes-256-cbc", secret, iv);
const y = Buffer.concat([decipher.update(Buffer.from("bc3b393dafcd0d45ee7b6cce7a4b1fb0", "hex")), decipher.final()]);
console.log(y.toString()); executes in Node and Deno like the below:
Also we miss the length check of key and iv. That causes the panic. We should throw RangeError and TypeError for invalid length of those. |
createDecipheriv
I think I found the cause of the error. It looks like import { NonEmptyArray } from "https://deno.land/x/fun@v2.0.0/array.ts";
import { Buffer } from "node:buffer";
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
import { string } from "https://deno.land/x/fun@v2.0.0/mod.ts";
const ALGORITHM = "aes-256-cbc";
const IV_LENGTH = 16; // For AES, this is always 16
const split = string.split(":");
const secret = "a test secret.. that is 16 x 2..";
function ensureSecret(secret: string) {
if (secret.length !== 32) {
throw new Error(
"secret must be a 32 char string, length: " + secret.length,
);
}
}
function encrypt(json: string, secret: string): string {
ensureSecret(secret);
const iv = randomBytes(IV_LENGTH);
const cipher = createCipheriv(ALGORITHM, Buffer.from(secret), iv);
let encrypted = cipher.update(JSON.stringify(json));
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString("hex") + ":" + encrypted.toString("hex");
}
function decrypt(encryptedString: string, secret: string): string {
ensureSecret(secret);
const pieces: NonEmptyArray<string> = split(encryptedString);
const firstElement = pieces[0];
const restElements = pieces.slice(1);
const iv = Buffer.from(firstElement, "hex");
const encryptedText = Buffer.from(restElements.join(":"), "hex");
const decipher = createDecipheriv(ALGORITHM, Buffer.from(secret), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
const encString = encrypt("foo bar baz", secret);
console.log("decrypted: ", decrypt(encString, secret)); This executes like: $ deno example.ts
decrypted: "foo bar baz" I'll work on the fix soon |
Version: Deno 1.45.5
The crash is at line:
const encryptedText = Buffer.from(restElements.join(":"), "hex");
The text was updated successfully, but these errors were encountered: