Skip to content

Commit

Permalink
feat: Move vc-util here and reanme it to ic-verifiable-credentials
Browse files Browse the repository at this point in the history
This copies over `vc-util` from the internet identity repository and
renames it to `ic-verifiable-credentials`. The metadata is updated as
well.
  • Loading branch information
Frederik Rothenberger committed Jun 17, 2024
1 parent c581fe7 commit a55d75b
Show file tree
Hide file tree
Showing 8 changed files with 1,799 additions and 27 deletions.
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ resolver = "2"

members = [
"dummy-relying-party",
"dummy-issuer"
"dummy-issuer",
"rust-packages/ic-verifiable-credentials",
]

[workspace.package]
Expand All @@ -19,15 +20,16 @@ base64 = "0.21"
sha2 = "0.10"
lazy_static = "1.4"
serde_cbor = "0.11"
serde_bytes = "0.11"
anyhow = "1.0"
candid = "0.10"
ic-cdk = "0.13"
ic-cdk-macros = "0.13"
ic-certification = "2.2"
ic-http-certification = "2.5"
ic-verifiable-credentials = { path = "rust-packages/ic-verifiable-credentials" }

# II dependencies
vc_util = { git="https://github.com/dfinity/internet-identity", rev="f668535241bb01fa9a7fb508b6579407c8afe59c" }
canister_sig_util = { git="https://github.com/dfinity/internet-identity", rev="f668535241bb01fa9a7fb508b6579407c8afe59c" }

[workspace.dependencies.serde]
Expand Down
2 changes: 1 addition & 1 deletion dummy-issuer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ candid.workspace = true
ic-cdk.workspace = true
ic-cdk-macros.workspace = true
ic-certification.workspace = true
ic-verifiable-credentials.workspace = true

# II Dependencies
vc_util.workspace = true
canister_sig_util.workspace = true

# Other dependencies
Expand Down
4 changes: 2 additions & 2 deletions dummy-issuer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ use serde_bytes::ByteBuf;
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::cell::RefCell;
use vc_util::issuer_api::{
use ic_verifiable_credentials::issuer_api::{
ArgumentValue, CredentialSpec, DerivationOriginData, DerivationOriginError,
DerivationOriginRequest, GetCredentialRequest, Icrc21ConsentInfo, Icrc21Error,
Icrc21VcConsentMessageRequest, IssueCredentialError, IssuedCredentialData,
PrepareCredentialRequest, PreparedCredentialData,
};
use vc_util::{
use ic_verifiable_credentials::{
build_credential_jwt, did_for_principal, vc_jwt_to_jws, vc_signing_input,
vc_signing_input_hash, CredentialParams,
};
Expand Down
2 changes: 1 addition & 1 deletion dummy-issuer/tests/dummy_issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ic_cdk::api::management_canister::main::CanisterId;
use pocket_ic::{PocketIc, WasmResult};
use serde::de::DeserializeOwned;
use serde_json::Value;
use vc_util::issuer_api::{
use ic_verifiable_credentials::issuer_api::{
ArgumentValue, CredentialSpec, DerivationOriginData, DerivationOriginError,
DerivationOriginRequest, GetCredentialRequest, Icrc21ConsentInfo, Icrc21ConsentPreferences,
Icrc21Error, Icrc21VcConsentMessageRequest, PrepareCredentialRequest, SignedIdAlias,
Expand Down
30 changes: 30 additions & 0 deletions rust-packages/ic-verifiable-credentials/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "ic-verifiable-credentials"
description = "Verifiable credentials issuing and verification for IC canisters."
version = "0.1.0"
keywords = ["internet-computer", "verifiable", "credentials", "icp", "dfinity"]
categories = ["api-bindings", "data-structures", "no-std"]
edition = "2021"

[dependencies]
# ic dependencies
candid.workspace = true
ic-certification.workspace = true
canister_sig_util.workspace = true

# vc dependencies
ic-crypto-standalone-sig-verifier = { git = "https://github.com/dfinity/ic", rev = "e69bcc7b319cbb3ebc22ec55af35287741244db6" }
ic-types = { git = "https://github.com/dfinity/ic", rev = "e69bcc7b319cbb3ebc22ec55af35287741244db6" }
identity_core = { git = "https://github.com/dfinity/identity.rs.git", rev = "aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8", default-features = false, features = ["ic-wasm"] }
identity_credential = { git = "https://github.com/dfinity/identity.rs.git", rev = "aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8", default-features = false , features = ["ic-wasm", "validator"] }
identity_jose = { git = "https://github.com/dfinity/identity.rs.git", rev = "aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8", default-features = false}

# other dependencies
serde.workspace = true
serde_bytes.workspace = true
serde_cbor.workspace = true
serde_json = "1"
sha2.workspace = true

[dev-dependencies]
assert_matches = "1.5"
213 changes: 213 additions & 0 deletions rust-packages/ic-verifiable-credentials/src/issuer_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
use candid::{CandidType, Deserialize, Nat};
use serde_bytes::ByteBuf;
use serde_json::{Number, Value};
use std::collections::HashMap;
use std::fmt::{Display, Formatter};

/// API to be implemented by an issuer of verifiable credentials.
/// (cf. https://github.com/dfinity/internet-identity/blob/main/docs/vc-spec.md)
#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct SignedIdAlias {
pub credential_jws: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct PrepareCredentialRequest {
pub signed_id_alias: SignedIdAlias,
pub credential_spec: CredentialSpec,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub enum IssueCredentialError {
UnknownSubject(String),
UnauthorizedSubject(String),
InvalidIdAlias(String),
SignatureNotFound(String),
Internal(String),
UnsupportedCredentialSpec(String),
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct GetCredentialRequest {
pub signed_id_alias: SignedIdAlias,
pub credential_spec: CredentialSpec,
pub prepared_context: Option<ByteBuf>,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct PreparedCredentialData {
pub prepared_context: Option<ByteBuf>,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct IssuedCredentialData {
pub vc_jws: String,
}

#[derive(Eq, PartialEq, Clone, Debug, CandidType, Deserialize)]
pub enum ArgumentValue {
String(String),
Int(i32),
}

impl Display for ArgumentValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self {
ArgumentValue::String(s) => write!(f, "'{}'", s),
ArgumentValue::Int(i) => write!(f, "{}", i),
}
}
}

impl From<ArgumentValue> for Value {
fn from(argument_value: ArgumentValue) -> Self {
match argument_value {
ArgumentValue::String(s) => Value::String(s),
ArgumentValue::Int(i) => Value::Number(Number::from(i)),
}
}
}

impl PartialEq<serde_json::Value> for ArgumentValue {
fn eq(&self, other: &Value) -> bool {
match self {
ArgumentValue::String(ls) => {
if let Some(rs) = other.as_str() {
ls.eq(rs)
} else {
false
}
}
ArgumentValue::Int(li) => {
if let Some(ri) = other.as_i64() {
(*li as i64) == ri
} else {
false
}
}
}
}
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct CredentialSpec {
pub credential_type: String,
pub arguments: Option<HashMap<String, ArgumentValue>>,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct ManifestRequest {}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub enum ManifestResponse {
Ok(ManifestData),
Err(String),
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct ManifestData {}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct Icrc21VcConsentMessageRequest {
pub credential_spec: CredentialSpec,
pub preferences: Icrc21ConsentPreferences,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct Icrc21ConsentPreferences {
pub language: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct Icrc21ErrorInfo {
pub description: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub enum Icrc21Error {
UnsupportedCanisterCall(Icrc21ErrorInfo),
ConsentMessageUnavailable(Icrc21ErrorInfo),
GenericError {
error_code: Nat,
description: String,
},
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct Icrc21ConsentInfo {
pub consent_message: String,
pub language: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct DerivationOriginRequest {
pub frontend_hostname: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub struct DerivationOriginData {
pub origin: String,
}

#[derive(Clone, Debug, CandidType, Deserialize, Eq, PartialEq)]
pub enum DerivationOriginError {
UnsupportedOrigin(String),
Internal(String),
}

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

#[test]
fn should_display_argument_values() {
assert_eq!("42", format!("{}", ArgumentValue::Int(42)));
assert_eq!("0", format!("{}", ArgumentValue::Int(0)));
assert_eq!("-7", format!("{}", ArgumentValue::Int(-7)));
assert_eq!("''", format!("{}", ArgumentValue::String("".to_string())));
assert_eq!(
"'some string'",
format!("{}", ArgumentValue::String("some string".to_string()))
);
}

#[test]
fn should_correctly_compare_argument_values() {
assert_eq!(ArgumentValue::Int(42), Value::from(42));
assert_eq!(ArgumentValue::Int(123456789), Value::from(123456789));
assert_eq!(ArgumentValue::Int(0), Value::from(0));

assert_ne!(ArgumentValue::Int(42), Value::from(11));
assert_ne!(ArgumentValue::Int(42), Value::from("some string"));
assert_ne!(ArgumentValue::Int(42), Value::from(true));
assert_ne!(ArgumentValue::Int(42), Value::from(vec![1, 2, 3]));

assert_eq!(
ArgumentValue::String("same string".to_string()),
Value::from("same string")
);
let long_string = "this is a bit longer string just for testing purposes";
assert_eq!(
ArgumentValue::String(long_string.to_string()),
Value::from(long_string)
);
assert_eq!(ArgumentValue::String("".to_string()), Value::from(""));

assert_ne!(
ArgumentValue::String("some string".to_string()),
Value::from("different")
);
assert_ne!(
ArgumentValue::String("a string".to_string()),
Value::from(42)
);
assert_ne!(
ArgumentValue::String("a string".to_string()),
Value::from(true)
);
assert_ne!(
ArgumentValue::String("a string".to_string()),
Value::from(vec![1, 2, 3])
);
}
}
Loading

0 comments on commit a55d75b

Please sign in to comment.