Automatically derive the kid from the key fingerprint if missing (#4876)
This commit is contained in:
@@ -9,13 +9,9 @@ use std::borrow::Cow;
|
|||||||
use anyhow::{Context, bail};
|
use anyhow::{Context, bail};
|
||||||
use camino::Utf8PathBuf;
|
use camino::Utf8PathBuf;
|
||||||
use futures_util::future::{try_join, try_join_all};
|
use futures_util::future::{try_join, try_join_all};
|
||||||
use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
|
use mas_jose::jwk::{JsonWebKey, JsonWebKeySet, Thumbprint};
|
||||||
use mas_keystore::{Encrypter, Keystore, PrivateKey};
|
use mas_keystore::{Encrypter, Keystore, PrivateKey};
|
||||||
use rand::{
|
use rand::{Rng, SeedableRng, distributions::Standard, prelude::Distribution as _};
|
||||||
Rng, SeedableRng,
|
|
||||||
distributions::{Alphanumeric, DistString, Standard},
|
|
||||||
prelude::Distribution as _,
|
|
||||||
};
|
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
@@ -132,7 +128,11 @@ impl From<Key> for KeyRaw {
|
|||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct KeyConfig {
|
pub struct KeyConfig {
|
||||||
kid: String,
|
/// The key ID `kid` of the key as used by JWKs.
|
||||||
|
///
|
||||||
|
/// If not given, `kid` will be the key’s RFC 7638 JWK Thumbprint.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
kid: Option<String>,
|
||||||
|
|
||||||
#[schemars(with = "PasswordRaw")]
|
#[schemars(with = "PasswordRaw")]
|
||||||
#[serde_as(as = "serde_with::TryFromInto<PasswordRaw>")]
|
#[serde_as(as = "serde_with::TryFromInto<PasswordRaw>")]
|
||||||
@@ -178,8 +178,13 @@ impl KeyConfig {
|
|||||||
None => PrivateKey::load(&key)?,
|
None => PrivateKey::load(&key)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let kid = match self.kid.clone() {
|
||||||
|
Some(kid) => kid,
|
||||||
|
None => private_key.thumbprint_sha256_base64(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(JsonWebKey::new(private_key)
|
Ok(JsonWebKey::new(private_key)
|
||||||
.with_kid(self.kid.clone())
|
.with_kid(kid)
|
||||||
.with_use(mas_iana::jose::JsonWebKeyUse::Sig))
|
.with_use(mas_iana::jose::JsonWebKeyUse::Sig))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +327,7 @@ impl SecretsConfig {
|
|||||||
.await
|
.await
|
||||||
.context("could not join blocking task")?;
|
.context("could not join blocking task")?;
|
||||||
let rsa_key = KeyConfig {
|
let rsa_key = KeyConfig {
|
||||||
kid: Alphanumeric.sample_string(&mut rng, 10),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(rsa_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
key: Key::Value(rsa_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
||||||
};
|
};
|
||||||
@@ -338,7 +343,7 @@ impl SecretsConfig {
|
|||||||
.await
|
.await
|
||||||
.context("could not join blocking task")?;
|
.context("could not join blocking task")?;
|
||||||
let ec_p256_key = KeyConfig {
|
let ec_p256_key = KeyConfig {
|
||||||
kid: Alphanumeric.sample_string(&mut rng, 10),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(ec_p256_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
key: Key::Value(ec_p256_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
||||||
};
|
};
|
||||||
@@ -354,7 +359,7 @@ impl SecretsConfig {
|
|||||||
.await
|
.await
|
||||||
.context("could not join blocking task")?;
|
.context("could not join blocking task")?;
|
||||||
let ec_p384_key = KeyConfig {
|
let ec_p384_key = KeyConfig {
|
||||||
kid: Alphanumeric.sample_string(&mut rng, 10),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(ec_p384_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
key: Key::Value(ec_p384_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
||||||
};
|
};
|
||||||
@@ -370,7 +375,7 @@ impl SecretsConfig {
|
|||||||
.await
|
.await
|
||||||
.context("could not join blocking task")?;
|
.context("could not join blocking task")?;
|
||||||
let ec_k256_key = KeyConfig {
|
let ec_k256_key = KeyConfig {
|
||||||
kid: Alphanumeric.sample_string(&mut rng, 10),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(ec_k256_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
key: Key::Value(ec_k256_key.to_pem(pem_rfc7468::LineEnding::LF)?.to_string()),
|
||||||
};
|
};
|
||||||
@@ -383,7 +388,7 @@ impl SecretsConfig {
|
|||||||
|
|
||||||
pub(crate) fn test() -> Self {
|
pub(crate) fn test() -> Self {
|
||||||
let rsa_key = KeyConfig {
|
let rsa_key = KeyConfig {
|
||||||
kid: "abcdef".to_owned(),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(
|
key: Key::Value(
|
||||||
indoc::indoc! {r"
|
indoc::indoc! {r"
|
||||||
@@ -402,7 +407,7 @@ impl SecretsConfig {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
let ecdsa_key = KeyConfig {
|
let ecdsa_key = KeyConfig {
|
||||||
kid: "ghijkl".to_owned(),
|
kid: None,
|
||||||
password: None,
|
password: None,
|
||||||
key: Key::Value(
|
key: Key::Value(
|
||||||
indoc::indoc! {r"
|
indoc::indoc! {r"
|
||||||
@@ -422,3 +427,68 @@ impl SecretsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use figment::{
|
||||||
|
Figment, Jail,
|
||||||
|
providers::{Format, Yaml},
|
||||||
|
};
|
||||||
|
use mas_jose::constraints::Constrainable;
|
||||||
|
use tokio::{runtime::Handle, task};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn load_config_inline_secrets() {
|
||||||
|
task::spawn_blocking(|| {
|
||||||
|
Jail::expect_with(|jail| {
|
||||||
|
jail.create_file(
|
||||||
|
"config.yaml",
|
||||||
|
indoc::indoc! {r"
|
||||||
|
secrets:
|
||||||
|
encryption: >-
|
||||||
|
0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff
|
||||||
|
keys:
|
||||||
|
- kid: lekid0
|
||||||
|
key: |
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIOtZfDuXZr/NC0V3sisR4Chf7RZg6a2dpZesoXMlsPeRoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAECfpqx64lrR85MOhdMxNmIgmz8IfmM5VY9ICX9aoaArnD9FjgkBIl
|
||||||
|
fGmQWxxXDSWH6SQln9tROVZaduenJqDtDw==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
- key: |
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIKlZz/GnH0idVH1PnAF4HQNwRafgBaE2tmyN1wjfdOQqoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEHrgPeG+Mt8eahih1h4qaPjhl7jT25cdzBkg3dbVks6gBR2Rx4ug9
|
||||||
|
h27LAir5RqxByHvua2XsP46rSTChof78uw==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
"},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let config = Figment::new()
|
||||||
|
.merge(Yaml::file("config.yaml"))
|
||||||
|
.extract_inner::<SecretsConfig>("secrets")?;
|
||||||
|
|
||||||
|
Handle::current().block_on(async move {
|
||||||
|
assert_eq!(
|
||||||
|
config.encryption().await.unwrap(),
|
||||||
|
[
|
||||||
|
0, 0, 17, 17, 34, 34, 51, 51, 68, 68, 85, 85, 102, 102, 119, 119, 136,
|
||||||
|
136, 153, 153, 170, 170, 187, 187, 204, 204, 221, 221, 238, 238, 255,
|
||||||
|
255
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
let key_store = config.key_store().await.unwrap();
|
||||||
|
assert!(key_store.iter().any(|k| k.kid() == Some("lekid0")));
|
||||||
|
assert!(key_store.iter().any(|k| k.kid() == Some("ONUCn80fsiISFWKrVMEiirNVr-QEvi7uQI0QH9q9q4o")));
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use mas_iana::jose::{
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -239,6 +240,28 @@ impl<P> JsonWebKey<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Methods to calculate RFC 7638 JWK Thumbprints.
|
||||||
|
pub trait Thumbprint {
|
||||||
|
/// Returns the RFC 7638 JWK Thumbprint JSON string.
|
||||||
|
fn thumbprint_prehashed(&self) -> String;
|
||||||
|
|
||||||
|
/// Returns the RFC 7638 SHA256-hashed JWK Thumbprint.
|
||||||
|
fn thumbprint_sha256(&self) -> [u8; 32] {
|
||||||
|
Sha256::digest(self.thumbprint_prehashed()).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the RFC 7638 SHA256-hashed JWK Thumbprint as base64url string.
|
||||||
|
fn thumbprint_sha256_base64(&self) -> String {
|
||||||
|
Base64UrlNoPad::new(self.thumbprint_sha256().into()).encode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Thumbprint> Thumbprint for JsonWebKey<P> {
|
||||||
|
fn thumbprint_prehashed(&self) -> String {
|
||||||
|
self.parameters.thumbprint_prehashed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<P> Constrainable for JsonWebKey<P>
|
impl<P> Constrainable for JsonWebKey<P>
|
||||||
where
|
where
|
||||||
P: ParametersInfo,
|
P: ParametersInfo,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use schemars::JsonSchema;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::ParametersInfo;
|
use super::ParametersInfo;
|
||||||
use crate::base64::Base64UrlNoPad;
|
use crate::{base64::Base64UrlNoPad, jwk::Thumbprint};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(tag = "kty")]
|
#[serde(tag = "kty")]
|
||||||
@@ -52,6 +52,22 @@ impl JsonWebKeyPublicParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Thumbprint for JsonWebKeyPublicParameters {
|
||||||
|
fn thumbprint_prehashed(&self) -> String {
|
||||||
|
match self {
|
||||||
|
JsonWebKeyPublicParameters::Rsa(RsaPublicParameters { n, e }) => {
|
||||||
|
format!("{{\"e\":\"{e}\",\"kty\":\"RSA\",\"n\":\"{n}\"}}")
|
||||||
|
}
|
||||||
|
JsonWebKeyPublicParameters::Ec(EcPublicParameters { crv, x, y }) => {
|
||||||
|
format!("{{\"crv\":\"{crv}\",\"kty\":\"EC\",\"x\":\"{x}\",\"y\":\"{y}\"}}")
|
||||||
|
}
|
||||||
|
JsonWebKeyPublicParameters::Okp(OkpPublicParameters { crv, x }) => {
|
||||||
|
format!("{{\"crv\":\"{crv}\",\"kty\":\"OKP\",\"x\":\"{x}\"}}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ParametersInfo for JsonWebKeyPublicParameters {
|
impl ParametersInfo for JsonWebKeyPublicParameters {
|
||||||
fn kty(&self) -> JsonWebKeyType {
|
fn kty(&self) -> JsonWebKeyType {
|
||||||
match self {
|
match self {
|
||||||
@@ -300,3 +316,31 @@ mod ec_impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_thumbprint_rfc_example() {
|
||||||
|
// From https://www.rfc-editor.org/rfc/rfc7638.html#section-3.1
|
||||||
|
let n = Base64UrlNoPad::parse(
|
||||||
|
"\
|
||||||
|
0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt\
|
||||||
|
VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6\
|
||||||
|
4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD\
|
||||||
|
W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9\
|
||||||
|
1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH\
|
||||||
|
aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let e = Base64UrlNoPad::parse("AQAB").unwrap();
|
||||||
|
|
||||||
|
let jwkpps = JsonWebKeyPublicParameters::Rsa(RsaPublicParameters { n, e });
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
jwkpps.thumbprint_sha256_base64(),
|
||||||
|
"NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
|
|||||||
pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
|
pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
|
||||||
use mas_jose::{
|
use mas_jose::{
|
||||||
jwa::{AsymmetricSigningKey, AsymmetricVerifyingKey},
|
jwa::{AsymmetricSigningKey, AsymmetricVerifyingKey},
|
||||||
jwk::{JsonWebKeyPublicParameters, ParametersInfo, PublicJsonWebKeySet},
|
jwk::{JsonWebKeyPublicParameters, ParametersInfo, PublicJsonWebKeySet, Thumbprint},
|
||||||
};
|
};
|
||||||
use pem_rfc7468::PemLabel;
|
use pem_rfc7468::PemLabel;
|
||||||
use pkcs1::EncodeRsaPrivateKey;
|
use pkcs1::EncodeRsaPrivateKey;
|
||||||
@@ -599,6 +599,12 @@ impl ParametersInfo for PrivateKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Thumbprint for PrivateKey {
|
||||||
|
fn thumbprint_prehashed(&self) -> String {
|
||||||
|
JsonWebKeyPublicParameters::from(self).thumbprint_prehashed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A structure to store a list of [`PrivateKey`]. The keys are held in an
|
/// A structure to store a list of [`PrivateKey`]. The keys are held in an
|
||||||
/// [`Arc`] to ensure they are only loaded once in memory and allow cheap
|
/// [`Arc`] to ensure they are only loaded once in memory and allow cheap
|
||||||
/// cloning
|
/// cloning
|
||||||
|
|||||||
@@ -1553,11 +1553,9 @@
|
|||||||
"KeyConfig": {
|
"KeyConfig": {
|
||||||
"description": "A single key with its key ID and optional password.",
|
"description": "A single key with its key ID and optional password.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
|
||||||
"kid"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"kid": {
|
"kid": {
|
||||||
|
"description": "The key ID `kid` of the key as used by JWKs.\n\nIf not given, `kid` will be the key’s RFC 7638 JWK Thumbprint.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"password_file": {
|
"password_file": {
|
||||||
|
|||||||
@@ -197,35 +197,7 @@ secrets:
|
|||||||
# Signing keys
|
# Signing keys
|
||||||
keys:
|
keys:
|
||||||
# It needs at least an RSA key to work properly
|
# It needs at least an RSA key to work properly
|
||||||
- kid: "ahM2bien"
|
- key_file: keys/rsa_key
|
||||||
key: |
|
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAuf28zPUp574jDRdX6uN0d7niZCIUpACFo+Po/13FuIGsrpze
|
|
||||||
yMX6CYWVPalgXW9FCrhxL+4toJRy5npjkgsLFsknL5/zXbWKFgt69cMwsWJ9Ra57
|
|
||||||
bonSlI7SoCuHhtw7j+sAlHAlqTOCAVz6P039Y/AGvO6xbC7f+9XftWlbbDcjKFcb
|
|
||||||
pQilkN9qtkdEH7TLayMAFOsgNvBlwF9+oj9w5PIk3veRTdBXI4GlHjhhzqGZKiRp
|
|
||||||
oP9HnycHHveyT+C33vuhQso5a3wcUNuvDVOixSqR4kvSt4UVWNK/KmEQmlWU1/m9
|
|
||||||
ClIwrs8Q79q0xkGaSa0iuG60nvm7tZez9TFkxwIDAQABAoIBAHA5YkppQ7fJSm0D
|
|
||||||
wNDCHeyABNJWng23IuwZAOXVNxB1bjSOAv8yNgS4zaw/Hx5BnW8yi1lYZb+W0x2u
|
|
||||||
i5X7g91j0nkyEi5g88kJdFAGTsM5ok0BUwkHsEBjTUPIACanjGjya48lfBP0OGWK
|
|
||||||
LJU2Acbjda1aeUPFpPDXw/w6bieEthQwroq3DHCMnk6i9bsxgIOXeN04ij9XBmsH
|
|
||||||
KPCP2hAUnZSlx5febYfHK7/W95aJp22qa//eHS8cKQZCJ0+dQuZwLhlGosTFqLUm
|
|
||||||
qhPlt/b1EvPPY0cq5rtUc2W31L0YayVEHVOQx1fQIkH2VIUNbAS+bfVy+o6WCRk6
|
|
||||||
s1XDhsECgYEA30tykVTN5LncY4eQIww2mW8v1j1EG6ngVShN3GuBTuXXaEOB8Duc
|
|
||||||
yT7yJt1ZhmaJwMk4agmZ1/f/ZXBtfLREGVzVvuwqRZ+LHbqIyhi0wQJA0aezPote
|
|
||||||
uTQnFn+IveHGtpQNDYGL/UgkexuCxbc2HOZG51JpunCK0TdtVfO/9OUCgYEA1TuS
|
|
||||||
2WAXzNudRG3xd/4OgtkLD9AvfSvyjw2LkwqCMb3A5UEqw7vubk/xgnRvqrAgJRWo
|
|
||||||
jndgRrRnikHCavDHBO0GAO/kzrFRfw+e+r4jcLl0Yadke8ndCc7VTnx4wQCrMi5H
|
|
||||||
7HEeRwaZONoj5PAPyA5X+N/gT0NNDA7KoQT45DsCgYBt+QWa6A5jaNpPNpPZfwlg
|
|
||||||
9e60cAYcLcUri6cVOOk9h1tYoW7cdy+XueWfGIMf+1460Z90MfhP8ncZaY6yzUGA
|
|
||||||
0EUBO+Tx10q3wIfgKNzU9hwgZZyU4CUtx668mOEqy4iHoVDwZu4gNyiobPsyDzKa
|
|
||||||
dxtSkDc8OHNV6RtzKpJOtQKBgFoRGcwbnLH5KYqX7eDDPRnj15pMU2LJx2DJVeU8
|
|
||||||
ERY1kl7Dke6vWNzbg6WYzPoJ/unrJhFXNyFmXj213QsSvN3FyD1pFvp/R28mB/7d
|
|
||||||
hVa93vzImdb3wxe7d7n5NYBAag9+IP8sIJ/bl6i9619uTxwvgtUqqzKPuOGY9dnh
|
|
||||||
oce1AoGBAKZyZc/NVgqV2KgAnnYlcwNn7sRSkM8dcq0/gBMNuSZkfZSuEd4wwUzR
|
|
||||||
iFlYp23O2nHWggTkzimuBPtD7Kq4jBey3ZkyGye+sAdmnKkOjNILNbpIZlT6gK3z
|
|
||||||
fBaFmJGRJinKA+BJeH79WFpYN6SBZ/c3s5BusAbEU7kE5eInyazP
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
- kid: "iv1aShae"
|
- kid: "iv1aShae"
|
||||||
key: |
|
key: |
|
||||||
-----BEGIN EC PRIVATE KEY-----
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
@@ -260,9 +232,7 @@ The following key types are supported:
|
|||||||
- ECDSA with the P-384 (`secp384r1`) curve
|
- ECDSA with the P-384 (`secp384r1`) curve
|
||||||
- ECDSA with the K-256 (`secp256k1`) curve
|
- ECDSA with the K-256 (`secp256k1`) curve
|
||||||
|
|
||||||
Each entry must have a unique `kid`, plus the key itself.
|
Each entry in the list corresponds to one signing key used by MAS.
|
||||||
The `kid` can be any case-sensitive string value as long as it is unique to this list;
|
|
||||||
a key’s `kid` value must be stable across restarts.
|
|
||||||
The key can either be specified inline (with the `key` property),
|
The key can either be specified inline (with the `key` property),
|
||||||
or loaded from a file (with the `key_file` property).
|
or loaded from a file (with the `key_file` property).
|
||||||
The following key formats are supported:
|
The following key formats are supported:
|
||||||
@@ -271,8 +241,15 @@ The following key formats are supported:
|
|||||||
- PKCS#8 PEM or DER-encoded RSA or ECDSA private key, encrypted or not
|
- PKCS#8 PEM or DER-encoded RSA or ECDSA private key, encrypted or not
|
||||||
- SEC1 PEM or DER-encoded ECDSA private key
|
- SEC1 PEM or DER-encoded ECDSA private key
|
||||||
|
|
||||||
|
A [JWK Key ID] is automatically derived from each key.
|
||||||
|
To override this default, set `kid` to a custom value.
|
||||||
|
The `kid` can be any case-sensitive string value as long as it is unique to this list;
|
||||||
|
a key’s `kid` value must be stable across restarts.
|
||||||
|
|
||||||
For PKCS#8 encoded keys, the `password` or `password_file` properties can be used to decrypt the key.
|
For PKCS#8 encoded keys, the `password` or `password_file` properties can be used to decrypt the key.
|
||||||
|
|
||||||
|
[JWK Key ID]: <https://datatracker.ietf.org/doc/html/rfc7517#section-4.5>
|
||||||
|
|
||||||
## `passwords`
|
## `passwords`
|
||||||
|
|
||||||
Settings related to the local password database
|
Settings related to the local password database
|
||||||
|
|||||||
Reference in New Issue
Block a user