1#[cfg(not(target_arch = "wasm32"))]
2pub mod c;
3mod did_methods;
4pub mod error;
5#[cfg(not(target_arch = "wasm32"))]
6pub mod jni;
7#[cfg(not(target_arch = "wasm32"))]
8pub mod runtime;
9#[cfg(not(any(target_arch = "wasm32", target_os = "windows")))]
10pub mod ssh_agent;
11
12#[macro_use]
13extern crate lazy_static;
14
15pub use crate::did_methods::DID_METHODS;
16pub use crate::error::Error;
17
18pub use ssi;
19pub use ssi::did::VerificationRelationship;
20pub use ssi::did::{
21 DIDCreate, DIDDeactivate, DIDDocumentOperation, DIDMethod, DIDRecover, DIDUpdate, Document,
22 Source, DIDURL,
23};
24pub use ssi::did_resolve::resolve_key;
25#[cfg(feature = "http-did")]
26pub use ssi::did_resolve::HTTPDIDResolver;
27pub use ssi::did_resolve::{
28 dereference, Content, ContentMetadata, DIDResolver, DereferencingInputMetadata,
29 DocumentMetadata, Metadata, ResolutionInputMetadata, ResolutionMetadata, ResolutionResult,
30 SeriesResolver,
31};
32pub use ssi::jsonld::ContextLoader;
33pub use ssi::jwk::JWK;
34pub use ssi::ldp::ProofPreparation;
35pub use ssi::tzkey::jwk_from_tezos_key;
36pub use ssi::vc::get_verification_method;
37pub use ssi::vc::Credential as VerifiableCredential;
38pub use ssi::vc::CredentialOrJWT;
39pub use ssi::vc::LinkedDataProofOptions;
40pub use ssi::vc::Presentation as VerifiablePresentation;
41pub use ssi::vc::VerificationResult;
42pub use ssi::vc::URI;
43pub use ssi::zcap::{Delegation, Invocation};
44
45use core::str::FromStr;
46use serde::{Deserialize, Serialize};
47
48#[derive(Debug, Serialize, Deserialize, Clone, Default)]
49#[non_exhaustive]
50#[serde(rename_all = "camelCase")]
51#[serde(deny_unknown_fields)]
52pub struct JWTOrLDPOptions {
53 #[serde(flatten)]
55 pub ldp_options: LinkedDataProofOptions,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub proof_format: Option<ProofFormat>,
59}
60
61impl JWTOrLDPOptions {
62 pub fn default_for_vp() -> Self {
63 Self {
64 ldp_options: LinkedDataProofOptions {
65 proof_purpose: Some(VerificationRelationship::Authentication),
66 ..Default::default()
67 },
68 proof_format: None,
69 }
70 }
71}
72
73#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
74#[non_exhaustive]
75pub enum ProofFormat {
76 #[serde(rename = "ldp")]
78 LDP,
79 #[serde(rename = "jwt")]
81 JWT,
82}
83impl Default for ProofFormat {
87 fn default() -> Self {
88 Self::LDP
89 }
90}
91
92impl std::fmt::Display for ProofFormat {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 match self {
95 Self::LDP => write!(f, "ldp"),
96 Self::JWT => write!(f, "jwt"),
97 }
98 }
99}
100
101impl FromStr for ProofFormat {
102 type Err = String;
103 fn from_str(s: &str) -> Result<Self, Self::Err> {
104 match &s[..] {
105 "ldp" => Ok(Self::LDP),
106 "jwt" => Ok(Self::JWT),
107 _ => Err(format!("Unexpected proof format: {}", s))?,
108 }
109 }
110}
111
112#[derive(thiserror::Error, Debug)]
113pub enum GenerateProofError {
114 #[cfg(not(any(target_arch = "wasm32", target_os = "windows")))]
115 #[error("Unable to sign: {0}")]
116 Sign(#[from] crate::ssh_agent::SignError),
117 #[error("SSI Linked Data Proof: {0}")]
118 LDP(#[from] ssi::ldp::Error),
119 #[error("IO: {0}")]
120 IO(#[from] std::io::Error),
121 #[error("WASM support for ssh-agent is not enabled")]
122 NoWASM,
123 #[error("Windows support for ssh-agent is not enabled")]
124 NoWindows,
125}
126
127pub async fn generate_proof(
128 document: &(dyn ssi::ldp::LinkedDataDocument + Sync),
129 key: Option<&JWK>,
130 options: LinkedDataProofOptions,
131 resolver: &dyn DIDResolver,
132 context_loader: &mut ContextLoader,
133 ssh_agent_sock_path_opt: Option<&str>,
134) -> Result<ssi::ldp::Proof, GenerateProofError> {
135 use ssi::ldp::LinkedDataProofs;
136 let proof = match ssh_agent_sock_path_opt {
137 #[cfg(target_arch = "wasm32")]
138 Some(_) => {
139 return Err(GenerateProofError::NoWASM);
140 }
141 #[cfg(target_os = "windows")]
142 Some(_) => {
143 return Err(GenerateProofError::NoWindows);
144 }
145 #[cfg(not(any(target_arch = "wasm32", target_os = "windows")))]
146 Some(sock_path) => {
147 use tokio::net::UnixStream;
148 let mut ssh_agent_sock = UnixStream::connect(sock_path).await?;
149 crate::ssh_agent::generate_proof(
150 &mut ssh_agent_sock,
151 document,
152 options,
153 resolver,
154 context_loader,
155 key,
156 )
157 .await?
158 }
159 None => {
160 let jwk = key.expect("JWK, Key Path, or SSH Agent option is required.");
161 LinkedDataProofs::sign(document, &options, resolver, context_loader, &jwk, None).await?
162 }
163 };
164
165 Ok(proof)
166}