mirror of
https://github.com/denoland/deno.git
synced 2025-01-05 13:59:01 -05:00
parent
16c1e023a5
commit
63454729a2
7 changed files with 232 additions and 17 deletions
|
@ -230,6 +230,7 @@
|
|||
"test-console-tty-colors.js",
|
||||
"test-crypto-hmac.js",
|
||||
"test-crypto-prime.js",
|
||||
"test-crypto-secret-keygen.js",
|
||||
"test-dgram-close-during-bind.js",
|
||||
"test-dgram-close-signal.js",
|
||||
"test-diagnostics-channel-has-subscribers.js",
|
||||
|
|
137
cli/tests/node_compat/test/parallel/test-crypto-secret-keygen.js
Normal file
137
cli/tests/node_compat/test/parallel/test-crypto-secret-keygen.js
Normal file
|
@ -0,0 +1,137 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const {
|
||||
generateKey,
|
||||
generateKeySync
|
||||
} = require('crypto');
|
||||
|
||||
[1, true, [], {}, Infinity, null, undefined].forEach((i) => {
|
||||
assert.throws(() => generateKey(i, 1, common.mustNotCall()), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "type" argument must be /
|
||||
});
|
||||
assert.throws(() => generateKeySync(i, 1), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "type" argument must be /
|
||||
});
|
||||
});
|
||||
|
||||
['', true, [], null, undefined].forEach((i) => {
|
||||
assert.throws(() => generateKey('aes', i, common.mustNotCall()), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "options" argument must be /
|
||||
});
|
||||
assert.throws(() => generateKeySync('aes', i), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "options" argument must be /
|
||||
});
|
||||
});
|
||||
|
||||
['', true, {}, [], null, undefined].forEach((length) => {
|
||||
assert.throws(() => generateKey('hmac', { length }, common.mustNotCall()), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "options\.length" property must be /
|
||||
});
|
||||
assert.throws(() => generateKeySync('hmac', { length }), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "options\.length" property must be /
|
||||
});
|
||||
});
|
||||
|
||||
assert.throws(() => generateKey('aes', { length: 256 }), {
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKey('hmac', { length: -1 }, common.mustNotCall()), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKey('hmac', { length: 4 }, common.mustNotCall()), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKey('hmac', { length: 7 }, common.mustNotCall()), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => generateKey('hmac', { length: 2 ** 31 }, common.mustNotCall()), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKeySync('hmac', { length: -1 }), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKeySync('hmac', { length: 4 }), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKeySync('hmac', { length: 7 }), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => generateKeySync('hmac', { length: 2 ** 31 }), {
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => generateKeySync('aes', { length: 123 }), {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
message: /The property 'options\.length' must be one of: 128, 192, 256/
|
||||
});
|
||||
|
||||
{
|
||||
const key = generateKeySync('aes', { length: 128 });
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, 128 / 8);
|
||||
|
||||
generateKey('aes', { length: 128 }, common.mustSucceed((key) => {
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, 128 / 8);
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const key = generateKeySync('aes', { length: 256 });
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, 256 / 8);
|
||||
|
||||
generateKey('aes', { length: 256 }, common.mustSucceed((key) => {
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, 256 / 8);
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const key = generateKeySync('hmac', { length: 123 });
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, Math.floor(123 / 8));
|
||||
|
||||
generateKey('hmac', { length: 123 }, common.mustSucceed((key) => {
|
||||
assert(key);
|
||||
const keybuf = key.export();
|
||||
assert.strictEqual(keybuf.byteLength, Math.floor(123 / 8));
|
||||
}));
|
||||
}
|
||||
|
||||
assert.throws(
|
||||
() => generateKey('unknown', { length: 123 }, common.mustNotCall()), {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
message: /The argument 'type' must be a supported key type/
|
||||
});
|
||||
|
||||
assert.throws(() => generateKeySync('unknown', { length: 123 }), {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
message: /The argument 'type' must be a supported key type/
|
||||
});
|
|
@ -8,6 +8,7 @@ use deno_core::ResourceId;
|
|||
use deno_core::StringOrBuffer;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use num_bigint::BigInt;
|
||||
use rand::Rng;
|
||||
use std::future::Future;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -402,3 +403,19 @@ pub async fn op_node_pbkdf2_async(
|
|||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_node_generate_secret(buf: &mut [u8]) {
|
||||
rand::thread_rng().fill(buf);
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub async fn op_node_generate_secret_async(len: i32) -> ZeroCopyBuf {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let mut buf = vec![0u8; len as usize];
|
||||
rand::thread_rng().fill(&mut buf[..]);
|
||||
buf.into()
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
|
|
@ -170,6 +170,8 @@ deno_core::extension!(deno_node,
|
|||
crypto::op_node_check_prime_bytes_async,
|
||||
crypto::op_node_pbkdf2,
|
||||
crypto::op_node_pbkdf2_async,
|
||||
crypto::op_node_generate_secret,
|
||||
crypto::op_node_generate_secret_async,
|
||||
crypto::op_node_sign,
|
||||
winerror::op_node_sys_to_uv_error,
|
||||
v8::op_v8_cached_data_version_tag,
|
||||
|
|
|
@ -2,18 +2,80 @@
|
|||
// Copyright Joyent, Inc. and Node.js contributors. All rights reserved. MIT license.
|
||||
|
||||
import { KeyObject } from "ext:deno_node/internal/crypto/keys.ts";
|
||||
import { kAesKeyLengths } from "ext:deno_node/internal/crypto/util.ts";
|
||||
import {
|
||||
SecretKeyObject,
|
||||
setOwnedKey,
|
||||
} from "ext:deno_node/internal/crypto/keys.ts";
|
||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
||||
import { ERR_INVALID_ARG_VALUE } from "ext:deno_node/internal/errors.ts";
|
||||
import {
|
||||
validateFunction,
|
||||
validateInteger,
|
||||
validateObject,
|
||||
validateOneOf,
|
||||
validateString,
|
||||
} from "ext:deno_node/internal/validators.mjs";
|
||||
import { Buffer } from "ext:deno_node/buffer.ts";
|
||||
import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts";
|
||||
|
||||
export function generateKey(
|
||||
_type: "hmac" | "aes",
|
||||
_options: {
|
||||
const { core } = globalThis.__bootstrap;
|
||||
const { ops } = core;
|
||||
|
||||
function validateGenerateKey(
|
||||
type: "hmac" | "aes",
|
||||
options: { length: number },
|
||||
) {
|
||||
validateString(type, "type");
|
||||
validateObject(options, "options");
|
||||
const { length } = options;
|
||||
switch (type) {
|
||||
case "hmac":
|
||||
validateInteger(length, "options.length", 8, 2 ** 31 - 1);
|
||||
break;
|
||||
case "aes":
|
||||
validateOneOf(length, "options.length", kAesKeyLengths);
|
||||
break;
|
||||
default:
|
||||
throw new ERR_INVALID_ARG_VALUE(
|
||||
"type",
|
||||
type,
|
||||
"must be a supported key type",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function generateKeySync(
|
||||
type: "hmac" | "aes",
|
||||
options: {
|
||||
length: number;
|
||||
},
|
||||
_callback: (err: Error | null, key: KeyObject) => void,
|
||||
): KeyObject {
|
||||
validateGenerateKey(type, options);
|
||||
const { length } = options;
|
||||
|
||||
const key = new Uint8Array(Math.floor(length / 8));
|
||||
ops.op_node_generate_secret(key);
|
||||
|
||||
return new SecretKeyObject(setOwnedKey(key));
|
||||
}
|
||||
|
||||
export function generateKey(
|
||||
type: "hmac" | "aes",
|
||||
options: {
|
||||
length: number;
|
||||
},
|
||||
callback: (err: Error | null, key: KeyObject) => void,
|
||||
) {
|
||||
notImplemented("crypto.generateKey");
|
||||
validateGenerateKey(type, options);
|
||||
validateFunction(callback, "callback");
|
||||
const { length } = options;
|
||||
|
||||
core.opAsync("op_node_generate_secret_async", Math.floor(length / 8)).then(
|
||||
(key) => {
|
||||
callback(null, new SecretKeyObject(setOwnedKey(key)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export interface BasePrivateKeyEncodingOptions<T extends KeyFormat> {
|
||||
|
@ -662,15 +724,6 @@ export function generateKeyPairSync(
|
|||
notImplemented("crypto.generateKeyPairSync");
|
||||
}
|
||||
|
||||
export function generateKeySync(
|
||||
_type: "hmac" | "aes",
|
||||
_options: {
|
||||
length: number;
|
||||
},
|
||||
): KeyObject {
|
||||
notImplemented("crypto.generateKeySync");
|
||||
}
|
||||
|
||||
export default {
|
||||
generateKey,
|
||||
generateKeySync,
|
||||
|
|
|
@ -279,7 +279,7 @@ export function prepareSecretKey(
|
|||
return getArrayBufferOrView(key, "key", encoding);
|
||||
}
|
||||
|
||||
class SecretKeyObject extends KeyObject {
|
||||
export class SecretKeyObject extends KeyObject {
|
||||
constructor(handle: unknown) {
|
||||
super("secret", handle);
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ class SecretKeyObject extends KeyObject {
|
|||
}
|
||||
}
|
||||
|
||||
function setOwnedKey(key: Uint8Array): unknown {
|
||||
export function setOwnedKey(key: Uint8Array): unknown {
|
||||
const handle = {};
|
||||
KEY_STORE.set(handle, key);
|
||||
return handle;
|
||||
|
@ -345,4 +345,6 @@ export default {
|
|||
isCryptoKey,
|
||||
KeyObject,
|
||||
prepareSecretKey,
|
||||
setOwnedKey,
|
||||
SecretKeyObject,
|
||||
};
|
||||
|
|
|
@ -133,7 +133,9 @@ export function setEngine(_engine: string, _flags: typeof constants) {
|
|||
notImplemented("crypto.setEngine");
|
||||
}
|
||||
|
||||
export { kHandle, kKeyObject };
|
||||
const kAesKeyLengths = [128, 192, 256];
|
||||
|
||||
export { kAesKeyLengths, kHandle, kKeyObject };
|
||||
|
||||
export default {
|
||||
getDefaultEncoding,
|
||||
|
@ -147,4 +149,5 @@ export default {
|
|||
toBuf,
|
||||
kHandle,
|
||||
kKeyObject,
|
||||
kAesKeyLengths,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue