Skip to content

Commit

Permalink
wip(pass-webauthn): apply changes and leave for finishing Attestation.
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 committed Oct 14, 2024
1 parent 025f5c9 commit 95fa042
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 65 deletions.
79 changes: 25 additions & 54 deletions pass-webauthn/src/impls.rs
Original file line number Diff line number Diff line change
@@ -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;

Check failure on line 4 in pass-webauthn/src/impls.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared crate or module `sp_io`

error[E0433]: failed to resolve: use of undeclared crate or module `sp_io` --> pass-webauthn/src/impls.rs:4:5 | 4 | use sp_io::hashing::blake2_256; | ^^^^^ use of undeclared crate or module `sp_io`
use traits_authn::{
AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId,
UserChallengeResponse,
util::VerifyCredential, AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId,
HashedUserId, UserChallengeResponse,
};
use verifier::webauthn_verify;

Expand All @@ -15,25 +14,6 @@ impl<Cx> Attestation<Cx>
where
Cx: Parameter,
{
pub fn new(
authenticator_data: Vec<u8>,
client_data: Vec<u8>,
signature: Vec<u8>,
public_key: Vec<u8>,
) -> 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<AuthorityId, ()> {
let client_data_json =
Expand Down Expand Up @@ -64,7 +44,7 @@ where
}

fn used_challenge(&self) -> (Cx, Challenge) {
(self.context(), self.challenge())
(self.context, self.challenge())
}

fn authority(&self) -> AuthorityId {
Expand All @@ -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
}
}

Expand All @@ -94,40 +74,36 @@ where
CxOf<Ch>: Parameter + Copy + 'static,
{
fn from(value: Attestation<CxOf<Ch>>) -> Self {
Device::new(DeviceInfo(value.device_id().clone()))
Device::new(DeviceInfo {
device_id: value.device_id().clone(),
public_key: value.public_key,
})
}
}

impl<Cx> VerifyCredential<Credential<Cx>> for DeviceInfo {
fn verify(&self, credential: &Credential<Cx>) -> Option<()> {
webauthn_verify(
&credential.authenticator_data,
&credential.client_data,
&credential.signature,
&self.public_key,
)
.ok()
}
}

#[cfg(any(feature = "runtime", test))]
impl AsRef<DeviceId> for DeviceInfo {
fn as_ref(&self) -> &DeviceId {
&self.0
&self.device_id
}
}

impl<Cx> Credential<Cx>
where
Cx: Parameter,
{
pub fn new(
authenticator_data: Vec<u8>,
client_data: Vec<u8>,
signature: Vec<u8>,
public_key: Vec<u8>,
) -> 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])");
}
Expand All @@ -138,18 +114,13 @@ impl<Cx> UserChallengeResponse<Cx> for Credential<Cx>
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 {
Expand Down
25 changes: 14 additions & 11 deletions pass-webauthn/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<Ch> = <Ch as Challenger>::Context;

mod impls;
#[cfg(test)]
mod tests;

mod impls;
pub type DEREncodedPublicKey = [u8; 91];

#[cfg(any(feature = "runtime", test))]
pub type Authenticator<Ch, A> = Auth<Device<Ch, A>, Attestation<CxOf<Ch>>>;
Expand All @@ -23,22 +22,26 @@ pub type Device<Ch, A> = Dev<DeviceInfo, A, Ch, Credential<CxOf<Ch>>>;

#[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<Cx> {
__phantom: PhantomData<Cx>,
pub(crate) credential_id: DeviceId,
pub(crate) context: Cx,
pub(crate) authenticator_data: Vec<u8>,
pub(crate) client_data: Vec<u8>,
pub(crate) public_key: Vec<u8>,
pub(crate) signature: Vec<u8>,
pub(crate) attestation_data: Vec<u8>,
pub(crate) public_key: DEREncodedPublicKey,
}

#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)]
pub struct Credential<Cx> {
__phantom: PhantomData<Cx>,
pub(crate) user_id: HashedUserId,
pub(crate) context: Cx,
pub(crate) authenticator_data: Vec<u8>,
pub(crate) client_data: Vec<u8>,
pub(crate) public_key: Vec<u8>,
pub(crate) signature: Vec<u8>,
}

0 comments on commit 95fa042

Please sign in to comment.