Skip to content

Commit

Permalink
update example (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
nitro-neal authored Sep 25, 2024
1 parent 0a59cf2 commit a87c16a
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 19 deletions.
3 changes: 2 additions & 1 deletion examples/KotlinExample/Justfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dev:
mvn compile
java -cp "target/classes/:target/dependency/*" com.example.HelloWorldKt
mvn dependency:copy-dependencies
java -cp "target/classes:target/dependency/*" com.example.HelloWorldKt

run:
(cd ../../bound/kt; mvn clean install)
Expand Down
104 changes: 96 additions & 8 deletions examples/KotlinExample/pom.xml
Original file line number Diff line number Diff line change
@@ -1,35 +1,91 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- Model Version -->
<modelVersion>4.0.0</modelVersion>

<!-- Project Coordinates -->
<groupId>com.example</groupId>
<artifactId>hello-world-kotlin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<!-- Properties -->
<properties>
<kotlin.version>1.9.22</kotlin.version>
<kotlin.version>1.8.0</kotlin.version>
<kotlin.jvm.target>11</kotlin.jvm.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<!-- Repositories -->
<repositories>
<!-- Maven Central -->
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<!-- Maven Local -->
<repository>
<id>local</id>
<url>file://${user.home}/.m2/repository</url>
</repository>
<!-- Custom Snapshot Repository -->
<repository>
<id>tbd-oss-snapshots</id>
<name>tbd-oss-snapshots</name>
<url>https://blockxyz.jfrog.io/artifactory/tbd-oss-snapshots-maven2/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>

<!-- Dependencies -->
<dependencies>
<!-- Kotlin Standard Library -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>

<!-- For local development dependency -->
<!-- Install the dependency locally by running `mvn install` in the `bound/kt` directory -->
<!--
<dependency>
<groupId>xyz.block</groupId>
<artifactId>web5</artifactId>
<version>0.0.0-main-SNAPSHOT</version>
</dependency>
-->
<!-- For a snapshot from Maven -->
<!-- Update the short git commit SHA below -->
<!--
<dependency>
<groupId>xyz.block</groupId>
<artifactId>web5</artifactId>
<version>commit-81f2d76-SNAPSHOT</version>
</dependency>
-->
<!-- For the official release on Maven Central -->
<dependency>
<groupId>web5.sdk</groupId>
<artifactId>web5-kt</artifactId>
<version>1.0-SNAPSHOT</version>
<groupId>xyz.block</groupId>
<artifactId>web5</artifactId>
<version>0.0.5</version>
</dependency>

</dependencies>

<!-- Build Configuration -->
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<!-- Kotlin Maven Plugin -->
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
Expand All @@ -54,6 +110,38 @@
<jvmTarget>${kotlin.jvm.target}</jvmTarget>
</configuration>
</plugin>

<!-- Maven Compiler Plugin -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>

<!-- Maven Shade Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>MainKt</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
130 changes: 120 additions & 10 deletions examples/KotlinExample/src/main/kotlin/com/example/HelloWorld.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,124 @@
package com.example

import web5.sdk.Curve
import web5.sdk.LocalKeyManager
import web5.sdk.dids.methods.jwk.DidJwk
import web5.sdk.vc.*
import web5.sdk.vc.pex.*
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue

fun main(args: Array<String>) {
val keyManager = LocalKeyManager.newInMemory()
val keyAlias = keyManager.generatePrivateKey(Curve.ED25519, null)
val payload = "hello world".toByteArray().map { it.toUByte() }
val signature = keyManager.sign(keyAlias, payload)
val publicKey = keyManager.getPublicKey(keyAlias)
publicKey.verify(payload, signature.map { it.toUByte() })
println("Success!")
}
// Initialize the JSON mapper
val jsonMapper = jacksonObjectMapper()

// Step 1: Create an issuer DID (Decentralized Identifier)
// Typically, this is the entity that issues the Verifiable Credential (VC)
val issuer = DidJwk.create()
val issuerUri = issuer.did.uri
println("Issuer DID URI: $issuerUri")

// Step 2: Define a Presentation Definition (PD)
// This specifies the requirements that credentials must meet to be accepted
val inputDescriptor = InputDescriptor(
id = "test_input",
name = "Test Input",
purpose = "Testing Input",
constraints = Constraints(
fields = listOf(
Field(
id = "field1",
name = "Field 1",
path = listOf("$.credentialSubject.id"),
purpose = "Must match DID JWK pattern",
filter = Filter(
type = "string",
pattern = "^did:jwk:.*$" // Regex pattern to match DID JWK
),
optional = false,
predicate = Optionality.Required
)
)
)
)

// Create the Presentation Definition with the InputDescriptor
val presentationDefinition = PresentationDefinition(
id = "test_presentation_definition",
name = "Test Presentation Definition",
purpose = "Testing Presentation Exchange",
inputDescriptors = listOf(inputDescriptor)
)
println("Presentation Definition created: $presentationDefinition")

// Step 3: Create a Verifiable Credential (VC) that meets the PD criteria
// The credentialSubject.id matches the pattern specified in the PD
val vc = VerifiableCredential.create(
Issuer.StringIssuer(issuerUri),
CredentialSubject(issuerUri)
)

// Sign the VC using the issuer's DID
val vcJwt = vc.sign(issuer)
println("Verifiable Credential JWT created and signed:\n$vcJwt\n")

// Step 4: Select credentials that match the PD's input descriptors
val vcJwts = listOf(vcJwt)
val presentationResult = presentationDefinition.createPresentationFromCredentials(vcJwts)
println("Presentation Result after matching credentials:\n$presentationResult\n")

// Step 5: Create a Verifiable Presentation (VP) with the selected credentials
// The holder is the entity presenting the credentials
val holder = DidJwk.create()
val holderUri = holder.did.uri
println("Holder DID URI: $holderUri")

// Include the presentation submission data to link the presentation to the PD
val additionalData = mapOf(
"presentation_submission" to presentationResult.presentationSubmission
)

val vpCreateOptions = VerifiablePresentationCreateOptions(
additionalProperties = additionalData
)

// Generate the VP with the matched credentials and additional data
val vp = VerifiablePresentation.create(
holderUri,
presentationResult.matchedVcJwts,
vpCreateOptions
)
println("Verifiable Presentation created:\n$vp\n")

// Step 6: Sign the VP to generate a JWT format presentation
val signedVpJwt = vp.sign(holder)
println("Signed Verifiable Presentation JWT:\n$signedVpJwt\n")

// Step 7: Decode and verify the signed VP to ensure correctness
val decodedVp = VerifiablePresentation.fromVpJwt(signedVpJwt, true)
println("Decoded Verifiable Presentation:\n$decodedVp\n")

// Step 8: Print the holder URI to verify it matches the expected holder
println("Decoded VP Holder URI: ${decodedVp.holder}\n")

// Step 9: Print the Verifiable Credentials included in the presentation
println("Verifiable Credentials in VP:")
decodedVp.verifiableCredential.forEach { credential ->
println(credential)
}
println()

// Step 10: Retrieve the presentation_submission from the decoded VP's additional data
val decodedPresentationSubmissionMap = decodedVp.additionalProperties?.get("presentation_submission") as? Map<*, *>
println("Presentation Submission from decoded VP:\n$decodedPresentationSubmissionMap\n")

// Step 11: Convert the map back to PresentationSubmission
val jsonPresentationSubmission = jsonMapper.writeValueAsString(decodedPresentationSubmissionMap)
val decodedPresentationSubmission = jsonMapper.readValue<PresentationSubmission>(jsonPresentationSubmission)
println("Decoded Presentation Submission object:\n$decodedPresentationSubmission\n")

// Step 12: Verify that the presentation_submission in additional_data matches the original one
if (decodedPresentationSubmission == presentationResult.presentationSubmission) {
println("Presentation submissions match.")
} else {
println("Presentation submissions do not match.")
}
}

0 comments on commit a87c16a

Please sign in to comment.