Add full XCA curve and digest parity
This commit is contained in:
@@ -4,6 +4,10 @@ use sycamore::prelude::*;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
|
||||
use crate::api;
|
||||
use crate::components::crypto::{
|
||||
add_key_parameters, apply_signature_hash, key_parameter_input, key_type_select,
|
||||
signature_hash_input,
|
||||
};
|
||||
use crate::components::extension_form::{
|
||||
build_extra_extensions, extension_fields, load_extra_extensions, ExtensionSignals,
|
||||
};
|
||||
@@ -14,7 +18,7 @@ use crate::components::list_editor::{
|
||||
use crate::components::nav::{app_nav, whoami};
|
||||
use crate::components::ui::{page_header, toast_error};
|
||||
use crate::model::{
|
||||
CertificateDetail, CertificateSummary, DnAttribute, KeySummary, Me, TemplateSummary,
|
||||
CertificateDetail, CertificateSummary, DnAttribute, KeySummary, Me, OptionsPage, TemplateSummary,
|
||||
};
|
||||
|
||||
const DEFAULT_EXPLICIT_DN: [&str; 7] = ["C", "ST", "L", "O", "OU", "CN", "emailAddress"];
|
||||
@@ -73,6 +77,7 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
let reactive_root = use_global_scope();
|
||||
let id: &'static str = Box::leak(vault_id.clone().into_boxed_str());
|
||||
let me = create_signal(None::<Me>);
|
||||
let options = create_signal(None::<OptionsPage>);
|
||||
let keys = create_signal(Vec::<KeySummary>::new());
|
||||
let signers = create_signal(Vec::<CertificateSummary>::new());
|
||||
let templates = create_signal(Vec::<TemplateSummary>::new());
|
||||
@@ -82,6 +87,7 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
let request_id = query_param("request").unwrap_or_default();
|
||||
let request_mode = !request_id.is_empty();
|
||||
let request_id_for_load = request_id.clone();
|
||||
let request_key_id = create_signal(String::new());
|
||||
|
||||
let name = create_signal(String::new());
|
||||
let comment = create_signal(String::new());
|
||||
@@ -90,6 +96,7 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
let new_key = create_signal(false);
|
||||
let key_type = create_signal("rsa".to_string());
|
||||
let key_size = create_signal("2048".to_string());
|
||||
let curve = create_signal("secp256r1".to_string());
|
||||
let template_id = create_signal(String::new());
|
||||
let template_apply_mode = create_signal("all".to_string());
|
||||
let ca_default_template = create_signal(None::<String>);
|
||||
@@ -256,6 +263,9 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
if let Some(size) = key.get("size").and_then(|v| v.as_i64()) {
|
||||
key_size.set(size.to_string());
|
||||
}
|
||||
if let Some(value) = key.get("curve").and_then(|v| v.as_str()) {
|
||||
curve.set(value.to_string());
|
||||
}
|
||||
}
|
||||
if let Some(items) = settings.get("explicit_dn").and_then(|v| v.as_array()) {
|
||||
let names = items
|
||||
@@ -277,8 +287,9 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(options) = api::options(&id).await {
|
||||
dn_attributes.set(options.dn_attributes);
|
||||
if let Ok(page) = api::options(id).await {
|
||||
dn_attributes.set(page.dn_attributes.clone());
|
||||
options.set(Some(page));
|
||||
}
|
||||
if !request_mode {
|
||||
if let Some(cert_id) = from_cert.clone() {
|
||||
@@ -311,6 +322,7 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
if request_mode {
|
||||
if let Ok(value) = api::request(&id, &request_id_for_load).await {
|
||||
name.set(format!("{} certificate", value.summary.name));
|
||||
request_key_id.set(value.summary.key_id.clone().unwrap_or_default());
|
||||
let subject_json =
|
||||
serde_json::to_value(&value.subject_entries).unwrap_or(json!([]));
|
||||
reactive_root.run_in(|| apply_subject_json(&form, &subject_json));
|
||||
@@ -318,6 +330,34 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
}
|
||||
});
|
||||
|
||||
let signing_key_type = move || {
|
||||
let keys = keys.get_clone();
|
||||
let signer = signer_id.get_clone();
|
||||
if signer != "self" {
|
||||
let issuer_key_id = signers
|
||||
.get_clone()
|
||||
.into_iter()
|
||||
.find(|cert| cert.id == signer)
|
||||
.and_then(|cert| cert.key_id);
|
||||
return issuer_key_id.and_then(|key_id| {
|
||||
keys.into_iter()
|
||||
.find(|key| key.id == key_id)
|
||||
.map(|key| key.key_type)
|
||||
});
|
||||
}
|
||||
if !request_mode && new_key.get() {
|
||||
return Some(key_type.get_clone());
|
||||
}
|
||||
let subject_key_id = if request_mode {
|
||||
request_key_id.get_clone()
|
||||
} else {
|
||||
key_id.get_clone()
|
||||
};
|
||||
keys.into_iter()
|
||||
.find(|key| key.id == subject_key_id)
|
||||
.map(|key| key.key_type)
|
||||
};
|
||||
|
||||
let apply_template_id = move |template: String, mode: String| {
|
||||
if template.is_empty() {
|
||||
return;
|
||||
@@ -430,10 +470,14 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
"comment": comment.get_clone(),
|
||||
"subject": subject,
|
||||
"extensions": extensions,
|
||||
"signature_hash": signature_hash.get_clone(),
|
||||
"signer_id": if signer == "self" { serde_json::Value::Null } else { json!(signer) },
|
||||
"validity": validity_value(&form),
|
||||
});
|
||||
apply_signature_hash(
|
||||
&mut payload,
|
||||
signing_key_type().as_deref(),
|
||||
&signature_hash.get_clone(),
|
||||
);
|
||||
if validity_mode.get_clone() == "absolute" && !no_expiration.get() {
|
||||
payload["not_before"] = json!(not_before_text.get_clone());
|
||||
payload["not_after"] = json!(not_after_text.get_clone());
|
||||
@@ -443,11 +487,17 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
payload["modify_subject"] = json!(true);
|
||||
payload["copy_request_extensions"] = json!(false);
|
||||
} else if new_key.get() {
|
||||
payload["new_key"] = json!({
|
||||
let mut generated_key = json!({
|
||||
"key_type": key_type.get_clone(),
|
||||
"size": key_size.get_clone().parse::<i64>().unwrap_or(2048),
|
||||
"name": format!("{} key", name.get_clone()),
|
||||
});
|
||||
add_key_parameters(
|
||||
&mut generated_key,
|
||||
&key_type.get_clone(),
|
||||
&key_size.get_clone(),
|
||||
&curve.get_clone(),
|
||||
);
|
||||
payload["new_key"] = generated_key;
|
||||
} else if !key_id.get_clone().is_empty() {
|
||||
payload["key_id"] = json!(key_id.get_clone());
|
||||
} else {
|
||||
@@ -494,15 +544,18 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
}
|
||||
};
|
||||
let signer = signer_id.get_clone();
|
||||
let payload = json!({
|
||||
let mut payload = json!({
|
||||
"name": if name.get_clone().is_empty() { "preview".to_string() } else { name.get_clone() },
|
||||
"subject": subject,
|
||||
"extensions": extensions,
|
||||
"signature_hash": signature_hash.get_clone(),
|
||||
"signer_id": if signer == "self" { serde_json::Value::Null } else { json!(signer) },
|
||||
"validity": validity_value(&form),
|
||||
});
|
||||
let mut payload = payload;
|
||||
apply_signature_hash(
|
||||
&mut payload,
|
||||
signing_key_type().as_deref(),
|
||||
&signature_hash.get_clone(),
|
||||
);
|
||||
if validity_mode.get_clone() == "absolute" && !no_expiration.get() {
|
||||
payload["not_before"] = json!(not_before_text.get_clone());
|
||||
payload["not_after"] = json!(not_after_text.get_clone());
|
||||
@@ -602,13 +655,12 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
}
|
||||
}
|
||||
div(class="col-md-6") {
|
||||
label(class="form-label") { "Signature hash" }
|
||||
select(class="form-select", bind:value=signature_hash) {
|
||||
option(value="sha256") { "SHA-256" }
|
||||
option(value="sha384") { "SHA-384" }
|
||||
option(value="sha512") { "SHA-512" }
|
||||
option(value="sha1") { "SHA-1" }
|
||||
}
|
||||
(signature_hash_input(
|
||||
"Signature hash",
|
||||
options,
|
||||
signing_key_type,
|
||||
signature_hash,
|
||||
))
|
||||
}
|
||||
div(class="col-md-6") {
|
||||
label(class="form-label") { "Template" }
|
||||
@@ -661,15 +713,10 @@ pub fn CertificateNewPage(vault_id: String, from_cert: Option<String>) -> View {
|
||||
div(class="row g-3") {
|
||||
div(class="col-md-4") {
|
||||
label(class="form-label") { "Key type" }
|
||||
select(class="form-select", bind:value=key_type) {
|
||||
option(value="rsa") { "RSA" }
|
||||
option(value="ec") { "EC" }
|
||||
option(value="ed25519") { "ED25519" }
|
||||
}
|
||||
(key_type_select(options, key_type))
|
||||
}
|
||||
div(class="col-md-4") {
|
||||
label(class="form-label") { "Key size" }
|
||||
input(class="form-control", bind:value=key_size)
|
||||
(key_parameter_input(options, key_type, key_size, curve))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user