Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Example To Use Production Jar #364

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.")
}
}
Loading