mirror of
https://github.com/denoland/deno.git
synced 2025-02-14 17:47:35 -05:00
Merge branch 'main' into jupyter_comms
This commit is contained in:
commit
747338662a
68 changed files with 2136 additions and 1103 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -1148,7 +1148,6 @@ dependencies = [
|
|||
"fs3",
|
||||
"glibc_version",
|
||||
"glob",
|
||||
"ignore",
|
||||
"import_map",
|
||||
"indexmap",
|
||||
"jsonc-parser",
|
||||
|
@ -1308,13 +1307,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_config"
|
||||
version = "0.19.1"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddc80f97cffe52c9a430201f288111fc89d33491b1675c0e01feb3a497ce76b3"
|
||||
checksum = "64772162a8e8c1b3a9c48b4a0924e29f5b8f0ae23ea2027361937e96d04d493d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_semver",
|
||||
"glob",
|
||||
"ignore",
|
||||
"import_map",
|
||||
"indexmap",
|
||||
"jsonc-parser",
|
||||
|
|
|
@ -101,7 +101,7 @@ console_static_text = "=0.8.1"
|
|||
data-encoding = "2.3.3"
|
||||
data-url = "=0.3.0"
|
||||
deno_cache_dir = "=0.10.0"
|
||||
deno_config = { version = "=0.19.1", default-features = false }
|
||||
deno_config = { version = "=0.20.0", default-features = false }
|
||||
dlopen2 = "0.6.1"
|
||||
ecb = "=0.1.2"
|
||||
elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem"] }
|
||||
|
|
|
@ -44,7 +44,7 @@ default = ["upgrade", "__vendored_zlib_ng"]
|
|||
upgrade = []
|
||||
# A dev feature to disable creations and loading of snapshots in favor of
|
||||
# loading JS sources at runtime.
|
||||
__runtime_js_sources = ["deno_runtime/__runtime_js_sources"]
|
||||
hmr = ["deno_runtime/hmr"]
|
||||
# Vendor zlib as zlib-ng
|
||||
__vendored_zlib_ng = ["flate2/zlib-ng-compat", "libz-sys/zlib-ng"]
|
||||
|
||||
|
@ -107,7 +107,6 @@ faster-hex.workspace = true
|
|||
flate2.workspace = true
|
||||
fs3.workspace = true
|
||||
glob = "0.3.1"
|
||||
ignore = "0.4"
|
||||
import_map = { version = "=0.20.0", features = ["ext"] }
|
||||
indexmap.workspace = true
|
||||
jsonc-parser.workspace = true
|
||||
|
@ -149,7 +148,6 @@ tower-lsp.workspace = true
|
|||
twox-hash.workspace = true
|
||||
typed-arena = "=2.0.1"
|
||||
uuid = { workspace = true, features = ["serde"] }
|
||||
walkdir = "=2.3.2"
|
||||
zeromq.workspace = true
|
||||
zstd.workspace = true
|
||||
|
||||
|
@ -164,6 +162,7 @@ nix.workspace = true
|
|||
deno_bench_util.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
test_util.workspace = true
|
||||
walkdir = "=2.3.2"
|
||||
|
||||
[package.metadata.winres]
|
||||
# This section defines the metadata that appears in the deno.exe PE header.
|
||||
|
|
|
@ -546,6 +546,7 @@ pub struct Flags {
|
|||
pub inspect_wait: Option<SocketAddr>,
|
||||
pub inspect: Option<SocketAddr>,
|
||||
pub location: Option<Url>,
|
||||
// TODO(bartlomieju): deprecated, to be removed in Deno 2.
|
||||
pub lock_write: bool,
|
||||
pub lock: Option<String>,
|
||||
pub log_level: Option<Level>,
|
||||
|
@ -3623,12 +3624,14 @@ If value is not provided, defaults to \"deno.lock\" in the current working direc
|
|||
.value_hint(ValueHint::FilePath)
|
||||
}
|
||||
|
||||
// TODO(bartlomieju): deprecated, to be removed in Deno 2.
|
||||
fn lock_write_arg() -> Arg {
|
||||
Arg::new("lock-write")
|
||||
.action(ArgAction::SetTrue)
|
||||
.long("lock-write")
|
||||
.help("Force overwriting the lock file.")
|
||||
.conflicts_with("no-lock")
|
||||
.hide(true)
|
||||
}
|
||||
|
||||
fn no_lock_arg() -> Arg {
|
||||
|
@ -4747,6 +4750,7 @@ fn check_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
|||
fn lock_args_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||
lock_arg_parse(flags, matches);
|
||||
no_lock_arg_parse(flags, matches);
|
||||
// TODO(bartlomieju): deprecated, to be removed in Deno 2.
|
||||
if matches.get_flag("lock-write") {
|
||||
flags.lock_write = true;
|
||||
}
|
||||
|
@ -7855,7 +7859,7 @@ mod tests {
|
|||
let r = flags_from_vec(svec![
|
||||
"deno",
|
||||
"run",
|
||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,::,127.0.0.1,[::1],1.2.3.4",
|
||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,[::],127.0.0.1,[::1],1.2.3.4",
|
||||
"script.ts"
|
||||
]);
|
||||
assert_eq!(
|
||||
|
@ -7867,7 +7871,7 @@ mod tests {
|
|||
unsafely_ignore_certificate_errors: Some(svec![
|
||||
"deno.land",
|
||||
"localhost",
|
||||
"::",
|
||||
"[::]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4"
|
||||
|
@ -7883,7 +7887,7 @@ mod tests {
|
|||
let r = flags_from_vec(svec![
|
||||
"deno",
|
||||
"repl",
|
||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,::,127.0.0.1,[::1],1.2.3.4"]);
|
||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,[::],127.0.0.1,[::1],1.2.3.4"]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
|
@ -7895,7 +7899,7 @@ mod tests {
|
|||
unsafely_ignore_certificate_errors: Some(svec![
|
||||
"deno.land",
|
||||
"localhost",
|
||||
"::",
|
||||
"[::]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4"
|
||||
|
@ -8087,7 +8091,7 @@ mod tests {
|
|||
let r = flags_from_vec(svec![
|
||||
"deno",
|
||||
"run",
|
||||
"--allow-net=deno.land,deno.land:80,::,127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||
"--allow-net=deno.land,deno.land:80,[::],127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||
"script.ts"
|
||||
]);
|
||||
assert_eq!(
|
||||
|
@ -8100,7 +8104,7 @@ mod tests {
|
|||
allow_net: Some(svec![
|
||||
"deno.land",
|
||||
"deno.land:80",
|
||||
"::",
|
||||
"[::]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4:5678",
|
||||
|
@ -8122,7 +8126,7 @@ mod tests {
|
|||
let r = flags_from_vec(svec![
|
||||
"deno",
|
||||
"run",
|
||||
"--deny-net=deno.land,deno.land:80,::,127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||
"--deny-net=deno.land,deno.land:80,[::],127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||
"script.ts"
|
||||
]);
|
||||
assert_eq!(
|
||||
|
@ -8135,7 +8139,7 @@ mod tests {
|
|||
deny_net: Some(svec![
|
||||
"deno.land",
|
||||
"deno.land:80",
|
||||
"::",
|
||||
"[::]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4:5678",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::url::Url;
|
||||
use deno_runtime::deno_permissions::NetDescriptor;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -42,21 +43,17 @@ pub fn validator(host_and_port: &str) -> Result<String, String> {
|
|||
/// `127.0.0.1:port` and `localhost:port`.
|
||||
pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
|
||||
let mut out: Vec<String> = vec![];
|
||||
for host_and_port in paths.iter() {
|
||||
if Url::parse(&format!("internal://{host_and_port}")).is_ok()
|
||||
|| host_and_port.parse::<IpAddr>().is_ok()
|
||||
{
|
||||
out.push(host_and_port.to_owned())
|
||||
} else if let Ok(port) = host_and_port.parse::<BarePort>() {
|
||||
for host_and_port in paths.into_iter() {
|
||||
if let Ok(port) = host_and_port.parse::<BarePort>() {
|
||||
// we got bare port, let's add default hosts
|
||||
for host in ["0.0.0.0", "127.0.0.1", "localhost"].iter() {
|
||||
out.push(format!("{}:{}", host, port.0));
|
||||
}
|
||||
} else {
|
||||
return Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Bad host:port pair: {host_and_port}"),
|
||||
));
|
||||
host_and_port.parse::<NetDescriptor>().map_err(|e| {
|
||||
clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}"))
|
||||
})?;
|
||||
out.push(host_and_port)
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
|
@ -121,8 +118,8 @@ mod tests {
|
|||
let entries = svec![
|
||||
"deno.land",
|
||||
"deno.land:80",
|
||||
"::",
|
||||
"::1",
|
||||
"[::]",
|
||||
"[::1]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4:5678",
|
||||
|
@ -142,8 +139,8 @@ mod tests {
|
|||
let expected = svec![
|
||||
"deno.land",
|
||||
"deno.land:80",
|
||||
"::",
|
||||
"::1",
|
||||
"[::]",
|
||||
"[::1]",
|
||||
"127.0.0.1",
|
||||
"[::1]",
|
||||
"1.2.3.4:5678",
|
||||
|
@ -174,10 +171,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6() {
|
||||
let entries =
|
||||
svec!["::", "::1", "[::1]", "[::]:5678", "[::1]:5678", "::cafe"];
|
||||
let expected =
|
||||
svec!["::", "::1", "[::1]", "[::]:5678", "[::1]:5678", "::cafe"];
|
||||
let entries = svec!["[::1]", "[::]:5678", "[::1]:5678"];
|
||||
let expected = svec!["[::1]", "[::]:5678", "[::1]:5678"];
|
||||
let actual = parse(entries).unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
@ -190,12 +185,36 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error2() {
|
||||
let entries = svec!["0123:4567:890a:bcde:fg::"];
|
||||
let entries = svec!["::1"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error3() {
|
||||
let entries = svec!["::"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error4() {
|
||||
let entries = svec!["::cafe"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error5() {
|
||||
let entries = svec!["1::1"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error6() {
|
||||
let entries = svec!["0123:4567:890a:bcde:fg::"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_net_args_ipv6_error7() {
|
||||
let entries = svec!["[::q]:8080"];
|
||||
assert!(parse(entries).is_err());
|
||||
}
|
||||
|
|
|
@ -130,6 +130,10 @@ impl CliLockfile {
|
|||
};
|
||||
|
||||
let lockfile = if flags.lock_write {
|
||||
log::warn!(
|
||||
"{} \"--lock-write\" flag is deprecated and will be removed in Deno 2.",
|
||||
crate::colors::yellow("Warning")
|
||||
);
|
||||
CliLockfile::new(
|
||||
Lockfile::new_empty(filename, true),
|
||||
flags.frozen_lockfile,
|
||||
|
|
|
@ -10,9 +10,11 @@ mod package_json;
|
|||
use deno_ast::SourceMapOption;
|
||||
use deno_config::workspace::CreateResolverOptions;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::VendorEnablement;
|
||||
use deno_config::workspace::Workspace;
|
||||
use deno_config::workspace::WorkspaceDiscoverOptions;
|
||||
use deno_config::workspace::WorkspaceDiscoverStart;
|
||||
use deno_config::workspace::WorkspaceEmptyOptions;
|
||||
use deno_config::workspace::WorkspaceMemberContext;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_config::WorkspaceLintConfig;
|
||||
|
@ -778,7 +780,6 @@ pub struct CliOptions {
|
|||
flags: Flags,
|
||||
initial_cwd: PathBuf,
|
||||
maybe_node_modules_folder: Option<PathBuf>,
|
||||
maybe_vendor_folder: Option<PathBuf>,
|
||||
npmrc: Arc<ResolvedNpmRc>,
|
||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||
overrides: CliOptionOverrides,
|
||||
|
@ -822,15 +823,6 @@ impl CliOptions {
|
|||
root_folder.pkg_json.as_deref(),
|
||||
)
|
||||
.with_context(|| "Resolving node_modules folder.")?;
|
||||
let maybe_vendor_folder = if force_global_cache {
|
||||
None
|
||||
} else {
|
||||
resolve_vendor_folder(
|
||||
&initial_cwd,
|
||||
&flags,
|
||||
root_folder.deno_json.as_deref(),
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(env_file_name) = &flags.env_file {
|
||||
match from_filename(env_file_name) {
|
||||
|
@ -859,7 +851,6 @@ impl CliOptions {
|
|||
maybe_lockfile,
|
||||
npmrc,
|
||||
maybe_node_modules_folder,
|
||||
maybe_vendor_folder,
|
||||
overrides: Default::default(),
|
||||
workspace,
|
||||
disable_deprecated_api_warning,
|
||||
|
@ -871,6 +862,10 @@ impl CliOptions {
|
|||
let initial_cwd =
|
||||
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
|
||||
let config_fs_adapter = DenoConfigFsAdapter::new(&RealFs);
|
||||
let maybe_vendor_override = flags.vendor.map(|v| match v {
|
||||
true => VendorEnablement::Enable { cwd: &initial_cwd },
|
||||
false => VendorEnablement::Disable,
|
||||
});
|
||||
let resolve_workspace_discover_options = || {
|
||||
let additional_config_file_names: &'static [&'static str] =
|
||||
if matches!(flags.subcommand, DenoSubcommand::Publish(..)) {
|
||||
|
@ -899,8 +894,16 @@ impl CliOptions {
|
|||
config_parse_options,
|
||||
additional_config_file_names,
|
||||
discover_pkg_json,
|
||||
maybe_vendor_override,
|
||||
}
|
||||
};
|
||||
let resolve_empty_options = || WorkspaceEmptyOptions {
|
||||
root_dir: Arc::new(
|
||||
ModuleSpecifier::from_directory_path(&initial_cwd).unwrap(),
|
||||
),
|
||||
use_vendor_dir: maybe_vendor_override
|
||||
.unwrap_or(VendorEnablement::Disable),
|
||||
};
|
||||
|
||||
let workspace = match &flags.config_flag {
|
||||
deno_config::ConfigFlag::Discover => {
|
||||
|
@ -910,9 +913,7 @@ impl CliOptions {
|
|||
&resolve_workspace_discover_options(),
|
||||
)?
|
||||
} else {
|
||||
Workspace::empty(Arc::new(
|
||||
ModuleSpecifier::from_directory_path(&initial_cwd).unwrap(),
|
||||
))
|
||||
Workspace::empty(resolve_empty_options())
|
||||
}
|
||||
}
|
||||
deno_config::ConfigFlag::Path(path) => {
|
||||
|
@ -922,9 +923,9 @@ impl CliOptions {
|
|||
&resolve_workspace_discover_options(),
|
||||
)?
|
||||
}
|
||||
deno_config::ConfigFlag::Disabled => Workspace::empty(Arc::new(
|
||||
ModuleSpecifier::from_directory_path(&initial_cwd).unwrap(),
|
||||
)),
|
||||
deno_config::ConfigFlag::Disabled => {
|
||||
Workspace::empty(resolve_empty_options())
|
||||
}
|
||||
};
|
||||
|
||||
for diagnostic in workspace.diagnostics() {
|
||||
|
@ -1258,7 +1259,6 @@ impl CliOptions {
|
|||
flags: self.flags.clone(),
|
||||
initial_cwd: self.initial_cwd.clone(),
|
||||
maybe_node_modules_folder: Some(path),
|
||||
maybe_vendor_folder: self.maybe_vendor_folder.clone(),
|
||||
npmrc: self.npmrc.clone(),
|
||||
maybe_lockfile: self.maybe_lockfile.clone(),
|
||||
workspace: self.workspace.clone(),
|
||||
|
@ -1276,7 +1276,7 @@ impl CliOptions {
|
|||
}
|
||||
|
||||
pub fn vendor_dir_path(&self) -> Option<&PathBuf> {
|
||||
self.maybe_vendor_folder.as_ref()
|
||||
self.workspace.vendor_dir_path()
|
||||
}
|
||||
|
||||
pub fn resolve_root_cert_store_provider(
|
||||
|
@ -1801,31 +1801,6 @@ fn resolve_node_modules_folder(
|
|||
Ok(Some(canonicalize_path_maybe_not_exists(&path)?))
|
||||
}
|
||||
|
||||
fn resolve_vendor_folder(
|
||||
cwd: &Path,
|
||||
flags: &Flags,
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
) -> Option<PathBuf> {
|
||||
let use_vendor_dir = flags
|
||||
.vendor
|
||||
.or_else(|| maybe_config_file.and_then(|c| c.json.vendor))
|
||||
.unwrap_or(false);
|
||||
// Unlike the node_modules directory, there is no need to canonicalize
|
||||
// this directory because it's just used as a cache and the resolved
|
||||
// specifier is not based on the canonicalized path (unlike the modules
|
||||
// in the node_modules folder).
|
||||
if !use_vendor_dir {
|
||||
None
|
||||
} else if let Some(config_path) = maybe_config_file
|
||||
.as_ref()
|
||||
.and_then(|c| c.specifier.to_file_path().ok())
|
||||
{
|
||||
Some(config_path.parent().unwrap().join("vendor"))
|
||||
} else {
|
||||
Some(cwd.join("vendor"))
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_import_map_specifier(
|
||||
maybe_import_map_path: Option<&str>,
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
|
@ -1962,9 +1937,8 @@ pub fn config_to_deno_graph_workspace_member(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::util::fs::FileCollector;
|
||||
|
||||
use super::*;
|
||||
use deno_config::glob::FileCollector;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
|
@ -2109,7 +2083,7 @@ mod test {
|
|||
let mut files = FileCollector::new(|_| true)
|
||||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.collect_file_patterns(resolved_files)
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, resolved_files)
|
||||
.unwrap();
|
||||
|
||||
files.sort();
|
||||
|
|
|
@ -325,7 +325,7 @@ mod ts {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "__runtime_js_sources"))]
|
||||
#[cfg(not(feature = "hmr"))]
|
||||
fn create_cli_snapshot(snapshot_path: PathBuf) {
|
||||
use deno_runtime::ops::bootstrap::SnapshotOptions;
|
||||
|
||||
|
@ -469,7 +469,7 @@ fn main() {
|
|||
let compiler_snapshot_path = o.join("COMPILER_SNAPSHOT.bin");
|
||||
ts::create_compiler_snapshot(compiler_snapshot_path, &c);
|
||||
|
||||
#[cfg(not(feature = "__runtime_js_sources"))]
|
||||
#[cfg(not(feature = "hmr"))]
|
||||
{
|
||||
let cli_snapshot_path = o.join("CLI_SNAPSHOT.bin");
|
||||
create_cli_snapshot(cli_snapshot_path);
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
use log::debug;
|
||||
|
||||
#[cfg(not(feature = "__runtime_js_sources"))]
|
||||
#[cfg(not(feature = "hmr"))]
|
||||
static CLI_SNAPSHOT: &[u8] =
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin"));
|
||||
|
||||
pub fn deno_isolate_init() -> Option<&'static [u8]> {
|
||||
debug!("Deno isolate init with snapshots.");
|
||||
#[cfg(not(feature = "__runtime_js_sources"))]
|
||||
#[cfg(not(feature = "hmr"))]
|
||||
{
|
||||
Some(CLI_SNAPSHOT)
|
||||
}
|
||||
#[cfg(feature = "__runtime_js_sources")]
|
||||
#[cfg(feature = "hmr")]
|
||||
{
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1299,7 +1299,13 @@ impl ConfigData {
|
|||
}
|
||||
};
|
||||
|
||||
let vendor_dir = config_file.as_ref().and_then(|c| c.vendor_dir_path());
|
||||
let vendor_dir = config_file.as_ref().and_then(|c| {
|
||||
if c.vendor() == Some(true) {
|
||||
Some(c.specifier.to_file_path().ok()?.parent()?.join("vendor"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
// Load lockfile
|
||||
let lockfile = config_file.as_ref().and_then(resolve_lockfile_from_config);
|
||||
|
|
|
@ -3568,6 +3568,11 @@ impl Inner {
|
|||
},
|
||||
additional_config_file_names: &[],
|
||||
discover_pkg_json: true,
|
||||
maybe_vendor_override: if force_global_cache {
|
||||
Some(deno_config::workspace::VendorEnablement::Disable)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
)?);
|
||||
let cli_options = CliOptions::new(
|
||||
|
|
|
@ -145,6 +145,26 @@ impl FileSystem for DenoCompileFileSystem {
|
|||
RealFs.chown_async(path, uid, gid).await
|
||||
}
|
||||
|
||||
fn lchown_sync(
|
||||
&self,
|
||||
path: &Path,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
self.error_if_in_vfs(path)?;
|
||||
RealFs.lchown_sync(path, uid, gid)
|
||||
}
|
||||
|
||||
async fn lchown_async(
|
||||
&self,
|
||||
path: PathBuf,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
self.error_if_in_vfs(&path)?;
|
||||
RealFs.lchown_async(path, uid, gid).await
|
||||
}
|
||||
|
||||
fn remove_sync(&self, path: &Path, recursive: bool) -> FsResult<()> {
|
||||
self.error_if_in_vfs(path)?;
|
||||
RealFs.remove_sync(path, recursive)
|
||||
|
|
|
@ -13,12 +13,12 @@ use crate::tools::test::format_test_error;
|
|||
use crate::tools::test::TestFilter;
|
||||
use crate::util::file_watcher;
|
||||
use crate::util::fs::collect_specifiers;
|
||||
use crate::util::fs::WalkEntry;
|
||||
use crate::util::path::is_script_ext;
|
||||
use crate::util::path::matches_pattern_or_exact_path;
|
||||
use crate::version::get_user_agent;
|
||||
use crate::worker::CliMainWorkerFactory;
|
||||
|
||||
use deno_config::glob::WalkEntry;
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::JsError;
|
||||
|
|
|
@ -9,11 +9,11 @@ use crate::factory::CliFactory;
|
|||
use crate::npm::CliNpmResolver;
|
||||
use crate::tools::fmt::format_json;
|
||||
use crate::tools::test::is_supported_test_path;
|
||||
use crate::util::fs::FileCollector;
|
||||
use crate::util::text_encoding::source_map_from_code;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::glob::PathOrPattern;
|
||||
use deno_config::glob::PathOrPatternSet;
|
||||
|
@ -408,7 +408,7 @@ fn collect_coverages(
|
|||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
|
||||
.collect_file_patterns(file_patterns)?;
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, file_patterns)?;
|
||||
|
||||
let coverage_patterns = FilePatterns {
|
||||
base: initial_cwd.to_path_buf(),
|
||||
|
|
|
@ -19,10 +19,10 @@ use crate::factory::CliFactory;
|
|||
use crate::util::diff::diff;
|
||||
use crate::util::file_watcher;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
use crate::util::fs::FileCollector;
|
||||
use crate::util::path::get_extension;
|
||||
use async_trait::async_trait;
|
||||
use deno_ast::ParsedSource;
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::bail;
|
||||
|
@ -200,7 +200,7 @@ fn collect_fmt_files(
|
|||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
|
||||
.collect_file_patterns(files)
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files)
|
||||
}
|
||||
|
||||
/// Formats markdown (using <https://github.com/dprint/dprint-plugin-markdown>) and its code blocks
|
||||
|
|
|
@ -8,6 +8,7 @@ use deno_ast::ModuleSpecifier;
|
|||
use deno_ast::ParsedSource;
|
||||
use deno_ast::SourceRange;
|
||||
use deno_ast::SourceTextInfo;
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::workspace::Workspace;
|
||||
use deno_config::workspace::WorkspaceMemberContext;
|
||||
|
@ -60,7 +61,6 @@ use crate::tools::fmt::run_parallelized;
|
|||
use crate::util::file_watcher;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
use crate::util::fs::specifier_from_file_path;
|
||||
use crate::util::fs::FileCollector;
|
||||
use crate::util::path::is_script_ext;
|
||||
use crate::util::sync::AtomicFlag;
|
||||
|
||||
|
@ -401,7 +401,7 @@ fn collect_lint_files(
|
|||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
|
||||
.collect_file_patterns(files)
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files)
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
|
|
|
@ -8,12 +8,12 @@ use std::path::PathBuf;
|
|||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_core::error::AnyError;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::args::CliOptions;
|
||||
use crate::util::fs::FileCollector;
|
||||
|
||||
use super::diagnostics::PublishDiagnostic;
|
||||
use super::diagnostics::PublishDiagnosticsCollector;
|
||||
|
@ -319,14 +319,14 @@ fn collect_paths(
|
|||
file_patterns: FilePatterns,
|
||||
) -> Result<Vec<PathBuf>, AnyError> {
|
||||
FileCollector::new(|e| {
|
||||
if !e.file_type.is_file() {
|
||||
if !e.metadata.is_file {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(e.path) {
|
||||
diagnostics_collector.push(PublishDiagnostic::UnsupportedFileType {
|
||||
specifier,
|
||||
kind: if e.file_type.is_symlink() {
|
||||
"symlink".to_owned()
|
||||
kind: if e.metadata.is_symlink {
|
||||
"symlink".to_string()
|
||||
} else {
|
||||
format!("{:?}", e.file_type)
|
||||
"Unknown".to_string()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -341,5 +341,5 @@ fn collect_paths(
|
|||
.ignore_node_modules()
|
||||
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
|
||||
.use_gitignore()
|
||||
.collect_file_patterns(file_patterns)
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, file_patterns)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use crate::graph_util::has_graph_root_local_dependent_changed;
|
|||
use crate::ops;
|
||||
use crate::util::file_watcher;
|
||||
use crate::util::fs::collect_specifiers;
|
||||
use crate::util::fs::WalkEntry;
|
||||
use crate::util::path::get_extension;
|
||||
use crate::util::path::is_script_ext;
|
||||
use crate::util::path::mapped_specifier_for_tsc;
|
||||
|
@ -27,6 +26,7 @@ use deno_ast::swc::common::comments::CommentKind;
|
|||
use deno_ast::MediaType;
|
||||
use deno_ast::SourceRangedForSpanned;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::glob::WalkEntry;
|
||||
use deno_core::anyhow;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context as _;
|
||||
|
|
339
cli/util/fs.rs
339
cli/util/fs.rs
|
@ -1,8 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env::current_dir;
|
||||
use std::fs::FileType;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Error;
|
||||
use std::io::ErrorKind;
|
||||
|
@ -11,11 +9,12 @@ use std::path::Path;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
use deno_config::glob::PathOrPattern;
|
||||
use deno_config::glob::PathOrPatternSet;
|
||||
use deno_config::glob::WalkEntry;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -25,8 +24,6 @@ use deno_core::ModuleSpecifier;
|
|||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::PathClean;
|
||||
|
||||
use crate::util::gitignore::DirGitIgnores;
|
||||
use crate::util::gitignore::GitIgnoreTree;
|
||||
use crate::util::path::get_atomic_file_path;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressBarStyle;
|
||||
|
@ -270,192 +267,6 @@ pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
|
|||
Ok(normalize_path(resolved_path))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WalkEntry<'a> {
|
||||
pub path: &'a Path,
|
||||
pub file_type: &'a FileType,
|
||||
pub patterns: &'a FilePatterns,
|
||||
}
|
||||
|
||||
/// Collects file paths that satisfy the given predicate, by recursively walking `files`.
|
||||
/// If the walker visits a path that is listed in `ignore`, it skips descending into the directory.
|
||||
pub struct FileCollector<TFilter: Fn(WalkEntry) -> bool> {
|
||||
file_filter: TFilter,
|
||||
ignore_git_folder: bool,
|
||||
ignore_node_modules: bool,
|
||||
vendor_folder: Option<PathBuf>,
|
||||
use_gitignore: bool,
|
||||
}
|
||||
|
||||
impl<TFilter: Fn(WalkEntry) -> bool> FileCollector<TFilter> {
|
||||
pub fn new(file_filter: TFilter) -> Self {
|
||||
Self {
|
||||
file_filter,
|
||||
ignore_git_folder: false,
|
||||
ignore_node_modules: false,
|
||||
vendor_folder: None,
|
||||
use_gitignore: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ignore_node_modules(mut self) -> Self {
|
||||
self.ignore_node_modules = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vendor_folder(mut self, vendor_folder: Option<PathBuf>) -> Self {
|
||||
self.vendor_folder = vendor_folder;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ignore_git_folder(mut self) -> Self {
|
||||
self.ignore_git_folder = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn use_gitignore(mut self) -> Self {
|
||||
self.use_gitignore = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn collect_file_patterns(
|
||||
&self,
|
||||
file_patterns: FilePatterns,
|
||||
) -> Result<Vec<PathBuf>, AnyError> {
|
||||
fn is_pattern_matched(
|
||||
maybe_git_ignore: Option<&DirGitIgnores>,
|
||||
path: &Path,
|
||||
is_dir: bool,
|
||||
file_patterns: &FilePatterns,
|
||||
) -> bool {
|
||||
use deno_config::glob::FilePatternsMatch;
|
||||
|
||||
let path_kind = match is_dir {
|
||||
true => deno_config::glob::PathKind::Directory,
|
||||
false => deno_config::glob::PathKind::File,
|
||||
};
|
||||
match file_patterns.matches_path_detail(path, path_kind) {
|
||||
FilePatternsMatch::Passed => {
|
||||
// check gitignore
|
||||
let is_gitignored = maybe_git_ignore
|
||||
.as_ref()
|
||||
.map(|git_ignore| git_ignore.is_ignored(path, is_dir))
|
||||
.unwrap_or(false);
|
||||
!is_gitignored
|
||||
}
|
||||
FilePatternsMatch::PassedOptedOutExclude => true,
|
||||
FilePatternsMatch::Excluded => false,
|
||||
}
|
||||
}
|
||||
|
||||
let mut maybe_git_ignores = if self.use_gitignore {
|
||||
// Override explicitly specified include paths in the
|
||||
// .gitignore file. This does not apply to globs because
|
||||
// that is way too complicated to reason about.
|
||||
let include_paths = file_patterns
|
||||
.include
|
||||
.as_ref()
|
||||
.map(|include| {
|
||||
include
|
||||
.inner()
|
||||
.iter()
|
||||
.filter_map(|path_or_pattern| {
|
||||
if let PathOrPattern::Path(p) = path_or_pattern {
|
||||
Some(p.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
Some(GitIgnoreTree::new(
|
||||
Arc::new(deno_runtime::deno_fs::RealFs),
|
||||
include_paths,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut target_files = Vec::new();
|
||||
let mut visited_paths = HashSet::new();
|
||||
let file_patterns_by_base = file_patterns.split_by_base();
|
||||
for file_patterns in file_patterns_by_base {
|
||||
let file = normalize_path(&file_patterns.base);
|
||||
// use an iterator in order to minimize the number of file system operations
|
||||
let mut iterator = WalkDir::new(&file)
|
||||
.follow_links(false) // the default, but be explicit
|
||||
.into_iter();
|
||||
loop {
|
||||
let e = match iterator.next() {
|
||||
None => break,
|
||||
Some(Err(_)) => continue,
|
||||
Some(Ok(entry)) => entry,
|
||||
};
|
||||
let file_type = e.file_type();
|
||||
let is_dir = file_type.is_dir();
|
||||
let path = e.path().to_path_buf();
|
||||
let maybe_gitignore =
|
||||
maybe_git_ignores.as_mut().and_then(|git_ignores| {
|
||||
if is_dir {
|
||||
git_ignores.get_resolved_git_ignore_for_dir(&path)
|
||||
} else {
|
||||
git_ignores.get_resolved_git_ignore_for_file(&path)
|
||||
}
|
||||
});
|
||||
if !is_pattern_matched(
|
||||
maybe_gitignore.as_deref(),
|
||||
&path,
|
||||
is_dir,
|
||||
&file_patterns,
|
||||
) {
|
||||
if is_dir {
|
||||
iterator.skip_current_dir();
|
||||
}
|
||||
} else if is_dir {
|
||||
// allow the user to opt out of ignoring by explicitly specifying the dir
|
||||
let opt_out_ignore = file == path;
|
||||
let should_ignore_dir = !opt_out_ignore && self.is_ignored_dir(&path);
|
||||
if should_ignore_dir || !visited_paths.insert(path.clone()) {
|
||||
iterator.skip_current_dir();
|
||||
}
|
||||
} else if (self.file_filter)(WalkEntry {
|
||||
path: &path,
|
||||
file_type: &file_type,
|
||||
patterns: &file_patterns,
|
||||
}) && visited_paths.insert(path.clone())
|
||||
{
|
||||
target_files.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(target_files)
|
||||
}
|
||||
|
||||
fn is_ignored_dir(&self, path: &Path) -> bool {
|
||||
path
|
||||
.file_name()
|
||||
.map(|dir_name| {
|
||||
let dir_name = dir_name.to_string_lossy().to_lowercase();
|
||||
let is_ignored_file = match dir_name.as_str() {
|
||||
"node_modules" => self.ignore_node_modules,
|
||||
".git" => self.ignore_git_folder,
|
||||
_ => false,
|
||||
};
|
||||
is_ignored_file
|
||||
})
|
||||
.unwrap_or(false)
|
||||
|| self.is_vendor_folder(path)
|
||||
}
|
||||
|
||||
fn is_vendor_folder(&self, path: &Path) -> bool {
|
||||
self
|
||||
.vendor_folder
|
||||
.as_ref()
|
||||
.map(|vendor_folder| path == *vendor_folder)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects module specifiers that satisfy the given predicate as a file path, by recursively walking `include`.
|
||||
/// Specifiers that start with http and https are left intact.
|
||||
/// Note: This ignores all .git and node_modules folders.
|
||||
|
@ -501,7 +312,7 @@ pub fn collect_specifiers(
|
|||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.set_vendor_folder(vendor_folder)
|
||||
.collect_file_patterns(files)?;
|
||||
.collect_file_patterns(&deno_config::fs::RealDenoConfigFs, files)?;
|
||||
let mut collected_files_as_urls = collected_files
|
||||
.iter()
|
||||
.map(|f| specifier_from_file_path(f).unwrap())
|
||||
|
@ -953,150 +764,6 @@ mod tests {
|
|||
assert_eq!(resolve_from_cwd(expected).unwrap(), absolute_expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect_files() {
|
||||
fn create_files(dir_path: &PathRef, files: &[&str]) {
|
||||
dir_path.create_dir_all();
|
||||
for f in files {
|
||||
dir_path.join(f).write("");
|
||||
}
|
||||
}
|
||||
|
||||
// dir.ts
|
||||
// ├── a.ts
|
||||
// ├── b.js
|
||||
// ├── child
|
||||
// | ├── git
|
||||
// | | └── git.js
|
||||
// | ├── node_modules
|
||||
// | | └── node_modules.js
|
||||
// | ├── vendor
|
||||
// | | └── vendor.js
|
||||
// │ ├── e.mjs
|
||||
// │ ├── f.mjsx
|
||||
// │ ├── .foo.TS
|
||||
// │ └── README.md
|
||||
// ├── c.tsx
|
||||
// ├── d.jsx
|
||||
// └── ignore
|
||||
// ├── g.d.ts
|
||||
// └── .gitignore
|
||||
|
||||
let t = TempDir::new();
|
||||
|
||||
let root_dir_path = t.path().join("dir.ts");
|
||||
let root_dir_files = ["a.ts", "b.js", "c.tsx", "d.jsx"];
|
||||
create_files(&root_dir_path, &root_dir_files);
|
||||
|
||||
let child_dir_path = root_dir_path.join("child");
|
||||
let child_dir_files = ["e.mjs", "f.mjsx", ".foo.TS", "README.md"];
|
||||
create_files(&child_dir_path, &child_dir_files);
|
||||
|
||||
t.create_dir_all("dir.ts/child/node_modules");
|
||||
t.write("dir.ts/child/node_modules/node_modules.js", "");
|
||||
t.create_dir_all("dir.ts/child/.git");
|
||||
t.write("dir.ts/child/.git/git.js", "");
|
||||
t.create_dir_all("dir.ts/child/vendor");
|
||||
t.write("dir.ts/child/vendor/vendor.js", "");
|
||||
|
||||
let ignore_dir_path = root_dir_path.join("ignore");
|
||||
let ignore_dir_files = ["g.d.ts", ".gitignore"];
|
||||
create_files(&ignore_dir_path, &ignore_dir_files);
|
||||
|
||||
let file_patterns = FilePatterns {
|
||||
base: root_dir_path.to_path_buf(),
|
||||
include: None,
|
||||
exclude: PathOrPatternSet::new(vec![PathOrPattern::Path(
|
||||
ignore_dir_path.to_path_buf(),
|
||||
)]),
|
||||
};
|
||||
let file_collector = FileCollector::new(|e| {
|
||||
// exclude dotfiles
|
||||
e.path
|
||||
.file_name()
|
||||
.and_then(|f| f.to_str())
|
||||
.map(|f| !f.starts_with('.'))
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
let result = file_collector
|
||||
.collect_file_patterns(file_patterns.clone())
|
||||
.unwrap();
|
||||
let expected = [
|
||||
"README.md",
|
||||
"a.ts",
|
||||
"b.js",
|
||||
"c.tsx",
|
||||
"d.jsx",
|
||||
"e.mjs",
|
||||
"f.mjsx",
|
||||
"git.js",
|
||||
"node_modules.js",
|
||||
"vendor.js",
|
||||
];
|
||||
let mut file_names = result
|
||||
.into_iter()
|
||||
.map(|r| r.file_name().unwrap().to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>();
|
||||
file_names.sort();
|
||||
assert_eq!(file_names, expected);
|
||||
|
||||
// test ignoring the .git and node_modules folder
|
||||
let file_collector = file_collector
|
||||
.ignore_git_folder()
|
||||
.ignore_node_modules()
|
||||
.set_vendor_folder(Some(child_dir_path.join("vendor").to_path_buf()));
|
||||
let result = file_collector
|
||||
.collect_file_patterns(file_patterns.clone())
|
||||
.unwrap();
|
||||
let expected = [
|
||||
"README.md",
|
||||
"a.ts",
|
||||
"b.js",
|
||||
"c.tsx",
|
||||
"d.jsx",
|
||||
"e.mjs",
|
||||
"f.mjsx",
|
||||
];
|
||||
let mut file_names = result
|
||||
.into_iter()
|
||||
.map(|r| r.file_name().unwrap().to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>();
|
||||
file_names.sort();
|
||||
assert_eq!(file_names, expected);
|
||||
|
||||
// test opting out of ignoring by specifying the dir
|
||||
let file_patterns = FilePatterns {
|
||||
base: root_dir_path.to_path_buf(),
|
||||
include: Some(PathOrPatternSet::new(vec![
|
||||
PathOrPattern::Path(root_dir_path.to_path_buf()),
|
||||
PathOrPattern::Path(
|
||||
root_dir_path.to_path_buf().join("child/node_modules/"),
|
||||
),
|
||||
])),
|
||||
exclude: PathOrPatternSet::new(vec![PathOrPattern::Path(
|
||||
ignore_dir_path.to_path_buf(),
|
||||
)]),
|
||||
};
|
||||
let result = file_collector.collect_file_patterns(file_patterns).unwrap();
|
||||
let expected = [
|
||||
"README.md",
|
||||
"a.ts",
|
||||
"b.js",
|
||||
"c.tsx",
|
||||
"d.jsx",
|
||||
"e.mjs",
|
||||
"f.mjsx",
|
||||
"node_modules.js",
|
||||
];
|
||||
let mut file_names = result
|
||||
.into_iter()
|
||||
.map(|r| r.file_name().unwrap().to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>();
|
||||
file_names.sort();
|
||||
assert_eq!(file_names, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect_specifiers() {
|
||||
fn create_files(dir_path: &PathRef, files: &[&str]) {
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Resolved gitignore for a directory.
|
||||
pub struct DirGitIgnores {
|
||||
current: Option<Rc<ignore::gitignore::Gitignore>>,
|
||||
parent: Option<Rc<DirGitIgnores>>,
|
||||
}
|
||||
|
||||
impl DirGitIgnores {
|
||||
pub fn is_ignored(&self, path: &Path, is_dir: bool) -> bool {
|
||||
let mut is_ignored = false;
|
||||
if let Some(parent) = &self.parent {
|
||||
is_ignored = parent.is_ignored(path, is_dir);
|
||||
}
|
||||
if let Some(current) = &self.current {
|
||||
match current.matched(path, is_dir) {
|
||||
ignore::Match::None => {}
|
||||
ignore::Match::Ignore(_) => {
|
||||
is_ignored = true;
|
||||
}
|
||||
ignore::Match::Whitelist(_) => {
|
||||
is_ignored = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
is_ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves gitignores in a directory tree taking into account
|
||||
/// ancestor gitignores that may be found in a directory.
|
||||
pub struct GitIgnoreTree {
|
||||
fs: Arc<dyn deno_runtime::deno_fs::FileSystem>,
|
||||
ignores: HashMap<PathBuf, Option<Rc<DirGitIgnores>>>,
|
||||
include_paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl GitIgnoreTree {
|
||||
pub fn new(
|
||||
fs: Arc<dyn deno_runtime::deno_fs::FileSystem>,
|
||||
// paths that should override what's in the gitignore
|
||||
include_paths: Vec<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
fs,
|
||||
ignores: Default::default(),
|
||||
include_paths,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_resolved_git_ignore_for_dir(
|
||||
&mut self,
|
||||
dir_path: &Path,
|
||||
) -> Option<Rc<DirGitIgnores>> {
|
||||
// for directories, provide itself in order to tell
|
||||
// if it should stop searching for gitignores because
|
||||
// maybe this dir_path is a .git directory
|
||||
let parent = dir_path.parent()?;
|
||||
self.get_resolved_git_ignore_inner(parent, Some(dir_path))
|
||||
}
|
||||
|
||||
pub fn get_resolved_git_ignore_for_file(
|
||||
&mut self,
|
||||
file_path: &Path,
|
||||
) -> Option<Rc<DirGitIgnores>> {
|
||||
let dir_path = file_path.parent()?;
|
||||
self.get_resolved_git_ignore_inner(dir_path, None)
|
||||
}
|
||||
|
||||
fn get_resolved_git_ignore_inner(
|
||||
&mut self,
|
||||
dir_path: &Path,
|
||||
maybe_parent: Option<&Path>,
|
||||
) -> Option<Rc<DirGitIgnores>> {
|
||||
let maybe_resolved = self.ignores.get(dir_path).cloned();
|
||||
if let Some(resolved) = maybe_resolved {
|
||||
resolved
|
||||
} else {
|
||||
let resolved = self.resolve_gitignore_in_dir(dir_path, maybe_parent);
|
||||
self.ignores.insert(dir_path.to_owned(), resolved.clone());
|
||||
resolved
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_gitignore_in_dir(
|
||||
&mut self,
|
||||
dir_path: &Path,
|
||||
maybe_parent: Option<&Path>,
|
||||
) -> Option<Rc<DirGitIgnores>> {
|
||||
if let Some(parent) = maybe_parent {
|
||||
// stop searching if the parent dir had a .git directory in it
|
||||
if self.fs.exists_sync(&parent.join(".git")) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let parent = dir_path.parent().and_then(|parent| {
|
||||
self.get_resolved_git_ignore_inner(parent, Some(dir_path))
|
||||
});
|
||||
let current = self
|
||||
.fs
|
||||
.read_text_file_lossy_sync(&dir_path.join(".gitignore"), None)
|
||||
.ok()
|
||||
.and_then(|text| {
|
||||
let mut builder = ignore::gitignore::GitignoreBuilder::new(dir_path);
|
||||
for line in text.lines() {
|
||||
builder.add_line(None, line).ok()?;
|
||||
}
|
||||
// override the gitignore contents to include these paths
|
||||
for path in &self.include_paths {
|
||||
if let Ok(suffix) = path.strip_prefix(dir_path) {
|
||||
let suffix = suffix.to_string_lossy().replace('\\', "/");
|
||||
let _ignore = builder.add_line(None, &format!("!/{}", suffix));
|
||||
if !suffix.ends_with('/') {
|
||||
let _ignore = builder.add_line(None, &format!("!/{}/", suffix));
|
||||
}
|
||||
}
|
||||
}
|
||||
let gitignore = builder.build().ok()?;
|
||||
Some(Rc::new(gitignore))
|
||||
});
|
||||
if parent.is_none() && current.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(Rc::new(DirGitIgnores { current, parent }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use deno_runtime::deno_fs::InMemoryFs;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn git_ignore_tree() {
|
||||
let fs = InMemoryFs::default();
|
||||
fs.setup_text_files(vec![
|
||||
("/.gitignore".into(), "file.txt".into()),
|
||||
("/sub_dir/.gitignore".into(), "data.txt".into()),
|
||||
(
|
||||
"/sub_dir/sub_dir/.gitignore".into(),
|
||||
"!file.txt\nignore.txt".into(),
|
||||
),
|
||||
]);
|
||||
let mut ignore_tree = GitIgnoreTree::new(Arc::new(fs), Vec::new());
|
||||
let mut run_test = |path: &str, expected: bool| {
|
||||
let path = PathBuf::from(path);
|
||||
let gitignore =
|
||||
ignore_tree.get_resolved_git_ignore_for_file(&path).unwrap();
|
||||
assert_eq!(
|
||||
gitignore.is_ignored(&path, /* is_dir */ false),
|
||||
expected,
|
||||
"Path: {}",
|
||||
path.display()
|
||||
);
|
||||
};
|
||||
run_test("/file.txt", true);
|
||||
run_test("/other.txt", false);
|
||||
run_test("/data.txt", false);
|
||||
run_test("/sub_dir/file.txt", true);
|
||||
run_test("/sub_dir/other.txt", false);
|
||||
run_test("/sub_dir/data.txt", true);
|
||||
run_test("/sub_dir/sub_dir/file.txt", false); // unignored up here
|
||||
run_test("/sub_dir/sub_dir/sub_dir/file.txt", false);
|
||||
run_test("/sub_dir/sub_dir/sub_dir/ignore.txt", true);
|
||||
run_test("/sub_dir/sub_dir/ignore.txt", true);
|
||||
run_test("/sub_dir/ignore.txt", false);
|
||||
run_test("/ignore.txt", false);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ pub mod display;
|
|||
pub mod draw_thread;
|
||||
pub mod file_watcher;
|
||||
pub mod fs;
|
||||
pub mod gitignore;
|
||||
pub mod logger;
|
||||
pub mod path;
|
||||
pub mod progress_bar;
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
/// Simplifies the use of an atomic boolean as a flag.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AtomicFlag(AtomicBool);
|
||||
|
||||
impl AtomicFlag {
|
||||
/// Raises the flag returning if the raise was successful.
|
||||
pub fn raise(&self) -> bool {
|
||||
!self.0.swap(true, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Gets if the flag is raised.
|
||||
pub fn is_raised(&self) -> bool {
|
||||
self.0.load(Ordering::SeqCst)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn atomic_flag_raises() {
|
||||
let flag = AtomicFlag::default();
|
||||
assert!(!flag.is_raised()); // false by default
|
||||
assert!(flag.raise());
|
||||
assert!(flag.is_raised());
|
||||
assert!(!flag.raise());
|
||||
assert!(flag.is_raised());
|
||||
}
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
mod async_flag;
|
||||
mod atomic_flag;
|
||||
mod sync_read_async_write_lock;
|
||||
mod task_queue;
|
||||
mod value_creator;
|
||||
|
||||
pub use async_flag::AsyncFlag;
|
||||
pub use atomic_flag::AtomicFlag;
|
||||
pub use sync_read_async_write_lock::SyncReadAsyncWriteLock;
|
||||
pub use task_queue::TaskQueue;
|
||||
pub use task_queue::TaskQueuePermit;
|
||||
pub use value_creator::MultiRuntimeAsyncValueCreator;
|
||||
// todo(dsherret): this being in the unsync module is slightly confusing, but it's Sync
|
||||
pub use deno_core::unsync::AtomicFlag;
|
||||
|
|
|
@ -35,7 +35,7 @@ ring = { workspace = true, features = ["std"] }
|
|||
rsa.workspace = true
|
||||
serde.workspace = true
|
||||
serde_bytes.workspace = true
|
||||
sha1 = { version = "0.10.6", features = ["oid"] }
|
||||
sha1.workspace = true
|
||||
sha2.workspace = true
|
||||
signature.workspace = true
|
||||
spki.workspace = true
|
||||
|
|
|
@ -178,6 +178,24 @@ impl FileSystem for InMemoryFs {
|
|||
self.chown_sync(&path, uid, gid)
|
||||
}
|
||||
|
||||
fn lchown_sync(
|
||||
&self,
|
||||
_path: &Path,
|
||||
_uid: Option<u32>,
|
||||
_gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
Err(FsError::NotSupported)
|
||||
}
|
||||
|
||||
async fn lchown_async(
|
||||
&self,
|
||||
path: PathBuf,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
self.lchown_sync(&path, uid, gid)
|
||||
}
|
||||
|
||||
fn remove_sync(&self, _path: &Path, _recursive: bool) -> FsResult<()> {
|
||||
Err(FsError::NotSupported)
|
||||
}
|
||||
|
|
|
@ -146,6 +146,19 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
|
|||
gid: Option<u32>,
|
||||
) -> FsResult<()>;
|
||||
|
||||
fn lchown_sync(
|
||||
&self,
|
||||
path: &Path,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()>;
|
||||
async fn lchown_async(
|
||||
&self,
|
||||
path: PathBuf,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()>;
|
||||
|
||||
fn remove_sync(&self, path: &Path, recursive: bool) -> FsResult<()>;
|
||||
async fn remove_async(&self, path: PathBuf, recursive: bool) -> FsResult<()>;
|
||||
|
||||
|
@ -330,23 +343,68 @@ impl<'a> DenoConfigFsAdapter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
||||
fn read_to_string(&self, path: &Path) -> Result<String, std::io::Error> {
|
||||
use deno_io::fs::FsError;
|
||||
use std::io::ErrorKind;
|
||||
fn read_to_string_lossy(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Result<String, std::io::Error> {
|
||||
self
|
||||
.0
|
||||
.read_text_file_lossy_sync(path, None)
|
||||
.map_err(|err| match err {
|
||||
FsError::Io(io) => io,
|
||||
FsError::FileBusy => std::io::Error::new(ErrorKind::Other, "file busy"),
|
||||
FsError::NotSupported => {
|
||||
std::io::Error::new(ErrorKind::Other, "not supported")
|
||||
}
|
||||
FsError::PermissionDenied(name) => std::io::Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
format!("requires {}", name),
|
||||
),
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
}
|
||||
|
||||
fn stat_sync(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Result<deno_config::fs::FsMetadata, std::io::Error> {
|
||||
self
|
||||
.0
|
||||
.stat_sync(path)
|
||||
.map(|stat| deno_config::fs::FsMetadata {
|
||||
is_file: stat.is_file,
|
||||
is_directory: stat.is_directory,
|
||||
is_symlink: stat.is_symlink,
|
||||
})
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
}
|
||||
|
||||
fn read_dir(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Result<Vec<deno_config::fs::FsDirEntry>, std::io::Error> {
|
||||
self
|
||||
.0
|
||||
.read_dir_sync(path)
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
.map(|entries| {
|
||||
entries
|
||||
.into_iter()
|
||||
.map(|e| deno_config::fs::FsDirEntry {
|
||||
path: path.join(e.name),
|
||||
metadata: deno_config::fs::FsMetadata {
|
||||
is_file: e.is_file,
|
||||
is_directory: e.is_directory,
|
||||
is_symlink: e.is_symlink,
|
||||
},
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn map_deno_fs_to_config_err(fs_err: deno_io::fs::FsError) -> std::io::Error {
|
||||
use deno_io::fs::FsError;
|
||||
use std::io::ErrorKind;
|
||||
match fs_err {
|
||||
FsError::Io(io) => io,
|
||||
FsError::FileBusy => std::io::Error::new(ErrorKind::Other, "file busy"),
|
||||
FsError::NotSupported => {
|
||||
std::io::Error::new(ErrorKind::Other, "not supported")
|
||||
}
|
||||
FsError::PermissionDenied(name) => std::io::Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
format!("requires {}", name),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -303,6 +303,24 @@ impl FileSystem for RealFs {
|
|||
.await?
|
||||
}
|
||||
|
||||
fn lchown_sync(
|
||||
&self,
|
||||
path: &Path,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
lchown(path, uid, gid)
|
||||
}
|
||||
|
||||
async fn lchown_async(
|
||||
&self,
|
||||
path: PathBuf,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> FsResult<()> {
|
||||
spawn_blocking(move || lchown(&path, uid, gid)).await?
|
||||
}
|
||||
|
||||
fn write_file_sync(
|
||||
&self,
|
||||
path: &Path,
|
||||
|
@ -431,6 +449,31 @@ fn chown(_path: &Path, _uid: Option<u32>, _gid: Option<u32>) -> FsResult<()> {
|
|||
Err(FsError::NotSupported)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn lchown(path: &Path, uid: Option<u32>, gid: Option<u32>) -> FsResult<()> {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
let c_path = std::ffi::CString::new(path.as_os_str().as_bytes()).unwrap();
|
||||
// -1 = leave unchanged
|
||||
let uid = uid
|
||||
.map(|uid| uid as libc::uid_t)
|
||||
.unwrap_or(-1i32 as libc::uid_t);
|
||||
let gid = gid
|
||||
.map(|gid| gid as libc::gid_t)
|
||||
.unwrap_or(-1i32 as libc::gid_t);
|
||||
// SAFETY: `c_path` is a valid C string and lives throughout this function call.
|
||||
let result = unsafe { libc::lchown(c_path.as_ptr(), uid, gid) };
|
||||
if result != 0 {
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: implement lchown for Windows
|
||||
#[cfg(not(unix))]
|
||||
fn lchown(_path: &Path, _uid: Option<u32>, _gid: Option<u32>) -> FsResult<()> {
|
||||
Err(FsError::NotSupported)
|
||||
}
|
||||
|
||||
fn remove(path: &Path, recursive: bool) -> FsResult<()> {
|
||||
// TODO: this is racy. This should open fds, and then `unlink` those.
|
||||
let metadata = fs::symlink_metadata(path)?;
|
||||
|
|
|
@ -49,7 +49,7 @@ k256 = "0.13.1"
|
|||
lazy-regex.workspace = true
|
||||
libc.workspace = true
|
||||
libz-sys.workspace = true
|
||||
md-5 = "0.10.5"
|
||||
md-5 = { version = "0.10.5", features = ["oid"] }
|
||||
md4 = "0.10.2"
|
||||
num-bigint.workspace = true
|
||||
num-bigint-dig = "0.8.2"
|
||||
|
@ -66,14 +66,14 @@ rand.workspace = true
|
|||
regex.workspace = true
|
||||
reqwest.workspace = true
|
||||
ring.workspace = true
|
||||
ripemd = "0.1.3"
|
||||
ripemd = { version = "0.1.3", features = ["oid"] }
|
||||
rsa.workspace = true
|
||||
scrypt = "0.11.0"
|
||||
sec1 = "0.7"
|
||||
serde = "1.0.149"
|
||||
sha1.workspace = true
|
||||
sha2.workspace = true
|
||||
sha3 = "0.10.8"
|
||||
sha3 = { version = "0.10.8", features = ["oid"] }
|
||||
signature.workspace = true
|
||||
simd-json = "0.13.4"
|
||||
sm3 = "0.4.2"
|
||||
|
|
|
@ -315,6 +315,8 @@ deno_core::extension!(deno_node,
|
|||
ops::fs::op_node_fs_exists_sync<P>,
|
||||
ops::fs::op_node_cp_sync<P>,
|
||||
ops::fs::op_node_cp<P>,
|
||||
ops::fs::op_node_lchown_sync<P>,
|
||||
ops::fs::op_node_lchown<P>,
|
||||
ops::fs::op_node_lutimes_sync<P>,
|
||||
ops::fs::op_node_lutimes<P>,
|
||||
ops::fs::op_node_statfs<P>,
|
||||
|
@ -365,6 +367,7 @@ deno_core::extension!(deno_node,
|
|||
ops::os::op_node_os_set_priority<P>,
|
||||
ops::os::op_node_os_username<P>,
|
||||
ops::os::op_geteuid<P>,
|
||||
ops::os::op_getegid<P>,
|
||||
ops::os::op_cpus<P>,
|
||||
ops::os::op_homedir<P>,
|
||||
op_node_build_os,
|
||||
|
@ -426,6 +429,7 @@ deno_core::extension!(deno_node,
|
|||
"_fs/_fs_fsync.ts",
|
||||
"_fs/_fs_ftruncate.ts",
|
||||
"_fs/_fs_futimes.ts",
|
||||
"_fs/_fs_lchown.ts",
|
||||
"_fs/_fs_link.ts",
|
||||
"_fs/_fs_lstat.ts",
|
||||
"_fs/_fs_lutimes.ts",
|
||||
|
|
|
@ -56,30 +56,110 @@ impl Hasher {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! match_fixed_digest {
|
||||
($algorithm_name:expr, fn <$type:ident>() $body:block, _ => $other:block) => {
|
||||
match $algorithm_name {
|
||||
"blake2b512" => {
|
||||
type $type = ::blake2::Blake2b512;
|
||||
$body
|
||||
}
|
||||
"blake2s256" => {
|
||||
type $type = ::blake2::Blake2s256;
|
||||
$body
|
||||
}
|
||||
_ => match_fixed_digest_with_eager_block_buffer!($algorithm_name, fn <$type>() $body, _ => $other)
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use match_fixed_digest;
|
||||
|
||||
macro_rules! match_fixed_digest_with_eager_block_buffer {
|
||||
($algorithm_name:expr, fn <$type:ident>() $body:block, _ => $other:block) => {
|
||||
match $algorithm_name {
|
||||
"rsa-sm3" | "sm3" | "sm3withrsaencryption" => {
|
||||
type $type = ::sm3::Sm3;
|
||||
$body
|
||||
}
|
||||
"md5-sha1" => {
|
||||
type $type = crate::ops::crypto::md5_sha1::Md5Sha1;
|
||||
$body
|
||||
}
|
||||
_ => match_fixed_digest_with_oid!($algorithm_name, fn <$type>() $body, _ => $other)
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use match_fixed_digest_with_eager_block_buffer;
|
||||
|
||||
macro_rules! match_fixed_digest_with_oid {
|
||||
($algorithm_name:expr, fn <$type:ident>() $body:block, _ => $other:block) => {
|
||||
match $algorithm_name {
|
||||
"rsa-md5" | "md5" | "md5withrsaencryption" | "ssl3-md5" => {
|
||||
type $type = ::md5::Md5;
|
||||
$body
|
||||
}
|
||||
"rsa-ripemd160" | "ripemd" | "ripemd160" | "ripemd160withrsa"
|
||||
| "rmd160" => {
|
||||
type $type = ::ripemd::Ripemd160;
|
||||
$body
|
||||
}
|
||||
"rsa-sha1"
|
||||
| "rsa-sha1-2"
|
||||
| "sha1"
|
||||
| "sha1-2"
|
||||
| "sha1withrsaencryption"
|
||||
| "ssl3-sha1" => {
|
||||
type $type = ::sha1::Sha1;
|
||||
$body
|
||||
}
|
||||
"rsa-sha224" | "sha224" | "sha224withrsaencryption" => {
|
||||
type $type = ::sha2::Sha224;
|
||||
$body
|
||||
}
|
||||
"rsa-sha256" | "sha256" | "sha256withrsaencryption" => {
|
||||
type $type = ::sha2::Sha256;
|
||||
$body
|
||||
}
|
||||
"rsa-sha384" | "sha384" | "sha384withrsaencryption" => {
|
||||
type $type = ::sha2::Sha384;
|
||||
$body
|
||||
}
|
||||
"rsa-sha512" | "sha512" | "sha512withrsaencryption" => {
|
||||
type $type = ::sha2::Sha512;
|
||||
$body
|
||||
}
|
||||
"rsa-sha512/224" | "sha512-224" | "sha512-224withrsaencryption" => {
|
||||
type $type = ::sha2::Sha512_224;
|
||||
$body
|
||||
}
|
||||
"rsa-sha512/256" | "sha512-256" | "sha512-256withrsaencryption" => {
|
||||
type $type = ::sha2::Sha512_256;
|
||||
$body
|
||||
}
|
||||
"rsa-sha3-224" | "id-rsassa-pkcs1-v1_5-with-sha3-224" | "sha3-224" => {
|
||||
type $type = ::sha3::Sha3_224;
|
||||
$body
|
||||
}
|
||||
"rsa-sha3-256" | "id-rsassa-pkcs1-v1_5-with-sha3-256" | "sha3-256" => {
|
||||
type $type = ::sha3::Sha3_256;
|
||||
$body
|
||||
}
|
||||
"rsa-sha3-384" | "id-rsassa-pkcs1-v1_5-with-sha3-384" | "sha3-384" => {
|
||||
type $type = ::sha3::Sha3_384;
|
||||
$body
|
||||
}
|
||||
"rsa-sha3-512" | "id-rsassa-pkcs1-v1_5-with-sha3-512" | "sha3-512" => {
|
||||
type $type = ::sha3::Sha3_512;
|
||||
$body
|
||||
}
|
||||
_ => $other,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use match_fixed_digest_with_oid;
|
||||
|
||||
pub enum Hash {
|
||||
Blake2b512(Box<blake2::Blake2b512>),
|
||||
Blake2s256(Box<blake2::Blake2s256>),
|
||||
|
||||
Md4(Box<md4::Md4>),
|
||||
Md5(Box<md5::Md5>),
|
||||
|
||||
Ripemd160(Box<ripemd::Ripemd160>),
|
||||
|
||||
Sha1(Box<sha1::Sha1>),
|
||||
|
||||
Sha224(Box<sha2::Sha224>),
|
||||
Sha256(Box<sha2::Sha256>),
|
||||
Sha384(Box<sha2::Sha384>),
|
||||
Sha512(Box<sha2::Sha512>),
|
||||
Sha512_224(Box<sha2::Sha512_224>),
|
||||
Sha512_256(Box<sha2::Sha512_256>),
|
||||
|
||||
Sha3_224(Box<sha3::Sha3_224>),
|
||||
Sha3_256(Box<sha3::Sha3_256>),
|
||||
Sha3_384(Box<sha3::Sha3_384>),
|
||||
Sha3_512(Box<sha3::Sha3_512>),
|
||||
|
||||
Sm3(Box<sm3::Sm3>),
|
||||
FixedSize(Box<dyn DynDigest>),
|
||||
|
||||
Shake128(Box<sha3::Shake128>, /* output_length: */ Option<usize>),
|
||||
Shake256(Box<sha3::Shake256>, /* output_length: */ Option<usize>),
|
||||
|
@ -98,105 +178,32 @@ impl Hash {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let algorithm = match algorithm_name {
|
||||
"blake2b512" => Blake2b512(Default::default()),
|
||||
"blake2s256" => Blake2s256(Default::default()),
|
||||
|
||||
"md4" => Md4(Default::default()),
|
||||
"md5" => Md5(Default::default()),
|
||||
|
||||
"ripemd160" => Ripemd160(Default::default()),
|
||||
|
||||
"sha1" => Sha1(Default::default()),
|
||||
"sha224" => Sha224(Default::default()),
|
||||
"sha256" => Sha256(Default::default()),
|
||||
"sha384" => Sha384(Default::default()),
|
||||
"sha512" => Sha512(Default::default()),
|
||||
"sha512-224" => Sha512_224(Default::default()),
|
||||
"sha512-256" => Sha512_256(Default::default()),
|
||||
|
||||
"sha3-224" => Sha3_224(Default::default()),
|
||||
"sha3-256" => Sha3_256(Default::default()),
|
||||
"sha3-384" => Sha3_384(Default::default()),
|
||||
"sha3-512" => Sha3_512(Default::default()),
|
||||
|
||||
"sm3" => Sm3(Default::default()),
|
||||
|
||||
let algorithm = match_fixed_digest!(
|
||||
algorithm_name,
|
||||
fn <D>() {
|
||||
let digest: D = Digest::new();
|
||||
if let Some(length) = output_length {
|
||||
if length != digest.output_size() {
|
||||
return Err(generic_error(
|
||||
"Output length mismatch for non-extendable algorithm",
|
||||
));
|
||||
}
|
||||
}
|
||||
FixedSize(Box::new(digest))
|
||||
},
|
||||
_ => {
|
||||
return Err(generic_error(format!(
|
||||
"Digest method not supported: {algorithm_name}"
|
||||
)))
|
||||
}
|
||||
};
|
||||
if let Some(length) = output_length {
|
||||
if length != algorithm.output_length() {
|
||||
return Err(generic_error(
|
||||
"Output length mismatch for non-extendable algorithm",
|
||||
));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Ok(algorithm)
|
||||
}
|
||||
|
||||
pub fn output_length(&self) -> usize {
|
||||
match self {
|
||||
Blake2b512(context) => context.output_size(),
|
||||
Blake2s256(context) => context.output_size(),
|
||||
|
||||
Md4(context) => context.output_size(),
|
||||
Md5(context) => context.output_size(),
|
||||
|
||||
Ripemd160(context) => context.output_size(),
|
||||
|
||||
Sha1(context) => context.output_size(),
|
||||
Sha224(context) => context.output_size(),
|
||||
Sha256(context) => context.output_size(),
|
||||
Sha384(context) => context.output_size(),
|
||||
Sha512(context) => context.output_size(),
|
||||
Sha512_224(context) => context.output_size(),
|
||||
Sha512_256(context) => context.output_size(),
|
||||
|
||||
Sha3_224(context) => context.output_size(),
|
||||
Sha3_256(context) => context.output_size(),
|
||||
Sha3_384(context) => context.output_size(),
|
||||
Sha3_512(context) => context.output_size(),
|
||||
|
||||
Sm3(context) => context.output_size(),
|
||||
|
||||
Shake128(_, _) => unreachable!(
|
||||
"output_length() should not be called on extendable algorithms"
|
||||
),
|
||||
Shake256(_, _) => unreachable!(
|
||||
"output_length() should not be called on extendable algorithms"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, data: &[u8]) {
|
||||
match self {
|
||||
Blake2b512(context) => Digest::update(&mut **context, data),
|
||||
Blake2s256(context) => Digest::update(&mut **context, data),
|
||||
|
||||
Md4(context) => Digest::update(&mut **context, data),
|
||||
Md5(context) => Digest::update(&mut **context, data),
|
||||
|
||||
Ripemd160(context) => Digest::update(&mut **context, data),
|
||||
|
||||
Sha1(context) => Digest::update(&mut **context, data),
|
||||
Sha224(context) => Digest::update(&mut **context, data),
|
||||
Sha256(context) => Digest::update(&mut **context, data),
|
||||
Sha384(context) => Digest::update(&mut **context, data),
|
||||
Sha512(context) => Digest::update(&mut **context, data),
|
||||
Sha512_224(context) => Digest::update(&mut **context, data),
|
||||
Sha512_256(context) => Digest::update(&mut **context, data),
|
||||
|
||||
Sha3_224(context) => Digest::update(&mut **context, data),
|
||||
Sha3_256(context) => Digest::update(&mut **context, data),
|
||||
Sha3_384(context) => Digest::update(&mut **context, data),
|
||||
Sha3_512(context) => Digest::update(&mut **context, data),
|
||||
|
||||
Sm3(context) => Digest::update(&mut **context, data),
|
||||
|
||||
FixedSize(context) => DynDigest::update(&mut **context, data),
|
||||
Shake128(context, _) => Update::update(&mut **context, data),
|
||||
Shake256(context, _) => Update::update(&mut **context, data),
|
||||
};
|
||||
|
@ -204,28 +211,7 @@ impl Hash {
|
|||
|
||||
pub fn digest_and_drop(self) -> Box<[u8]> {
|
||||
match self {
|
||||
Blake2b512(context) => context.finalize(),
|
||||
Blake2s256(context) => context.finalize(),
|
||||
|
||||
Md4(context) => context.finalize(),
|
||||
Md5(context) => context.finalize(),
|
||||
|
||||
Ripemd160(context) => context.finalize(),
|
||||
|
||||
Sha1(context) => context.finalize(),
|
||||
Sha224(context) => context.finalize(),
|
||||
Sha256(context) => context.finalize(),
|
||||
Sha384(context) => context.finalize(),
|
||||
Sha512(context) => context.finalize(),
|
||||
Sha512_224(context) => context.finalize(),
|
||||
Sha512_256(context) => context.finalize(),
|
||||
|
||||
Sha3_224(context) => context.finalize(),
|
||||
Sha3_256(context) => context.finalize(),
|
||||
Sha3_384(context) => context.finalize(),
|
||||
Sha3_512(context) => context.finalize(),
|
||||
|
||||
Sm3(context) => context.finalize(),
|
||||
FixedSize(context) => context.finalize(),
|
||||
|
||||
// The default output lengths align with Node.js
|
||||
Shake128(context, output_length) => {
|
||||
|
@ -242,69 +228,77 @@ impl Hash {
|
|||
output_length: Option<usize>,
|
||||
) -> Result<Self, AnyError> {
|
||||
let hash = match self {
|
||||
Shake128(context, _) => {
|
||||
return Ok(Shake128(context.clone(), output_length))
|
||||
}
|
||||
Shake256(context, _) => {
|
||||
return Ok(Shake256(context.clone(), output_length))
|
||||
FixedSize(context) => {
|
||||
if let Some(length) = output_length {
|
||||
if length != context.output_size() {
|
||||
return Err(generic_error(
|
||||
"Output length mismatch for non-extendable algorithm",
|
||||
));
|
||||
}
|
||||
}
|
||||
FixedSize(context.box_clone())
|
||||
}
|
||||
|
||||
Blake2b512(context) => Blake2b512(context.clone()),
|
||||
Blake2s256(context) => Blake2s256(context.clone()),
|
||||
|
||||
Md4(context) => Md4(context.clone()),
|
||||
Md5(context) => Md5(context.clone()),
|
||||
|
||||
Ripemd160(context) => Ripemd160(context.clone()),
|
||||
|
||||
Sha1(context) => Sha1(context.clone()),
|
||||
Sha224(context) => Sha224(context.clone()),
|
||||
Sha256(context) => Sha256(context.clone()),
|
||||
Sha384(context) => Sha384(context.clone()),
|
||||
Sha512(context) => Sha512(context.clone()),
|
||||
Sha512_224(context) => Sha512_224(context.clone()),
|
||||
Sha512_256(context) => Sha512_256(context.clone()),
|
||||
|
||||
Sha3_224(context) => Sha3_224(context.clone()),
|
||||
Sha3_256(context) => Sha3_256(context.clone()),
|
||||
Sha3_384(context) => Sha3_384(context.clone()),
|
||||
Sha3_512(context) => Sha3_512(context.clone()),
|
||||
|
||||
Sm3(context) => Sm3(context.clone()),
|
||||
Shake128(context, _) => Shake128(context.clone(), output_length),
|
||||
Shake256(context, _) => Shake256(context.clone(), output_length),
|
||||
};
|
||||
|
||||
if let Some(length) = output_length {
|
||||
if length != hash.output_length() {
|
||||
return Err(generic_error(
|
||||
"Output length mismatch for non-extendable algorithm",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
pub fn get_hashes() -> Vec<&'static str> {
|
||||
vec![
|
||||
"blake2s256",
|
||||
"RSA-MD5",
|
||||
"RSA-RIPEMD160",
|
||||
"RSA-SHA1",
|
||||
"RSA-SHA1-2",
|
||||
"RSA-SHA224",
|
||||
"RSA-SHA256",
|
||||
"RSA-SHA3-224",
|
||||
"RSA-SHA3-256",
|
||||
"RSA-SHA3-384",
|
||||
"RSA-SHA3-512",
|
||||
"RSA-SHA384",
|
||||
"RSA-SHA512",
|
||||
"RSA-SHA512/224",
|
||||
"RSA-SHA512/256",
|
||||
"RSA-SM3",
|
||||
"blake2b512",
|
||||
"md4",
|
||||
"blake2s256",
|
||||
"id-rsassa-pkcs1-v1_5-with-sha3-224",
|
||||
"id-rsassa-pkcs1-v1_5-with-sha3-256",
|
||||
"id-rsassa-pkcs1-v1_5-with-sha3-384",
|
||||
"id-rsassa-pkcs1-v1_5-with-sha3-512",
|
||||
"md5",
|
||||
"md5-sha1",
|
||||
"md5WithRSAEncryption",
|
||||
"ripemd",
|
||||
"ripemd160",
|
||||
"ripemd160WithRSA",
|
||||
"rmd160",
|
||||
"sha1",
|
||||
"sha1WithRSAEncryption",
|
||||
"sha224",
|
||||
"sha224WithRSAEncryption",
|
||||
"sha256",
|
||||
"sha384",
|
||||
"sha512",
|
||||
"sha512-224",
|
||||
"sha512-256",
|
||||
"sha256WithRSAEncryption",
|
||||
"sha3-224",
|
||||
"sha3-256",
|
||||
"sha3-384",
|
||||
"sha3-512",
|
||||
"sha384",
|
||||
"sha384WithRSAEncryption",
|
||||
"sha512",
|
||||
"sha512-224",
|
||||
"sha512-224WithRSAEncryption",
|
||||
"sha512-256",
|
||||
"sha512-256WithRSAEncryption",
|
||||
"sha512WithRSAEncryption",
|
||||
"shake128",
|
||||
"shake256",
|
||||
"sm3",
|
||||
"sm3WithRSAEncryption",
|
||||
"ssl3-md5",
|
||||
"ssl3-sha1",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
99
ext/node/ops/crypto/md5_sha1.rs
Normal file
99
ext/node/ops/crypto/md5_sha1.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
use core::fmt;
|
||||
use digest::core_api::AlgorithmName;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::core_api::Buffer;
|
||||
use digest::core_api::BufferKindUser;
|
||||
use digest::core_api::CoreWrapper;
|
||||
use digest::core_api::FixedOutputCore;
|
||||
use digest::core_api::OutputSizeUser;
|
||||
use digest::core_api::UpdateCore;
|
||||
use digest::HashMarker;
|
||||
use digest::Output;
|
||||
use digest::Reset;
|
||||
|
||||
pub type Md5Sha1 = CoreWrapper<Md5Sha1Core>;
|
||||
|
||||
pub struct Md5Sha1Core {
|
||||
md5: md5::Md5Core,
|
||||
sha1: sha1::Sha1Core,
|
||||
}
|
||||
|
||||
impl HashMarker for Md5Sha1Core {}
|
||||
|
||||
impl BlockSizeUser for Md5Sha1Core {
|
||||
type BlockSize = sec1::consts::U64;
|
||||
}
|
||||
|
||||
impl BufferKindUser for Md5Sha1Core {
|
||||
type BufferKind = digest::block_buffer::Eager;
|
||||
}
|
||||
|
||||
impl OutputSizeUser for Md5Sha1Core {
|
||||
type OutputSize = sec1::consts::U36;
|
||||
}
|
||||
|
||||
impl UpdateCore for Md5Sha1Core {
|
||||
#[inline]
|
||||
fn update_blocks(&mut self, blocks: &[digest::core_api::Block<Self>]) {
|
||||
self.md5.update_blocks(blocks);
|
||||
self.sha1.update_blocks(blocks);
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedOutputCore for Md5Sha1Core {
|
||||
#[inline]
|
||||
fn finalize_fixed_core(
|
||||
&mut self,
|
||||
buffer: &mut Buffer<Self>,
|
||||
out: &mut Output<Self>,
|
||||
) {
|
||||
let mut md5_output = Output::<md5::Md5Core>::default();
|
||||
self
|
||||
.md5
|
||||
.finalize_fixed_core(&mut buffer.clone(), &mut md5_output);
|
||||
let mut sha1_output = Output::<sha1::Sha1Core>::default();
|
||||
self.sha1.finalize_fixed_core(buffer, &mut sha1_output);
|
||||
out[..16].copy_from_slice(&md5_output);
|
||||
out[16..].copy_from_slice(&sha1_output);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Md5Sha1Core {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
md5: Default::default(),
|
||||
sha1: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Md5Sha1Core {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
md5: self.md5.clone(),
|
||||
sha1: self.sha1.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reset for Md5Sha1Core {
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
*self = Default::default();
|
||||
}
|
||||
}
|
||||
|
||||
impl AlgorithmName for Md5Sha1Core {
|
||||
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("Md5Sha1")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Md5Sha1Core {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("Md5Sha1Core { ... }")
|
||||
}
|
||||
}
|
|
@ -46,9 +46,13 @@ use spki::EncodePublicKey;
|
|||
mod cipher;
|
||||
mod dh;
|
||||
mod digest;
|
||||
mod md5_sha1;
|
||||
mod primes;
|
||||
pub mod x509;
|
||||
|
||||
use self::digest::match_fixed_digest_with_eager_block_buffer;
|
||||
use self::digest::match_fixed_digest_with_oid;
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_node_check_prime(
|
||||
#[bigint] num: i64,
|
||||
|
@ -382,33 +386,30 @@ pub fn op_node_sign(
|
|||
RSA_ENCRYPTION_OID => {
|
||||
use rsa::pkcs1v15::SigningKey;
|
||||
let key = RsaPrivateKey::from_pkcs1_der(pkey)?;
|
||||
Ok(
|
||||
match digest_type {
|
||||
"sha224" => {
|
||||
let signing_key = SigningKey::<sha2::Sha224>::new(key);
|
||||
signing_key.sign_prehash(digest)?.to_vec()
|
||||
}
|
||||
"sha256" => {
|
||||
let signing_key = SigningKey::<sha2::Sha256>::new(key);
|
||||
signing_key.sign_prehash(digest)?.to_vec()
|
||||
}
|
||||
"sha384" => {
|
||||
let signing_key = SigningKey::<sha2::Sha384>::new(key);
|
||||
signing_key.sign_prehash(digest)?.to_vec()
|
||||
}
|
||||
"sha512" => {
|
||||
let signing_key = SigningKey::<sha2::Sha512>::new(key);
|
||||
signing_key.sign_prehash(digest)?.to_vec()
|
||||
}
|
||||
_ => {
|
||||
return Err(type_error(format!(
|
||||
"Unknown digest algorithm: {}",
|
||||
digest_type
|
||||
)))
|
||||
}
|
||||
|
||||
// md5-sha1 is special, because it's not wrapped in an ASN.1 DigestInfo
|
||||
// (so has no prefix).
|
||||
// See https://github.com/openssl/openssl/blob/af82623d32962b3eff5b0f0b0dedec5eb730b231/crypto/rsa/rsa_sign.c#L285
|
||||
if digest_type == "md5-sha1" {
|
||||
let signing_key = SigningKey::<md5_sha1::Md5Sha1>::new_unprefixed(key);
|
||||
let signature = signing_key.sign_prehash(digest)?.to_vec();
|
||||
return Ok(signature.into());
|
||||
}
|
||||
|
||||
let signature = match_fixed_digest_with_oid!(
|
||||
digest_type,
|
||||
fn <D>() {
|
||||
let signing_key = SigningKey::<D>::new(key);
|
||||
signing_key.sign_prehash(digest)?.to_vec()
|
||||
},
|
||||
_ => {
|
||||
return Err(type_error(format!(
|
||||
"digest not allowed for RSA signature: {}",
|
||||
digest_type
|
||||
)))
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
);
|
||||
Ok(signature.into())
|
||||
}
|
||||
// signature structure encoding is DER by default for DSA and ECDSA.
|
||||
//
|
||||
|
@ -456,29 +457,35 @@ pub fn op_node_verify(
|
|||
)))
|
||||
}
|
||||
};
|
||||
Ok(match digest_type {
|
||||
"sha224" => VerifyingKey::<sha2::Sha224>::new(key)
|
||||
|
||||
// md5-sha1 is special, because it's not wrapped in an ASN.1 DigestInfo
|
||||
// (so has no prefix).
|
||||
// See https://github.com/openssl/openssl/blob/af82623d32962b3eff5b0f0b0dedec5eb730b231/crypto/rsa/rsa_sign.c#L285
|
||||
if digest_type == "md5-sha1" {
|
||||
let verifying_key =
|
||||
VerifyingKey::<md5_sha1::Md5Sha1>::new_unprefixed(key);
|
||||
let verified = verifying_key
|
||||
.verify_prehash(digest, &signature.try_into()?)
|
||||
.is_ok(),
|
||||
"sha256" => VerifyingKey::<sha2::Sha256>::new(key)
|
||||
.verify_prehash(digest, &signature.try_into()?)
|
||||
.is_ok(),
|
||||
"sha384" => VerifyingKey::<sha2::Sha384>::new(key)
|
||||
.verify_prehash(digest, &signature.try_into()?)
|
||||
.is_ok(),
|
||||
"sha512" => VerifyingKey::<sha2::Sha512>::new(key)
|
||||
.verify_prehash(digest, &signature.try_into()?)
|
||||
.is_ok(),
|
||||
.is_ok();
|
||||
return Ok(verified);
|
||||
}
|
||||
|
||||
Ok(match_fixed_digest_with_oid!(
|
||||
digest_type,
|
||||
fn <D>() {
|
||||
let verifying_key = VerifyingKey::<D>::new(key);
|
||||
verifying_key.verify_prehash(digest, &signature.try_into()?).is_ok()
|
||||
},
|
||||
_ => {
|
||||
return Err(type_error(format!(
|
||||
"Unknown digest algorithm: {}",
|
||||
"digest not allowed for RSA signature: {}",
|
||||
digest_type
|
||||
)))
|
||||
}
|
||||
})
|
||||
))
|
||||
}
|
||||
_ => Err(type_error(format!(
|
||||
"Verifying with {} keys is not supported yet",
|
||||
"Verifying with {} keys is not supported",
|
||||
key_type
|
||||
))),
|
||||
}
|
||||
|
@ -488,28 +495,22 @@ fn pbkdf2_sync(
|
|||
password: &[u8],
|
||||
salt: &[u8],
|
||||
iterations: u32,
|
||||
digest: &str,
|
||||
algorithm_name: &str,
|
||||
derived_key: &mut [u8],
|
||||
) -> Result<(), AnyError> {
|
||||
macro_rules! pbkdf2_hmac {
|
||||
($digest:ty) => {{
|
||||
pbkdf2::pbkdf2_hmac::<$digest>(password, salt, iterations, derived_key)
|
||||
}};
|
||||
}
|
||||
|
||||
match digest {
|
||||
"md4" => pbkdf2_hmac!(md4::Md4),
|
||||
"md5" => pbkdf2_hmac!(md5::Md5),
|
||||
"ripemd160" => pbkdf2_hmac!(ripemd::Ripemd160),
|
||||
"sha1" => pbkdf2_hmac!(sha1::Sha1),
|
||||
"sha224" => pbkdf2_hmac!(sha2::Sha224),
|
||||
"sha256" => pbkdf2_hmac!(sha2::Sha256),
|
||||
"sha384" => pbkdf2_hmac!(sha2::Sha384),
|
||||
"sha512" => pbkdf2_hmac!(sha2::Sha512),
|
||||
_ => return Err(type_error("Unknown digest")),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
match_fixed_digest_with_eager_block_buffer!(
|
||||
algorithm_name,
|
||||
fn <D>() {
|
||||
pbkdf2::pbkdf2_hmac::<D>(password, salt, iterations, derived_key);
|
||||
Ok(())
|
||||
},
|
||||
_ => {
|
||||
Err(type_error(format!(
|
||||
"unsupported digest: {}",
|
||||
algorithm_name
|
||||
)))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[op2]
|
||||
|
@ -558,50 +559,40 @@ pub async fn op_node_generate_secret_async(#[smi] len: i32) -> ToJsBuffer {
|
|||
}
|
||||
|
||||
fn hkdf_sync(
|
||||
hash: &str,
|
||||
digest_algorithm: &str,
|
||||
ikm: &[u8],
|
||||
salt: &[u8],
|
||||
info: &[u8],
|
||||
okm: &mut [u8],
|
||||
) -> Result<(), AnyError> {
|
||||
macro_rules! hkdf {
|
||||
($hash:ty) => {{
|
||||
let hk = Hkdf::<$hash>::new(Some(salt), ikm);
|
||||
match_fixed_digest_with_eager_block_buffer!(
|
||||
digest_algorithm,
|
||||
fn <D>() {
|
||||
let hk = Hkdf::<D>::new(Some(salt), ikm);
|
||||
hk.expand(info, okm)
|
||||
.map_err(|_| type_error("HKDF-Expand failed"))?;
|
||||
}};
|
||||
}
|
||||
|
||||
match hash {
|
||||
"md4" => hkdf!(md4::Md4),
|
||||
"md5" => hkdf!(md5::Md5),
|
||||
"ripemd160" => hkdf!(ripemd::Ripemd160),
|
||||
"sha1" => hkdf!(sha1::Sha1),
|
||||
"sha224" => hkdf!(sha2::Sha224),
|
||||
"sha256" => hkdf!(sha2::Sha256),
|
||||
"sha384" => hkdf!(sha2::Sha384),
|
||||
"sha512" => hkdf!(sha2::Sha512),
|
||||
_ => return Err(type_error("Unknown digest")),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
.map_err(|_| type_error("HKDF-Expand failed"))
|
||||
},
|
||||
_ => {
|
||||
Err(type_error(format!("Unsupported digest: {}", digest_algorithm)))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_node_hkdf(
|
||||
#[string] hash: &str,
|
||||
#[string] digest_algorithm: &str,
|
||||
#[buffer] ikm: &[u8],
|
||||
#[buffer] salt: &[u8],
|
||||
#[buffer] info: &[u8],
|
||||
#[buffer] okm: &mut [u8],
|
||||
) -> Result<(), AnyError> {
|
||||
hkdf_sync(hash, ikm, salt, info, okm)
|
||||
hkdf_sync(digest_algorithm, ikm, salt, info, okm)
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
#[serde]
|
||||
pub async fn op_node_hkdf_async(
|
||||
#[string] hash: String,
|
||||
#[string] digest_algorithm: String,
|
||||
#[buffer] ikm: JsBuffer,
|
||||
#[buffer] salt: JsBuffer,
|
||||
#[buffer] info: JsBuffer,
|
||||
|
@ -609,7 +600,7 @@ pub async fn op_node_hkdf_async(
|
|||
) -> Result<ToJsBuffer, AnyError> {
|
||||
spawn_blocking(move || {
|
||||
let mut okm = vec![0u8; okm_len];
|
||||
hkdf_sync(&hash, &ikm, &salt, &info, &mut okm)?;
|
||||
hkdf_sync(&digest_algorithm, &ikm, &salt, &info, &mut okm)?;
|
||||
Ok(okm.into())
|
||||
})
|
||||
.await?
|
||||
|
|
|
@ -273,3 +273,44 @@ where
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op2]
|
||||
pub fn op_node_lchown_sync<P>(
|
||||
state: &mut OpState,
|
||||
#[string] path: String,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> Result<(), AnyError>
|
||||
where
|
||||
P: NodePermissions + 'static,
|
||||
{
|
||||
let path = PathBuf::from(path);
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write_with_api_name(&path, Some("node:fs.lchownSync"))?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.lchown_sync(&path, uid, gid)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
pub async fn op_node_lchown<P>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[string] path: String,
|
||||
uid: Option<u32>,
|
||||
gid: Option<u32>,
|
||||
) -> Result<(), AnyError>
|
||||
where
|
||||
P: NodePermissions + 'static,
|
||||
{
|
||||
let path = PathBuf::from(path);
|
||||
let fs = {
|
||||
let mut state = state.borrow_mut();
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write_with_api_name(&path, Some("node:fs.lchown"))?;
|
||||
state.borrow::<FileSystemRc>().clone()
|
||||
};
|
||||
fs.lchown_async(path, uid, gid).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -75,6 +75,25 @@ where
|
|||
Ok(euid)
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_getegid<P>(state: &mut OpState) -> Result<u32, AnyError>
|
||||
where
|
||||
P: NodePermissions + 'static,
|
||||
{
|
||||
{
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
permissions.check_sys("getegid", "node:os.getegid()")?;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
let egid = 0;
|
||||
#[cfg(unix)]
|
||||
// SAFETY: Call to libc getegid.
|
||||
let egid = unsafe { libc::getegid() };
|
||||
|
||||
Ok(egid)
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
pub fn op_cpus<P>(state: &mut OpState) -> Result<Vec<cpus::CpuInfo>, AnyError>
|
||||
|
|
61
ext/node/polyfills/_fs/_fs_lchown.ts
Normal file
61
ext/node/polyfills/_fs/_fs_lchown.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// TODO(petamoriken): enable prefer-primordials for node polyfills
|
||||
// deno-lint-ignore-file prefer-primordials
|
||||
|
||||
import {
|
||||
type CallbackWithError,
|
||||
makeCallback,
|
||||
} from "ext:deno_node/_fs/_fs_common.ts";
|
||||
import {
|
||||
getValidatedPath,
|
||||
kMaxUserId,
|
||||
} from "ext:deno_node/internal/fs/utils.mjs";
|
||||
import * as pathModule from "node:path";
|
||||
import { validateInteger } from "ext:deno_node/internal/validators.mjs";
|
||||
import type { Buffer } from "node:buffer";
|
||||
import { promisify } from "ext:deno_node/internal/util.mjs";
|
||||
import { op_node_lchown, op_node_lchown_sync } from "ext:core/ops";
|
||||
|
||||
/**
|
||||
* Asynchronously changes the owner and group
|
||||
* of a file, without following symlinks.
|
||||
*/
|
||||
export function lchown(
|
||||
path: string | Buffer | URL,
|
||||
uid: number,
|
||||
gid: number,
|
||||
callback: CallbackWithError,
|
||||
) {
|
||||
callback = makeCallback(callback);
|
||||
path = getValidatedPath(path).toString();
|
||||
validateInteger(uid, "uid", -1, kMaxUserId);
|
||||
validateInteger(gid, "gid", -1, kMaxUserId);
|
||||
|
||||
op_node_lchown(pathModule.toNamespacedPath(path), uid, gid).then(
|
||||
() => callback(null),
|
||||
callback,
|
||||
);
|
||||
}
|
||||
|
||||
export const lchownPromise = promisify(lchown) as (
|
||||
path: string | Buffer | URL,
|
||||
uid: number,
|
||||
gid: number,
|
||||
) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Synchronously changes the owner and group
|
||||
* of a file, without following symlinks.
|
||||
*/
|
||||
export function lchownSync(
|
||||
path: string | Buffer | URL,
|
||||
uid: number,
|
||||
gid: number,
|
||||
) {
|
||||
path = getValidatedPath(path).toString();
|
||||
validateInteger(uid, "uid", -1, kMaxUserId);
|
||||
validateInteger(gid, "gid", -1, kMaxUserId);
|
||||
|
||||
op_node_lchown_sync(pathModule.toNamespacedPath(path), uid, gid);
|
||||
}
|
|
@ -27,6 +27,11 @@ import { fstat, fstatSync } from "ext:deno_node/_fs/_fs_fstat.ts";
|
|||
import { fsync, fsyncSync } from "ext:deno_node/_fs/_fs_fsync.ts";
|
||||
import { ftruncate, ftruncateSync } from "ext:deno_node/_fs/_fs_ftruncate.ts";
|
||||
import { futimes, futimesSync } from "ext:deno_node/_fs/_fs_futimes.ts";
|
||||
import {
|
||||
lchown,
|
||||
lchownPromise,
|
||||
lchownSync,
|
||||
} from "ext:deno_node/_fs/_fs_lchown.ts";
|
||||
import { link, linkPromise, linkSync } from "ext:deno_node/_fs/_fs_link.ts";
|
||||
import { lstat, lstatPromise, lstatSync } from "ext:deno_node/_fs/_fs_lstat.ts";
|
||||
import {
|
||||
|
@ -173,7 +178,7 @@ const promises = {
|
|||
unlink: unlinkPromise,
|
||||
chmod: chmodPromise,
|
||||
// lchmod: promisify(lchmod),
|
||||
// lchown: promisify(lchown),
|
||||
lchown: lchownPromise,
|
||||
chown: chownPromise,
|
||||
utimes: utimesPromise,
|
||||
lutimes: lutimesPromise,
|
||||
|
@ -218,6 +223,8 @@ export default {
|
|||
ftruncateSync,
|
||||
futimes,
|
||||
futimesSync,
|
||||
lchown,
|
||||
lchownSync,
|
||||
link,
|
||||
linkSync,
|
||||
lstat,
|
||||
|
|
|
@ -1349,7 +1349,6 @@ export class ServerResponse extends NodeWritable {
|
|||
// used by `npm:on-finished`
|
||||
finished = false;
|
||||
headersSent = false;
|
||||
#firstChunk: Chunk | null = null;
|
||||
#resolve: (value: Response | PromiseLike<Response>) => void;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
#socketOverride: any | null = null;
|
||||
|
@ -1386,28 +1385,25 @@ export class ServerResponse extends NodeWritable {
|
|||
autoDestroy: true,
|
||||
defaultEncoding: "utf-8",
|
||||
emitClose: true,
|
||||
// FIXME: writes don't work when a socket is assigned and then
|
||||
// detached.
|
||||
write: (chunk, encoding, cb) => {
|
||||
// Writes chunks are directly written to the socket if
|
||||
// one is assigned via assignSocket()
|
||||
if (this.#socketOverride && this.#socketOverride.writable) {
|
||||
this.#socketOverride.write(chunk, encoding);
|
||||
return cb();
|
||||
}
|
||||
if (!this.headersSent) {
|
||||
if (this.#firstChunk === null) {
|
||||
this.#firstChunk = chunk;
|
||||
return cb();
|
||||
} else {
|
||||
ServerResponse.#enqueue(controller, this.#firstChunk);
|
||||
this.#firstChunk = null;
|
||||
this.respond(false);
|
||||
}
|
||||
ServerResponse.#enqueue(controller, chunk);
|
||||
this.respond(false);
|
||||
return cb();
|
||||
}
|
||||
ServerResponse.#enqueue(controller, chunk);
|
||||
return cb();
|
||||
},
|
||||
final: (cb) => {
|
||||
if (this.#firstChunk) {
|
||||
this.respond(true, this.#firstChunk);
|
||||
} else if (!this.headersSent) {
|
||||
if (!this.headersSent) {
|
||||
this.respond(true);
|
||||
}
|
||||
controller.close();
|
||||
|
@ -1654,9 +1650,6 @@ export function Server(opts, requestListener?: ServerHandler): ServerImpl {
|
|||
}
|
||||
|
||||
export class ServerImpl extends EventEmitter {
|
||||
#httpConnections: Set<Deno.HttpConn> = new Set();
|
||||
#listener?: Deno.Listener;
|
||||
|
||||
#addr: Deno.NetAddr | null = null;
|
||||
#hasClosed = false;
|
||||
#server: Deno.HttpServer;
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
} from "ext:deno_node/internal/crypto/util.ts";
|
||||
import {
|
||||
createSecretKey,
|
||||
getKeyMaterial,
|
||||
isKeyObject,
|
||||
KeyObject,
|
||||
} from "ext:deno_node/internal/crypto/keys.ts";
|
||||
|
@ -35,7 +36,7 @@ import {
|
|||
|
||||
const validateParameters = hideStackFrames((hash, key, salt, info, length) => {
|
||||
validateString(hash, "digest");
|
||||
key = new Uint8Array(prepareKey(key));
|
||||
key = getKeyMaterial(prepareKey(key));
|
||||
validateByteSource(salt, "salt");
|
||||
validateByteSource(info, "info");
|
||||
|
||||
|
@ -108,6 +109,8 @@ export function hkdf(
|
|||
|
||||
validateFunction(callback, "callback");
|
||||
|
||||
hash = hash.toLowerCase();
|
||||
|
||||
op_node_hkdf_async(hash, key, salt, info, length)
|
||||
.then((okm) => callback(null, okm.buffer))
|
||||
.catch((err) => callback(new ERR_CRYPTO_INVALID_DIGEST(err), undefined));
|
||||
|
@ -128,6 +131,8 @@ export function hkdfSync(
|
|||
length,
|
||||
));
|
||||
|
||||
hash = hash.toLowerCase();
|
||||
|
||||
const okm = new Uint8Array(length);
|
||||
try {
|
||||
op_node_hkdf(hash, key, salt, info, okm);
|
||||
|
|
|
@ -7,8 +7,19 @@ import { op_node_pbkdf2, op_node_pbkdf2_async } from "ext:core/ops";
|
|||
|
||||
import { Buffer } from "node:buffer";
|
||||
import { HASH_DATA } from "ext:deno_node/internal/crypto/types.ts";
|
||||
import {
|
||||
validateFunction,
|
||||
validateString,
|
||||
validateUint32,
|
||||
} from "ext:deno_node/internal/validators.mjs";
|
||||
import { getArrayBufferOrView } from "ext:deno_node/internal/crypto/keys.ts";
|
||||
import {
|
||||
ERR_CRYPTO_INVALID_DIGEST,
|
||||
ERR_OUT_OF_RANGE,
|
||||
} from "ext:deno_node/internal/errors.ts";
|
||||
|
||||
export const MAX_ALLOC = Math.pow(2, 30) - 1;
|
||||
export const MAX_I32 = 2 ** 31 - 1;
|
||||
|
||||
export type NormalizedAlgorithms =
|
||||
| "md5"
|
||||
|
@ -29,6 +40,30 @@ export type Algorithms =
|
|||
| "sha384"
|
||||
| "sha512";
|
||||
|
||||
function check(
|
||||
password: HASH_DATA,
|
||||
salt: HASH_DATA,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
digest: string,
|
||||
) {
|
||||
validateString(digest, "digest");
|
||||
password = getArrayBufferOrView(password, "password", "buffer");
|
||||
salt = getArrayBufferOrView(salt, "salt", "buffer");
|
||||
validateUint32(iterations, "iterations", true);
|
||||
validateUint32(keylen, "keylen");
|
||||
|
||||
if (iterations > MAX_I32) {
|
||||
throw new ERR_OUT_OF_RANGE("iterations", `<= ${MAX_I32}`, iterations);
|
||||
}
|
||||
|
||||
if (keylen > MAX_I32) {
|
||||
throw new ERR_OUT_OF_RANGE("keylen", `<= ${MAX_I32}`, keylen);
|
||||
}
|
||||
|
||||
return { password, salt, iterations, keylen, digest };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterations Needs to be higher or equal than zero
|
||||
* @param keylen Needs to be higher or equal than zero but less than max allocation size (2^30)
|
||||
|
@ -39,18 +74,21 @@ export function pbkdf2Sync(
|
|||
salt: HASH_DATA,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
digest: Algorithms = "sha1",
|
||||
digest: string,
|
||||
): Buffer {
|
||||
if (typeof iterations !== "number" || iterations < 0) {
|
||||
throw new TypeError("Bad iterations");
|
||||
}
|
||||
if (typeof keylen !== "number" || keylen < 0 || keylen > MAX_ALLOC) {
|
||||
throw new TypeError("Bad key length");
|
||||
}
|
||||
({ password, salt, iterations, keylen, digest } = check(
|
||||
password,
|
||||
salt,
|
||||
iterations,
|
||||
keylen,
|
||||
digest,
|
||||
));
|
||||
|
||||
digest = digest.toLowerCase() as NormalizedAlgorithms;
|
||||
|
||||
const DK = new Uint8Array(keylen);
|
||||
if (!op_node_pbkdf2(password, salt, iterations, digest, DK)) {
|
||||
throw new Error("Invalid digest");
|
||||
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
|
||||
}
|
||||
|
||||
return Buffer.from(DK);
|
||||
|
@ -66,16 +104,26 @@ export function pbkdf2(
|
|||
salt: HASH_DATA,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
digest: Algorithms = "sha1",
|
||||
digest: string,
|
||||
callback: (err: Error | null, derivedKey?: Buffer) => void,
|
||||
) {
|
||||
if (typeof iterations !== "number" || iterations < 0) {
|
||||
throw new TypeError("Bad iterations");
|
||||
}
|
||||
if (typeof keylen !== "number" || keylen < 0 || keylen > MAX_ALLOC) {
|
||||
throw new TypeError("Bad key length");
|
||||
if (typeof digest === "function") {
|
||||
callback = digest;
|
||||
digest = undefined as unknown as string;
|
||||
}
|
||||
|
||||
({ password, salt, iterations, keylen, digest } = check(
|
||||
password,
|
||||
salt,
|
||||
iterations,
|
||||
keylen,
|
||||
digest,
|
||||
));
|
||||
|
||||
validateFunction(callback, "callback");
|
||||
|
||||
digest = digest.toLowerCase() as NormalizedAlgorithms;
|
||||
|
||||
op_node_pbkdf2_async(
|
||||
password,
|
||||
salt,
|
||||
|
|
|
@ -67,10 +67,6 @@ export class SignImpl extends Writable {
|
|||
|
||||
algorithm = algorithm.toLowerCase();
|
||||
|
||||
if (algorithm.startsWith("rsa-")) {
|
||||
// Allows RSA-[digest_algorithm] as a valid algorithm
|
||||
algorithm = algorithm.slice(4);
|
||||
}
|
||||
this.#digestType = algorithm;
|
||||
this.hash = createHash(this.#digestType);
|
||||
}
|
||||
|
@ -121,11 +117,6 @@ export class VerifyImpl extends Writable {
|
|||
|
||||
algorithm = algorithm.toLowerCase();
|
||||
|
||||
if (algorithm.startsWith("rsa-")) {
|
||||
// Allows RSA-[digest_algorithm] as a valid algorithm
|
||||
algorithm = algorithm.slice(4);
|
||||
}
|
||||
|
||||
this.#digestType = algorithm;
|
||||
this.hash = createHash(this.#digestType);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { Buffer } from "../../buffer.ts";
|
||||
|
||||
export type HASH_DATA = string | ArrayBufferView | Buffer;
|
||||
export type HASH_DATA = string | ArrayBufferView | Buffer | ArrayBuffer;
|
||||
|
||||
export type BinaryToTextEncoding = "base64" | "base64url" | "hex" | "binary";
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { core, internals } from "ext:core/mod.js";
|
||||
import { initializeDebugEnv } from "ext:deno_node/internal/util/debuglog.ts";
|
||||
import {
|
||||
op_getegid,
|
||||
op_geteuid,
|
||||
op_node_process_kill,
|
||||
op_process_abort,
|
||||
|
@ -309,15 +310,16 @@ export function kill(pid: number, sig: string | number = "SIGTERM") {
|
|||
return true;
|
||||
}
|
||||
|
||||
let getgid, getuid, geteuid;
|
||||
let getgid, getuid, getegid, geteuid;
|
||||
|
||||
if (!isWindows) {
|
||||
getgid = () => Deno.gid();
|
||||
getuid = () => Deno.uid();
|
||||
getegid = () => op_getegid();
|
||||
geteuid = () => op_geteuid();
|
||||
}
|
||||
|
||||
export { geteuid, getgid, getuid };
|
||||
export { getegid, geteuid, getgid, getuid };
|
||||
|
||||
const ALLOWED_FLAGS = buildAllowedFlags();
|
||||
|
||||
|
@ -685,6 +687,9 @@ Process.prototype.getgid = getgid;
|
|||
/** This method is removed on Windows */
|
||||
Process.prototype.getuid = getuid;
|
||||
|
||||
/** This method is removed on Windows */
|
||||
Process.prototype.getegid = getegid;
|
||||
|
||||
/** This method is removed on Windows */
|
||||
Process.prototype.geteuid = geteuid;
|
||||
|
||||
|
@ -726,6 +731,7 @@ Process.prototype.noDeprecation = false;
|
|||
if (isWindows) {
|
||||
delete Process.prototype.getgid;
|
||||
delete Process.prototype.getuid;
|
||||
delete Process.prototype.getegid;
|
||||
delete Process.prototype.geteuid;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ include_js_files_for_snapshotting = [
|
|||
]
|
||||
# A dev feature to disable creations and loading of snapshots in favor of
|
||||
# loading JS sources at runtime.
|
||||
__runtime_js_sources = ["include_js_files_for_snapshotting"]
|
||||
hmr = ["include_js_files_for_snapshotting"]
|
||||
# Signal that only snapshotted JS sources should be used. This will
|
||||
# conditionally exclude the runtime source transpilation logic, and add an
|
||||
# assertion that a snapshot is provided.
|
||||
|
|
|
@ -4,10 +4,8 @@ use ::deno_permissions::parse_sys_kind;
|
|||
use ::deno_permissions::PermissionState;
|
||||
use ::deno_permissions::PermissionsContainer;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::uri_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::url;
|
||||
use deno_core::OpState;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
@ -65,7 +63,7 @@ pub fn op_query_permission(
|
|||
"net" => permissions.net.query(
|
||||
match args.host.as_deref() {
|
||||
None => None,
|
||||
Some(h) => Some(parse_host(h)?),
|
||||
Some(h) => Some(h.parse()?),
|
||||
}
|
||||
.as_ref(),
|
||||
),
|
||||
|
@ -100,7 +98,7 @@ pub fn op_revoke_permission(
|
|||
"net" => permissions.net.revoke(
|
||||
match args.host.as_deref() {
|
||||
None => None,
|
||||
Some(h) => Some(parse_host(h)?),
|
||||
Some(h) => Some(h.parse()?),
|
||||
}
|
||||
.as_ref(),
|
||||
),
|
||||
|
@ -135,7 +133,7 @@ pub fn op_request_permission(
|
|||
"net" => permissions.net.request(
|
||||
match args.host.as_deref() {
|
||||
None => None,
|
||||
Some(h) => Some(parse_host(h)?),
|
||||
Some(h) => Some(h.parse()?),
|
||||
}
|
||||
.as_ref(),
|
||||
),
|
||||
|
@ -155,13 +153,3 @@ pub fn op_request_permission(
|
|||
};
|
||||
Ok(PermissionStatus::from(perm))
|
||||
}
|
||||
|
||||
fn parse_host(host_str: &str) -> Result<(String, Option<u16>), AnyError> {
|
||||
let url = url::Url::parse(&format!("http://{host_str}/"))
|
||||
.map_err(|_| uri_error("Invalid host"))?;
|
||||
if url.path() != "/" {
|
||||
return Err(uri_error("Invalid host"));
|
||||
}
|
||||
let hostname = url.host_str().unwrap();
|
||||
Ok((hostname.to_string(), url.port()))
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ use deno_core::url;
|
|||
use deno_core::url::Url;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_terminal::colors;
|
||||
use fqdn::fqdn;
|
||||
use fqdn::FQDN;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::borrow::Cow;
|
||||
|
@ -25,6 +24,8 @@ use std::ffi::OsStr;
|
|||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::net::IpAddr;
|
||||
use std::net::Ipv6Addr;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
@ -691,14 +692,49 @@ impl Descriptor for WriteDescriptor {
|
|||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct NetDescriptor(pub FQDN, pub Option<u16>);
|
||||
pub enum Host {
|
||||
Fqdn(FQDN),
|
||||
Ip(IpAddr),
|
||||
}
|
||||
|
||||
impl NetDescriptor {
|
||||
fn new<T: AsRef<str>>(host: &&(T, Option<u16>)) -> Self {
|
||||
NetDescriptor(fqdn!(host.0.as_ref()), host.1)
|
||||
impl FromStr for Host {
|
||||
type Err = AnyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.starts_with('[') && s.ends_with(']') {
|
||||
let ip = s[1..s.len() - 1]
|
||||
.parse::<Ipv6Addr>()
|
||||
.map_err(|_| uri_error(format!("invalid IPv6 address: '{s}'")))?;
|
||||
return Ok(Host::Ip(IpAddr::V6(ip)));
|
||||
}
|
||||
let (without_trailing_dot, has_trailing_dot) =
|
||||
s.strip_suffix('.').map_or((s, false), |s| (s, true));
|
||||
if let Ok(ip) = without_trailing_dot.parse::<IpAddr>() {
|
||||
if has_trailing_dot {
|
||||
return Err(uri_error(format!(
|
||||
"invalid host: '{without_trailing_dot}'"
|
||||
)));
|
||||
}
|
||||
Ok(Host::Ip(ip))
|
||||
} else {
|
||||
let lower = if s.chars().all(|c| c.is_ascii_lowercase()) {
|
||||
Cow::Borrowed(s)
|
||||
} else {
|
||||
Cow::Owned(s.to_ascii_lowercase())
|
||||
};
|
||||
let fqdn = FQDN::from_str(&lower)
|
||||
.with_context(|| format!("invalid host: '{s}'"))?;
|
||||
if fqdn.is_root() {
|
||||
return Err(uri_error(format!("invalid empty host: '{s}'")));
|
||||
}
|
||||
Ok(Host::Fqdn(fqdn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct NetDescriptor(pub Host, pub Option<u16>);
|
||||
|
||||
impl Descriptor for NetDescriptor {
|
||||
type Arg = String;
|
||||
|
||||
|
@ -731,26 +767,72 @@ impl Descriptor for NetDescriptor {
|
|||
impl FromStr for NetDescriptor {
|
||||
type Err = AnyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// Set the scheme to `unknown` to parse the URL, as we really don't know
|
||||
// what the scheme is. We only using Url::parse to parse the host and port
|
||||
// and don't care about the scheme.
|
||||
let url = url::Url::parse(&format!("unknown://{s}"))?;
|
||||
let hostname = url
|
||||
.host_str()
|
||||
.ok_or(url::ParseError::EmptyHost)?
|
||||
.to_string();
|
||||
fn from_str(hostname: &str) -> Result<Self, Self::Err> {
|
||||
// If this is a IPv6 address enclosed in square brackets, parse it as such.
|
||||
if hostname.starts_with('[') {
|
||||
if let Some((ip, after)) = hostname.split_once(']') {
|
||||
let ip = ip[1..].parse::<Ipv6Addr>().map_err(|_| {
|
||||
uri_error(format!("invalid IPv6 address in '{hostname}': '{ip}'"))
|
||||
})?;
|
||||
let port = if let Some(port) = after.strip_prefix(':') {
|
||||
let port = port.parse::<u16>().map_err(|_| {
|
||||
uri_error(format!("invalid port in '{hostname}': '{port}'"))
|
||||
})?;
|
||||
Some(port)
|
||||
} else if after.is_empty() {
|
||||
None
|
||||
} else {
|
||||
return Err(uri_error(format!("invalid host: '{hostname}'")));
|
||||
};
|
||||
return Ok(NetDescriptor(Host::Ip(IpAddr::V6(ip)), port));
|
||||
} else {
|
||||
return Err(uri_error(format!("invalid host: '{hostname}'")));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(NetDescriptor(fqdn!(&hostname), url.port()))
|
||||
// Otherwise it is an IPv4 address or a FQDN with an optional port.
|
||||
let (host, port) = match hostname.split_once(':') {
|
||||
Some((_, "")) => {
|
||||
return Err(uri_error(format!("invalid empty port in '{hostname}'")));
|
||||
}
|
||||
Some((host, port)) => (host, port),
|
||||
None => (hostname, ""),
|
||||
};
|
||||
let host = host.parse::<Host>()?;
|
||||
|
||||
let port = if port.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let port = port.parse::<u16>().map_err(|_| {
|
||||
// If the user forgot to enclose an IPv6 address in square brackets, we
|
||||
// should give them a hint. There are always at least two colons in an
|
||||
// IPv6 address, so this heuristic finds likely a bare IPv6 address.
|
||||
if port.contains(':') {
|
||||
uri_error(format!(
|
||||
"ipv6 addresses must be enclosed in square brackets: '{hostname}'"
|
||||
))
|
||||
} else {
|
||||
uri_error(format!("invalid port in '{hostname}': '{port}'"))
|
||||
}
|
||||
})?;
|
||||
Some(port)
|
||||
};
|
||||
|
||||
Ok(NetDescriptor(host, port))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NetDescriptor {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&match self.1 {
|
||||
None => self.0.to_string(),
|
||||
Some(port) => format!("{}:{}", self.0, port),
|
||||
})
|
||||
match &self.0 {
|
||||
Host::Fqdn(fqdn) => write!(f, "{fqdn}"),
|
||||
Host::Ip(IpAddr::V4(ip)) => write!(f, "{ip}"),
|
||||
Host::Ip(IpAddr::V6(ip)) => write!(f, "[{ip}]"),
|
||||
}?;
|
||||
if let Some(port) = self.1 {
|
||||
write!(f, ":{}", port)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,7 +997,9 @@ impl Descriptor for SysDescriptor {
|
|||
pub fn parse_sys_kind(kind: &str) -> Result<&str, AnyError> {
|
||||
match kind {
|
||||
"hostname" | "osRelease" | "osUptime" | "loadavg" | "networkInterfaces"
|
||||
| "systemMemoryInfo" | "uid" | "gid" | "cpus" | "homedir" => Ok(kind),
|
||||
| "systemMemoryInfo" | "uid" | "gid" | "cpus" | "homedir" | "getegid" => {
|
||||
Ok(kind)
|
||||
}
|
||||
_ => Err(type_error(format!("unknown system info kind \"{kind}\""))),
|
||||
}
|
||||
}
|
||||
|
@ -1105,37 +1189,25 @@ impl UnaryPermission<WriteDescriptor> {
|
|||
}
|
||||
|
||||
impl UnaryPermission<NetDescriptor> {
|
||||
pub fn query<T: AsRef<str>>(
|
||||
&self,
|
||||
host: Option<&(T, Option<u16>)>,
|
||||
) -> PermissionState {
|
||||
self.query_desc(
|
||||
host.map(|h| NetDescriptor::new(&h)).as_ref(),
|
||||
AllowPartial::TreatAsPartialGranted,
|
||||
)
|
||||
pub fn query(&self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||
self.query_desc(host, AllowPartial::TreatAsPartialGranted)
|
||||
}
|
||||
|
||||
pub fn request<T: AsRef<str>>(
|
||||
&mut self,
|
||||
host: Option<&(T, Option<u16>)>,
|
||||
) -> PermissionState {
|
||||
self.request_desc(host.map(|h| NetDescriptor::new(&h)).as_ref(), || None)
|
||||
pub fn request(&mut self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||
self.request_desc(host, || None)
|
||||
}
|
||||
|
||||
pub fn revoke<T: AsRef<str>>(
|
||||
&mut self,
|
||||
host: Option<&(T, Option<u16>)>,
|
||||
) -> PermissionState {
|
||||
self.revoke_desc(host.map(|h| NetDescriptor::new(&h)).as_ref())
|
||||
pub fn revoke(&mut self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||
self.revoke_desc(host)
|
||||
}
|
||||
|
||||
pub fn check<T: AsRef<str>>(
|
||||
pub fn check(
|
||||
&mut self,
|
||||
host: &(T, Option<u16>),
|
||||
host: &NetDescriptor,
|
||||
api_name: Option<&str>,
|
||||
) -> Result<(), AnyError> {
|
||||
skip_check_if_is_permission_fully_granted!(self);
|
||||
self.check_desc(Some(&NetDescriptor::new(&host)), false, api_name, || None)
|
||||
self.check_desc(Some(host), false, api_name, || None)
|
||||
}
|
||||
|
||||
pub fn check_url(
|
||||
|
@ -1144,17 +1216,14 @@ impl UnaryPermission<NetDescriptor> {
|
|||
api_name: Option<&str>,
|
||||
) -> Result<(), AnyError> {
|
||||
skip_check_if_is_permission_fully_granted!(self);
|
||||
let hostname = url
|
||||
let host = url
|
||||
.host_str()
|
||||
.ok_or_else(|| uri_error("Missing host"))?
|
||||
.to_string();
|
||||
let host = &(&hostname, url.port_or_known_default());
|
||||
let display_host = match url.port() {
|
||||
None => hostname.clone(),
|
||||
Some(port) => format!("{hostname}:{port}"),
|
||||
};
|
||||
self.check_desc(Some(&NetDescriptor::new(&host)), false, api_name, || {
|
||||
Some(format!("\"{}\"", display_host))
|
||||
.ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?;
|
||||
let host = host.parse::<Host>()?;
|
||||
let port = url.port_or_known_default();
|
||||
let descriptor = NetDescriptor(host, port);
|
||||
self.check_desc(Some(&descriptor), false, api_name, || {
|
||||
Some(format!("\"{descriptor}\""))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1780,7 +1849,9 @@ impl PermissionsContainer {
|
|||
host: &(T, Option<u16>),
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError> {
|
||||
self.0.lock().net.check(host, Some(api_name))
|
||||
let hostname = host.0.as_ref().parse::<Host>()?;
|
||||
let descriptor = NetDescriptor(hostname, host.1);
|
||||
self.0.lock().net.check(&descriptor, Some(api_name))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -2207,7 +2278,9 @@ pub fn create_child_permissions(
|
|||
mod tests {
|
||||
use super::*;
|
||||
use deno_core::serde_json::json;
|
||||
use fqdn::fqdn;
|
||||
use prompter::tests::*;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
// Creates vector of strings, Vec<String>
|
||||
macro_rules! svec {
|
||||
|
@ -2361,12 +2434,12 @@ mod tests {
|
|||
];
|
||||
|
||||
for (host, port, is_ok) in domain_tests {
|
||||
let host = host.parse().unwrap();
|
||||
let descriptor = NetDescriptor(host, Some(port));
|
||||
assert_eq!(
|
||||
is_ok,
|
||||
perms.net.check(&(host, Some(port)), None).is_ok(),
|
||||
"{}:{}",
|
||||
host,
|
||||
port,
|
||||
perms.net.check(&descriptor, None).is_ok(),
|
||||
"{descriptor}",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2402,8 +2475,13 @@ mod tests {
|
|||
("192.168.0.1", 0),
|
||||
];
|
||||
|
||||
for (host, port) in domain_tests {
|
||||
assert!(perms.net.check(&(host, Some(port)), None).is_ok());
|
||||
for (host_str, port) in domain_tests {
|
||||
let host = host_str.parse().unwrap();
|
||||
let descriptor = NetDescriptor(host, Some(port));
|
||||
assert!(
|
||||
perms.net.check(&descriptor, None).is_ok(),
|
||||
"expected {host_str}:{port} to pass"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2438,8 +2516,13 @@ mod tests {
|
|||
("192.168.0.1", 0),
|
||||
];
|
||||
|
||||
for (host, port) in domain_tests {
|
||||
assert!(perms.net.check(&(host, Some(port)), None).is_err());
|
||||
for (host_str, port) in domain_tests {
|
||||
let host = host_str.parse().unwrap();
|
||||
let descriptor = NetDescriptor(host, Some(port));
|
||||
assert!(
|
||||
perms.net.check(&descriptor, None).is_err(),
|
||||
"expected {host_str}:{port} to fail"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2714,15 +2797,15 @@ mod tests {
|
|||
assert_eq!(perms4.ffi.query(Some(Path::new("/foo"))), PermissionState::Denied);
|
||||
assert_eq!(perms4.ffi.query(Some(Path::new("/foo/bar"))), PermissionState::Denied);
|
||||
assert_eq!(perms4.ffi.query(Some(Path::new("/bar"))), PermissionState::Granted);
|
||||
assert_eq!(perms1.net.query::<&str>(None), PermissionState::Granted);
|
||||
assert_eq!(perms1.net.query(Some(&("127.0.0.1", None))), PermissionState::Granted);
|
||||
assert_eq!(perms2.net.query::<&str>(None), PermissionState::Prompt);
|
||||
assert_eq!(perms2.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms3.net.query::<&str>(None), PermissionState::Prompt);
|
||||
assert_eq!(perms3.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Denied);
|
||||
assert_eq!(perms4.net.query::<&str>(None), PermissionState::GrantedPartial);
|
||||
assert_eq!(perms4.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Denied);
|
||||
assert_eq!(perms4.net.query(Some(&("192.168.0.1", Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms1.net.query(None), PermissionState::Granted);
|
||||
assert_eq!(perms1.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
|
||||
assert_eq!(perms2.net.query(None), PermissionState::Prompt);
|
||||
assert_eq!(perms2.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms3.net.query(None), PermissionState::Prompt);
|
||||
assert_eq!(perms3.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
|
||||
assert_eq!(perms4.net.query(None), PermissionState::GrantedPartial);
|
||||
assert_eq!(perms4.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
|
||||
assert_eq!(perms4.net.query(Some(&NetDescriptor("192.168.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms1.env.query(None), PermissionState::Granted);
|
||||
assert_eq!(perms1.env.query(Some("HOME")), PermissionState::Granted);
|
||||
assert_eq!(perms2.env.query(None), PermissionState::Prompt);
|
||||
|
@ -2780,9 +2863,9 @@ mod tests {
|
|||
prompt_value.set(true);
|
||||
assert_eq!(perms.ffi.request(None), PermissionState::Denied);
|
||||
prompt_value.set(true);
|
||||
assert_eq!(perms.net.request(Some(&("127.0.0.1", None))), PermissionState::Granted);
|
||||
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
|
||||
prompt_value.set(false);
|
||||
assert_eq!(perms.net.request(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||
prompt_value.set(true);
|
||||
assert_eq!(perms.env.request(Some("HOME")), PermissionState::Granted);
|
||||
assert_eq!(perms.env.query(None), PermissionState::Prompt);
|
||||
|
@ -2851,9 +2934,9 @@ mod tests {
|
|||
assert_eq!(perms.ffi.revoke(Some(Path::new("/foo/bar"))), PermissionState::Prompt);
|
||||
assert_eq!(perms.ffi.query(Some(Path::new("/foo"))), PermissionState::Prompt);
|
||||
assert_eq!(perms.ffi.query(Some(Path::new("/foo/baz"))), PermissionState::Granted);
|
||||
assert_eq!(perms.net.revoke(Some(&("127.0.0.1", Some(9000)))), PermissionState::Prompt);
|
||||
assert_eq!(perms.net.query(Some(&("127.0.0.1", None))), PermissionState::Prompt);
|
||||
assert_eq!(perms.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms.net.revoke(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(9000)))), PermissionState::Prompt);
|
||||
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Prompt);
|
||||
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||
assert_eq!(perms.env.revoke(Some("HOME")), PermissionState::Prompt);
|
||||
assert_eq!(perms.env.revoke(Some("hostname")), PermissionState::Prompt);
|
||||
assert_eq!(perms.run.revoke(Some("deno")), PermissionState::Prompt);
|
||||
|
@ -2886,13 +2969,43 @@ mod tests {
|
|||
assert!(perms.ffi.check(Path::new("/bar"), None).is_err());
|
||||
|
||||
prompt_value.set(true);
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
prompt_value.set(false);
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_ok());
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_err());
|
||||
assert!(perms.net.check(&("127.0.0.1", None), None).is_err());
|
||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_err());
|
||||
assert!(perms.net.check(&("deno.land", None), None).is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||
None
|
||||
)
|
||||
.is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(&NetDescriptor("127.0.0.1".parse().unwrap(), None), None)
|
||||
.is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(&NetDescriptor("deno.land".parse().unwrap(), None), None)
|
||||
.is_err());
|
||||
|
||||
prompt_value.set(true);
|
||||
assert!(perms.run.check("cat", None).is_ok());
|
||||
|
@ -2946,14 +3059,50 @@ mod tests {
|
|||
assert!(perms.ffi.check(Path::new("/bar"), None).is_ok());
|
||||
|
||||
prompt_value.set(false);
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_err());
|
||||
prompt_value.set(true);
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_err());
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_ok());
|
||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
prompt_value.set(false);
|
||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_ok());
|
||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||
None
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
prompt_value.set(false);
|
||||
assert!(perms.run.check("cat", None).is_err());
|
||||
|
@ -3042,10 +3191,28 @@ mod tests {
|
|||
..Permissions::none_without_prompt()
|
||||
};
|
||||
|
||||
perms.net.check(&("allowed.domain.", None), None).unwrap();
|
||||
perms.net.check(&("1.1.1.1.", None), None).unwrap();
|
||||
assert!(perms.net.check(&("denied.domain.", None), None).is_err());
|
||||
assert!(perms.net.check(&("2.2.2.2.", None), None).is_err());
|
||||
perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("allowed.domain.".parse().unwrap(), None),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
perms
|
||||
.net
|
||||
.check(&NetDescriptor("1.1.1.1".parse().unwrap(), None), None)
|
||||
.unwrap();
|
||||
assert!(perms
|
||||
.net
|
||||
.check(
|
||||
&NetDescriptor("denied.domain.".parse().unwrap(), None),
|
||||
None
|
||||
)
|
||||
.is_err());
|
||||
assert!(perms
|
||||
.net
|
||||
.check(&NetDescriptor("2.2.2.2".parse().unwrap(), None), None)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -3331,4 +3498,109 @@ mod tests {
|
|||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_host_parse() {
|
||||
let hosts = &[
|
||||
("deno.land", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||
("DENO.land", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||
("deno.land.", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||
(
|
||||
"1.1.1.1",
|
||||
Some(Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)))),
|
||||
),
|
||||
(
|
||||
"::1",
|
||||
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))),
|
||||
),
|
||||
(
|
||||
"[::1]",
|
||||
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))),
|
||||
),
|
||||
("[::1", None),
|
||||
("::1]", None),
|
||||
("deno. land", None),
|
||||
("1. 1.1.1", None),
|
||||
("1.1.1.1.", None),
|
||||
("1::1.", None),
|
||||
("deno.land.", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||
(".deno.land", None),
|
||||
(
|
||||
"::ffff:1.1.1.1",
|
||||
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(
|
||||
0, 0, 0, 0, 0, 0xffff, 0x0101, 0x0101,
|
||||
)))),
|
||||
),
|
||||
];
|
||||
|
||||
for (host_str, expected) in hosts {
|
||||
assert_eq!(host_str.parse::<Host>().ok(), *expected, "{host_str}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_net_descriptor_parse() {
|
||||
let cases = &[
|
||||
(
|
||||
"deno.land",
|
||||
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), None)),
|
||||
),
|
||||
(
|
||||
"DENO.land",
|
||||
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), None)),
|
||||
),
|
||||
(
|
||||
"deno.land:8000",
|
||||
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), Some(8000))),
|
||||
),
|
||||
("deno.land:", None),
|
||||
("deno.land:a", None),
|
||||
("deno. land:a", None),
|
||||
("deno.land.: a", None),
|
||||
(
|
||||
"1.1.1.1",
|
||||
Some(NetDescriptor(
|
||||
Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))),
|
||||
None,
|
||||
)),
|
||||
),
|
||||
("1.1.1.1.", None),
|
||||
("1.1.1.1..", None),
|
||||
(
|
||||
"1.1.1.1:8000",
|
||||
Some(NetDescriptor(
|
||||
Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))),
|
||||
Some(8000),
|
||||
)),
|
||||
),
|
||||
("::", None),
|
||||
(":::80", None),
|
||||
("::80", None),
|
||||
(
|
||||
"[::]",
|
||||
Some(NetDescriptor(
|
||||
Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))),
|
||||
None,
|
||||
)),
|
||||
),
|
||||
("[::1", None),
|
||||
("::1]", None),
|
||||
("::1]", None),
|
||||
("[::1]:", None),
|
||||
("[::1]:a", None),
|
||||
(
|
||||
"[::1]:443",
|
||||
Some(NetDescriptor(
|
||||
Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))),
|
||||
Some(443),
|
||||
)),
|
||||
),
|
||||
("", None),
|
||||
("deno.land..", None),
|
||||
];
|
||||
|
||||
for (input, expected) in cases {
|
||||
assert_eq!(input.parse::<NetDescriptor>().ok(), *expected, "'{input}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -518,8 +518,11 @@ impl WebWorker {
|
|||
ops::web_worker::deno_web_worker::init_ops_and_esm(),
|
||||
];
|
||||
|
||||
#[cfg(__runtime_js_sources)]
|
||||
assert!(cfg!(not(feature = "only_snapshotted_js_sources")), "'__runtime_js_sources' is incompatible with 'only_snapshotted_js_sources'.");
|
||||
#[cfg(hmr)]
|
||||
assert!(
|
||||
cfg!(not(feature = "only_snapshotted_js_sources")),
|
||||
"'hmr' is incompatible with 'only_snapshotted_js_sources'."
|
||||
);
|
||||
|
||||
for extension in &mut extensions {
|
||||
if options.startup_snapshot.is_some() {
|
||||
|
|
|
@ -454,8 +454,11 @@ impl MainWorker {
|
|||
ops::web_worker::deno_web_worker::init_ops_and_esm().disable(),
|
||||
];
|
||||
|
||||
#[cfg(__runtime_js_sources)]
|
||||
assert!(cfg!(not(feature = "only_snapshotted_js_sources")), "'__runtime_js_sources' is incompatible with 'only_snapshotted_js_sources'.");
|
||||
#[cfg(hmr)]
|
||||
assert!(
|
||||
cfg!(not(feature = "only_snapshotted_js_sources")),
|
||||
"'hmr' is incompatible with 'only_snapshotted_js_sources'."
|
||||
);
|
||||
|
||||
for extension in &mut extensions {
|
||||
if options.startup_snapshot.is_some() {
|
||||
|
|
|
@ -57,11 +57,14 @@ util::unit_test_factory!(
|
|||
buffer_test,
|
||||
child_process_test,
|
||||
console_test,
|
||||
crypto_cipher_test = crypto / crypto_cipher_test,
|
||||
crypto_cipher_gcm_test = crypto / crypto_cipher_gcm_test,
|
||||
crypto_cipher_test = crypto / crypto_cipher_test,
|
||||
crypto_hash_test = crypto / crypto_hash_test,
|
||||
crypto_hkdf_test = crypto / crypto_hkdf_test,
|
||||
crypto_key_test = crypto / crypto_key_test,
|
||||
crypto_misc_test = crypto / crypto_misc_test,
|
||||
crypto_pbkdf2_test = crypto / crypto_pbkdf2_test,
|
||||
crypto_scrypt_test = crypto / crypto_scrypt_test,
|
||||
crypto_sign_test = crypto / crypto_sign_test,
|
||||
events_test,
|
||||
dgram_test,
|
||||
|
@ -72,8 +75,6 @@ util::unit_test_factory!(
|
|||
_randomBytes_test = internal / _randomBytes_test,
|
||||
_randomFill_test = internal / _randomFill_test,
|
||||
_randomInt_test = internal / _randomInt_test,
|
||||
pbkdf2_test = internal / pbkdf2_test,
|
||||
scrypt_test = internal / scrypt_test,
|
||||
module_test,
|
||||
net_test,
|
||||
os_test,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
"test-crypto-dh.js",
|
||||
"test-crypto-hkdf.js",
|
||||
"test-crypto-hmac.js",
|
||||
"test-crypto-pbkdf2.js",
|
||||
"test-crypto-prime.js",
|
||||
"test-crypto-stream.js",
|
||||
"test-crypto-x509.js",
|
||||
|
@ -257,6 +258,7 @@
|
|||
"test-crypto-hash.js",
|
||||
"test-crypto-hkdf.js",
|
||||
"test-crypto-hmac.js",
|
||||
"test-crypto-pbkdf2.js",
|
||||
"test-crypto-prime.js",
|
||||
"test-crypto-secret-keygen.js",
|
||||
"test-crypto-stream.js",
|
||||
|
@ -325,6 +327,7 @@
|
|||
"test-fs-chown-type-check.js",
|
||||
"test-fs-copyfile.js",
|
||||
"test-fs-empty-readStream.js",
|
||||
"test-fs-lchown.js",
|
||||
"test-fs-mkdir.js",
|
||||
"test-fs-open-flags.js",
|
||||
"test-fs-open-mode-mask.js",
|
||||
|
|
|
@ -505,7 +505,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
|
|||
- [parallel/test-crypto-op-during-process-exit.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-op-during-process-exit.js)
|
||||
- [parallel/test-crypto-padding-aes256.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-padding-aes256.js)
|
||||
- [parallel/test-crypto-padding.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-padding.js)
|
||||
- [parallel/test-crypto-pbkdf2.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-pbkdf2.js)
|
||||
- [parallel/test-crypto-private-decrypt-gh32240.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-private-decrypt-gh32240.js)
|
||||
- [parallel/test-crypto-psychic-signatures.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-psychic-signatures.js)
|
||||
- [parallel/test-crypto-publicDecrypt-fails-first-time.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-crypto-publicDecrypt-fails-first-time.js)
|
||||
|
@ -795,7 +794,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
|
|||
- [parallel/test-fs-fmap.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-fmap.js)
|
||||
- [parallel/test-fs-fsync.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-fsync.js)
|
||||
- [parallel/test-fs-lchmod.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-lchmod.js)
|
||||
- [parallel/test-fs-lchown.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-lchown.js)
|
||||
- [parallel/test-fs-link.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-link.js)
|
||||
- [parallel/test-fs-long-path.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-long-path.js)
|
||||
- [parallel/test-fs-make-callback.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-fs-make-callback.js)
|
||||
|
|
251
tests/node_compat/test/parallel/test-crypto-pbkdf2.js
Normal file
251
tests/node_compat/test/parallel/test-crypto-pbkdf2.js
Normal file
|
@ -0,0 +1,251 @@
|
|||
// deno-fmt-ignore-file
|
||||
// deno-lint-ignore-file
|
||||
|
||||
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||
// Taken from Node 18.12.1
|
||||
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const crypto = require('crypto');
|
||||
|
||||
function runPBKDF2(password, salt, iterations, keylen, hash) {
|
||||
const syncResult =
|
||||
crypto.pbkdf2Sync(password, salt, iterations, keylen, hash);
|
||||
|
||||
crypto.pbkdf2(password, salt, iterations, keylen, hash,
|
||||
common.mustSucceed((asyncResult) => {
|
||||
assert.deepStrictEqual(asyncResult, syncResult);
|
||||
}));
|
||||
|
||||
return syncResult;
|
||||
}
|
||||
|
||||
function testPBKDF2(password, salt, iterations, keylen, expected, encoding) {
|
||||
const actual = runPBKDF2(password, salt, iterations, keylen, 'sha256');
|
||||
assert.strictEqual(actual.toString(encoding || 'latin1'), expected);
|
||||
}
|
||||
|
||||
//
|
||||
// Test PBKDF2 with RFC 6070 test vectors (except #4)
|
||||
//
|
||||
|
||||
testPBKDF2('password', 'salt', 1, 20,
|
||||
'\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52' +
|
||||
'\x56\xc4\xf8\x37\xa8\x65\x48\xc9');
|
||||
|
||||
testPBKDF2('password', 'salt', 2, 20,
|
||||
'\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9' +
|
||||
'\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e');
|
||||
|
||||
testPBKDF2('password', 'salt', 4096, 20,
|
||||
'\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6' +
|
||||
'\x84\x5c\x4c\x8d\x96\x28\x93\xa0');
|
||||
|
||||
testPBKDF2('passwordPASSWORDpassword',
|
||||
'saltSALTsaltSALTsaltSALTsaltSALTsalt',
|
||||
4096,
|
||||
25,
|
||||
'\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11' +
|
||||
'\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c');
|
||||
|
||||
testPBKDF2('pass\0word', 'sa\0lt', 4096, 16,
|
||||
'\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65' +
|
||||
'\x0a\x86\x87');
|
||||
|
||||
testPBKDF2('password', 'salt', 32, 32,
|
||||
'64c486c55d30d4c5a079b8823b7d7cb37ff0556f537da8410233bcec330ed956',
|
||||
'hex');
|
||||
|
||||
// Error path should not leak memory (check with valgrind).
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2('password', 'salt', 1, 20, 'sha1'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
}
|
||||
);
|
||||
|
||||
for (const iterations of [-1, 0, 2147483648]) {
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('password', 'salt', iterations, 20, 'sha1'),
|
||||
{
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
['str', null, undefined, [], {}].forEach((notNumber) => {
|
||||
assert.throws(
|
||||
() => {
|
||||
crypto.pbkdf2Sync('password', 'salt', 1, notNumber, 'sha256');
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "keylen" argument must be of type number.' +
|
||||
`${common.invalidArgTypeHelper(notNumber)}`
|
||||
});
|
||||
});
|
||||
|
||||
[Infinity, -Infinity, NaN].forEach((input) => {
|
||||
assert.throws(
|
||||
() => {
|
||||
crypto.pbkdf2('password', 'salt', 1, input, 'sha256',
|
||||
common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
message: 'The value of "keylen" is out of range. It ' +
|
||||
`must be an integer. Received ${input}`
|
||||
});
|
||||
});
|
||||
|
||||
[-1, 2147483648, 4294967296].forEach((input) => {
|
||||
assert.throws(
|
||||
() => {
|
||||
crypto.pbkdf2('password', 'salt', 1, input, 'sha256',
|
||||
common.mustNotCall());
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
name: 'RangeError',
|
||||
});
|
||||
});
|
||||
|
||||
// Should not get FATAL ERROR with empty password and salt
|
||||
// https://github.com/nodejs/node/issues/8571
|
||||
crypto.pbkdf2('', '', 1, 32, 'sha256', common.mustSucceed());
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2('password', 'salt', 8, 8, common.mustNotCall()),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "digest" argument must be of type string. ' +
|
||||
'Received undefined'
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('password', 'salt', 8, 8),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "digest" argument must be of type string. ' +
|
||||
'Received undefined'
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('password', 'salt', 8, 8, null),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "digest" argument must be of type string. ' +
|
||||
'Received null'
|
||||
});
|
||||
[1, {}, [], true, undefined, null].forEach((input) => {
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2(input, 'salt', 8, 8, 'sha256', common.mustNotCall()),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2('pass', input, 8, 8, 'sha256', common.mustNotCall()),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync(input, 'salt', 8, 8, 'sha256'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('pass', input, 8, 8, 'sha256'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
['test', {}, [], true, undefined, null].forEach((i) => {
|
||||
const received = common.invalidArgTypeHelper(i);
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2('pass', 'salt', i, 8, 'sha256', common.mustNotCall()),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: `The "iterations" argument must be of type number.${received}`
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('pass', 'salt', i, 8, 'sha256'),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: `The "iterations" argument must be of type number.${received}`
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Any TypedArray should work for password and salt.
|
||||
// TODO(@lucacasonato): SharedArrayBuffer is not supported
|
||||
for (const SomeArray of [Uint8Array, Uint16Array, Uint32Array, Float32Array,
|
||||
Float64Array, ArrayBuffer/*, SharedArrayBuffer*/]) {
|
||||
runPBKDF2(new SomeArray(10), 'salt', 8, 8, 'sha256');
|
||||
runPBKDF2('pass', new SomeArray(10), 8, 8, 'sha256');
|
||||
}
|
||||
|
||||
// TODO(@lucacasonato): we throw this asynchronously
|
||||
// assert.throws(
|
||||
// () => crypto.pbkdf2('pass', 'salt', 8, 8, 'md55', common.mustNotCall()),
|
||||
// {
|
||||
// code: 'ERR_CRYPTO_INVALID_DIGEST',
|
||||
// name: 'TypeError',
|
||||
// message: 'Invalid digest: md55'
|
||||
// }
|
||||
// );
|
||||
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('pass', 'salt', 8, 8, 'md55'),
|
||||
{
|
||||
code: 'ERR_CRYPTO_INVALID_DIGEST',
|
||||
name: 'TypeError',
|
||||
message: 'Invalid digest: md55'
|
||||
}
|
||||
);
|
||||
|
||||
if (!common.hasOpenSSL3) {
|
||||
// TODO(@lucacasonato): we don't support blake2b512 and blake2s256
|
||||
const kNotPBKDF2Supported = ['shake128', 'shake256', 'blake2b512', 'blake2s256'];
|
||||
crypto.getHashes()
|
||||
.filter((hash) => !kNotPBKDF2Supported.includes(hash))
|
||||
.forEach((hash) => {
|
||||
runPBKDF2(new Uint8Array(10), 'salt', 8, 8, hash);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// This should not crash.
|
||||
assert.throws(
|
||||
() => crypto.pbkdf2Sync('1', '2', 1, 1, '%'),
|
||||
{
|
||||
code: 'ERR_CRYPTO_INVALID_DIGEST',
|
||||
name: 'TypeError',
|
||||
message: 'Invalid digest: %'
|
||||
}
|
||||
);
|
||||
}
|
71
tests/node_compat/test/parallel/test-fs-lchown.js
Normal file
71
tests/node_compat/test/parallel/test-fs-lchown.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
// deno-fmt-ignore-file
|
||||
// deno-lint-ignore-file
|
||||
|
||||
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||
// Taken from Node 18.12.1
|
||||
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
|
||||
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { promises } = fs;
|
||||
|
||||
// Validate the path argument.
|
||||
[false, 1, {}, [], null, undefined].forEach((i) => {
|
||||
const err = { name: 'TypeError', code: 'ERR_INVALID_ARG_TYPE' };
|
||||
|
||||
assert.throws(() => fs.lchown(i, 1, 1, common.mustNotCall()), err);
|
||||
assert.throws(() => fs.lchownSync(i, 1, 1), err);
|
||||
promises.lchown(false, 1, 1)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError(err));
|
||||
});
|
||||
|
||||
// Validate the uid and gid arguments.
|
||||
[false, 'test', {}, [], null, undefined].forEach((i) => {
|
||||
const err = { name: 'TypeError', code: 'ERR_INVALID_ARG_TYPE' };
|
||||
|
||||
assert.throws(
|
||||
() => fs.lchown('not_a_file_that_exists', i, 1, common.mustNotCall()),
|
||||
err
|
||||
);
|
||||
assert.throws(
|
||||
() => fs.lchown('not_a_file_that_exists', 1, i, common.mustNotCall()),
|
||||
err
|
||||
);
|
||||
assert.throws(() => fs.lchownSync('not_a_file_that_exists', i, 1), err);
|
||||
assert.throws(() => fs.lchownSync('not_a_file_that_exists', 1, i), err);
|
||||
|
||||
promises.lchown('not_a_file_that_exists', i, 1)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError(err));
|
||||
|
||||
promises.lchown('not_a_file_that_exists', 1, i)
|
||||
.then(common.mustNotCall())
|
||||
.catch(common.expectsError(err));
|
||||
});
|
||||
|
||||
// Validate the callback argument.
|
||||
[false, 1, 'test', {}, [], null, undefined].forEach((i) => {
|
||||
assert.throws(() => fs.lchown('not_a_file_that_exists', 1, 1, i), {
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
});
|
||||
|
||||
if (!common.isWindows) {
|
||||
const testFile = tmpdir.resolve(path.basename(__filename));
|
||||
const uid = process.geteuid();
|
||||
const gid = process.getegid();
|
||||
|
||||
tmpdir.refresh();
|
||||
fs.copyFileSync(__filename, testFile);
|
||||
fs.lchownSync(testFile, uid, gid);
|
||||
fs.lchown(testFile, uid, gid, common.mustSucceed(async (err) => {
|
||||
await promises.lchown(testFile, uid, gid);
|
||||
}));
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
The 'compilerOptions' field can only be specified in the root workspace deno.json file.
|
||||
The "compilerOptions" field can only be specified in the root workspace deno.json file.
|
||||
at file:///[WILDLINE]/sub/deno.json
|
||||
The 'lint.report' field can only be specified in the root workspace deno.json file.
|
||||
The "lint.report" field can only be specified in the root workspace deno.json file.
|
||||
at file:///[WILDLINE]/sub/deno.json
|
||||
Checked 1 file
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at blob:null/[WILDCARD]:1:8
|
||||
await import(URL.createObjectURL(blob));
|
||||
^
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
||||
await import(`data:application/javascript;base64,${btoa(code)}`);
|
||||
^
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at http://localhost:4545/dynamic_import/static_remote.ts:2:8
|
||||
await import(
|
||||
^
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
Warning "--lock-write" flag is deprecated and will be removed in Deno 2.
|
||||
Download http://localhost:4545/lockfile/no_dts/mod.js
|
||||
Download http://localhost:4545/lockfile/no_dts/mod.d.ts
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at blob:null/[WILDCARD]:1:8
|
||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||
at Worker.#pollControl[WILDCARD]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||
at Worker.#pollControl[WILDCARD]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
await import("" + "https://example.com/some/file.ts");
|
||||
^
|
||||
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||
at http://localhost:4545/workers/static_remote.ts:2:8
|
||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||
at Worker.#pollControl [WILDCARD]
|
||||
|
|
36
tests/unit_node/crypto/crypto_hkdf_test.ts
Normal file
36
tests/unit_node/crypto/crypto_hkdf_test.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
import { hkdfSync } from "node:crypto";
|
||||
import { assertEquals } from "@std/assert/mod.ts";
|
||||
import { Buffer } from "node:buffer";
|
||||
import nodeFixtures from "../testdata/crypto_digest_fixtures.json" with {
|
||||
type: "json",
|
||||
};
|
||||
|
||||
Deno.test("crypto.hkdfSync - compare with node", async (t) => {
|
||||
const DATA = "Hello, world!";
|
||||
const SALT = "salt";
|
||||
const INFO = "info";
|
||||
const KEY_LEN = 64;
|
||||
|
||||
for (const { digest, hkdf } of nodeFixtures) {
|
||||
await t.step({
|
||||
name: digest,
|
||||
ignore: digest.includes("blake"),
|
||||
fn() {
|
||||
let actual: string | null;
|
||||
try {
|
||||
actual = Buffer.from(hkdfSync(
|
||||
digest,
|
||||
DATA,
|
||||
SALT,
|
||||
INFO,
|
||||
KEY_LEN,
|
||||
)).toString("hex");
|
||||
} catch {
|
||||
actual = null;
|
||||
}
|
||||
assertEquals(actual, hkdf);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,6 +1,9 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
import { pbkdf2, pbkdf2Sync } from "node:crypto";
|
||||
import { assert, assertEquals } from "@std/assert/mod.ts";
|
||||
import nodeFixtures from "../testdata/crypto_digest_fixtures.json" with {
|
||||
type: "json",
|
||||
};
|
||||
|
||||
type Algorithms =
|
||||
| "md5"
|
||||
|
@ -377,6 +380,35 @@ Deno.test("pbkdf2Sync hashes data correctly", () => {
|
|||
});
|
||||
});
|
||||
|
||||
Deno.test("crypto.pbkdf2Sync - compare with node", async (t) => {
|
||||
const DATA = "Hello, world!";
|
||||
const SALT = "salt";
|
||||
const ITERATIONS = 1000;
|
||||
const KEY_LEN = 64;
|
||||
|
||||
for (const { digest, pkdf2 } of nodeFixtures) {
|
||||
await t.step({
|
||||
name: digest,
|
||||
ignore: digest.includes("blake"),
|
||||
fn() {
|
||||
let actual: string | null;
|
||||
try {
|
||||
actual = pbkdf2Sync(
|
||||
DATA,
|
||||
SALT,
|
||||
ITERATIONS,
|
||||
KEY_LEN,
|
||||
digest as Algorithms,
|
||||
).toString("hex");
|
||||
} catch {
|
||||
actual = null;
|
||||
}
|
||||
assertEquals(actual, pkdf2);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// TODO(@littledivy): assertCallbackErrorUncaught exits for async operations on the thread pool.
|
||||
// Deno.test("[std/node/crypto] pbkdf2 callback isn't called twice if error is thrown", async () => {
|
||||
// const importUrl = new URL("node:crypto", import.meta.url);
|
|
@ -3,6 +3,9 @@
|
|||
import { assert, assertEquals } from "@std/testing/asserts.ts";
|
||||
import { createSign, createVerify, sign, verify } from "node:crypto";
|
||||
import { Buffer } from "node:buffer";
|
||||
import fixtures from "../testdata/crypto_digest_fixtures.json" with {
|
||||
type: "json",
|
||||
};
|
||||
|
||||
const rsaPrivatePem = Buffer.from(
|
||||
await Deno.readFile(
|
||||
|
@ -138,3 +141,41 @@ AwEH
|
|||
createSign("SHA256").update("test").sign(pem, "base64");
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test("crypto.createSign|sign - compare with node", async (t) => {
|
||||
const DATA = "Hello, world!";
|
||||
const privateKey = Deno.readTextFileSync(
|
||||
new URL(import.meta.resolve("../testdata/rsa_private.pem")),
|
||||
);
|
||||
for (const { digest, signature } of fixtures) {
|
||||
await t.step(digest, () => {
|
||||
let actual: string | null;
|
||||
try {
|
||||
const s = createSign(digest);
|
||||
s.update(DATA);
|
||||
actual = s.sign(privateKey).toString("hex");
|
||||
} catch {
|
||||
actual = null;
|
||||
}
|
||||
assertEquals(actual, signature);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("crypto.createVerify|verify - compare with node", async (t) => {
|
||||
const DATA = "Hello, world!";
|
||||
const publicKey = Deno.readTextFileSync(
|
||||
new URL(import.meta.resolve("../testdata/rsa_public.pem")),
|
||||
);
|
||||
for (const { digest, signature } of fixtures) {
|
||||
await t.step({
|
||||
name: digest,
|
||||
ignore: signature === null,
|
||||
fn: () => {
|
||||
const s = createVerify(digest);
|
||||
s.update(DATA);
|
||||
s.verify(publicKey, signature!);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
69
tests/unit_node/crypto/generate_fixture.mjs
Normal file
69
tests/unit_node/crypto/generate_fixture.mjs
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// Run this file with `node` to regenerate the testdata/crypto_digest_fixtures.json file.
|
||||
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import crypto from "node:crypto";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
const privateKey = readFileSync(
|
||||
join(import.meta.dirname, "..", "testdata", "rsa_private.pem"),
|
||||
);
|
||||
|
||||
const fixtures = [];
|
||||
|
||||
const DATA = "Hello, world!";
|
||||
const SALT = "salt";
|
||||
const INFO = "info";
|
||||
const ITERATIONS = 1000;
|
||||
const KEY_LEN = 64;
|
||||
|
||||
for (const digest of crypto.getHashes()) {
|
||||
const hasher = crypto.createHash(digest);
|
||||
hasher.update(DATA);
|
||||
let hash;
|
||||
try {
|
||||
hash = hasher.digest().toString("hex");
|
||||
} catch {
|
||||
hash = null;
|
||||
}
|
||||
|
||||
const sign = crypto.createSign(digest);
|
||||
sign.update(DATA);
|
||||
let signature;
|
||||
try {
|
||||
signature = sign.sign(privateKey).toString("hex");
|
||||
} catch {
|
||||
signature = null;
|
||||
}
|
||||
|
||||
let pkdf2;
|
||||
try {
|
||||
pkdf2 = crypto.pbkdf2Sync(DATA, SALT, ITERATIONS, KEY_LEN, digest).toString(
|
||||
"hex",
|
||||
);
|
||||
} catch {
|
||||
pkdf2 = null;
|
||||
}
|
||||
|
||||
let hkdf;
|
||||
try {
|
||||
hkdf = Buffer.from(crypto.hkdfSync(digest, DATA, SALT, INFO, KEY_LEN))
|
||||
.toString("hex");
|
||||
} catch {
|
||||
hkdf = null;
|
||||
}
|
||||
|
||||
fixtures.push({
|
||||
digest,
|
||||
hash,
|
||||
signature,
|
||||
pkdf2,
|
||||
hkdf,
|
||||
});
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
join(import.meta.dirname, "..", "testdata", "crypto_digest_fixtures.json"),
|
||||
JSON.stringify(fixtures, null, 2),
|
||||
);
|
|
@ -1045,11 +1045,15 @@ Deno.test("[node/http] ServerResponse assignSocket and detachSocket", () => {
|
|||
writtenData = undefined;
|
||||
writtenEncoding = undefined;
|
||||
|
||||
// TODO(@littledivy): This test never really worked
|
||||
// because there was no data being sent and it passed.
|
||||
//
|
||||
// @ts-ignore it's a socket mock
|
||||
res.detachSocket(socket);
|
||||
res.write("Hello World!", "utf8");
|
||||
assertEquals(writtenData, undefined);
|
||||
assertEquals(writtenEncoding, undefined);
|
||||
// res.detachSocket(socket);
|
||||
// res.write("Hello World!", "utf8");
|
||||
//
|
||||
// assertEquals(writtenData, undefined);
|
||||
// assertEquals(writtenEncoding, undefined);
|
||||
});
|
||||
|
||||
Deno.test("[node/http] ServerResponse getHeaders", () => {
|
||||
|
@ -1252,6 +1256,38 @@ Deno.test("[node/http] http.request() post streaming body works", async () => {
|
|||
assertEquals(server.listening, false);
|
||||
});
|
||||
|
||||
// https://github.com/denoland/deno/issues/24239
|
||||
Deno.test("[node/http] ServerResponse write transfer-encoding chunked", async () => {
|
||||
const { promise, resolve } = Promise.withResolvers<void>();
|
||||
const server = http.createServer((_req, res) => {
|
||||
res.setHeader("Content-Type", "text/event-stream");
|
||||
res.setHeader("Cache-Control", "no-cache");
|
||||
res.setHeader("Connection", "keep-alive");
|
||||
res.setHeader("Transfer-Encoding", "chunked");
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
|
||||
res.writeHead(200, {
|
||||
"Other-Header": "value",
|
||||
});
|
||||
res.write("");
|
||||
});
|
||||
|
||||
server.listen(async () => {
|
||||
const { port } = server.address() as { port: number };
|
||||
const res = await fetch(`http://localhost:${port}`);
|
||||
assertEquals(res.status, 200);
|
||||
assertEquals(res.headers.get("content-type"), "text/event-stream");
|
||||
assertEquals(res.headers.get("Other-Header"), "value");
|
||||
await res.body!.cancel();
|
||||
|
||||
server.close(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await promise;
|
||||
});
|
||||
|
||||
Deno.test("[node/http] Server.address() can be null", () => {
|
||||
const server = http.createServer((_req, res) => res.end("it works"));
|
||||
assertEquals(server.address(), null);
|
||||
|
|
366
tests/unit_node/testdata/crypto_digest_fixtures.json
vendored
Normal file
366
tests/unit_node/testdata/crypto_digest_fixtures.json
vendored
Normal file
|
@ -0,0 +1,366 @@
|
|||
[
|
||||
{
|
||||
"digest": "RSA-MD5",
|
||||
"hash": "6cd3556deb0da54bca060b4c39479839",
|
||||
"signature": "45f2e7ac7c0d323c18e9c8554d15e21a8fb72944928e0b7acc2185402448c39af05340391ee9aac64c45a947bc3ed801de8791aaa5788a62e909d7c8d92e63c7f119753219a48c29ea78e371d3a89c0bd64d756b829fa6faaa8fa46bc28228dd4430aca845c02f3b6b835b140247838ac5b96434d1049115785f3f52034e0cc46f6cafc5f2921b9928403aea1edd85f3a99e12324abeeaaaa040b320f8af157c5df7fd7479415771fd116daed933b43eac51b3c274ba9283aaf3f1b6f1f527a0cea76f9a43dca3b9ff03834feed13a0fd488e6750a9d46ddb1ad69ac88090af050458eeafd1e9fa317c4ecc61d90289d5378e6e3693ef6da2e4a4803b6108145",
|
||||
"pkdf2": "3083f052ca2e90daf96a87b8b8c1daa069bff60c73045c9504d3b424807b5410a724ea5ba28b9bccb6bad59c0e181663b07156a59b09cee85ffe223f21ff6db6",
|
||||
"hkdf": "f516674e1b1faf2c1a505041634460d94739e2e39be4e6a097f926f5cc9788c09892efcb407019dc469c4014c8d847cf4c5a6eeefccf8e5266ca3dd02ea57529"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-RIPEMD160",
|
||||
"hash": "58262d1fbdbe4530d8865d3518c6d6e41002610f",
|
||||
"signature": "31b25b680d0df8cb27df71c38fe7931a185c056b98c072a4f4956d6105a44ed53d7e457d366074cc26cd1cd0c226cf0cac509264f42651c208eb73f29f48dc2022009595e4ccf97662cf2840d69987f51118e9854fd10497a9e1dcb2ef390c9d09767f7d801aa2dd3d5c0e51249a195769593696725ba81e9a6c961a4b2c13827c467ccafa76f0ea5a9f43b936f3b35a8c316f116e0ac0d6f56ed8c0189d28ea1dc3a56b97a75c8f5c5cdc1682a76b5d852dd7282371ecb379abf0864eff0c437fca813d0ddc1ce34e8327a604336eeab6d907edf39e0303f0b8a45e0721e15d85c8c329047920b1ec8863bc6c0b172a57a6bb3611edb1f5c4d49aa1089cb5fd",
|
||||
"pkdf2": "2473b58bc86761bd5e8d35153475d44e8ba2dd4a156d6e69d79cbc33244f35bfea27bb3122354d98dbd792c679d8994f10a8eaf7c946e6a65566413a13060386",
|
||||
"hkdf": "c7d8a2fe1ae6d243aef0b989c2483221f0e9c3234719273438dca33b97269435047f441ae104903fafaa051267ab34ba469449511a8e40fc5444a01e03cfe651"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA1",
|
||||
"hash": "943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "80174b0678707d38335940a010bd6acc1a6ade2c911251d013875816eb4c5169d9d4cb2ac9f6ce4b29b92f5750f185a273abd7c8a2434a9d1a50df5311999655d2a535c77b79997ed34fe51a863c450251d1b85bbb4dd10da1162e6e74194af606579a8724e55b93bded2d10216bb63cf00e848ceea6cdba78eab4f735ca620b36fdfd19bf15706df860a4c589160ce3c32aa51c27561de82a00cdcca709045cb8622adb6f759eb5e0f2f3f6056ca1b1a91206712ce92f5684d64931bc001bec7d2e8d2469f0818106070698160e9e21404971ea45940797fa3a61a39a25b7c6c75986accd4832db50a25ef3fceca629e104e2f03affd83b94cf074614e11c18",
|
||||
"pkdf2": "e77df42e685bd1fe2e19e374e1dd8470df71182311e048a6a280f36ef24c661e46fe8e8cc763942615934a631ac3aeda24bb9fda71e04f89f0c85f2f762abd98",
|
||||
"hkdf": "936c59e9394b5b1fdc26bd2eec0dc8c8d52fb97198e021805f0ae58c3f8b631d0020002b1ce0df9d890377fcc808166c906f128d06d77d404061d56560f3340d"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA1-2",
|
||||
"hash": "943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "80174b0678707d38335940a010bd6acc1a6ade2c911251d013875816eb4c5169d9d4cb2ac9f6ce4b29b92f5750f185a273abd7c8a2434a9d1a50df5311999655d2a535c77b79997ed34fe51a863c450251d1b85bbb4dd10da1162e6e74194af606579a8724e55b93bded2d10216bb63cf00e848ceea6cdba78eab4f735ca620b36fdfd19bf15706df860a4c589160ce3c32aa51c27561de82a00cdcca709045cb8622adb6f759eb5e0f2f3f6056ca1b1a91206712ce92f5684d64931bc001bec7d2e8d2469f0818106070698160e9e21404971ea45940797fa3a61a39a25b7c6c75986accd4832db50a25ef3fceca629e104e2f03affd83b94cf074614e11c18",
|
||||
"pkdf2": "e77df42e685bd1fe2e19e374e1dd8470df71182311e048a6a280f36ef24c661e46fe8e8cc763942615934a631ac3aeda24bb9fda71e04f89f0c85f2f762abd98",
|
||||
"hkdf": "936c59e9394b5b1fdc26bd2eec0dc8c8d52fb97198e021805f0ae58c3f8b631d0020002b1ce0df9d890377fcc808166c906f128d06d77d404061d56560f3340d"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA224",
|
||||
"hash": "8552d8b7a7dc5476cb9e25dee69a8091290764b7f2a64fe6e78e9568",
|
||||
"signature": "70a8b455d63d2af5b12b0eefcb50ae245dcac054a74fd8a5beccca5ed12fd545e4dcdf2da3455f49e5eaf559772dc885ae24fd9e42790a1e175ec221a22329f2cc67d5c8ad1f9377fa1d713cb0d554f8335325a6080c272c10fb59f5fb7da9b39dcc76a50b49ed5f28d8cdd0499fbf5a19cae4b5b4a4a103201933a0e94e5532c6aaf05fbb060a3be5dcd5addef23b80651c51831ee479142cb1ddac0a37c6251f6eceee55217fcced2462fb7bef3e3aeeda98672598dc6aca6a49fb2df1b3f0ac569b666afeb8ca3f5b1bfa0bcca49f5fe6d3784fba1bb931077633d5a0a731c2bb22a820c8497ac1db888bd542f73ba2358d3a9bc056a7eca2f3a78b437820",
|
||||
"pkdf2": "d3adee1df932bac56eecdba710702025678d6e024d315c925ae274a3796c474219291983a76f2b8bd67aad26fbebcf5bb5088c99b6124ae1b9c7c9b2eb37c8f4",
|
||||
"hkdf": "1c3a0bd11a8c71c010353b075474aa2a6740f5cade0fff895019e08ebdaa68f8dfc4e74a5e013e2e9e0ab6852884311c1dac89432d34b2f762113ebf9a37597a"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA256",
|
||||
"hash": "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3",
|
||||
"signature": "67b67a87fc4a576342fc46167395a255654dddc5036e8a7d323acf862470e0612b90b1abf22166e3d124d4866e82146b5735fb85895355d027efdcb406a8cb87c8f00aea128e74cb95ca8a69cb970e3f02a11a6911253f9fba54ae7b75d7f1f29d51338d43f4ed59a36e3b7e408591cd9feaa818f1b0c6df6155cc89cc95c6686ce82a78fd8d34e82d9047ce936c3a67ac85d2924083610d6db5040409f09a46f97d35248b5451ca51be6cfbc9f94ff630eb8ff95e114a666cc1cc011af03d77f9b24f8add5244a83e0784dbcf785ebcfcd015b876963666b113dc26f0222aa95fdfbe1e64ac6b48780e1ff69b2588ff4bce9b15f9d53abba96b813a3d657cbe",
|
||||
"pkdf2": "a8a2a7dcf7b65c8498ab1fbc62d56fa47255d668c1c3f21c5b236259d1dd8b11859026e737216cceb7a8facb8d27656f2b990db98786f12a8ce68e56a30f0c0b",
|
||||
"hkdf": "a35a5ba99add2c508b9014ca7eb7d461a85989257b29a46a0041361c85b2c48838199873987b5419ede395aa09129bcb5fbd607b8b769e6711e1fea5e0ebcbc0"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA3-224",
|
||||
"hash": "6a33e22f20f16642697e8bd549ff7b759252ad56c05a1b0acc31dc69",
|
||||
"signature": "2504c7a4735c251aa01644ae56a9f7c891f45e9fb6e25fea1c25074139dcab114e77d64ae7788bcbd8d5d452db60b47e6a0b324b0e3482ff794581da0cbe960a97ba75c1023eab2320fa9022ae715b5aa2fe1186916fb9a1c931d9f28ba8e12a4dd145efff6abfcfb68eca6536655c96cf059df406d5c51d1814b2f61c6bdc10a2b083d29f50a064bc6ffdddf5cb45df2577a7149a430e1314f87427972d8bb4775bd92e99a2298095cb83e60e50f503aab6d9fd41398b55d5dcfa6022049891561e6395a7a3e56a1d92a8667733a68d9b0374952d95e4d5a51b0b22d390cf579bb536e59cea8272b2d5749fa70d48c396b6ba94188ce677beb8f00937640096",
|
||||
"pkdf2": "014d30aa9d1c1d8e3920f4bcc399f37b16d6c346d570d4345229d64ab95e504b1c6b253133c218a2b46f29aa0f9792d7ad60761159cc3550cb9a0914bfdc9951",
|
||||
"hkdf": "b6c671ec02ee7f215dcee9ecade623831658470156f3edab205b7e3a70587f3c538eac8ec92e3a5bf6808b9b939d84e4f8ba5ee3532d7adb152211cc8f79cf9b"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA3-256",
|
||||
"hash": "f345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722",
|
||||
"signature": "b3b475d03da73b4bf8fefa5f49231dfd8f95605e0c3ea058d4607f1274ddcf4f69b1751df8493df1c5fe31883aff197688de1991885bb9ed4266f7df0db4fc99b33bee32a9237a9c2714e461fefb311923c1e91fe7cbe1830206bb0b3d962bfccdf5c37e8ce9e01f203851e34f22162175f44048002483ff2e3ffc658506a23f358f3192dbba759a8e1f66d3abf934b72295f1b51f8a92c837c76006084b65c0df8e072e43b1122bb15b3043dceb026e2cf311d04d6f4a3506e7e5b8a08fcaa0caeaa18a6397d185e5b5d1bc962f22b80db798a42fa206cd2db53b02bc5e2e69d9566f1ff3fccb4690545ff19424001cf3c0504c53adc0f2ce4354596b8a4d69",
|
||||
"pkdf2": "4ba48814e191c34c9d38f5ccf6c5cf1a61082c2f8b36e99bd8210781af995734f62c6a714ad6639ecb55224d91b2ac7d69030335d2c367d833823814ef9f2213",
|
||||
"hkdf": "e60f1e8214b7907d63d8cfb2bfb083051d3c9a56e4f94aabc1ff3543986aac5d4823db903090af81824964d6ca39da8388495e8838a9c0c407cb3546f44f9a04"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA3-384",
|
||||
"hash": "6ba9ea268965916f5937228dde678c202f9fe756a87d8b1b7362869583a45901fd1a27289d72fc0e3ff48b1b78827d3a",
|
||||
"signature": "256542ac61773cec2261fbc8cde4d6524e7a91f9fefcc08792c7c4b27fb843d099a5fce9819503949ad8fde307a7fc4185754dc5ed3d473da065376e4a9c804265dc4ff858a774d6eb19e663a26339d087a3e96b8f9133becc0ee2b404cfcfca58ffadbd48a5c31dced92f188b40bd179efdf9ae5394d0e02b513958f46adbdf745e8dada0dd97e38bf28bf7ad87aeb6771a40e3fef5f35161d4eeafe7b6ba1c2101388a22e75586fab599cbc070bf4d0fbe8304a7c579a34ce0000c87b33882c2d86ff11dbc218604fa7e7203e4efaa6e9605ae41958c0c2de0b7d76da9a6e606b3c38d29dad55675f9f138b11afc96e71ba5e41924bc5c676db777aed7ea04",
|
||||
"pkdf2": "f609fda1c21cf4e59e7142438f2e04bb29f72010d49546e1c192755c6af3b97903da8483be8356afb865ffc334d23fa2439063c287ec9491618bfb5f791675f4",
|
||||
"hkdf": "818ae5bc92cf582db87d73316e1a0649b457dfcd198db3e4edb1c6b20515dcf14f8758951765d9e2b4f7914a75ea04815e82050a6ca602c1a76f6c9999813955"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA3-512",
|
||||
"hash": "8e47f1185ffd014d238fabd02a1a32defe698cbf38c037a90e3c0a0a32370fb52cbd641250508502295fcabcbf676c09470b27443868c8e5f70e26dc337288af",
|
||||
"signature": "925bd1da0c91caba58c0a407f4f63e9b16f52444c3b71476f4043ee00ef97bb428a396e8a45d75b3204142d2e18886f36b0b0a1c6d25d80b010e4063ffb310741907e3217badadaf53d018100d78eace2e941c0ec2b6f9b47ceee455d55bfb1711b1255ae1fa0d8fb5bf869009c1b558b02fd4cabd83c55a76a1d96bdb4cdbb42f6ad1f36984c39e6c6fe4edc3a771766742ec461d29e8a93704a48323c0c0f9cc066bf1daeb4e83aa3aa7a3c2067495cf320a9e98b7f1db638a23fc135992fcc3bbfb52be115c35b055cdbf4733c30098674ff19f1ef218a4643b0e2ecb7c0597a406b304b67a36eed0300313a65a4af5621ef59a5ffe53e7d6763a83e0014a",
|
||||
"pkdf2": "e1f0b454bf5d729fbb13e534229521a87aee130078555791d83834a8c51fb681ce4dfe02afd5f063082d8abba0b456084c677aeb6f8e0d70305322ec2ea97203",
|
||||
"hkdf": "f27d87f9f6b87718073c8d2ad6bae00b4162cecde350c856252dd611120c433373a0c0d3946a8582bf855bf581439a14ca4f355fcd18881331f4a3b1027e84b2"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA384",
|
||||
"hash": "55bc556b0d2fe0fce582ba5fe07baafff035653638c7ac0d5494c2a64c0bea1cc57331c7c12a45cdbca7f4c34a089eeb",
|
||||
"signature": "77d465006b8843cf30c5e93b7d3f63b0daf2df1d693c4e1c0f9c759ec8410c088f331c5bf89bca7218edd1bdf3f2d948c9be9656f44a630748395429a09289acb05be80b0d000bacd7826c33a584dcbcf658839015d07561668e882bad4505c475a04766a7eabb35b15b8b54d6fcf9ebdd25b699f0d88906ba2999de1e8e59cc75969bc819fd514b1002a6667a03c861fafee03cccb9fd926352139dc1a916ba56b36e9e69fd328cb2403b9f747350721261158021df9ab2a75a7c5a3e39b42f3722ea1997a039ecc033f64366974336dbfd3294820400fe623d2993593c51f4398290a51bf05dc452c5991e26e8971be759472635e86b08230d04d05bce88f4",
|
||||
"pkdf2": "b2e2b9e03d9e6f5218b74be7002c8704558feae855272ab3a973ee7deb387c26483f87fb6463bc5768406b398896a29ac2d17bd45afccf369a403ffa396bb455",
|
||||
"hkdf": "54aef7f7256a147e52d67888a4543c6084b4ac46cd7bf919576bf8c4e9dad6b8a1fc9ad9c6f90f2af8e76d8d815ae2226d67a11ccb524a0c0be3cc858f4ddb10"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA512",
|
||||
"hash": "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421",
|
||||
"signature": "50e2973977e1be1218134a1f50732a8f54c4b0dfb836be816c304edce9bef4b1be566a295b05c6c82de00eb915bc61ca4bab073a13061987ca19af280202a4c6c496cf6262655e6a6f1a53f923ca048b4bc21e31282edd239cec8840b2411c1aa2abe5b9bf7de5066f43f6e2e0a0691ac6f2fc71ed679ae644b6d799261ed694dc9e27c81142ffb88883440ee92a6086d7c3d62572eac13480034219a9edbda7e5556f335bbe1a37ef0df26ae3ffe99b968d40a93d9ca9a3c76025409b5da041242afa977a5a0438be946562a48a764dc6d4c924fec82590e01b807d410a432b95ee2e5173d245a565cdecdc321521d6f61e965628013181bc7a9462a450d895",
|
||||
"pkdf2": "284f17da4e32b7b4780b31f94405e115ca7e6ae025b05d8398f421c3a3f36d903a1fae9471674342bec7d51c6f32996df0c843a20105c8451e9cd17ecbddb3ed",
|
||||
"hkdf": "cf181757f66abf44c88cd3d4ad0ed99b82cf47a8a6f870ff1561a12da7af03251590250af7473a1a3c5c5e794f29c44e8f25f69fb7985258161e74b433510262"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA512/224",
|
||||
"hash": "32620068b859669b45b31008e08b7384649ad2ca3f5163a3a71e5745",
|
||||
"signature": "b5d1ec54de69d29dbc77595fec62bb16019b7cc275ead04338c17ee4b759fcb8443477e1708d45374b786acfeb616c1078d199b2a28d76f46d4b74a498c2bfb2b174632da895cae5558f36101f0596adb40152ac09b49f1726f293237bcf604ab7bf461c7e2dd78c909d7503ec4132722551842f7e8ef54317f4b58784c447fd68067c689c288c8401dc95276356e1396a127eac82a0bd0753cc4c00718e7240d523af95a1cd960885da64172e3325a225557f96e6307340dd45a499ac20af01a2e3e7a4be706a40249c6ce7e24dabdcbd577744c34cf8e182d9a7923c52cd508a0e39125003a0c74ac714f5c892187c6fc7417d552127b3c24c57e484212ab6",
|
||||
"pkdf2": "69e623258a79c04b84aabc9333b17fc8a5ee8d7ebd06dd80236865584ccc98fce3180319f74748f6a6c2b44833425a6ab52e8ab22db62365799f14727102485d",
|
||||
"hkdf": "c155ac0b2833f309322f258625df2c9926570fabbe66eff9713b977291054b57b8cd3280079613d8167a99f259087422cff9756780148bf683c1d5c03e015907"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SHA512/256",
|
||||
"hash": "330c723f25267587db0b9f493463e017011239169cb57a6db216c63774367115",
|
||||
"signature": "6313742057ecbf4f54476799b018d1e18c2db920ef23386208f1e23e5af30d38edc0d11f1220e2cc0f898cd3e4cd9d4920fed30ff9f725404d4750f230fe9dafdfde95280a8713043359a09d45fbda484c469e61ae4fd615d616e76f6daa27acd3542d823e88f2dfd943b39f38884f9ed4695b8f004b4c67777de63474fe9dbbfeab966113907663f14c7822658aab70dceb7d1a6ed9842085762ab100ee915941295a045b29ef09af19eab58c79d3e5ffcbda61e2be35770c1d3b55156357c3cca806309b1ddc7e52f47e245d1d49237f0aa7156e89c76a17780a62fa552eeb7b623410e387d0a9412d4688725ed8df0a86e8b548ea6bb785ea48b6c0e39332",
|
||||
"pkdf2": "c3d18f17c825a1630bc10695bfd4faa0309e862d010c0b74fb41b6ce5e46853cc435560a1b9cd940254103068aebc1f24d2580385b1890e7f10356ef4c8f507d",
|
||||
"hkdf": "8451f1238da8577794ecc9b75832cabff44f279e5f8258cbf553c21f9735c19c7974e9a74879b4c59386116bb1a4bb50f149c9a4146b10de312fa679c1343b80"
|
||||
},
|
||||
{
|
||||
"digest": "RSA-SM3",
|
||||
"hash": "e3bca101b496880c3653dad85861d0e784b00a8c18f7574472d156060e9096bf",
|
||||
"signature": null,
|
||||
"pkdf2": "70b3d2ac3b82dd7b8c35db45f99f49e029be2b6f1ef9ce1d9137267b729c06f7099dc7f571f2b05dbe5172118a7ae787cd4836fbf9ddce9aacc933c7c4e5537b",
|
||||
"hkdf": "88b773032a2f131b1aa4ebdb69fdde7c42281b7c689bfe1f5bd43c7e1a6f555f101657c3f83ccd5918b4c6a8df04d0b58ebf77ec2181f8c5e7cfecb6f13fba61"
|
||||
},
|
||||
{
|
||||
"digest": "blake2b512",
|
||||
"hash": "a2764d133a16816b5847a737a786f2ece4c148095c5faa73e24b4cc5d666c3e45ec271504e14dc6127ddfce4e144fb23b91a6f7b04b53d695502290722953b0f",
|
||||
"signature": null,
|
||||
"pkdf2": "ae8782ec9a457cf51606ac8cfc97c4c5f9fe2485714f7be7fddfddf02c7bb9c977ebea731b17ec2a7cf197e91be085dbce87392e53f548ac7c14e28876c9a271",
|
||||
"hkdf": "65c9a327ea321c4e5beab11527862dee68b39349c909652d4e796f88ba5ede82011d6c17996c7f90c71ea1003244b0e845d02e0a852f5e08add5cea53ae21d7f"
|
||||
},
|
||||
{
|
||||
"digest": "blake2s256",
|
||||
"hash": "30d8777f0e178582ec8cd2fcdc18af57c828ee2f89e978df52c8e7af078bd5cf",
|
||||
"signature": null,
|
||||
"pkdf2": "242e2926b524dd35a4684b4300a6e0e219b58ad1513847a3ac731f08696b5491d6b3a14146864fcc1d292c85908fe364267670c9a680bbe8117bf3b2519efee9",
|
||||
"hkdf": "f17e4306bf70cbd74e7d16595eab65178a7d6545ff3a8d78800ea69697e6c360f24bafe2772ff80fb1a4381bb69c3f98c39033f246f86521609a4dda95b7a1d7"
|
||||
},
|
||||
{
|
||||
"digest": "id-rsassa-pkcs1-v1_5-with-sha3-224",
|
||||
"hash": "6a33e22f20f16642697e8bd549ff7b759252ad56c05a1b0acc31dc69",
|
||||
"signature": "2504c7a4735c251aa01644ae56a9f7c891f45e9fb6e25fea1c25074139dcab114e77d64ae7788bcbd8d5d452db60b47e6a0b324b0e3482ff794581da0cbe960a97ba75c1023eab2320fa9022ae715b5aa2fe1186916fb9a1c931d9f28ba8e12a4dd145efff6abfcfb68eca6536655c96cf059df406d5c51d1814b2f61c6bdc10a2b083d29f50a064bc6ffdddf5cb45df2577a7149a430e1314f87427972d8bb4775bd92e99a2298095cb83e60e50f503aab6d9fd41398b55d5dcfa6022049891561e6395a7a3e56a1d92a8667733a68d9b0374952d95e4d5a51b0b22d390cf579bb536e59cea8272b2d5749fa70d48c396b6ba94188ce677beb8f00937640096",
|
||||
"pkdf2": "014d30aa9d1c1d8e3920f4bcc399f37b16d6c346d570d4345229d64ab95e504b1c6b253133c218a2b46f29aa0f9792d7ad60761159cc3550cb9a0914bfdc9951",
|
||||
"hkdf": "b6c671ec02ee7f215dcee9ecade623831658470156f3edab205b7e3a70587f3c538eac8ec92e3a5bf6808b9b939d84e4f8ba5ee3532d7adb152211cc8f79cf9b"
|
||||
},
|
||||
{
|
||||
"digest": "id-rsassa-pkcs1-v1_5-with-sha3-256",
|
||||
"hash": "f345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722",
|
||||
"signature": "b3b475d03da73b4bf8fefa5f49231dfd8f95605e0c3ea058d4607f1274ddcf4f69b1751df8493df1c5fe31883aff197688de1991885bb9ed4266f7df0db4fc99b33bee32a9237a9c2714e461fefb311923c1e91fe7cbe1830206bb0b3d962bfccdf5c37e8ce9e01f203851e34f22162175f44048002483ff2e3ffc658506a23f358f3192dbba759a8e1f66d3abf934b72295f1b51f8a92c837c76006084b65c0df8e072e43b1122bb15b3043dceb026e2cf311d04d6f4a3506e7e5b8a08fcaa0caeaa18a6397d185e5b5d1bc962f22b80db798a42fa206cd2db53b02bc5e2e69d9566f1ff3fccb4690545ff19424001cf3c0504c53adc0f2ce4354596b8a4d69",
|
||||
"pkdf2": "4ba48814e191c34c9d38f5ccf6c5cf1a61082c2f8b36e99bd8210781af995734f62c6a714ad6639ecb55224d91b2ac7d69030335d2c367d833823814ef9f2213",
|
||||
"hkdf": "e60f1e8214b7907d63d8cfb2bfb083051d3c9a56e4f94aabc1ff3543986aac5d4823db903090af81824964d6ca39da8388495e8838a9c0c407cb3546f44f9a04"
|
||||
},
|
||||
{
|
||||
"digest": "id-rsassa-pkcs1-v1_5-with-sha3-384",
|
||||
"hash": "6ba9ea268965916f5937228dde678c202f9fe756a87d8b1b7362869583a45901fd1a27289d72fc0e3ff48b1b78827d3a",
|
||||
"signature": "256542ac61773cec2261fbc8cde4d6524e7a91f9fefcc08792c7c4b27fb843d099a5fce9819503949ad8fde307a7fc4185754dc5ed3d473da065376e4a9c804265dc4ff858a774d6eb19e663a26339d087a3e96b8f9133becc0ee2b404cfcfca58ffadbd48a5c31dced92f188b40bd179efdf9ae5394d0e02b513958f46adbdf745e8dada0dd97e38bf28bf7ad87aeb6771a40e3fef5f35161d4eeafe7b6ba1c2101388a22e75586fab599cbc070bf4d0fbe8304a7c579a34ce0000c87b33882c2d86ff11dbc218604fa7e7203e4efaa6e9605ae41958c0c2de0b7d76da9a6e606b3c38d29dad55675f9f138b11afc96e71ba5e41924bc5c676db777aed7ea04",
|
||||
"pkdf2": "f609fda1c21cf4e59e7142438f2e04bb29f72010d49546e1c192755c6af3b97903da8483be8356afb865ffc334d23fa2439063c287ec9491618bfb5f791675f4",
|
||||
"hkdf": "818ae5bc92cf582db87d73316e1a0649b457dfcd198db3e4edb1c6b20515dcf14f8758951765d9e2b4f7914a75ea04815e82050a6ca602c1a76f6c9999813955"
|
||||
},
|
||||
{
|
||||
"digest": "id-rsassa-pkcs1-v1_5-with-sha3-512",
|
||||
"hash": "8e47f1185ffd014d238fabd02a1a32defe698cbf38c037a90e3c0a0a32370fb52cbd641250508502295fcabcbf676c09470b27443868c8e5f70e26dc337288af",
|
||||
"signature": "925bd1da0c91caba58c0a407f4f63e9b16f52444c3b71476f4043ee00ef97bb428a396e8a45d75b3204142d2e18886f36b0b0a1c6d25d80b010e4063ffb310741907e3217badadaf53d018100d78eace2e941c0ec2b6f9b47ceee455d55bfb1711b1255ae1fa0d8fb5bf869009c1b558b02fd4cabd83c55a76a1d96bdb4cdbb42f6ad1f36984c39e6c6fe4edc3a771766742ec461d29e8a93704a48323c0c0f9cc066bf1daeb4e83aa3aa7a3c2067495cf320a9e98b7f1db638a23fc135992fcc3bbfb52be115c35b055cdbf4733c30098674ff19f1ef218a4643b0e2ecb7c0597a406b304b67a36eed0300313a65a4af5621ef59a5ffe53e7d6763a83e0014a",
|
||||
"pkdf2": "e1f0b454bf5d729fbb13e534229521a87aee130078555791d83834a8c51fb681ce4dfe02afd5f063082d8abba0b456084c677aeb6f8e0d70305322ec2ea97203",
|
||||
"hkdf": "f27d87f9f6b87718073c8d2ad6bae00b4162cecde350c856252dd611120c433373a0c0d3946a8582bf855bf581439a14ca4f355fcd18881331f4a3b1027e84b2"
|
||||
},
|
||||
{
|
||||
"digest": "md5",
|
||||
"hash": "6cd3556deb0da54bca060b4c39479839",
|
||||
"signature": "45f2e7ac7c0d323c18e9c8554d15e21a8fb72944928e0b7acc2185402448c39af05340391ee9aac64c45a947bc3ed801de8791aaa5788a62e909d7c8d92e63c7f119753219a48c29ea78e371d3a89c0bd64d756b829fa6faaa8fa46bc28228dd4430aca845c02f3b6b835b140247838ac5b96434d1049115785f3f52034e0cc46f6cafc5f2921b9928403aea1edd85f3a99e12324abeeaaaa040b320f8af157c5df7fd7479415771fd116daed933b43eac51b3c274ba9283aaf3f1b6f1f527a0cea76f9a43dca3b9ff03834feed13a0fd488e6750a9d46ddb1ad69ac88090af050458eeafd1e9fa317c4ecc61d90289d5378e6e3693ef6da2e4a4803b6108145",
|
||||
"pkdf2": "3083f052ca2e90daf96a87b8b8c1daa069bff60c73045c9504d3b424807b5410a724ea5ba28b9bccb6bad59c0e181663b07156a59b09cee85ffe223f21ff6db6",
|
||||
"hkdf": "f516674e1b1faf2c1a505041634460d94739e2e39be4e6a097f926f5cc9788c09892efcb407019dc469c4014c8d847cf4c5a6eeefccf8e5266ca3dd02ea57529"
|
||||
},
|
||||
{
|
||||
"digest": "md5-sha1",
|
||||
"hash": "6cd3556deb0da54bca060b4c39479839943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "1b8bddcb86fca178c4318ff04be6956fc92815b54b38d7cd5c0c12be1b3c2b5defc960d9fc162d0f2e8eddeb075cb5b751c89d2e7550d50e1939f89c5c96bd7c4b8ad16fd02f5295f9806f275b0959f9fa226131c6996e64ce5f2595729036967762070033e40c3b7f63c8567158ce78143332a00669a0c4126b80c7ba9bdcf61e03eda99fddb9ea779a4038e87d6615d166e9b88272cb91de68126bbf505764feebd68b526358a0cf46526aea26566907763a5250f9169d1e6e674cc37fe5feb20f2a87b9251383829ad33d5bc1fbf78f87c625703b68a4f30e9a31b248a5d094d712cf5c8ca1394fe9a9d8800b5d90b0f51f4b2e547287239a210504807d8a",
|
||||
"pkdf2": "4d8d010a2ab473080923a782f8d497d2be83c3dd78b3da755754ab098f4b9d629e583f343fabc938ab0cce8bdaa5ad4c515d10fc9c0ce416e5752a9060bb9831",
|
||||
"hkdf": "9265d75fdd9ef3609109d7703c75773d02175d68376422f4078bede7e3ac4f024a6b0e28333e316c276d6bb6f1177f8300490bf78c98f20ba8e6d2f287515b56"
|
||||
},
|
||||
{
|
||||
"digest": "md5WithRSAEncryption",
|
||||
"hash": "6cd3556deb0da54bca060b4c39479839",
|
||||
"signature": "45f2e7ac7c0d323c18e9c8554d15e21a8fb72944928e0b7acc2185402448c39af05340391ee9aac64c45a947bc3ed801de8791aaa5788a62e909d7c8d92e63c7f119753219a48c29ea78e371d3a89c0bd64d756b829fa6faaa8fa46bc28228dd4430aca845c02f3b6b835b140247838ac5b96434d1049115785f3f52034e0cc46f6cafc5f2921b9928403aea1edd85f3a99e12324abeeaaaa040b320f8af157c5df7fd7479415771fd116daed933b43eac51b3c274ba9283aaf3f1b6f1f527a0cea76f9a43dca3b9ff03834feed13a0fd488e6750a9d46ddb1ad69ac88090af050458eeafd1e9fa317c4ecc61d90289d5378e6e3693ef6da2e4a4803b6108145",
|
||||
"pkdf2": "3083f052ca2e90daf96a87b8b8c1daa069bff60c73045c9504d3b424807b5410a724ea5ba28b9bccb6bad59c0e181663b07156a59b09cee85ffe223f21ff6db6",
|
||||
"hkdf": "f516674e1b1faf2c1a505041634460d94739e2e39be4e6a097f926f5cc9788c09892efcb407019dc469c4014c8d847cf4c5a6eeefccf8e5266ca3dd02ea57529"
|
||||
},
|
||||
{
|
||||
"digest": "ripemd",
|
||||
"hash": "58262d1fbdbe4530d8865d3518c6d6e41002610f",
|
||||
"signature": "31b25b680d0df8cb27df71c38fe7931a185c056b98c072a4f4956d6105a44ed53d7e457d366074cc26cd1cd0c226cf0cac509264f42651c208eb73f29f48dc2022009595e4ccf97662cf2840d69987f51118e9854fd10497a9e1dcb2ef390c9d09767f7d801aa2dd3d5c0e51249a195769593696725ba81e9a6c961a4b2c13827c467ccafa76f0ea5a9f43b936f3b35a8c316f116e0ac0d6f56ed8c0189d28ea1dc3a56b97a75c8f5c5cdc1682a76b5d852dd7282371ecb379abf0864eff0c437fca813d0ddc1ce34e8327a604336eeab6d907edf39e0303f0b8a45e0721e15d85c8c329047920b1ec8863bc6c0b172a57a6bb3611edb1f5c4d49aa1089cb5fd",
|
||||
"pkdf2": "2473b58bc86761bd5e8d35153475d44e8ba2dd4a156d6e69d79cbc33244f35bfea27bb3122354d98dbd792c679d8994f10a8eaf7c946e6a65566413a13060386",
|
||||
"hkdf": "c7d8a2fe1ae6d243aef0b989c2483221f0e9c3234719273438dca33b97269435047f441ae104903fafaa051267ab34ba469449511a8e40fc5444a01e03cfe651"
|
||||
},
|
||||
{
|
||||
"digest": "ripemd160",
|
||||
"hash": "58262d1fbdbe4530d8865d3518c6d6e41002610f",
|
||||
"signature": "31b25b680d0df8cb27df71c38fe7931a185c056b98c072a4f4956d6105a44ed53d7e457d366074cc26cd1cd0c226cf0cac509264f42651c208eb73f29f48dc2022009595e4ccf97662cf2840d69987f51118e9854fd10497a9e1dcb2ef390c9d09767f7d801aa2dd3d5c0e51249a195769593696725ba81e9a6c961a4b2c13827c467ccafa76f0ea5a9f43b936f3b35a8c316f116e0ac0d6f56ed8c0189d28ea1dc3a56b97a75c8f5c5cdc1682a76b5d852dd7282371ecb379abf0864eff0c437fca813d0ddc1ce34e8327a604336eeab6d907edf39e0303f0b8a45e0721e15d85c8c329047920b1ec8863bc6c0b172a57a6bb3611edb1f5c4d49aa1089cb5fd",
|
||||
"pkdf2": "2473b58bc86761bd5e8d35153475d44e8ba2dd4a156d6e69d79cbc33244f35bfea27bb3122354d98dbd792c679d8994f10a8eaf7c946e6a65566413a13060386",
|
||||
"hkdf": "c7d8a2fe1ae6d243aef0b989c2483221f0e9c3234719273438dca33b97269435047f441ae104903fafaa051267ab34ba469449511a8e40fc5444a01e03cfe651"
|
||||
},
|
||||
{
|
||||
"digest": "ripemd160WithRSA",
|
||||
"hash": "58262d1fbdbe4530d8865d3518c6d6e41002610f",
|
||||
"signature": "31b25b680d0df8cb27df71c38fe7931a185c056b98c072a4f4956d6105a44ed53d7e457d366074cc26cd1cd0c226cf0cac509264f42651c208eb73f29f48dc2022009595e4ccf97662cf2840d69987f51118e9854fd10497a9e1dcb2ef390c9d09767f7d801aa2dd3d5c0e51249a195769593696725ba81e9a6c961a4b2c13827c467ccafa76f0ea5a9f43b936f3b35a8c316f116e0ac0d6f56ed8c0189d28ea1dc3a56b97a75c8f5c5cdc1682a76b5d852dd7282371ecb379abf0864eff0c437fca813d0ddc1ce34e8327a604336eeab6d907edf39e0303f0b8a45e0721e15d85c8c329047920b1ec8863bc6c0b172a57a6bb3611edb1f5c4d49aa1089cb5fd",
|
||||
"pkdf2": "2473b58bc86761bd5e8d35153475d44e8ba2dd4a156d6e69d79cbc33244f35bfea27bb3122354d98dbd792c679d8994f10a8eaf7c946e6a65566413a13060386",
|
||||
"hkdf": "c7d8a2fe1ae6d243aef0b989c2483221f0e9c3234719273438dca33b97269435047f441ae104903fafaa051267ab34ba469449511a8e40fc5444a01e03cfe651"
|
||||
},
|
||||
{
|
||||
"digest": "rmd160",
|
||||
"hash": "58262d1fbdbe4530d8865d3518c6d6e41002610f",
|
||||
"signature": "31b25b680d0df8cb27df71c38fe7931a185c056b98c072a4f4956d6105a44ed53d7e457d366074cc26cd1cd0c226cf0cac509264f42651c208eb73f29f48dc2022009595e4ccf97662cf2840d69987f51118e9854fd10497a9e1dcb2ef390c9d09767f7d801aa2dd3d5c0e51249a195769593696725ba81e9a6c961a4b2c13827c467ccafa76f0ea5a9f43b936f3b35a8c316f116e0ac0d6f56ed8c0189d28ea1dc3a56b97a75c8f5c5cdc1682a76b5d852dd7282371ecb379abf0864eff0c437fca813d0ddc1ce34e8327a604336eeab6d907edf39e0303f0b8a45e0721e15d85c8c329047920b1ec8863bc6c0b172a57a6bb3611edb1f5c4d49aa1089cb5fd",
|
||||
"pkdf2": "2473b58bc86761bd5e8d35153475d44e8ba2dd4a156d6e69d79cbc33244f35bfea27bb3122354d98dbd792c679d8994f10a8eaf7c946e6a65566413a13060386",
|
||||
"hkdf": "c7d8a2fe1ae6d243aef0b989c2483221f0e9c3234719273438dca33b97269435047f441ae104903fafaa051267ab34ba469449511a8e40fc5444a01e03cfe651"
|
||||
},
|
||||
{
|
||||
"digest": "sha1",
|
||||
"hash": "943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "80174b0678707d38335940a010bd6acc1a6ade2c911251d013875816eb4c5169d9d4cb2ac9f6ce4b29b92f5750f185a273abd7c8a2434a9d1a50df5311999655d2a535c77b79997ed34fe51a863c450251d1b85bbb4dd10da1162e6e74194af606579a8724e55b93bded2d10216bb63cf00e848ceea6cdba78eab4f735ca620b36fdfd19bf15706df860a4c589160ce3c32aa51c27561de82a00cdcca709045cb8622adb6f759eb5e0f2f3f6056ca1b1a91206712ce92f5684d64931bc001bec7d2e8d2469f0818106070698160e9e21404971ea45940797fa3a61a39a25b7c6c75986accd4832db50a25ef3fceca629e104e2f03affd83b94cf074614e11c18",
|
||||
"pkdf2": "e77df42e685bd1fe2e19e374e1dd8470df71182311e048a6a280f36ef24c661e46fe8e8cc763942615934a631ac3aeda24bb9fda71e04f89f0c85f2f762abd98",
|
||||
"hkdf": "936c59e9394b5b1fdc26bd2eec0dc8c8d52fb97198e021805f0ae58c3f8b631d0020002b1ce0df9d890377fcc808166c906f128d06d77d404061d56560f3340d"
|
||||
},
|
||||
{
|
||||
"digest": "sha1WithRSAEncryption",
|
||||
"hash": "943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "80174b0678707d38335940a010bd6acc1a6ade2c911251d013875816eb4c5169d9d4cb2ac9f6ce4b29b92f5750f185a273abd7c8a2434a9d1a50df5311999655d2a535c77b79997ed34fe51a863c450251d1b85bbb4dd10da1162e6e74194af606579a8724e55b93bded2d10216bb63cf00e848ceea6cdba78eab4f735ca620b36fdfd19bf15706df860a4c589160ce3c32aa51c27561de82a00cdcca709045cb8622adb6f759eb5e0f2f3f6056ca1b1a91206712ce92f5684d64931bc001bec7d2e8d2469f0818106070698160e9e21404971ea45940797fa3a61a39a25b7c6c75986accd4832db50a25ef3fceca629e104e2f03affd83b94cf074614e11c18",
|
||||
"pkdf2": "e77df42e685bd1fe2e19e374e1dd8470df71182311e048a6a280f36ef24c661e46fe8e8cc763942615934a631ac3aeda24bb9fda71e04f89f0c85f2f762abd98",
|
||||
"hkdf": "936c59e9394b5b1fdc26bd2eec0dc8c8d52fb97198e021805f0ae58c3f8b631d0020002b1ce0df9d890377fcc808166c906f128d06d77d404061d56560f3340d"
|
||||
},
|
||||
{
|
||||
"digest": "sha224",
|
||||
"hash": "8552d8b7a7dc5476cb9e25dee69a8091290764b7f2a64fe6e78e9568",
|
||||
"signature": "70a8b455d63d2af5b12b0eefcb50ae245dcac054a74fd8a5beccca5ed12fd545e4dcdf2da3455f49e5eaf559772dc885ae24fd9e42790a1e175ec221a22329f2cc67d5c8ad1f9377fa1d713cb0d554f8335325a6080c272c10fb59f5fb7da9b39dcc76a50b49ed5f28d8cdd0499fbf5a19cae4b5b4a4a103201933a0e94e5532c6aaf05fbb060a3be5dcd5addef23b80651c51831ee479142cb1ddac0a37c6251f6eceee55217fcced2462fb7bef3e3aeeda98672598dc6aca6a49fb2df1b3f0ac569b666afeb8ca3f5b1bfa0bcca49f5fe6d3784fba1bb931077633d5a0a731c2bb22a820c8497ac1db888bd542f73ba2358d3a9bc056a7eca2f3a78b437820",
|
||||
"pkdf2": "d3adee1df932bac56eecdba710702025678d6e024d315c925ae274a3796c474219291983a76f2b8bd67aad26fbebcf5bb5088c99b6124ae1b9c7c9b2eb37c8f4",
|
||||
"hkdf": "1c3a0bd11a8c71c010353b075474aa2a6740f5cade0fff895019e08ebdaa68f8dfc4e74a5e013e2e9e0ab6852884311c1dac89432d34b2f762113ebf9a37597a"
|
||||
},
|
||||
{
|
||||
"digest": "sha224WithRSAEncryption",
|
||||
"hash": "8552d8b7a7dc5476cb9e25dee69a8091290764b7f2a64fe6e78e9568",
|
||||
"signature": "70a8b455d63d2af5b12b0eefcb50ae245dcac054a74fd8a5beccca5ed12fd545e4dcdf2da3455f49e5eaf559772dc885ae24fd9e42790a1e175ec221a22329f2cc67d5c8ad1f9377fa1d713cb0d554f8335325a6080c272c10fb59f5fb7da9b39dcc76a50b49ed5f28d8cdd0499fbf5a19cae4b5b4a4a103201933a0e94e5532c6aaf05fbb060a3be5dcd5addef23b80651c51831ee479142cb1ddac0a37c6251f6eceee55217fcced2462fb7bef3e3aeeda98672598dc6aca6a49fb2df1b3f0ac569b666afeb8ca3f5b1bfa0bcca49f5fe6d3784fba1bb931077633d5a0a731c2bb22a820c8497ac1db888bd542f73ba2358d3a9bc056a7eca2f3a78b437820",
|
||||
"pkdf2": "d3adee1df932bac56eecdba710702025678d6e024d315c925ae274a3796c474219291983a76f2b8bd67aad26fbebcf5bb5088c99b6124ae1b9c7c9b2eb37c8f4",
|
||||
"hkdf": "1c3a0bd11a8c71c010353b075474aa2a6740f5cade0fff895019e08ebdaa68f8dfc4e74a5e013e2e9e0ab6852884311c1dac89432d34b2f762113ebf9a37597a"
|
||||
},
|
||||
{
|
||||
"digest": "sha256",
|
||||
"hash": "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3",
|
||||
"signature": "67b67a87fc4a576342fc46167395a255654dddc5036e8a7d323acf862470e0612b90b1abf22166e3d124d4866e82146b5735fb85895355d027efdcb406a8cb87c8f00aea128e74cb95ca8a69cb970e3f02a11a6911253f9fba54ae7b75d7f1f29d51338d43f4ed59a36e3b7e408591cd9feaa818f1b0c6df6155cc89cc95c6686ce82a78fd8d34e82d9047ce936c3a67ac85d2924083610d6db5040409f09a46f97d35248b5451ca51be6cfbc9f94ff630eb8ff95e114a666cc1cc011af03d77f9b24f8add5244a83e0784dbcf785ebcfcd015b876963666b113dc26f0222aa95fdfbe1e64ac6b48780e1ff69b2588ff4bce9b15f9d53abba96b813a3d657cbe",
|
||||
"pkdf2": "a8a2a7dcf7b65c8498ab1fbc62d56fa47255d668c1c3f21c5b236259d1dd8b11859026e737216cceb7a8facb8d27656f2b990db98786f12a8ce68e56a30f0c0b",
|
||||
"hkdf": "a35a5ba99add2c508b9014ca7eb7d461a85989257b29a46a0041361c85b2c48838199873987b5419ede395aa09129bcb5fbd607b8b769e6711e1fea5e0ebcbc0"
|
||||
},
|
||||
{
|
||||
"digest": "sha256WithRSAEncryption",
|
||||
"hash": "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3",
|
||||
"signature": "67b67a87fc4a576342fc46167395a255654dddc5036e8a7d323acf862470e0612b90b1abf22166e3d124d4866e82146b5735fb85895355d027efdcb406a8cb87c8f00aea128e74cb95ca8a69cb970e3f02a11a6911253f9fba54ae7b75d7f1f29d51338d43f4ed59a36e3b7e408591cd9feaa818f1b0c6df6155cc89cc95c6686ce82a78fd8d34e82d9047ce936c3a67ac85d2924083610d6db5040409f09a46f97d35248b5451ca51be6cfbc9f94ff630eb8ff95e114a666cc1cc011af03d77f9b24f8add5244a83e0784dbcf785ebcfcd015b876963666b113dc26f0222aa95fdfbe1e64ac6b48780e1ff69b2588ff4bce9b15f9d53abba96b813a3d657cbe",
|
||||
"pkdf2": "a8a2a7dcf7b65c8498ab1fbc62d56fa47255d668c1c3f21c5b236259d1dd8b11859026e737216cceb7a8facb8d27656f2b990db98786f12a8ce68e56a30f0c0b",
|
||||
"hkdf": "a35a5ba99add2c508b9014ca7eb7d461a85989257b29a46a0041361c85b2c48838199873987b5419ede395aa09129bcb5fbd607b8b769e6711e1fea5e0ebcbc0"
|
||||
},
|
||||
{
|
||||
"digest": "sha3-224",
|
||||
"hash": "6a33e22f20f16642697e8bd549ff7b759252ad56c05a1b0acc31dc69",
|
||||
"signature": "2504c7a4735c251aa01644ae56a9f7c891f45e9fb6e25fea1c25074139dcab114e77d64ae7788bcbd8d5d452db60b47e6a0b324b0e3482ff794581da0cbe960a97ba75c1023eab2320fa9022ae715b5aa2fe1186916fb9a1c931d9f28ba8e12a4dd145efff6abfcfb68eca6536655c96cf059df406d5c51d1814b2f61c6bdc10a2b083d29f50a064bc6ffdddf5cb45df2577a7149a430e1314f87427972d8bb4775bd92e99a2298095cb83e60e50f503aab6d9fd41398b55d5dcfa6022049891561e6395a7a3e56a1d92a8667733a68d9b0374952d95e4d5a51b0b22d390cf579bb536e59cea8272b2d5749fa70d48c396b6ba94188ce677beb8f00937640096",
|
||||
"pkdf2": "014d30aa9d1c1d8e3920f4bcc399f37b16d6c346d570d4345229d64ab95e504b1c6b253133c218a2b46f29aa0f9792d7ad60761159cc3550cb9a0914bfdc9951",
|
||||
"hkdf": "b6c671ec02ee7f215dcee9ecade623831658470156f3edab205b7e3a70587f3c538eac8ec92e3a5bf6808b9b939d84e4f8ba5ee3532d7adb152211cc8f79cf9b"
|
||||
},
|
||||
{
|
||||
"digest": "sha3-256",
|
||||
"hash": "f345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722",
|
||||
"signature": "b3b475d03da73b4bf8fefa5f49231dfd8f95605e0c3ea058d4607f1274ddcf4f69b1751df8493df1c5fe31883aff197688de1991885bb9ed4266f7df0db4fc99b33bee32a9237a9c2714e461fefb311923c1e91fe7cbe1830206bb0b3d962bfccdf5c37e8ce9e01f203851e34f22162175f44048002483ff2e3ffc658506a23f358f3192dbba759a8e1f66d3abf934b72295f1b51f8a92c837c76006084b65c0df8e072e43b1122bb15b3043dceb026e2cf311d04d6f4a3506e7e5b8a08fcaa0caeaa18a6397d185e5b5d1bc962f22b80db798a42fa206cd2db53b02bc5e2e69d9566f1ff3fccb4690545ff19424001cf3c0504c53adc0f2ce4354596b8a4d69",
|
||||
"pkdf2": "4ba48814e191c34c9d38f5ccf6c5cf1a61082c2f8b36e99bd8210781af995734f62c6a714ad6639ecb55224d91b2ac7d69030335d2c367d833823814ef9f2213",
|
||||
"hkdf": "e60f1e8214b7907d63d8cfb2bfb083051d3c9a56e4f94aabc1ff3543986aac5d4823db903090af81824964d6ca39da8388495e8838a9c0c407cb3546f44f9a04"
|
||||
},
|
||||
{
|
||||
"digest": "sha3-384",
|
||||
"hash": "6ba9ea268965916f5937228dde678c202f9fe756a87d8b1b7362869583a45901fd1a27289d72fc0e3ff48b1b78827d3a",
|
||||
"signature": "256542ac61773cec2261fbc8cde4d6524e7a91f9fefcc08792c7c4b27fb843d099a5fce9819503949ad8fde307a7fc4185754dc5ed3d473da065376e4a9c804265dc4ff858a774d6eb19e663a26339d087a3e96b8f9133becc0ee2b404cfcfca58ffadbd48a5c31dced92f188b40bd179efdf9ae5394d0e02b513958f46adbdf745e8dada0dd97e38bf28bf7ad87aeb6771a40e3fef5f35161d4eeafe7b6ba1c2101388a22e75586fab599cbc070bf4d0fbe8304a7c579a34ce0000c87b33882c2d86ff11dbc218604fa7e7203e4efaa6e9605ae41958c0c2de0b7d76da9a6e606b3c38d29dad55675f9f138b11afc96e71ba5e41924bc5c676db777aed7ea04",
|
||||
"pkdf2": "f609fda1c21cf4e59e7142438f2e04bb29f72010d49546e1c192755c6af3b97903da8483be8356afb865ffc334d23fa2439063c287ec9491618bfb5f791675f4",
|
||||
"hkdf": "818ae5bc92cf582db87d73316e1a0649b457dfcd198db3e4edb1c6b20515dcf14f8758951765d9e2b4f7914a75ea04815e82050a6ca602c1a76f6c9999813955"
|
||||
},
|
||||
{
|
||||
"digest": "sha3-512",
|
||||
"hash": "8e47f1185ffd014d238fabd02a1a32defe698cbf38c037a90e3c0a0a32370fb52cbd641250508502295fcabcbf676c09470b27443868c8e5f70e26dc337288af",
|
||||
"signature": "925bd1da0c91caba58c0a407f4f63e9b16f52444c3b71476f4043ee00ef97bb428a396e8a45d75b3204142d2e18886f36b0b0a1c6d25d80b010e4063ffb310741907e3217badadaf53d018100d78eace2e941c0ec2b6f9b47ceee455d55bfb1711b1255ae1fa0d8fb5bf869009c1b558b02fd4cabd83c55a76a1d96bdb4cdbb42f6ad1f36984c39e6c6fe4edc3a771766742ec461d29e8a93704a48323c0c0f9cc066bf1daeb4e83aa3aa7a3c2067495cf320a9e98b7f1db638a23fc135992fcc3bbfb52be115c35b055cdbf4733c30098674ff19f1ef218a4643b0e2ecb7c0597a406b304b67a36eed0300313a65a4af5621ef59a5ffe53e7d6763a83e0014a",
|
||||
"pkdf2": "e1f0b454bf5d729fbb13e534229521a87aee130078555791d83834a8c51fb681ce4dfe02afd5f063082d8abba0b456084c677aeb6f8e0d70305322ec2ea97203",
|
||||
"hkdf": "f27d87f9f6b87718073c8d2ad6bae00b4162cecde350c856252dd611120c433373a0c0d3946a8582bf855bf581439a14ca4f355fcd18881331f4a3b1027e84b2"
|
||||
},
|
||||
{
|
||||
"digest": "sha384",
|
||||
"hash": "55bc556b0d2fe0fce582ba5fe07baafff035653638c7ac0d5494c2a64c0bea1cc57331c7c12a45cdbca7f4c34a089eeb",
|
||||
"signature": "77d465006b8843cf30c5e93b7d3f63b0daf2df1d693c4e1c0f9c759ec8410c088f331c5bf89bca7218edd1bdf3f2d948c9be9656f44a630748395429a09289acb05be80b0d000bacd7826c33a584dcbcf658839015d07561668e882bad4505c475a04766a7eabb35b15b8b54d6fcf9ebdd25b699f0d88906ba2999de1e8e59cc75969bc819fd514b1002a6667a03c861fafee03cccb9fd926352139dc1a916ba56b36e9e69fd328cb2403b9f747350721261158021df9ab2a75a7c5a3e39b42f3722ea1997a039ecc033f64366974336dbfd3294820400fe623d2993593c51f4398290a51bf05dc452c5991e26e8971be759472635e86b08230d04d05bce88f4",
|
||||
"pkdf2": "b2e2b9e03d9e6f5218b74be7002c8704558feae855272ab3a973ee7deb387c26483f87fb6463bc5768406b398896a29ac2d17bd45afccf369a403ffa396bb455",
|
||||
"hkdf": "54aef7f7256a147e52d67888a4543c6084b4ac46cd7bf919576bf8c4e9dad6b8a1fc9ad9c6f90f2af8e76d8d815ae2226d67a11ccb524a0c0be3cc858f4ddb10"
|
||||
},
|
||||
{
|
||||
"digest": "sha384WithRSAEncryption",
|
||||
"hash": "55bc556b0d2fe0fce582ba5fe07baafff035653638c7ac0d5494c2a64c0bea1cc57331c7c12a45cdbca7f4c34a089eeb",
|
||||
"signature": "77d465006b8843cf30c5e93b7d3f63b0daf2df1d693c4e1c0f9c759ec8410c088f331c5bf89bca7218edd1bdf3f2d948c9be9656f44a630748395429a09289acb05be80b0d000bacd7826c33a584dcbcf658839015d07561668e882bad4505c475a04766a7eabb35b15b8b54d6fcf9ebdd25b699f0d88906ba2999de1e8e59cc75969bc819fd514b1002a6667a03c861fafee03cccb9fd926352139dc1a916ba56b36e9e69fd328cb2403b9f747350721261158021df9ab2a75a7c5a3e39b42f3722ea1997a039ecc033f64366974336dbfd3294820400fe623d2993593c51f4398290a51bf05dc452c5991e26e8971be759472635e86b08230d04d05bce88f4",
|
||||
"pkdf2": "b2e2b9e03d9e6f5218b74be7002c8704558feae855272ab3a973ee7deb387c26483f87fb6463bc5768406b398896a29ac2d17bd45afccf369a403ffa396bb455",
|
||||
"hkdf": "54aef7f7256a147e52d67888a4543c6084b4ac46cd7bf919576bf8c4e9dad6b8a1fc9ad9c6f90f2af8e76d8d815ae2226d67a11ccb524a0c0be3cc858f4ddb10"
|
||||
},
|
||||
{
|
||||
"digest": "sha512",
|
||||
"hash": "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421",
|
||||
"signature": "50e2973977e1be1218134a1f50732a8f54c4b0dfb836be816c304edce9bef4b1be566a295b05c6c82de00eb915bc61ca4bab073a13061987ca19af280202a4c6c496cf6262655e6a6f1a53f923ca048b4bc21e31282edd239cec8840b2411c1aa2abe5b9bf7de5066f43f6e2e0a0691ac6f2fc71ed679ae644b6d799261ed694dc9e27c81142ffb88883440ee92a6086d7c3d62572eac13480034219a9edbda7e5556f335bbe1a37ef0df26ae3ffe99b968d40a93d9ca9a3c76025409b5da041242afa977a5a0438be946562a48a764dc6d4c924fec82590e01b807d410a432b95ee2e5173d245a565cdecdc321521d6f61e965628013181bc7a9462a450d895",
|
||||
"pkdf2": "284f17da4e32b7b4780b31f94405e115ca7e6ae025b05d8398f421c3a3f36d903a1fae9471674342bec7d51c6f32996df0c843a20105c8451e9cd17ecbddb3ed",
|
||||
"hkdf": "cf181757f66abf44c88cd3d4ad0ed99b82cf47a8a6f870ff1561a12da7af03251590250af7473a1a3c5c5e794f29c44e8f25f69fb7985258161e74b433510262"
|
||||
},
|
||||
{
|
||||
"digest": "sha512-224",
|
||||
"hash": "32620068b859669b45b31008e08b7384649ad2ca3f5163a3a71e5745",
|
||||
"signature": "b5d1ec54de69d29dbc77595fec62bb16019b7cc275ead04338c17ee4b759fcb8443477e1708d45374b786acfeb616c1078d199b2a28d76f46d4b74a498c2bfb2b174632da895cae5558f36101f0596adb40152ac09b49f1726f293237bcf604ab7bf461c7e2dd78c909d7503ec4132722551842f7e8ef54317f4b58784c447fd68067c689c288c8401dc95276356e1396a127eac82a0bd0753cc4c00718e7240d523af95a1cd960885da64172e3325a225557f96e6307340dd45a499ac20af01a2e3e7a4be706a40249c6ce7e24dabdcbd577744c34cf8e182d9a7923c52cd508a0e39125003a0c74ac714f5c892187c6fc7417d552127b3c24c57e484212ab6",
|
||||
"pkdf2": "69e623258a79c04b84aabc9333b17fc8a5ee8d7ebd06dd80236865584ccc98fce3180319f74748f6a6c2b44833425a6ab52e8ab22db62365799f14727102485d",
|
||||
"hkdf": "c155ac0b2833f309322f258625df2c9926570fabbe66eff9713b977291054b57b8cd3280079613d8167a99f259087422cff9756780148bf683c1d5c03e015907"
|
||||
},
|
||||
{
|
||||
"digest": "sha512-224WithRSAEncryption",
|
||||
"hash": "32620068b859669b45b31008e08b7384649ad2ca3f5163a3a71e5745",
|
||||
"signature": "b5d1ec54de69d29dbc77595fec62bb16019b7cc275ead04338c17ee4b759fcb8443477e1708d45374b786acfeb616c1078d199b2a28d76f46d4b74a498c2bfb2b174632da895cae5558f36101f0596adb40152ac09b49f1726f293237bcf604ab7bf461c7e2dd78c909d7503ec4132722551842f7e8ef54317f4b58784c447fd68067c689c288c8401dc95276356e1396a127eac82a0bd0753cc4c00718e7240d523af95a1cd960885da64172e3325a225557f96e6307340dd45a499ac20af01a2e3e7a4be706a40249c6ce7e24dabdcbd577744c34cf8e182d9a7923c52cd508a0e39125003a0c74ac714f5c892187c6fc7417d552127b3c24c57e484212ab6",
|
||||
"pkdf2": "69e623258a79c04b84aabc9333b17fc8a5ee8d7ebd06dd80236865584ccc98fce3180319f74748f6a6c2b44833425a6ab52e8ab22db62365799f14727102485d",
|
||||
"hkdf": "c155ac0b2833f309322f258625df2c9926570fabbe66eff9713b977291054b57b8cd3280079613d8167a99f259087422cff9756780148bf683c1d5c03e015907"
|
||||
},
|
||||
{
|
||||
"digest": "sha512-256",
|
||||
"hash": "330c723f25267587db0b9f493463e017011239169cb57a6db216c63774367115",
|
||||
"signature": "6313742057ecbf4f54476799b018d1e18c2db920ef23386208f1e23e5af30d38edc0d11f1220e2cc0f898cd3e4cd9d4920fed30ff9f725404d4750f230fe9dafdfde95280a8713043359a09d45fbda484c469e61ae4fd615d616e76f6daa27acd3542d823e88f2dfd943b39f38884f9ed4695b8f004b4c67777de63474fe9dbbfeab966113907663f14c7822658aab70dceb7d1a6ed9842085762ab100ee915941295a045b29ef09af19eab58c79d3e5ffcbda61e2be35770c1d3b55156357c3cca806309b1ddc7e52f47e245d1d49237f0aa7156e89c76a17780a62fa552eeb7b623410e387d0a9412d4688725ed8df0a86e8b548ea6bb785ea48b6c0e39332",
|
||||
"pkdf2": "c3d18f17c825a1630bc10695bfd4faa0309e862d010c0b74fb41b6ce5e46853cc435560a1b9cd940254103068aebc1f24d2580385b1890e7f10356ef4c8f507d",
|
||||
"hkdf": "8451f1238da8577794ecc9b75832cabff44f279e5f8258cbf553c21f9735c19c7974e9a74879b4c59386116bb1a4bb50f149c9a4146b10de312fa679c1343b80"
|
||||
},
|
||||
{
|
||||
"digest": "sha512-256WithRSAEncryption",
|
||||
"hash": "330c723f25267587db0b9f493463e017011239169cb57a6db216c63774367115",
|
||||
"signature": "6313742057ecbf4f54476799b018d1e18c2db920ef23386208f1e23e5af30d38edc0d11f1220e2cc0f898cd3e4cd9d4920fed30ff9f725404d4750f230fe9dafdfde95280a8713043359a09d45fbda484c469e61ae4fd615d616e76f6daa27acd3542d823e88f2dfd943b39f38884f9ed4695b8f004b4c67777de63474fe9dbbfeab966113907663f14c7822658aab70dceb7d1a6ed9842085762ab100ee915941295a045b29ef09af19eab58c79d3e5ffcbda61e2be35770c1d3b55156357c3cca806309b1ddc7e52f47e245d1d49237f0aa7156e89c76a17780a62fa552eeb7b623410e387d0a9412d4688725ed8df0a86e8b548ea6bb785ea48b6c0e39332",
|
||||
"pkdf2": "c3d18f17c825a1630bc10695bfd4faa0309e862d010c0b74fb41b6ce5e46853cc435560a1b9cd940254103068aebc1f24d2580385b1890e7f10356ef4c8f507d",
|
||||
"hkdf": "8451f1238da8577794ecc9b75832cabff44f279e5f8258cbf553c21f9735c19c7974e9a74879b4c59386116bb1a4bb50f149c9a4146b10de312fa679c1343b80"
|
||||
},
|
||||
{
|
||||
"digest": "sha512WithRSAEncryption",
|
||||
"hash": "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421",
|
||||
"signature": "50e2973977e1be1218134a1f50732a8f54c4b0dfb836be816c304edce9bef4b1be566a295b05c6c82de00eb915bc61ca4bab073a13061987ca19af280202a4c6c496cf6262655e6a6f1a53f923ca048b4bc21e31282edd239cec8840b2411c1aa2abe5b9bf7de5066f43f6e2e0a0691ac6f2fc71ed679ae644b6d799261ed694dc9e27c81142ffb88883440ee92a6086d7c3d62572eac13480034219a9edbda7e5556f335bbe1a37ef0df26ae3ffe99b968d40a93d9ca9a3c76025409b5da041242afa977a5a0438be946562a48a764dc6d4c924fec82590e01b807d410a432b95ee2e5173d245a565cdecdc321521d6f61e965628013181bc7a9462a450d895",
|
||||
"pkdf2": "284f17da4e32b7b4780b31f94405e115ca7e6ae025b05d8398f421c3a3f36d903a1fae9471674342bec7d51c6f32996df0c843a20105c8451e9cd17ecbddb3ed",
|
||||
"hkdf": "cf181757f66abf44c88cd3d4ad0ed99b82cf47a8a6f870ff1561a12da7af03251590250af7473a1a3c5c5e794f29c44e8f25f69fb7985258161e74b433510262"
|
||||
},
|
||||
{
|
||||
"digest": "shake128",
|
||||
"hash": "b5ffd113fa127f4d9c7e483cb52264ed",
|
||||
"signature": null,
|
||||
"pkdf2": null,
|
||||
"hkdf": null
|
||||
},
|
||||
{
|
||||
"digest": "shake256",
|
||||
"hash": "cf68a0d388047ed588ad72d3808cf9a3243f04d4901748c705fbf3a27d955542",
|
||||
"signature": null,
|
||||
"pkdf2": null,
|
||||
"hkdf": null
|
||||
},
|
||||
{
|
||||
"digest": "sm3",
|
||||
"hash": "e3bca101b496880c3653dad85861d0e784b00a8c18f7574472d156060e9096bf",
|
||||
"signature": null,
|
||||
"pkdf2": "70b3d2ac3b82dd7b8c35db45f99f49e029be2b6f1ef9ce1d9137267b729c06f7099dc7f571f2b05dbe5172118a7ae787cd4836fbf9ddce9aacc933c7c4e5537b",
|
||||
"hkdf": "88b773032a2f131b1aa4ebdb69fdde7c42281b7c689bfe1f5bd43c7e1a6f555f101657c3f83ccd5918b4c6a8df04d0b58ebf77ec2181f8c5e7cfecb6f13fba61"
|
||||
},
|
||||
{
|
||||
"digest": "sm3WithRSAEncryption",
|
||||
"hash": "e3bca101b496880c3653dad85861d0e784b00a8c18f7574472d156060e9096bf",
|
||||
"signature": null,
|
||||
"pkdf2": "70b3d2ac3b82dd7b8c35db45f99f49e029be2b6f1ef9ce1d9137267b729c06f7099dc7f571f2b05dbe5172118a7ae787cd4836fbf9ddce9aacc933c7c4e5537b",
|
||||
"hkdf": "88b773032a2f131b1aa4ebdb69fdde7c42281b7c689bfe1f5bd43c7e1a6f555f101657c3f83ccd5918b4c6a8df04d0b58ebf77ec2181f8c5e7cfecb6f13fba61"
|
||||
},
|
||||
{
|
||||
"digest": "ssl3-md5",
|
||||
"hash": "6cd3556deb0da54bca060b4c39479839",
|
||||
"signature": "45f2e7ac7c0d323c18e9c8554d15e21a8fb72944928e0b7acc2185402448c39af05340391ee9aac64c45a947bc3ed801de8791aaa5788a62e909d7c8d92e63c7f119753219a48c29ea78e371d3a89c0bd64d756b829fa6faaa8fa46bc28228dd4430aca845c02f3b6b835b140247838ac5b96434d1049115785f3f52034e0cc46f6cafc5f2921b9928403aea1edd85f3a99e12324abeeaaaa040b320f8af157c5df7fd7479415771fd116daed933b43eac51b3c274ba9283aaf3f1b6f1f527a0cea76f9a43dca3b9ff03834feed13a0fd488e6750a9d46ddb1ad69ac88090af050458eeafd1e9fa317c4ecc61d90289d5378e6e3693ef6da2e4a4803b6108145",
|
||||
"pkdf2": "3083f052ca2e90daf96a87b8b8c1daa069bff60c73045c9504d3b424807b5410a724ea5ba28b9bccb6bad59c0e181663b07156a59b09cee85ffe223f21ff6db6",
|
||||
"hkdf": "f516674e1b1faf2c1a505041634460d94739e2e39be4e6a097f926f5cc9788c09892efcb407019dc469c4014c8d847cf4c5a6eeefccf8e5266ca3dd02ea57529"
|
||||
},
|
||||
{
|
||||
"digest": "ssl3-sha1",
|
||||
"hash": "943a702d06f34599aee1f8da8ef9f7296031d699",
|
||||
"signature": "80174b0678707d38335940a010bd6acc1a6ade2c911251d013875816eb4c5169d9d4cb2ac9f6ce4b29b92f5750f185a273abd7c8a2434a9d1a50df5311999655d2a535c77b79997ed34fe51a863c450251d1b85bbb4dd10da1162e6e74194af606579a8724e55b93bded2d10216bb63cf00e848ceea6cdba78eab4f735ca620b36fdfd19bf15706df860a4c589160ce3c32aa51c27561de82a00cdcca709045cb8622adb6f759eb5e0f2f3f6056ca1b1a91206712ce92f5684d64931bc001bec7d2e8d2469f0818106070698160e9e21404971ea45940797fa3a61a39a25b7c6c75986accd4832db50a25ef3fceca629e104e2f03affd83b94cf074614e11c18",
|
||||
"pkdf2": "e77df42e685bd1fe2e19e374e1dd8470df71182311e048a6a280f36ef24c661e46fe8e8cc763942615934a631ac3aeda24bb9fda71e04f89f0c85f2f762abd98",
|
||||
"hkdf": "936c59e9394b5b1fdc26bd2eec0dc8c8d52fb97198e021805f0ae58c3f8b631d0020002b1ce0df9d890377fcc808166c906f128d06d77d404061d56560f3340d"
|
||||
}
|
||||
]
|
Loading…
Add table
Reference in a new issue