Giter Club home page Giter Club logo

sd-jwt-kotlin's Introduction

SD-JWT Implementation in Kotlin

This is a Kotlin implementation of the Selective Disclosure for JWTs spec using the Nimbus JOSE + JWT library.

Up to date with draft version: 04

Checking Out the Implementation

In the Debugging.kt file there are examples that show how the library can be used on the issuance, wallet and verifier side.

Running the Examples

First Possibility

If you have Docker installed you can simply run:

  1. docker build -t sd-jwt .
  2. docker run -it --rm sd-jwt

Second Possibility (Linux)

  1. Install Java version 17 or newer (e.g. sudo apt install -y openjdk-17-jdk)
  2. Run tests with the gradle wrapper: ./gradlew test --tests SdJwtKtTest -i -PossrhUsername= -PossrhPassword=

Import into Gradle Project

Note: The current version is not yet available on Maven Central. It will probably be published under the version 0.1.0

The current SNAPSHOT version can be found in this repository.

build.gradle

plugins {
    /* ... */
    id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.10'
}

dependencies {
    /* ... */
    implementation 'org.sd-jwt:sd-jwt-kotlin:0.0.0'

    // https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
    implementation("com.nimbusds:nimbus-jose-jwt:9.30.1")
    // For ED25519 key pairs
    implementation("com.google.crypto.tink:tink:1.9.0")

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
}

Simple Library Usage

Initialization

First you need to define your credential as a kotlinx serializable data class.

@Serializable
private data class SimpleTestCredential(
    val iss: String,
    @SerialName("given_name") val givenName: String? = null,
    @SerialName("family_name") val familyName: String? = null,
    val email: String? = null,
    val b: Boolean? = null,
    val age: Int? = null
)

Then you need a few variables to get started.

val issuer = "http://issuer.example.com"

val issuerKeyJson = """{"kty":"OKP","d":"Pp1foKt6rJAvx0igrBEfOgrT0dgMVQDHmgJZbm2h518","crv":"Ed25519","kid":"IssuerKey","x":"1NYF4EFS2Ov9hqt35fVt2J-dktLV29hs8UFjxbOXnho"}"""
val issuerKey = OctetKeyPair.parse(issuerKeyJson)

val trustedIssuers = mutableMapOf<String, String>(issuer to issuerKey.toPublicJWK().toJSONString())

Issuer Creating the Credential

val claims = SimpleTestCredential(iss = issuer, "Alice", "Wonderland", "[email protected]", false, 21)
val discloseStructure = SimpleTestCredential(iss = "") // This  is required so that 'iss' is not hidden
val credential = createCredential(claims, issuerKey, discloseStructure = discloseStructure)

Wallet Creating the Presentation

val releaseClaims = SimpleTestCredential(iss = "", givenName = "", email = "", age = 0) // Non-null claims will be revealed
val presentation = createPresentation(credential, releaseClaims)

Verifier Parsing and Verifying the Credential

val verifiedSimpleTestCredential = verifyPresentation<SimpleTestCredential>(
        presentation, 
        trustedIssuers, 
        verifyHolderBinding = false
    )

Advanced Library Usage

This code shows how to

  • use holder binding
  • create a structured SD-JWT
  • create recursively disclosable claims (add HIDE_NAME to the @SerialName annotation)
  • add custom header fields to the SD-JWT
@Serializable
data class CredentialSubject(
    @SerialName("given_name") val givenName: String? = null,
    @SerialName("family_name") val familyName: String? = null,
    val email: String? = null
)

@Serializable
data class EmailCredential(
    val type: String,
    val iat: Long,
    val exp: Long,
    val iss: String,
    // Make this object recursively discloseable
    @SerialName(HIDE_NAME + "credentialSubject") val credentialSubject: CredentialSubject? = null 
)

val issuerKey = ECKeyGenerator(Curve.P_256)
    .keyID("Issuer")
    .generate()

val holderKey = ECKeyGenerator(Curve.P_256)
    .keyID("Holder")
    .generate()

val issuer = "did:jwk:${b64Encoder(issuerKey.toPublicJWK().toJSONString())}"

val trustedIssuers = mapOf<String, String>(issuer to issuerKey.toPublicJWK().toJSONString())

val userClaims = EmailCredential(
    type = "VerifiedEMail",
    iat = Date.from(Instant.now()).time / 1000,
    exp = Date.from(Instant.now().plusSeconds(3600 * 48)).time / 1000,
    iss = issuer,
    credentialSubject = CredentialSubject(
        givenName = "Alice",
        familyName = "Wonderland",
        email = "[email protected]"
    )
)

// Each non-null variable will be separately disclosed. 
// Primitive types that are not null will be in plain text in the SD-JWT.
val discloseStructure = EmailCredential(type = "", iat = 0, exp = 0, iss = "", credentialSubject = CredentialSubject())

// Add custom header fields to the SD-JWT
val header = SdJwtHeader(JOSEObjectType("vc+sd-jwt"), "credential-claims-set+json")

/***************** Create Credential *****************/
val credential = createCredential(userClaims, issuerKey, holderKey.toPublicJWK(), discloseStructure, sdJwtHeader = header)

/**************** Create Presentation ****************/
val releaseClaims = EmailCredential(type = "", iat = 0, exp = 0, iss = "", credentialSubject = CredentialSubject(email = ""))
val presentation = createPresentation(credential, releaseClaims, "https://nextcloud.example.com", "1234", holderKey)

/**************** Verify Presentation ****************/
val verifiedEmailCredential = verifyPresentation<EmailCredential>(
        presentation,
        trustedIssuers,
        "1234",
        "https://nextcloud.example.com",
        true
    )

sd-jwt-kotlin's People

Contributors

fabian-hk avatar cryptphil avatar tkuhrt avatar

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.