Skip to content

Commit

Permalink
feat: implement new wallet trait for askar
Browse files Browse the repository at this point in the history
Signed-off-by: Ondrej Prazak <[email protected]>
  • Loading branch information
Ondrej Prazak committed Dec 6, 2023
1 parent 13407b8 commit 0d8b974
Show file tree
Hide file tree
Showing 8 changed files with 1,308 additions and 14 deletions.
583 changes: 570 additions & 13 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions aries/aries_vcx_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ vdr_proxy_ledger = ["credx", "dep:indy-vdr-proxy-client"]
# Feature flag to allow legacy proof verification
legacy_proof = []

askar_wallet = ["dep:aries-askar"]

[dependencies]
agency_client = { path = "../misc/legacy/agency_client" }
aries-askar = { git = "https://github.com/hyperledger/aries-askar.git", tag = "v0.3.0", optional = true }
bs58 = { version = "0.5" }
indy-vdr = { git = "https://github.com/hyperledger/indy-vdr.git", rev = "c143268", default-features = false, features = ["log"] }
indy-credx = { git = "https://github.com/hyperledger/indy-shared-rs", tag = "v1.1.0", optional = true }
Expand Down
37 changes: 37 additions & 0 deletions aries/aries_vcx_core/src/errors/mapping_askar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use aries_askar::ErrorKind;

use super::error::{AriesVcxCoreError, AriesVcxCoreErrorKind};

impl From<aries_askar::Error> for AriesVcxCoreError {
fn from(err: aries_askar::Error) -> Self {
match err.kind() {
ErrorKind::Backend => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::Busy => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::Custom => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::Duplicate => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::DuplicationWalletRecord, err)
}
ErrorKind::Encryption => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::Input => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::NotFound => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletRecordNotFound, err)
}
ErrorKind::Unexpected => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
ErrorKind::Unsupported => {
AriesVcxCoreError::from_msg(AriesVcxCoreErrorKind::WalletUnexpected, err)
}
}
}
}
2 changes: 2 additions & 0 deletions aries/aries_vcx_core/src/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod error;
mod mapping_agency_client;
#[cfg(feature = "askar_wallet")]
mod mapping_askar;
#[cfg(feature = "credx")]
mod mapping_credx;
#[cfg(feature = "vdrtools_wallet")]
Expand Down
187 changes: 187 additions & 0 deletions aries/aries_vcx_core/src/wallet2/askar_wallet/askar_did_wallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
use aries_askar::kms::KeyAlg;
use async_trait::async_trait;

use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind};
use crate::wallet2::{DidWallet, SigType};
use crate::{errors::error::VcxCoreResult, wallet2::DidData};

use super::{AskarWallet, RngMethod};

#[async_trait]
impl DidWallet for AskarWallet {
async fn create_and_store_my_did(
&self,
seed: &str,
_method_name: Option<&str>,
) -> VcxCoreResult<DidData> {
let mut tx = self.backend.transaction(self.profile.clone()).await?;

let (did, local_key) = self
.insert_key(
&mut tx,
KeyAlg::Ed25519,
seed.as_bytes(),
RngMethod::RandomDet,
)
.await?;

let verkey = self.local_key_to_bs58_pubkey(&local_key)?;

self.insert_did(&mut tx, &did, &did, &verkey, None).await?;

tx.commit().await?;

Ok(DidData { did, verkey })
}

async fn did_key(&self, did: &str) -> VcxCoreResult<String> {
let mut session = self.backend.session(self.profile.clone()).await?;

let data = self.find_did(&mut session, did).await?;

if let Some(_) = data {
let local_key = self.fetch_local_key(&mut session, did).await?;
let verkey = self.local_key_to_bs58_pubkey(&local_key)?;

return Ok(verkey);
}

Err(AriesVcxCoreError::from_msg(
AriesVcxCoreErrorKind::WalletRecordNotFound,
"did not found",
))
}

async fn replace_did_key(&self, did: &str, seed: &str) -> VcxCoreResult<String> {
let mut tx = self.backend.transaction(self.profile.clone()).await?;

let data = self.find_did(&mut tx, did).await?;

if let Some(did_data) = data {
let key_name = &did_data.verkey[0..16];

let (new_key_name, local_key) = self
.insert_key(
&mut tx,
KeyAlg::Ed25519,
seed.as_bytes(),
RngMethod::RandomDet,
)
.await?;

let verkey = self.local_key_to_bs58_pubkey(&local_key)?;

self.insert_did(&mut tx, &new_key_name, &did, &verkey, None)
.await?;

tx.remove(key_name, did).await?;
tx.remove_key(key_name).await?;
tx.commit().await?;
return Ok(verkey);
}

Err(AriesVcxCoreError::from_msg(
AriesVcxCoreErrorKind::InvalidDid,
"did not found",
))
}

async fn sign(&self, key_name: &str, msg: &[u8], sig_type: SigType) -> VcxCoreResult<Vec<u8>> {
let mut session = self.backend.session(self.profile.clone()).await?;
let res = session.fetch_key(key_name, false).await?;

if let Some(key) = res {
let local_key = key.load_local_key()?;
let res = local_key.sign_message(msg, Some(sig_type.into()))?;
return Ok(res);
}

Err(AriesVcxCoreError::from_msg(
AriesVcxCoreErrorKind::WalletUnexpected,
"key not found",
))
}

async fn verify(
&self,
key_name: &str,
msg: &[u8],
signature: &[u8],
sig_type: SigType,
) -> VcxCoreResult<bool> {
let mut session = self.backend.session(self.profile.clone()).await?;

if let Some(key) = session.fetch_key(key_name, false).await? {
let local_key = key.load_local_key()?;
let res = local_key.verify_signature(msg, signature, Some(sig_type.into()))?;
return Ok(res);
}

Ok(false)
}
}

#[cfg(test)]
mod test {
use super::*;

use crate::errors::error::AriesVcxCoreErrorKind;
use crate::wallet2::askar_wallet::test_helper::create_test_wallet;

#[tokio::test]
async fn test_askar_should_sign_and_verify() {
let wallet = create_test_wallet().await;

let first_data = wallet
.create_and_store_my_did("foo".into(), None)
.await
.unwrap();

let second_data = wallet
.create_and_store_my_did("bar".into(), None)
.await
.unwrap();

let msg = "sign this message";
let sig = wallet
.sign(&first_data.verkey, msg.as_bytes(), SigType::EdDSA)
.await
.unwrap();

assert!(wallet
.verify(&first_data.verkey, msg.as_bytes(), &sig, SigType::EdDSA)
.await
.unwrap());
assert!(!wallet
.verify(&second_data.verkey, msg.as_bytes(), &sig, SigType::EdDSA)
.await
.unwrap());

let err = wallet
.verify(&first_data.verkey, msg.as_bytes(), &sig, SigType::ES384)
.await
.unwrap_err();

assert_eq!(AriesVcxCoreErrorKind::WalletUnexpected, err.kind());
assert!(err.to_string().contains("Unsupported signature type"));
}

#[tokio::test]
async fn test_askar_should_replace_did_key() {
let wallet = create_test_wallet().await;

let first_data = wallet
.create_and_store_my_did("foo".into(), None)
.await
.unwrap();

let res = wallet
.replace_did_key(&first_data.did, "goo")
.await
.unwrap();

let new_data = wallet.did_key(&first_data.did).await.unwrap();

assert_eq!(res, new_data);
}
}
Loading

0 comments on commit 0d8b974

Please sign in to comment.