Giter Club home page Giter Club logo

ssi's Introduction

SSI's documentation is currently packaged with the DIDKit documentation here.

SSI

SSI provides core Verifiable Credential and Decentralized Identifier functionality in Rust. Rust was chosen for its expressive type system, memory safety, simple dependency web, and suitability across different platforms including embedded systems. This library is embedded in the the cross-platform didkit library as a core dependency.

Security Audits

ssi has undergone the following security reviews:

We are setting up a process to accept contributions. Please feel free to open issues or PRs in the interim, but we cannot merge external changes until this process is in place.

Install

Crates.io

ssi = "0.4"

From Source

$ git clone https://github.com/spruceid/ssi
$ cd ssi
$ git submodule update --init
$ cargo build

Additional resources

ssi's People

Contributors

bumblefudge avatar charlesshuller avatar chunningham avatar clehner avatar cobward avatar fairingrey avatar kevinz917 avatar krhoda avatar mikelodder7 avatar obstropolos avatar sbihel avatar shoito avatar taylorbeeston avatar theosirian avatar timothee-haudebourg avatar tristanmiller-spruceid avatar vdods avatar voronar avatar w4ll3 avatar wyc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ssi's Issues

Build Fails on MacOS Catalina 10.15.7

Issue description

The http-jni-docs branch fails to build on MacOS Catalina with the following rustc version:

% rustc --version
rustc 1.50.0-nightly (da3846948 2020-11-21) 

Steps to reproduce the issue

  1. Run MacOS
  2. git clone [email protected]:spruceid/ssi.git
  3. git checkout http-jni-docs
  4. cargo build

What's the expected result?

  • Build success.

What's the actual result?

  • Build failure.

Build logs

didkit % cargo build
warning: unused import: `Statement`
 --> /Users/wayne/work/ssi/src/jsonld.rs:6:5
  |
6 |     Statement,
  |     ^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `identifier`
  --> /Users/wayne/work/ssi/src/jsonld.rs:69:9
   |
69 |     let identifier = match identifier {
   |         ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_identifier`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `node_map`
   --> /Users/wayne/work/ssi/src/jsonld.rs:329:5
    |
329 |     node_map: &NodeMap,
    |     ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_node_map`

warning: unused variable: `dataset`
   --> /Users/wayne/work/ssi/src/jsonld.rs:330:5
    |
330 |     dataset: &mut DataSet,
    |     ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dataset`

warning: unused variable: `options`
   --> /Users/wayne/work/ssi/src/jsonld.rs:331:5
    |
331 |     options: Option<&JsonLdOptions>,
    |     ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_options`

warning: field is never read: `produce_generalized_rdf`
  --> /Users/wayne/work/ssi/src/jsonld.rs:23:5
   |
23 |     produce_generalized_rdf: Option<bool>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: field is never read: `rdf_direction`
  --> /Users/wayne/work/ssi/src/jsonld.rs:24:5
   |
24 |     rdf_direction: Option<RdfDirection>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: 7 warnings emitted

   Compiling didkit_cbindings v0.1.0 (/Users/wayne/work/didkit/lib/cbindings)
   Compiling didkit-http v0.0.1 (/Users/wayne/work/didkit/http)
error: future cannot be sent between threads safely
   --> http/src/lib.rs:164:9
    |
164 | /         Box::pin(async move {
165 | |             let body_reader = hyper::body::aggregate(req).await?.reader();
166 | |             let issue_req: IssueCredentialRequest = match serde_json::from_reader(body_reader) {
167 | |                 Ok(reader) => reader,
...   |
188 | |                 .map_err(|err| err.into())
189 | |         })
    | |__________^ future created by async block is not `Send`
    |
    = help: the trait `Send` is not implemented for `(dyn StdError + 'static)`
note: future is not `Send` as this value is used across an await
   --> http/src/lib.rs:178:28
    |
177 |                   Err(err) => {
    |                       --- has type `didkit::Error` which is not `Send`
178 |                       return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |  ____________________________^
179 | |                         .await;
    | |______________________________^ await occurs here, with `err` maybe used later
180 |                   }
    |                   - `err` is later dropped here
    = note: required for the cast to the object type `dyn Future<Output = std::result::Result<Response<Body>, error::Error>> + Send`

error: future cannot be sent between threads safely
   --> http/src/lib.rs:164:9
    |
164 | /         Box::pin(async move {
165 | |             let body_reader = hyper::body::aggregate(req).await?.reader();
166 | |             let issue_req: IssueCredentialRequest = match serde_json::from_reader(body_reader) {
167 | |                 Ok(reader) => reader,
...   |
188 | |                 .map_err(|err| err.into())
189 | |         })
    | |__________^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `(dyn StdError + 'static)`
note: future is not `Send` as this value is used across an await
   --> http/src/lib.rs:178:28
    |
178 |                       return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |  ____________________________^
179 | |                         .await;
    | |______________________________^ first, await occurs here, with `err` maybe used later...
note: `err` is later dropped here
   --> http/src/lib.rs:179:31
    |
178 |                     return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |                                                                              --- has type `&didkit::Error` which is not `Send`
179 |                         .await;
    |                               ^
help: consider moving this into a `let` binding to create a shorter lived borrow
   --> http/src/lib.rs:178:78
    |
178 |                     return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |                                                                              ^^^^^^^^^^^^^^^
    = note: required for the cast to the object type `dyn Future<Output = std::result::Result<Response<Body>, error::Error>> + Send`

error: future cannot be sent between threads safely
   --> http/src/lib.rs:246:9
    |
246 | /         Box::pin(async move {
247 | |             let body_reader = hyper::body::aggregate(req).await?.reader();
248 | |             let issue_req: ProvePresentationRequest = match serde_json::from_reader(body_reader) {
249 | |                 Ok(reader) => reader,
...   |
270 | |                 .map_err(|err| err.into())
271 | |         })
    | |__________^ future created by async block is not `Send`
    |
    = help: the trait `Send` is not implemented for `(dyn StdError + 'static)`
note: future is not `Send` as this value is used across an await
   --> http/src/lib.rs:260:28
    |
259 |                   Err(err) => {
    |                       --- has type `didkit::Error` which is not `Send`
260 |                       return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |  ____________________________^
261 | |                         .await;
    | |______________________________^ await occurs here, with `err` maybe used later
262 |                   }
    |                   - `err` is later dropped here
    = note: required for the cast to the object type `dyn Future<Output = std::result::Result<Response<Body>, error::Error>> + Send`

error: future cannot be sent between threads safely
   --> http/src/lib.rs:246:9
    |
246 | /         Box::pin(async move {
247 | |             let body_reader = hyper::body::aggregate(req).await?.reader();
248 | |             let issue_req: ProvePresentationRequest = match serde_json::from_reader(body_reader) {
249 | |                 Ok(reader) => reader,
...   |
270 | |                 .map_err(|err| err.into())
271 | |         })
    | |__________^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `(dyn StdError + 'static)`
note: future is not `Send` as this value is used across an await
   --> http/src/lib.rs:260:28
    |
260 |                       return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |  ____________________________^
261 | |                         .await;
    | |______________________________^ first, await occurs here, with `err` maybe used later...
note: `err` is later dropped here
   --> http/src/lib.rs:261:31
    |
260 |                     return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |                                                                              --- has type `&didkit::Error` which is not `Send`
261 |                         .await;
    |                               ^
help: consider moving this into a `let` binding to create a shorter lived borrow
   --> http/src/lib.rs:260:78
    |
260 |                     return Self::response(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
    |                                                                              ^^^^^^^^^^^^^^^
    = note: required for the cast to the object type `dyn Future<Output = std::result::Result<Response<Body>, error::Error>> + Send`

error: aborting due to 4 previous errors

error: could not compile `didkit-http`

To learn more, run the command again with --verbose.
didkit % rustc --version
rustc 1.50.0-nightly (da3846948 2020-11-21)

Implement std::error

To release ssi publicly, we should use thiserror to easily derive std::error::Error and make the API even more easy to use.

The main benefit of std::error::Error is the chain of errors, makes debugging easier.

Support OS-provided crypto libraries/APIs

Re: spruceid/didkit#16, spruceid/didkit#16 (comment)

Performance: an OS may provide access to cryptographic hardware that is faster than using our own crypto dependencies on the CPU.

Security and interop: an OS may provide access to manage and use keys where the private key material is not exposed to the application (including ssi). This could be considered a special case of #53.

Using OS-provided crypto libraries could be done with feature flags as in #52, and/or or by detecting the library at runtime (dynamic linking), with fallback to our compiled code.

Check for changes in DID draft

The required context in did-core is now https://www.w3.org/ns/did/v1. Check if there are other changes in the data model that src/did.rs should be updated to reflect.

Linked data proof / verification method types needing specification

Proof type Verification method type Used with
Ed25519BLAKE2BDigestSize20Base58CheckEncodedSignature2021 Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021 did:tz:tz1
P256BLAKE2BDigestSize20Base58CheckEncodedSignature2021 P256PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021 did:tz:tz3
Eip712Signature2021 Eip712Method2021 did:ethr (experimental)
SolanaSignature2021 SolanaMethod2021 did:sol (experimental) or did:pkh:sol (did:pkh:solana)
AleoSignature2021 AleoMethod2021 or BlockchainVerificationMethod2021 did:pkh:aleo
TezosJcsSignature2021 TezosMethod2021 did:tz or did:pkh:tz
TezosSignature2021 TezosMethod2021 did:tz or did:pkh:tz
EthereumPersonalSignature2021 EcdsaSecp256k1VerificationKey2019 or EcdsaSecp256k1RecoveryMethod2020

Setup CI/CD

  • Compilation checks
  • Unit testing
  • Integration testing

1 test pending for vc-test-suite?

@clehner, phenomenal work on the test suite. I was running the test suite and found that only a single test was pending under the optional section. Is this intentional or is there a different mode I should run the test suite in?

Screen Shot 2020-09-06 at 5 32 00 PM

Support JSON Schema for VCs

A credential's credentialSchema may specify a URI for a JSON Schema file for validating the credential. (https://w3c.github.io/vc-data-model/#proofs-signatures)

A Rust library for JSON Schema is jsonschema.

jsonschema uses HTTP client library reqwest which pulls in a lot of dependencies (#18). Also, the requests are blocking and responses are not cached (Stranger6667/jsonschema-rs#75). But it looks like the resolver is not used internally to validation but only if the caller calls it. So this might not be a problem us, especially if reqwest is made optional (Stranger6667/jsonschema-rs#137), as we can do our own HTTP resolution (edit: maybe just using reqwest as well), e.g. alongside resolution for JSON-LD Context documents.

Another library is schemafy (mentioned in #21 (comment)) which generates types from schemas at compile time. But it doesn't have full support for the latest JSON Schema drafts. Its use may be limited here since I think we want to be able to validate credentials against arbitrary schemas at runtime.

Implement X.509-based DID method

We are encountering users who want to utilize traditional CA infrastructure in conjunction with DIDs/VCs. A DID method may be an appropriate way to ensure this interoperability.

I think an ultimate demo of this would be X.509-based DIDs talking to did:onion-based DIDs over TorGap as per spruceid/didkit#68

Possible examples of DIDs based on X.509:

did:x509:canonical:ccadb:example.com
did:x509:canonical:fcpca:website.gov
did:x509:md5:444bcb3a3fcf8389296c49467f27e1d6:server.corpinternal.com
did:x509:sha1:99b4251e2eee05d8292e8397a90165293d116028:server.corpinternal.com 
did:x509:sha2:2689367b205c16ce32ed4200942b8b8b1e262dfc70d9bc9fbc77c49699a4f1df:server.corpinternal.com

The finger/thumbprints (md5/sha1/sha2) can be defined as per:

Uncurated and undirected dump of prior and related work:
https://github.com/WebOfTrustInfo/rwot9-prague/blob/master/topics-and-advance-readings/X.509-DID-Method.md
https://www.researchgate.net/publication/342027346_Distributed-Ledger-based_Authentication_with_Decentralized_Identifiers_and_Verifiable_Credentials
https://hyperledger-fabric.readthedocs.io/en/release-2.2/identity/identity.html
https://arxiv.org/pdf/2003.05106.pdf
https://www.ndss-symposium.org/wp-content/uploads/diss2019_05_Lagutin_paper.pdf
https://github.com/WebOfTrustInfo/rwot1-sf/blob/master/draft-documents/Decentralized-Public-Key-Infrastructure-CURRENT.md
https://arxiv.org/pdf/2004.07063.pdf

This would be a good candidate specification for a CCG work item.

Implement `did-web`

We believe that many users would like to use this to test out the library. Fortunately, it looks like we have much of the implementation in did-resolver as per the HTTP resolver!

Consider moving DID methods out of this repo

By putting DID methods into their own repos but implementing the DID traits, we can ensure maximum modularity and extensibility. We should consider how this affects SSI and DIDKit, and if it would be worthwhile. What are the considerations and major changes?

Create dependency security/reliability audit strategy

We should minimize external dependencies where possible. Towards this end, we should do a cost-benefit analysis of our dependencies and their dependencies (and so on) to see if they warrant being in the branch. Things we want to avoid:

  • Unmaintained dependencies that are not responsive to bug fixes
  • Dependencies of poor quality that already have bugs or security vulnerabilities
  • Dependencies that pull in binaries or non-rust artifacts during compile or runtime
    etc.....

Todo:

  • Find resources online that can guide us in Rust dependency review
  • Come up with a general review strategy ourselves
  • Consult an expert on how to do this and receive feedback on our approach

Consider ID2020 Certification Requirements

ID2020 is an organization committed to solving important human rights and privacy issues globally, especially in the global south. They have technical and other requirements to certify software to their standards. We should use these to inform our roadmap, implementation, and products, then attaining certification if appropriate.

Compile-time JSON-LD context expansion

If we were to build a JSON-LD library, I wonder how tenable would be the idea of resolving and expanding contexts into code via metaprogramming prior to compilation. We could assume the JSON files are in hand--I wonder if there would be any benefits from a safety and performance perspective, and how much binary bloat such a flag might add. Just a thought--this is likely one of those "someday maybe" features that we revisit when the need actually arises.

cc @clehner

Asynchronous API for WASM

#47 introduces a dependency on async_std, as json-ld's JSON-LD expansion implementation is asynchronous. We keep the existing synchronous API by using block_on internally. But for WASM, block_on does not a return a value, and requires the future to be static, since it uses wasm_bindgen_futures::spawn_local. This is a problem for using #47 with WASM (#52) while keeping ssi's blocking API.

I see the following options to proceed:

  • Make block_on/spawn_local work somehow, maybe using global static storage and/or message passing.
  • Make json-ld support synchronous expansion.
  • Implement synchronous expansion in some limited way instead of using json-ld.
  • Require JSON-LD documents to be already expanded for generating/verifying ld-proofs. Add an asynchronous function to perform the expansion.
  • Make generate and verify functions asynchronous.

The last option might be the most sensible. I think we want to support asynchronous usage anyway, e.g. to be able to make HTTP requests during expansion and verification.

wasm-bindgen-futures can convert a Rust Future to a JS Promise. So if ssi uses async functions, DIDKit's WASM package should be able to wrap those with Promises.

Non-WASM use of ssi could continue to operate synchronously by using block_on in the application code. I think that would work for the DIDKit CLI and FFIs.
When we start to do actual I/O then we can update the FFIs to integrate with native event loops.

URI -> IRI for JSON-LD Processing

@clehner the JSON-LD spec works in IRIs instead of URIs, should we update our implementation and variable naming to accommodate for this? I realize that a lot of our data structures are not JSON-LD specific, but perhaps it would be cleaner to adopt IRI wholesale. I believe this would affect only variable naming in most instances, as Rust strings support UTF-8.

Do you have thoughts on this?

References:

Replacing git dependencies

Currently the ssi package depends on these:

Cargo book says crates.io does not allow packages to be published with git dependencies. So for publishing to crates.io, I think we need to either:

Edit: #139 means json no longer needs to be vendored. Vendoring json-ld is implemented in #138.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.