11// Copyright 2020-2024 IOTA Stiftung
22// SPDX-License-Identifier: Apache-2.0
33
4+ use anyhow:: Context ;
45use examples:: create_did;
56use examples:: random_stronghold_path;
67use examples:: MemStorage ;
78use examples:: API_ENDPOINT ;
89use identity_eddsa_verifier:: EdDSAJwsVerifier ;
10+ use identity_iota:: core:: FromJson ;
911use identity_iota:: core:: Object ;
1012use identity_iota:: core:: OrderedSet ;
1113use identity_iota:: core:: Url ;
1214use identity_iota:: credential:: CompoundJwtPresentationValidationError ;
15+ use identity_iota:: credential:: CredentialBuilder ;
1316use identity_iota:: credential:: DecodedJwtPresentation ;
1417use identity_iota:: credential:: Jwt ;
18+ use identity_iota:: credential:: JwtPresentationOptions ;
1519use identity_iota:: credential:: JwtPresentationValidationOptions ;
1620use identity_iota:: credential:: JwtPresentationValidator ;
1721use identity_iota:: credential:: JwtPresentationValidatorUtils ;
1822use identity_iota:: credential:: LinkedVerifiablePresentationService ;
23+ use identity_iota:: credential:: PresentationBuilder ;
24+ use identity_iota:: credential:: Subject ;
1925use identity_iota:: did:: CoreDID ;
2026use identity_iota:: did:: DIDUrl ;
2127use identity_iota:: did:: DID ;
@@ -25,7 +31,9 @@ use identity_iota::iota::IotaDID;
2531use identity_iota:: iota:: IotaDocument ;
2632use identity_iota:: iota:: IotaIdentityClientExt ;
2733use identity_iota:: resolver:: Resolver ;
34+ use identity_iota:: storage:: JwkDocumentExt ;
2835use identity_iota:: storage:: JwkMemStore ;
36+ use identity_iota:: storage:: JwsSignatureOptions ;
2937use identity_iota:: storage:: KeyIdMemstore ;
3038use iota_sdk:: client:: secret:: stronghold:: StrongholdSecretManager ;
3139use iota_sdk:: client:: secret:: SecretManager ;
@@ -36,8 +44,6 @@ use iota_sdk::types::block::output::AliasOutput;
3644use iota_sdk:: types:: block:: output:: AliasOutputBuilder ;
3745use iota_sdk:: types:: block:: output:: RentStructure ;
3846
39- const VP_JWT : & str = "eyJraWQiOiJkaWQ6aW90YTpybXM6MHg2Y2I5MWUyMGMxMzhhMTQ1MTUzMDY4ZTEwODNhMGEyYTUwYjU2ZDI1MGI3YjUzYzYwYmEzOTI4NGJkMWRjNzQxI1k5TUppd1k4U0s0NjlNcW0weXBZYzRYSUl5TnVpMzZIejdreVdkUEkyejQiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6aW90YTpybXM6MHg2Y2I5MWUyMGMxMzhhMTQ1MTUzMDY4ZTEwODNhMGEyYTUwYjU2ZDI1MGI3YjUzYzYwYmEzOTI4NGJkMWRjNzQxIiwibmJmIjoxNzI0Njg0NTEzLCJ2cCI6eyJAY29udGV4dCI6Imh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwidHlwZSI6IlZlcmlmaWFibGVQcmVzZW50YXRpb24iLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6WyJleUpyYVdRaU9pSmthV1E2YVc5MFlUcHliWE02TUhnek5ERTVNek5qWW1ReU1USm1NalkzT1dOaE5tSTFZbU00WXpGbE5EazROREV4WlRWaFpHUXdZMk0zWkRnNU1qZzVZV1ppTmpaaVpEZGtNMk5tTWpObEkyRlZkMTgyZGw5bGRUQlJlVFJQWWtOTFIwUlJNWFJEUW00elJGcGxVVzUxYmtkNlRWWlJlRWxrYjJNaUxDSjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSkZaRVJUUVNKOS5leUpwYzNNaU9pSmthV1E2YVc5MFlUcHliWE02TUhnek5ERTVNek5qWW1ReU1USm1NalkzT1dOaE5tSTFZbU00WXpGbE5EazROREV4WlRWaFpHUXdZMk0zWkRnNU1qZzVZV1ppTmpaaVpEZGtNMk5tTWpObElpd2libUptSWpveE56STBOamcwTlRFekxDSnFkR2tpT2lKb2RIUndjem92TDJWNFlXMXdiR1V1WldSMUwyTnlaV1JsYm5ScFlXeHpMek0zTXpJaUxDSnpkV0lpT2lKa2FXUTZhVzkwWVRweWJYTTZNSGcyWTJJNU1XVXlNR014TXpoaE1UUTFNVFV6TURZNFpURXdPRE5oTUdFeVlUVXdZalUyWkRJMU1HSTNZalV6WXpZd1ltRXpPVEk0TkdKa01XUmpOelF4SWl3aWRtTWlPbnNpUUdOdmJuUmxlSFFpT2lKb2RIUndjem92TDNkM2R5NTNNeTV2Y21jdk1qQXhPQzlqY21Wa1pXNTBhV0ZzY3k5Mk1TSXNJblI1Y0dVaU9sc2lWbVZ5YVdacFlXSnNaVU55WldSbGJuUnBZV3dpTENKVmJtbDJaWEp6YVhSNVJHVm5jbVZsUTNKbFpHVnVkR2xoYkNKZExDSmpjbVZrWlc1MGFXRnNVM1ZpYW1WamRDSTZleUpqWlhKMGFXWnBZMkYwWlNJNmV5SjBlWEJsSWpvaVFXTmpjbVZrYVhSaGRHbHZiaUlzSW14bGRtVnNJam96ZlgxOWZRLm5ldEpyMkZEaWlPYmRFVWVaaTkwcW90dG9BcFlYLVhacmxMQ0ZwOTA2RHZCMlJUbEw2WDVWb3JhYy1reFpNUThwMkpIUEZMbUk5ZzM5c3NuSG1MWkNnIl19fQ.vcpp_imMMv6inSOy9L-IsvF_WPfEYsuTpcPfEAHQfrBJ_O_zhZxZ0pzcbbvwJqh-wcmMgas0DuR_0NGcZK8CAw" ;
40-
4147#[ tokio:: main]
4248async fn main ( ) -> anyhow:: Result < ( ) > {
4349 // Create a new client to interact with the IOTA ledger.
@@ -57,7 +63,7 @@ async fn main() -> anyhow::Result<()> {
5763
5864 // Create a DID for the entity that will be the holder of the Verifiable Presentation.
5965 let storage: MemStorage = MemStorage :: new ( JwkMemStore :: new ( ) , KeyIdMemstore :: new ( ) ) ;
60- let ( _, mut did_document, _ ) : ( Address , IotaDocument , String ) =
66+ let ( _, mut did_document, fragment ) : ( Address , IotaDocument , String ) =
6167 create_did ( & client, & mut secret_manager, & storage) . await ?;
6268 let did: IotaDID = did_document. id ( ) . clone ( ) ;
6369
@@ -110,8 +116,8 @@ async fn main() -> anyhow::Result<()> {
110116 . verifiable_presentation_urls ( ) ;
111117
112118 // Fetch the verifiable presentation from the URL (for example using `reqwest`).
113- // But since the URLs are not actually online in this example , we will simply create an example JWT.
114- let presentation_jwt: Jwt = example_vp ( ) ;
119+ // But since the URLs do not point to actual online resource , we will simply create an example JWT.
120+ let presentation_jwt: Jwt = make_vp_jwt ( & did_document , & storage , & fragment ) . await ? ;
115121
116122 // Resolve the holder's document.
117123 let holder_did: CoreDID = JwtPresentationValidatorUtils :: extract_holder ( & presentation_jwt) ?;
@@ -152,7 +158,38 @@ async fn publish_document(
152158 Ok ( client. publish_did_output ( & secret_manager, alias_output) . await ?)
153159}
154160
155- /// A static VP, without nonce and expiry (created using basic example `6_create_vp.rs`).
156- fn example_vp ( ) -> Jwt {
157- Jwt :: from ( VP_JWT . to_string ( ) )
161+ async fn make_vp_jwt ( did_doc : & IotaDocument , storage : & MemStorage , fragment : & str ) -> anyhow:: Result < Jwt > {
162+ // first we create a credential encoding it as jwt
163+ let credential = CredentialBuilder :: new ( Object :: default ( ) )
164+ . id ( Url :: parse ( "https://example.edu/credentials/3732" ) ?)
165+ . issuer ( Url :: parse ( did_doc. id ( ) . as_str ( ) ) ?)
166+ . type_ ( "UniversityDegreeCredential" )
167+ . subject ( Subject :: from_json_value ( serde_json:: json!( {
168+ "id" : did_doc. id( ) . as_str( ) ,
169+ "name" : "Alice" ,
170+ "degree" : {
171+ "type" : "BachelorDegree" ,
172+ "name" : "Bachelor of Science and Arts" ,
173+ } ,
174+ "GPA" : "4.0" ,
175+ } ) ) ?)
176+ . build ( ) ?;
177+ let credential = did_doc
178+ . create_credential_jwt ( & credential, storage, fragment, & JwsSignatureOptions :: default ( ) , None )
179+ . await ?;
180+ // then we create a presentation including the just created JWT encoded credential.
181+ let presentation = PresentationBuilder :: new ( Url :: parse ( did_doc. id ( ) . as_str ( ) ) ?, Object :: default ( ) )
182+ . credential ( credential)
183+ . build ( ) ?;
184+ // we encode the presentation as JWT
185+ did_doc
186+ . create_presentation_jwt (
187+ & presentation,
188+ storage,
189+ fragment,
190+ & JwsSignatureOptions :: default ( ) ,
191+ & JwtPresentationOptions :: default ( ) ,
192+ )
193+ . await
194+ . context ( "jwt presentation failed" )
158195}
0 commit comments