Skip to content

Commit

Permalink
wip(fc-pallet-pass): handle authenticators as instances
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 committed Sep 26, 2024
1 parent 0acbe32 commit 2fad579
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 48 deletions.
146 changes: 101 additions & 45 deletions pallets/pass/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
use crate::{self as pallet_pass, Config};
use codec::{Decode, Encode, MaxEncodedLen};
use fc_traits_authn::Challenger;
use frame_support::{
derive_impl, ensure, parameter_types,
traits::{ConstU32, ConstU64, EqualPrivilegeOnly, OnInitialize},
derive_impl, parameter_types,
traits::{ConstU32, ConstU64, EqualPrivilegeOnly, OnInitialize, Randomness},
weights::Weight,
PalletId,
DebugNoBound, EqNoBound, PalletId,
};
use frame_system::EnsureRoot;
use frame_system::{EnsureRoot, EnsureSigned};
use scale_info::TypeInfo;
use sp_core::{blake2_256, H256};
use sp_io::TestExternalities;
use sp_runtime::{
str_array as s,
traits::{IdentifyAccount, IdentityLookup, Verify},
MultiSignature,
};
Expand Down Expand Up @@ -90,41 +92,103 @@ impl frame_support::traits::Randomness<H256, u64> for RandomnessFromBlockNumber
}
}

pub struct InvalidAuthenticationMethod;
impl fc_traits_authn::AuthenticationMethod for InvalidAuthenticationMethod {
fn get_device_id(&self, _device: Vec<u8>) -> Option<pallet_pass::DeviceId> {
None
#[derive(TypeInfo, MaxEncodedLen, DebugNoBound, EqNoBound, PartialEq, Clone, Encode, Decode)]
pub struct MockDeviceAttestation {
pub(crate) context: (),
pub(crate) user_id: fc_traits_authn::HashedUserId,
pub(crate) challenge: fc_traits_authn::Challenge,
pub(crate) device_id: fc_traits_authn::DeviceId,
}

impl fc_traits_authn::ChallengeResponse<()> for MockDeviceAttestation {
fn is_valid(&self) -> bool {
self.challenge == MockChallenger::generate(&self.context)
}

fn used_challenge(&self) -> ((), fc_traits_authn::Challenge) {
((), MockChallenger::generate(&self.context))
}

fn authority(&self) -> fc_traits_authn::AuthorityId {
s("DummyAuthenticator")
}
}

impl fc_traits_authn::UserAuthenticator for MockDeviceAttestation {
const AUTHORITY: fc_traits_authn::AuthorityId = s("MockDevice");
type Challenger = MockChallenger;
type Credential = Self;

fn device_id(&self) -> fc_traits_authn::DeviceId {
todo!()
}
}

impl fc_traits_authn::DeviceChallengeResponse<()> for MockDeviceAttestation {
fn device_id(&self) -> fc_traits_authn::DeviceId {
self.device_id
}
}

fn authenticate(
&self,
_device: Vec<u8>,
_challenge: &[u8],
_payload: &[u8],
) -> Result<(), fc_traits_authn::AuthenticateError> {
Err(fc_traits_authn::AuthenticateError::ChallengeFailed)
impl fc_traits_authn::UserChallengeResponse<()> for MockDeviceAttestation {
fn user_id(&self) -> fc_traits_authn::HashedUserId {
self.user_id
}
}

pub struct DummyAuthenticationMethod;
impl fc_traits_authn::AuthenticationMethod for DummyAuthenticationMethod {
fn get_device_id(&self, device: Vec<u8>) -> Option<pallet_pass::DeviceId> {
let len = device.len();
Some([(len as u8) + 1; 32])
pub struct MockChallenger;
impl fc_traits_authn::Challenger for MockChallenger {
type Context = ();

fn generate(_: &Self::Context) -> fc_traits_authn::Challenge {
let (hash, _) = RandomnessFromBlockNumber::random_seed();
hash.0
}
}

fn authenticate(
&self,
_device: Vec<u8>,
challenge: &[u8],
payload: &[u8],
) -> Result<(), fc_traits_authn::AuthenticateError> {
ensure!(
challenge == payload,
fc_traits_authn::AuthenticateError::ChallengeFailed
);
Ok(())
pub struct InvalidAuthenticator;
impl fc_traits_authn::Authenticator for InvalidAuthenticator {
const AUTHORITY: fc_traits_authn::AuthorityId = s("InvalidAuthenticator");
type Challenger = MockChallenger;
type DeviceAttestation = MockDeviceAttestation;
type Device = MockDevice;

fn verify_device(&self, _: &Self::DeviceAttestation) -> Option<Self::Device> {
None
}

fn unpack_device(&self, _: &Self::DeviceAttestation) -> Self::Device {
()
}
}

pub struct DummyAuthenticator;
impl fc_traits_authn::Authenticator for DummyAuthenticator {
const AUTHORITY: fc_traits_authn::AuthorityId = s("DummyAuthenticator");
type Challenger = MockChallenger;
type DeviceAttestation = MockDeviceAttestation;
type Device = MockDeviceAttestation;

fn unpack_device(&self, verification: &Self::DeviceAttestation) -> Self::Device {
todo!()
}
// fn get_device_id(&self, device: Vec<u8>) -> Option<pallet_pass::DeviceId> {
// let len = device.len();
// Some([(len as u8) + 1; 32])
// }

// fn authenticate(
// &self,
// _device: Vec<u8>,
// challenge: &[u8],
// payload: &[u8],
// ) -> Result<(), fc_traits_authn::AuthenticateError> {
// ensure!(
// challenge == payload,
// fc_traits_authn::AuthenticateError::ChallengeFailed
// );
// Ok(())
// }
}

#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Clone, Eq, PartialEq)]
Expand All @@ -133,15 +197,13 @@ pub enum MockAuthenticationMethods {
DummyAuthenticationMethod,
}

impl Into<Box<dyn fc_traits_authn::AuthenticationMethod>> for MockAuthenticationMethods {
fn into(self) -> Box<dyn fc_traits_authn::AuthenticationMethod> {
impl Into<Box<dyn fc_traits_authn::Authenticator>> for MockAuthenticationMethods {
fn into(self) -> Box<dyn fc_traits_authn::Authenticator> {
match self {
MockAuthenticationMethods::InvalidAuthenticationMethod => {
Box::new(InvalidAuthenticationMethod)
}
MockAuthenticationMethods::DummyAuthenticationMethod => {
Box::new(DummyAuthenticationMethod)
Box::new(InvalidAuthenticator)
}
MockAuthenticationMethods::DummyAuthenticationMethod => Box::new(DummyAuthenticator),
}
}
}
Expand All @@ -153,18 +215,12 @@ parameter_types! {
impl Config for Test {
type WeightInfo = ();
type RuntimeEvent = RuntimeEvent;
type AuthenticationMethod = MockAuthenticationMethods;
type Randomness = RandomnessFromBlockNumber;
type Authenticator = MockAuthenticationMethods;
type RegisterOrigin = EnsureSigned<Self::AccountId>;
type RuntimeCall = RuntimeCall;
type Scheduler = Scheduler;
type PalletId = PassPalletId;
type PalletsOrigin = OriginCaller;
type UninitializedTimeout = ConstU64<10>;
type MaxAccountNameLen = ConstU32<64>;
type MaxDeviceDescriptorLen = ConstU32<65535>;
type MaxDevicesPerAccount = ConstU32<5>;
type MaxSessionDuration = ConstU64<10>;
type ModForBlockNumber = ConstU32<10800>;
}

pub fn new_test_ext() -> sp_io::TestExternalities {
Expand Down
6 changes: 3 additions & 3 deletions traits/authn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ pub trait Authenticator {
type DeviceAttestation: DeviceChallengeResponse<CxOf<Self::Challenger>>;
type Device: UserAuthenticator<Challenger = Self::Challenger>;

fn verify_device(attestation: &Self::DeviceAttestation) -> Option<Self::Device> {
fn verify_device(&self, attestation: &Self::DeviceAttestation) -> Option<Self::Device> {
attestation.authority().eq(&Self::AUTHORITY).then_some(())?;
let (cx, challenge) = attestation.used_challenge();
Self::Challenger::check_challenge(&cx, &challenge)?;
attestation.is_valid().then_some(())?;
Some(Self::unpack_device(attestation))
Some(self.unpack_device(attestation))
}

/// Extract device information from the verification payload
fn unpack_device(verification: &Self::DeviceAttestation) -> Self::Device;
fn unpack_device(&self, verification: &Self::DeviceAttestation) -> Self::Device;
}

/// A device capable of verifying a user provided credential
Expand Down

0 comments on commit 2fad579

Please sign in to comment.