ssi 0.16.0

Core library for Verifiable Credentials and Decentralized Identifiers.
// To generate test vectors:
// cargo run --example present ldp ldp < examples/files/vc.jsonld > examples/files/vp.jsonld
// cargo run --example present ldp jwt < examples/files/vc.jsonld > examples/files/vp.jwt
// cargo run --example present jwt ldp < examples/files/vc.jwt > examples/files/vp-jwtvc.jsonld
// cargo run --example present jwt jwt < examples/files/vc.jwt > examples/files/vp-jwtvc.jwt
//
// For `nushell` users:
// cat examples/files/vc.jsonld | cargo run --example present ldp ldp | save examples/files/vp.jsonld
// cat examples/files/vc.jsonld | cargo run --example present ldp jwt | save examples/files/vp.jwt
// cat examples/files/vc.jwt | cargo run --example present jwt ldp | save examples/files/vp-jwtvc.jsonld
// cat examples/files/vc.jwt | cargo run --example present jwt jwt | save examples/files/vp-jwtvc.jwt
use ssi::{
    claims::{
        data_integrity::{AnySuite, CryptographicSuite, ProofOptions},
        jws::{JwsPayload, JwsString},
    },
    verification_methods::{ProofPurpose, SingleSecretSigner},
};
use ssi_claims::{
    data_integrity::AnyDataIntegrity,
    vc::{v1::ToJwtClaims, AnyJsonCredential},
    VerificationParameters,
};
use ssi_dids::DIDResolver;
use static_iref::{iri, uri};

async fn verify(proof_format_in: &str, proof_format_out: &str, input_vc: &str) {
    let vc = match proof_format_in {
        "ldp" => {
            let vc_ldp: AnyDataIntegrity<AnyJsonCredential> =
                serde_json::from_str(input_vc).unwrap();
            ssi::claims::JsonCredentialOrJws::Credential(Box::new(vc_ldp))
        }
        "jwt" => match JwsString::from_string(input_vc.to_string()) {
            Ok(vc_jwt) => ssi::claims::JsonCredentialOrJws::Jws(vc_jwt),
            Err(_) => {
                panic!("Input must be a compact JWT");
            }
        },
        format => panic!("unknown input proof format: {}", format),
    };

    let vp = ssi::claims::vc::v1::JsonPresentation::new(
        None,
        Some(uri!("did:example:foo").to_owned()),
        vec![vc],
    );

    let key_str = include_str!("../tests/ed25519-2020-10-18.json");
    let mut key: ssi::jwk::JWK = serde_json::from_str(key_str).unwrap();
    key.key_id = Some("did:example:foo#key2".to_string());
    let resolver = ssi::dids::example::ExampleDIDResolver::default().into_vm_resolver();
    let verifier = VerificationParameters::from_resolver(&resolver);
    let signer = SingleSecretSigner::new(key.clone()).into_local();

    // let mut proof_options = ssi::vc::LinkedDataProofOptions::default();
    // let verification_method = "did:example:foo#key2".to_string();
    // proof_options.verification_method = Some(ssi::vc::URI::String(verification_method));
    // proof_options.proof_purpose = Some(ssi::vc::ProofPurpose::Authentication);
    // proof_options.challenge = Some("example".to_string());
    let verification_method = iri!("did:example:foo#key2").into();

    match proof_format_out {
        "ldp" => {
            let mut params = ProofOptions::from_method(verification_method);

            params.proof_purpose = ProofPurpose::Authentication;
            params.challenge = Some("example".to_owned());

            let suite = AnySuite::pick(&key, params.verification_method.as_ref()).unwrap();
            let vp = suite.sign(vp, &resolver, &signer, params).await.unwrap();

            let result = vp.verify(verifier).await.expect("verification failed");
            if result.is_err() {
                panic!("verify failed");
            }

            let writer = std::io::BufWriter::new(std::io::stdout());
            serde_json::to_writer_pretty(writer, &vp).unwrap();
        }
        "jwt" => {
            let jwt = vp.to_jwt_claims().unwrap().sign(&key).await.unwrap();

            let result = jwt.verify(verifier).await.expect("verification failed");
            if result.is_err() {
                panic!("verify failed");
            }

            print!("{}", jwt);
        }
        format => panic!("unknown output proof format: {}", format),
    }
}

#[async_std::main]
async fn main() {
    let mut args = std::env::args().skip(1);
    let proof_format_in = args.next().unwrap();
    let proof_format_out = args.next().unwrap();

    let input_vc = std::io::read_to_string(std::io::stdin()).unwrap();
    verify(&proof_format_in[..], &proof_format_out[..], &input_vc).await;
}

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

    #[async_std::test]
    async fn ldp_ldp() {
        verify("ldp", "ldp", include_str!("files/vc.jsonld")).await;
    }

    #[async_std::test]
    async fn ldp_jwt() {
        verify("ldp", "jwt", include_str!("files/vc.jsonld")).await;
    }

    #[async_std::test]
    async fn jwt_ldp() {
        verify("jwt", "ldp", include_str!("files/vc.jwt")).await;
    }

    #[async_std::test]
    async fn jwt_jwt() {
        verify("jwt", "jwt", include_str!("files/vc.jwt")).await;
    }
}