From 95fa04264482bcc748a39840492cd83128cbe9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20Dorado=20Su=C3=A1rez?= Date: Mon, 14 Oct 2024 12:26:17 -0500 Subject: [PATCH] wip(pass-webauthn): apply changes and leave for finishing `Attestation`. --- pass-webauthn/src/impls.rs | 79 ++++++++++++-------------------------- pass-webauthn/src/lib.rs | 25 ++++++------ 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/pass-webauthn/src/impls.rs b/pass-webauthn/src/impls.rs index 96decc3..45260bb 100644 --- a/pass-webauthn/src/impls.rs +++ b/pass-webauthn/src/impls.rs @@ -1,11 +1,10 @@ -use core::marker::PhantomData; - use codec::Decode; use frame_support::{sp_runtime::traits::TrailingZeroInput, Parameter}; use serde_json::Value; +use sp_io::hashing::blake2_256; use traits_authn::{ - AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId, - UserChallengeResponse, + util::VerifyCredential, AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, + HashedUserId, UserChallengeResponse, }; use verifier::webauthn_verify; @@ -15,25 +14,6 @@ impl Attestation where Cx: Parameter, { - pub fn new( - authenticator_data: Vec, - client_data: Vec, - signature: Vec, - public_key: Vec, - ) -> Self { - Self { - __phantom: PhantomData, - authenticator_data, - client_data, - signature, - public_key, - } - } - - fn context(&self) -> Cx { - todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); - } - fn challenge(&self) -> Challenge { || -> Result { let client_data_json = @@ -64,7 +44,7 @@ where } fn used_challenge(&self) -> (Cx, Challenge) { - (self.context(), self.challenge()) + (self.context, self.challenge()) } fn authority(&self) -> AuthorityId { @@ -83,7 +63,7 @@ where } fn device_id(&self) -> &DeviceId { - todo!("Extract `device_id`, format into `DeviceId` format (that is, [u8; 32])"); + &self.credential_id } } @@ -94,14 +74,29 @@ where CxOf: Parameter + Copy + 'static, { fn from(value: Attestation>) -> Self { - Device::new(DeviceInfo(value.device_id().clone())) + Device::new(DeviceInfo { + device_id: value.device_id().clone(), + public_key: value.public_key, + }) + } +} + +impl VerifyCredential> for DeviceInfo { + fn verify(&self, credential: &Credential) -> Option<()> { + webauthn_verify( + &credential.authenticator_data, + &credential.client_data, + &credential.signature, + &self.public_key, + ) + .ok() } } #[cfg(any(feature = "runtime", test))] impl AsRef for DeviceInfo { fn as_ref(&self) -> &DeviceId { - &self.0 + &self.device_id } } @@ -109,25 +104,6 @@ impl Credential where Cx: Parameter, { - pub fn new( - authenticator_data: Vec, - client_data: Vec, - signature: Vec, - public_key: Vec, - ) -> Self { - Self { - __phantom: PhantomData, - authenticator_data, - client_data, - signature, - public_key, - } - } - - fn context(&self) -> Cx { - todo!("Extract `context` into `Cx` format (you can conveniently use `.decode()`)"); - } - fn challenge(&self) -> Challenge { todo!("Extract `challenge`, format into `Challenge` format (that is, [u8; 32])"); } @@ -138,18 +114,13 @@ impl UserChallengeResponse for Credential where Cx: Parameter + Copy + 'static, { + // TODO: @jgutierrezre please check if there are necessary validations involved here. fn is_valid(&self) -> bool { - webauthn_verify( - self.authenticator_data.as_ref(), - &self.client_data, - &self.signature, - &self.public_key, - ) - .is_ok() + true } fn used_challenge(&self) -> (Cx, Challenge) { - (self.context(), self.challenge()) + (self.context, self.challenge()) } fn authority(&self) -> AuthorityId { diff --git a/pass-webauthn/src/lib.rs b/pass-webauthn/src/lib.rs index 506a6ec..f361008 100644 --- a/pass-webauthn/src/lib.rs +++ b/pass-webauthn/src/lib.rs @@ -1,20 +1,19 @@ #![cfg_attr(not(feature = "std"), no_std)] -use core::marker::PhantomData; - use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use traits_authn::{ util::{Auth, Dev}, - Challenger, DeviceId, + Challenger, DeviceId, HashedUserId, }; type CxOf = ::Context; +mod impls; #[cfg(test)] mod tests; -mod impls; +pub type DEREncodedPublicKey = [u8; 91]; #[cfg(any(feature = "runtime", test))] pub type Authenticator = Auth, Attestation>>; @@ -23,22 +22,26 @@ pub type Device = Dev>>; #[cfg(any(feature = "runtime", test))] #[derive(MaxEncodedLen, TypeInfo, Decode, Encode)] -pub struct DeviceInfo(DeviceId); +pub struct DeviceInfo { + device_id: DeviceId, + //. A DER-encoded public key + public_key: DEREncodedPublicKey, +} #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Attestation { - __phantom: PhantomData, + pub(crate) credential_id: DeviceId, + pub(crate) context: Cx, pub(crate) authenticator_data: Vec, - pub(crate) client_data: Vec, - pub(crate) public_key: Vec, - pub(crate) signature: Vec, + pub(crate) attestation_data: Vec, + pub(crate) public_key: DEREncodedPublicKey, } #[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)] pub struct Credential { - __phantom: PhantomData, + pub(crate) user_id: HashedUserId, + pub(crate) context: Cx, pub(crate) authenticator_data: Vec, pub(crate) client_data: Vec, - pub(crate) public_key: Vec, pub(crate) signature: Vec, }