Skip to content

Commit

Permalink
1471 check shielding key inside pallet (#1479)
Browse files Browse the repository at this point in the history
* move checking valid user shielding key into pallet extrinsics: create_identity, verify_identity, remove_identity.

* pass the unit test

* update ts test

* revert back checking user shielding key

* add ts test

* use runtime network type

* fix unit test

* simply rename

* only log is enough

* add extra unit test to check InvalidUserShieldingKey

* refactor: move duplicate code

* refactor to remove duplicate code
  • Loading branch information
BillyWooo authored Mar 19, 2023
1 parent d8087ec commit 97e9576
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 33 deletions.
18 changes: 3 additions & 15 deletions tee-worker/app-libs/stf/src/trusted_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,7 @@ where
aes_encrypt_default(&key, &code.encode()),
)));
} else {
add_call_from_imp_error(
calls,
node_metadata_repo,
IMPError::InvalidUserShieldingKey,
);
error!("Can't create identity: InvalidUserShieldingKey");
}
},
Err(e) => {
Expand Down Expand Up @@ -544,11 +540,7 @@ where
aes_encrypt_default(&key, &identity.encode()),
)));
} else {
add_call_from_imp_error(
calls,
node_metadata_repo,
IMPError::InvalidUserShieldingKey,
);
error!("Can't remove identity: InvalidUserShieldingKey");
}
},
Err(e) => {
Expand Down Expand Up @@ -608,11 +600,7 @@ where
aes_encrypt_default(&key, &id_graph.encode()),
)));
} else {
add_call_from_imp_error(
calls,
node_metadata_repo,
IMPError::InvalidUserShieldingKey,
);
error!("Can't verify identity: InvalidUserShieldingKey");
}
},
Err(e) => {
Expand Down
1 change: 1 addition & 0 deletions tee-worker/litentry/core/data-providers/src/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl From<SubstrateNetwork> for VerifiedCredentialsNetwork {
SubstrateNetwork::Polkadot => Self::Polkadot,
SubstrateNetwork::Kusama => Self::Kusama,
SubstrateNetwork::Khala => Self::Khala,
SubstrateNetwork::TestNet => todo!(),
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion tee-worker/litentry/pallets/identity-management/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub mod pallet {
pub enum Error<T> {
/// challenge code doesn't exist
ChallengeCodeNotExist,
/// Invalid user shielding Key
InvalidUserShieldingKey,
/// the pair (litentry-account, identity) already verified when creating an identity
IdentityAlreadyVerified,
/// the pair (litentry-account, identity) doesn't exist
Expand Down Expand Up @@ -200,6 +202,8 @@ pub mod pallet {
parent_ss58_prefix: u16,
) -> DispatchResult {
T::ManageOrigin::ensure_origin(origin)?;
ensure!(Self::user_shielding_keys(&who).is_some(), Error::<T>::InvalidUserShieldingKey);

if let Some(c) = IDGraphs::<T>::get(&who, &identity) {
ensure!(
!(c.is_verified && c.creation_request_block != Some(0)),
Expand All @@ -218,7 +222,7 @@ pub mod pallet {
}

let prime_id = Identity::Substrate {
network: SubstrateNetwork::Litentry,
network: SubstrateNetwork::from_ss58_prefix(parent_ss58_prefix),
address: prime_user_address,
};
if IDGraphs::<T>::get(&who, &prime_id).is_none() {
Expand Down Expand Up @@ -250,6 +254,7 @@ pub mod pallet {
identity: Identity,
) -> DispatchResult {
T::ManageOrigin::ensure_origin(origin)?;
ensure!(Self::user_shielding_keys(&who).is_some(), Error::<T>::InvalidUserShieldingKey);
ensure!(IDGraphs::<T>::contains_key(&who, &identity), Error::<T>::IdentityNotExist);
if let Some(IdentityContext::<T> {
metadata,
Expand Down Expand Up @@ -281,6 +286,7 @@ pub mod pallet {
verification_request_block: ParentchainBlockNumber,
) -> DispatchResult {
T::ManageOrigin::ensure_origin(origin)?;
ensure!(Self::user_shielding_keys(&who).is_some(), Error::<T>::InvalidUserShieldingKey);
IDGraphs::<T>::try_mutate(&who, &identity, |context| -> DispatchResult {
let mut c = context.take().ok_or(Error::<T>::IdentityNotExist)?;

Expand Down
19 changes: 17 additions & 2 deletions tee-worker/litentry/pallets/identity-management/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.

use crate as pallet_tee_identity_management;
use crate::UserShieldingKeyType;
use frame_support::{
ord_parameter_types, parameter_types,
traits::{ConstU128, ConstU16, ConstU32},
};
use frame_system as system;
use frame_system::EnsureSignedBy;
use litentry_primitives::{Identity, IdentityString, SubstrateNetwork, Web2Network};
use litentry_primitives::{
Identity, IdentityString, SubstrateNetwork, Web2Network, USER_SHIELDING_KEY_LEN,
};
use sp_core::H256;
use sp_runtime::{
testing::Header,
Expand Down Expand Up @@ -102,6 +105,9 @@ impl pallet_tee_identity_management::Config for Test {

const ALICE_KEY: &str = "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d";

pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]);
pub const BOB: AccountId32 = AccountId32::new([2u8; 32]);

pub fn alice_twitter_identity(suffix: u32) -> Identity {
let address = IdentityString::try_from(format!("alice{}", suffix).as_bytes().to_vec())
.expect("convert to BoundedVec failed");
Expand All @@ -119,12 +125,21 @@ pub fn bob_web3_identity() -> Identity {
Identity::Substrate { network: SubstrateNetwork::Litentry, address: bob_key_hex.into() }
}

pub fn new_test_ext() -> sp_io::TestExternalities {
pub fn new_test_ext(set_shielding_key: bool) -> sp_io::TestExternalities {
let t = system::GenesisConfig::default().build_storage::<Test>().unwrap();

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| {
System::set_block_number(1);

if set_shielding_key {
let shielding_key: UserShieldingKeyType = [0u8; USER_SHIELDING_KEY_LEN];
let _ = IMT::set_user_shielding_key(
RuntimeOrigin::signed(ALICE),
BOB,
shielding_key.clone(),
);
}
});
ext
}
32 changes: 22 additions & 10 deletions tee-worker/litentry/pallets/identity-management/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub const BOB: AccountId32 = AccountId32::new([2u8; 32]);

#[test]
fn set_user_shielding_key_works() {
new_test_ext().execute_with(|| {
new_test_ext(false).execute_with(|| {
let shielding_key: UserShieldingKeyType = [0u8; USER_SHIELDING_KEY_LEN];
assert_eq!(IMT::user_shielding_keys(BOB), None);
assert_ok!(IMT::set_user_shielding_key(
Expand All @@ -45,7 +45,7 @@ fn set_user_shielding_key_works() {

#[test]
fn create_identity_works() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
let ss58_prefix = 131_u16;
let metadata: MetadataOf<Test> = vec![0u8; 16].try_into().unwrap();
assert_ok!(IMT::create_identity(
Expand All @@ -70,9 +70,21 @@ fn create_identity_works() {

#[test]
fn remove_identity_works() {
new_test_ext().execute_with(|| {
new_test_ext(false).execute_with(|| {
assert_noop!(
IMT::remove_identity(RuntimeOrigin::signed(ALICE), BOB, alice_web3_identity()),
Error::<Test>::InvalidUserShieldingKey
);

let shielding_key: UserShieldingKeyType = [0u8; USER_SHIELDING_KEY_LEN];
assert_ok!(IMT::set_user_shielding_key(
RuntimeOrigin::signed(ALICE),
BOB,
shielding_key.clone()
));

let metadata: MetadataOf<Test> = vec![0u8; 16].try_into().unwrap();
let ss58_prefix = 131_u16;
let ss58_prefix = 31_u16;
assert_noop!(
IMT::remove_identity(RuntimeOrigin::signed(ALICE), BOB, alice_web3_identity()),
Error::<Test>::IdentityNotExist
Expand Down Expand Up @@ -114,7 +126,7 @@ fn remove_identity_works() {

#[test]
fn verify_identity_works() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
let metadata: MetadataOf<Test> = vec![0u8; 16].try_into().unwrap();
let ss58_prefix = 131_u16;
assert_ok!(IMT::create_identity(
Expand Down Expand Up @@ -145,7 +157,7 @@ fn verify_identity_works() {

#[test]
fn get_id_graph_works() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
let metadata3: MetadataOf<Test> = vec![0u8; 16].try_into().unwrap();
let ss58_prefix = 131_u16;
assert_ok!(IMT::create_identity(
Expand Down Expand Up @@ -191,7 +203,7 @@ fn get_id_graph_works() {

#[test]
fn verify_identity_fails_when_too_early() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
const CREATION_REQUEST_BLOCK: ParentchainBlockNumber = 2;
const VERIFICATION_REQUEST_BLOCK: ParentchainBlockNumber = 1;

Expand Down Expand Up @@ -228,7 +240,7 @@ fn verify_identity_fails_when_too_early() {

#[test]
fn verify_identity_fails_when_too_late() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
const CREATION_REQUEST_BLOCK: ParentchainBlockNumber = 1;
const VERIFICATION_REQUEST_BLOCK: ParentchainBlockNumber = 5;

Expand Down Expand Up @@ -265,7 +277,7 @@ fn verify_identity_fails_when_too_late() {

#[test]
fn get_id_graph_with_max_len_works() {
new_test_ext().execute_with(|| {
new_test_ext(true).execute_with(|| {
// fill in 21 identities, starting from 1 to reserve place for prime_id
for i in 1..22 {
assert_ok!(IMT::create_identity(
Expand All @@ -292,6 +304,6 @@ fn get_id_graph_with_max_len_works() {
let id_graph = IMT::get_id_graph_with_max_len(&BOB, 30);
assert_eq!(id_graph.len(), 22);
assert_eq!(String::from_utf8(id_graph.get(0).unwrap().0.flat()).unwrap(), "did:twitter:web2:_:alice21");
assert_eq!(String::from_utf8(id_graph.get(21).unwrap().0.flat()).unwrap(), "did:litentry:web3:substrate:0x0202020202020202020202020202020202020202020202020202020202020202");
assert_eq!(String::from_utf8(id_graph.get(21).unwrap().0.flat()).unwrap(), "did:litmus:web3:substrate:0x0202020202020202020202020202020202020202020202020202020202020202");
});
}
13 changes: 13 additions & 0 deletions tee-worker/litentry/primitives/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub enum SubstrateNetwork {
Litentry,
Litmus,
Khala,
TestNet,
}

impl SubstrateNetwork {
Expand All @@ -84,6 +85,18 @@ impl SubstrateNetwork {
Self::Litentry => 31,
Self::Litmus => 131,
Self::Khala => 30,
Self::TestNet => 13,
}
}

pub fn from_ss58_prefix(prefix: u16) -> Self {
match prefix {
0 => Self::Polkadot,
2 => Self::Kusama,
31 => Self::Litentry,
131 => Self::Litmus,
30 => Self::Khala,
_ => Self::TestNet,
}
}
}
Expand Down
21 changes: 18 additions & 3 deletions tee-worker/ts-tests/identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ describeLitentry('Test Identity', (context) => {
var signature_ethereum;
var signature_substrate;

step('Invalid user shielding key', async function () {
const encode = context.api.createType('LitentryIdentity', substrateIdentity).toHex();
const ciphertext = encryptWithTeeShieldingKey(context.teeShieldingKey, encode).toString('hex');
const tx = context.api.tx.identityManagement.createIdentity(context.mrEnclave, context.defaultSigner[0].address, `0x${ciphertext}`, null);
await sendTxUntilInBlock(context.api, tx, context.defaultSigner[0]);

const events = await listenEvent(context.api, 'identityManagement', ['StfError']);
expect(events.length).to.be.equal(1);

await checkFailReason(events, 'InvalidUserShieldingKey', true);
})

step('set user shielding key', async function () {
const alice = await setUserShieldingKey(context, context.defaultSigner[0], aesKey, true);
assert.equal(alice, u8aToHex(context.defaultSigner[0].addressRaw), 'check caller error');
Expand Down Expand Up @@ -331,7 +343,8 @@ describeLitentry('Test Identity', (context) => {
const substratePrimeIdentity = <LitentryIdentity>{
Substrate: <SubstrateIdentity>{
address: `0x${Buffer.from(context.defaultSigner[0].publicKey).toString('hex')}`,
network: 'Litentry',
// When testing with integritee-node, change network to: TestNet
network: 'Litmus',
},
};

Expand All @@ -342,7 +355,8 @@ describeLitentry('Test Identity', (context) => {

const events = await listenEvent(context.api, 'identityManagement', ['StfError']);
expect(events.length).to.be.equal(1);
const result = events[0].method as string;

await checkFailReason(events, 'RemovePrimeIdentityDisallowed', true);
});

step('remove error identities', async function () {
Expand All @@ -359,8 +373,9 @@ describeLitentry('Test Identity', (context) => {

await checkFailReason(resp_not_exist_identities, 'IdentityNotExist', true);

//remove a challenge code before the code is set
//context.defaultSigner[2] doesn't have a challenge code
const bob = await setUserShieldingKey(context, context.defaultSigner[2], aesKey, true);
assert.equal(bob, u8aToHex(context.defaultSigner[2].addressRaw), 'check caller error');
const resp_not_created_identities = (await removeErrorIdentities(
context,
context.defaultSigner[2],
Expand Down
4 changes: 2 additions & 2 deletions tee-worker/ts-tests/type-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const teeTypes = {
_enum: ['Twitter', 'Discord', 'Github'],
},
SubstrateNetwork: {
_enum: ['Polkadot', 'Kusama', 'Litentry', 'Litmus'],
_enum: ['Polkadot', 'Kusama', 'Litentry', 'Litmus', 'Khala', 'TestNet'],
},
EvmNetwork: {
_enum: ['Ethereum', 'BSC'],
Expand Down Expand Up @@ -275,7 +275,7 @@ export type Web3Network = {
};

export type Web2Network = 'Twitter' | 'Discord' | 'Github';
export type SubstrateNetwork = 'Polkadot' | 'Kusama' | 'Litentry' | 'Litmus';
export type SubstrateNetwork = 'Polkadot' | 'Kusama' | 'Litentry' | 'Litmus' | 'Khala' | 'TestNet';
export type EvmNetwork = 'Ethereum' | 'BSC';

export type IdentityGenericEvent = {
Expand Down

0 comments on commit 97e9576

Please sign in to comment.