|
2 | 2 | use std::{env, error::Error, sync::LazyLock, time::Duration}; |
3 | 3 |
|
4 | 4 | use anyhow::{anyhow, Context}; |
5 | | -use c509_certificate::c509::C509; |
6 | 5 | use cardano_blockchain_types::{Network, Point, Slot, TxnIndex}; |
7 | 6 | use cardano_chain_follower::ChainFollower; |
8 | 7 | use catalyst_types::id_uri::IdUri; |
9 | | -use ed25519_dalek::{VerifyingKey, PUBLIC_KEY_LENGTH}; |
| 8 | +use ed25519_dalek::VerifyingKey; |
10 | 9 | use futures::{TryFutureExt, TryStreamExt}; |
11 | 10 | use moka::future::Cache; |
12 | | -use oid_registry::{Oid, OID_SIG_ED25519}; |
13 | 11 | use poem::{error::ResponseError, http::StatusCode, IntoResponse, Request}; |
14 | 12 | use poem_openapi::{auth::Bearer, payload::Json, SecurityScheme}; |
15 | 13 | use rbac_registration::{ |
16 | | - cardano::cip509::{Cip509, LocalRefInt, RoleNumber}, |
| 14 | + cardano::cip509::{Cip509, RoleNumber}, |
17 | 15 | registration::cardano::RegistrationChain, |
18 | 16 | }; |
19 | 17 | use tracing::{error, warn}; |
20 | | -use x509_cert::Certificate; |
21 | 18 |
|
22 | 19 | use super::token::CatalystRBACTokenV1; |
23 | 20 | use crate::{ |
@@ -161,6 +158,7 @@ async fn checker_api_catalyst_auth( |
161 | 158 | // } |
162 | 159 |
|
163 | 160 | // Step 8: get the latest stable signing certificate registered for Role 0. |
| 161 | + |
164 | 162 | let public_key = last_signing_key(token.network(), ®istrations) |
165 | 163 | .await |
166 | 164 | .map_err(|e| { |
@@ -233,41 +231,10 @@ async fn last_signing_key( |
233 | 231 | let chain = registration_chain(network, indexed_registrations) |
234 | 232 | .await |
235 | 233 | .context("Failed to build registration chain")?; |
236 | | - let key_ref = chain |
237 | | - .role_data() |
238 | | - .get(&RoleNumber::ROLE_0) |
239 | | - .context("Missing role 0 data")? |
240 | | - .data() |
241 | | - .signing_key() |
242 | | - .context("Missing signing key")?; |
243 | | - match key_ref.local_ref { |
244 | | - LocalRefInt::X509Certs => { |
245 | | - let cert = &chain |
246 | | - .x509_certs() |
247 | | - .get(&key_ref.key_offset) |
248 | | - .context("Missing X509 role 0 certificate")? |
249 | | - .last() |
250 | | - .and_then(|p| p.data().as_ref()) |
251 | | - .context("Unable to get last X509 role 0 certificate")?; |
252 | | - x509_key(cert) |
253 | | - }, |
254 | | - LocalRefInt::C509Certs => { |
255 | | - let cert = &chain |
256 | | - .c509_certs() |
257 | | - .get(&key_ref.key_offset) |
258 | | - .context("Missing C509 role 0 certificate")? |
259 | | - .last() |
260 | | - .and_then(|p| p.data().as_ref()) |
261 | | - .context("Unable to get last C509 role 0 certificate")?; |
262 | | - c509_key(cert) |
263 | | - }, |
264 | | - LocalRefInt::PubKeys => { |
265 | | - // We check this during Cip509 validation. |
266 | | - Err(anyhow!( |
267 | | - "Invalid signing key for role 0: it must reference a certificate, not public key" |
268 | | - )) |
269 | | - }, |
270 | | - } |
| 234 | + chain |
| 235 | + .get_latest_signing_pk_for_role(&RoleNumber::ROLE_0) |
| 236 | + .ok_or(anyhow!("Cannot find latest role 0 public key")) |
| 237 | + .map(|(pk, _)| pk) |
271 | 238 | } |
272 | 239 |
|
273 | 240 | /// Build a registration chain from the given indexed data. |
@@ -328,68 +295,3 @@ async fn registration(network: Network, slot: Slot, txn_index: TxnIndex) -> anyh |
328 | 295 | .context("Invalid RBAC registration")? |
329 | 296 | .context("No RBAC registration at this block and txn index") |
330 | 297 | } |
331 | | - |
332 | | -/// Returns `VerifyingKey` from the given X509 certificate. |
333 | | -fn x509_key(cert: &Certificate) -> anyhow::Result<VerifyingKey> { |
334 | | - let oid: Oid = cert |
335 | | - .tbs_certificate |
336 | | - .subject_public_key_info |
337 | | - .algorithm |
338 | | - .oid |
339 | | - .to_string() |
340 | | - .parse() |
341 | | - // `Context` cannot be used here because `OidParseError` doesn't implement `std::Error`. |
342 | | - .map_err(|e| anyhow!("Invalid signature algorithm OID: {e:?}"))?; |
343 | | - check_signature_algorithm(&oid)?; |
344 | | - let extended_public_key = cert |
345 | | - .tbs_certificate |
346 | | - .subject_public_key_info |
347 | | - .subject_public_key |
348 | | - .as_bytes() |
349 | | - .context("Invalid subject_public_key value (has unused bits)")?; |
350 | | - verifying_key(extended_public_key).context("Unable to get verifying key from X509 certificate") |
351 | | -} |
352 | | - |
353 | | -/// Returns `VerifyingKey` from the given C509 certificate. |
354 | | -fn c509_key(cert: &C509) -> anyhow::Result<VerifyingKey> { |
355 | | - let oid = cert |
356 | | - .tbs_cert() |
357 | | - .subject_public_key_algorithm() |
358 | | - .algo_identifier() |
359 | | - .oid(); |
360 | | - check_signature_algorithm(oid)?; |
361 | | - verifying_key(cert.tbs_cert().subject_public_key()) |
362 | | - .context("Unable to get verifying key from C509 certificate") |
363 | | -} |
364 | | - |
365 | | -/// Checks that the signature algorithm is supported. |
366 | | -fn check_signature_algorithm(oid: &Oid) -> anyhow::Result<()> { |
367 | | - // Currently the only supported signature algorithm is ED25519. |
368 | | - if *oid != OID_SIG_ED25519 { |
369 | | - return Err(anyhow!("Unsupported signature algorithm: {oid}")); |
370 | | - } |
371 | | - Ok(()) |
372 | | -} |
373 | | - |
374 | | -// TODO: The very similar logic exists in the `rbac-registration` crate. It should be |
375 | | -// moved somewhere and reused. See https://github.com/input-output-hk/catalyst-voices/issues/1952 |
376 | | -/// Creates `VerifyingKey` from the given extended public key. |
377 | | -fn verifying_key(extended_public_key: &[u8]) -> anyhow::Result<VerifyingKey> { |
378 | | - /// An extender public key length in bytes. |
379 | | - const EXTENDED_PUBLIC_KEY_LENGTH: usize = 64; |
380 | | - |
381 | | - if extended_public_key.len() != EXTENDED_PUBLIC_KEY_LENGTH { |
382 | | - return Err(anyhow!( |
383 | | - "Unexpected extended public key length in certificate: {}, expected {EXTENDED_PUBLIC_KEY_LENGTH}", |
384 | | - extended_public_key.len() |
385 | | - )); |
386 | | - } |
387 | | - // This should never fail because of the check above. |
388 | | - let public_key = extended_public_key |
389 | | - .get(0..PUBLIC_KEY_LENGTH) |
390 | | - .context("Unable to get public key part")?; |
391 | | - let bytes: &[u8; PUBLIC_KEY_LENGTH] = public_key |
392 | | - .try_into() |
393 | | - .context("Invalid public key length in X509 certificate")?; |
394 | | - VerifyingKey::from_bytes(bytes).context("Invalid public key in X509 certificate") |
395 | | -} |
0 commit comments