Skip to content

Commit

Permalink
feat(pollux): add sdjwt capability (#174)
Browse files Browse the repository at this point in the history
Signed-off-by: goncalo-frade-iohk <goncalo.frade@iohk.io>
  • Loading branch information
goncalo-frade-iohk authored Jul 18, 2024
1 parent 079b6a9 commit cd3baf8
Show file tree
Hide file tree
Showing 22 changed files with 800 additions and 256 deletions.
4 changes: 4 additions & 0 deletions edge-agent-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ kotlin {
implementation("io.iohk.atala.prism.anoncredskmp:anoncreds-kmp:0.4.6")
implementation("com.ionspin.kotlin:bignum:0.3.9")
implementation("org.bouncycastle:bcprov-jdk15on:1.68")
implementation("eu.europa.ec.eudi:eudi-lib-jvm-sdjwt-kt:0.4.0") {
exclude(group = "com.nimbusds", module = "nimbus-jose-jwt")
}
implementation(kotlin("reflect"))

implementation("com.apicatalog:titanium-json-ld-jre8:1.4.0")
implementation("org.glassfish:jakarta.json:2.0.1")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.apollo.utils.KMMEdPrivateKey
import org.hyperledger.identus.walletsdk.domain.models.Curve
Expand All @@ -13,6 +15,8 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PrivateKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.SignableKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import java.security.KeyFactory
import java.security.spec.PKCS8EncodedKeySpec

/**
* Represents a private key for the Ed25519 algorithm.
Expand Down Expand Up @@ -122,4 +126,11 @@ class Ed25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey, Sto
*/
override val restorationIdentifier: String
get() = "ed25519+priv"

override fun jca(): java.security.PrivateKey {
val privateKeyParams = Ed25519PrivateKeyParameters(raw, 0)
val pkcs8Encoded = privateKeyParams.encoded
val keyFactory = KeyFactory.getInstance("Ed25519", BouncyCastleProvider())
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(pkcs8Encoded))
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.apollo.utils.KMMEdPublicKey
import org.hyperledger.identus.walletsdk.domain.models.Curve
Expand All @@ -12,6 +14,8 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PEMKeyType
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.VerifiableKey
import java.security.KeyFactory
import java.security.spec.X509EncodedKeySpec

/**
* Represents an Ed25519 public key.
Expand Down Expand Up @@ -106,4 +110,11 @@ class Ed25519PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey, Sto
*/
override val restorationIdentifier: String
get() = "ed25519+pub"

override fun jca(): java.security.PublicKey {
val publicKeyParams = Ed25519PublicKeyParameters(raw, 0)
val x509Encoded = publicKeyParams.encoded
val keyFactory = KeyFactory.getInstance("Ed25519", BouncyCastleProvider())
return keyFactory.generatePublic(X509EncodedKeySpec(x509Encoded))
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jce.spec.ECNamedCurveSpec
import org.hyperledger.identus.apollo.base64.base64UrlDecodedBytes
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.apollo.derivation.DerivationPath
import org.hyperledger.identus.apollo.derivation.HDKey
import org.hyperledger.identus.apollo.utils.KMMECSecp256k1PrivateKey
import org.hyperledger.identus.apollo.utils.KMMEllipticCurve
import org.hyperledger.identus.walletsdk.domain.models.Curve
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.CurveKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.CurvePointXKey
Expand All @@ -20,6 +24,12 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.SeedKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.SignableKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import org.hyperledger.identus.walletsdk.pollux.EC
import java.math.BigInteger
import java.security.KeyFactory
import java.security.interfaces.ECPrivateKey
import java.security.spec.ECParameterSpec
import java.security.spec.ECPrivateKeySpec

/**
* The `Secp256k1PrivateKey` class represents a private key that uses the secp256k1 elliptic curve.
Expand Down Expand Up @@ -159,4 +169,13 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) :
val derivedHdKey = hdKey.derive(derivationPath.toString())
return Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw)
}

override fun jca(): java.security.PrivateKey {
val curveName = KMMEllipticCurve.SECP256k1.value
val sp = ECNamedCurveTable.getParameterSpec(curveName)
val params: ECParameterSpec = ECNamedCurveSpec(sp.name, sp.curve, sp.g, sp.n, sp.h)
val privateKeySpec = ECPrivateKeySpec(BigInteger(1, getValue()), params)
val keyFactory = KeyFactory.getInstance(EC, BouncyCastleProvider())
return keyFactory.generatePrivate(privateKeySpec) as ECPrivateKey
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jce.spec.ECNamedCurveSpec
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.apollo.utils.KMMECSecp256k1PublicKey
import org.hyperledger.identus.apollo.utils.KMMEllipticCurve
import org.hyperledger.identus.walletsdk.apollo.config.ECConfig
import org.hyperledger.identus.walletsdk.domain.models.Curve
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.CurveKey
Expand All @@ -16,6 +20,11 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PEMKeyType
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.VerifiableKey
import org.hyperledger.identus.walletsdk.pollux.EC
import java.security.KeyFactory
import java.security.interfaces.ECPublicKey
import java.security.spec.ECParameterSpec
import java.security.spec.ECPublicKeySpec

/**
* Represents a public key in the Secp256k1 elliptic curve algorithm.
Expand Down Expand Up @@ -126,4 +135,14 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey, S
fun getEncodedCompressed(): ByteArray {
return KMMECSecp256k1PublicKey(raw).getCompressed()
}

override fun jca(): java.security.PublicKey {
val curveName = KMMEllipticCurve.SECP256k1.value
val sp = ECNamedCurveTable.getParameterSpec(curveName)
val params: ECParameterSpec = ECNamedCurveSpec(sp.name, sp.curve, sp.g, sp.n, sp.h)

val publicKeySpec = ECPublicKeySpec(params.generator, params)
val keyFactory = KeyFactory.getInstance(EC, BouncyCastleProvider())
return keyFactory.generatePublic(publicKeySpec) as ECPublicKey
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.crypto.params.X25519PrivateKeyParameters
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.apollo.utils.KMMX25519PrivateKey
import org.hyperledger.identus.walletsdk.domain.models.Curve
Expand All @@ -13,6 +15,8 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PEMKeyType
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PrivateKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import java.security.KeyFactory
import java.security.spec.PKCS8EncodedKeySpec

/**
* Represents a private key for the X25519 elliptic curve.
Expand Down Expand Up @@ -101,4 +105,11 @@ class X25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), StorableKey, Expo
*/
override val restorationIdentifier: String
get() = "x25519+priv"

override fun jca(): java.security.PrivateKey {
val privateKeyParams = X25519PrivateKeyParameters(raw, 0)
val pkcs8Encoded = privateKeyParams.encoded
val keyFactory = KeyFactory.getInstance("X25519", BouncyCastleProvider())
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(pkcs8Encoded))
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.hyperledger.identus.walletsdk.apollo.utils

import org.bouncycastle.crypto.params.X25519PublicKeyParameters
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.hyperledger.identus.apollo.base64.base64UrlEncoded
import org.hyperledger.identus.walletsdk.domain.models.Curve
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.CurveKey
Expand All @@ -10,6 +12,8 @@ import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PEMKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PEMKeyType
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PublicKey
import org.hyperledger.identus.walletsdk.domain.models.keyManagement.StorableKey
import java.security.KeyFactory
import java.security.spec.X509EncodedKeySpec

/**
* Class representing a public key for the X25519 curve.
Expand Down Expand Up @@ -86,4 +90,11 @@ class X25519PublicKey(nativeValue: ByteArray) : PublicKey(), ExportableKey, Stor
*/
override val restorationIdentifier: String
get() = "x25519+pub"

override fun jca(): java.security.PublicKey {
val publicKeyParams = X25519PublicKeyParameters(raw, 0)
val x509Encoded = publicKeyParams.encoded
val keyFactory = KeyFactory.getInstance("X25519", BouncyCastleProvider())
return keyFactory.generatePublic(X509EncodedKeySpec(x509Encoded))
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.hyperledger.identus.walletsdk.domain.buildingblocks

import anoncreds_wrapper.CredentialDefinition
import anoncreds_wrapper.CredentialOffer
import anoncreds_wrapper.CredentialRequest
import anoncreds_wrapper.CredentialRequestMetadata
import anoncreds_wrapper.LinkSecret
import anoncreds_wrapper.Presentation
import anoncreds_wrapper.Schema
import kotlinx.serialization.json.JsonObject
import org.hyperledger.identus.walletsdk.domain.models.AttachmentDescriptor
import org.hyperledger.identus.walletsdk.domain.models.Credential
Expand All @@ -20,8 +17,6 @@ import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation
import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation.PresentationOptions
import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation.PresentationSubmission
import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation.PresentationSubmissionOptions
import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation.RequestPresentation
import org.hyperledger.identus.walletsdk.pollux.models.AnonCredential
import java.security.interfaces.ECPublicKey

/**
Expand Down Expand Up @@ -59,6 +54,20 @@ interface Pollux {
offerJson: JsonObject
): String

/**
* Processes the SDJWT credential request and returns a string representation of the processed result.
*
* @param subjectDID The DID of the subject for whom the request is being processed.
* @param privateKey The private key used for signing the JWT.
* @param offerJson The JSON object representing the credential offer.
* @return The string representation of the processed result.
*/
fun processCredentialRequestSDJWT(
subjectDID: DID,
privateKey: PrivateKey,
offerJson: JsonObject
): String

/**
* Processes a credential request for anonymous credentials.
*
Expand All @@ -75,27 +84,34 @@ interface Pollux {
linkSecretName: String
): Pair<CredentialRequest, CredentialRequestMetadata>

/**
* Creates a verifiable presentation JSON Web Token (JWT) for the given subjectDID, privateKey, credential, and requestPresentationJson.
*
* @param subjectDID The DID of the subject for whom the presentation is being created.
* @param privateKey The private key used to sign the JWT.
* @param credential The credential to be included in the presentation.
* @param requestPresentationJson The JSON object representing the request presentation.
* @return The created verifiable presentation JWT.
*/
fun createVerifiablePresentationJWT(
subjectDID: DID,
privateKey: PrivateKey,
credential: Credential,
requestPresentationJson: JsonObject
): String

suspend fun createVerifiablePresentationAnoncred(
request: RequestPresentation,
credential: AnonCredential,
linkSecret: LinkSecret
): Presentation
// /**
// * Creates a verifiable presentation JSON Web Token (JWT) for the given subjectDID, privateKey, credential, and requestPresentationJson.
// *
// * @param subjectDID The DID of the subject for whom the presentation is being created.
// * @param privateKey The private key used to sign the JWT.
// * @param credential The credential to be included in the presentation.
// * @param requestPresentationJson The JSON object representing the request presentation.
// * @return The created verifiable presentation JWT.
// */
// fun createVerifiablePresentationJWT(
// subjectDID: DID,
// privateKey: PrivateKey,
// credential: Credential,
// requestPresentationJson: JsonObject
// ): String
//
// fun createVerifiablePresentationSDJWT(
// subjectDID: DID,
// privateKey: PrivateKey,
// credential: Credential,
// requestPresentationJson: JsonObject
// ): String
//
// suspend fun createVerifiablePresentationAnoncred(
// request: RequestPresentation,
// credential: AnonCredential,
// linkSecret: LinkSecret
// ): Presentation

/**
* Restores a credential using the provided restoration identifier and credential data.
Expand Down Expand Up @@ -123,15 +139,15 @@ interface Pollux {
*/
fun extractCredentialFormatFromMessage(formats: Array<AttachmentDescriptor>): CredentialType

/**
* Retrieves the credential definition for the specified ID.
*
* @param id The ID of the credential definition.
* @return The credential definition.
*/
suspend fun getCredentialDefinition(id: String): CredentialDefinition

suspend fun getSchema(schemaId: String): Schema
// /**
// * Retrieves the credential definition for the specified ID.
// *
// * @param id The ID of the credential definition.
// * @return The credential definition.
// */
// suspend fun getCredentialDefinition(id: String): CredentialDefinition
//
// suspend fun getSchema(schemaId: String): Schema

suspend fun createPresentationDefinitionRequest(
type: CredentialType,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.hyperledger.identus.walletsdk.domain.models

import org.hyperledger.identus.walletsdk.domain.models.keyManagement.PrivateKey

sealed class CredentialOperationsOptions {
data class Schema(val id: String, val json: String) : CredentialOperationsOptions()
data class SchemaDownloader(val api: Api) : CredentialOperationsOptions()
data class CredentialDefinition(val id: String, val json: String) : CredentialOperationsOptions()
data class CredentialDefinitionDownloader(val api: Api) : CredentialOperationsOptions()
data class LinkSecret(val id: String, val secret: String) : CredentialOperationsOptions()
data class SubjectDID(val did: DID) : CredentialOperationsOptions()
data class Entropy(val entropy: String) : CredentialOperationsOptions()
data class SignableKey(val key: SignableKey?) : CredentialOperationsOptions()
data class ExportableKey(val key: PrivateKey?) : CredentialOperationsOptions()
data class ZkpPresentationParams(val attributes: Map<String, Boolean>, val predicates: List<String>) : CredentialOperationsOptions()
data class DisclosingClaims(val claims: List<String>) : CredentialOperationsOptions()
data class Custom(val key: String, val data: ByteArray) : CredentialOperationsOptions()
}

interface ProvableCredential {
suspend fun presentation(request: ByteArray, options: List<CredentialOperationsOptions>): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ data class VerifiableCredentialTypeContainer(
enum class CredentialType(val type: String) {
JWT("prism/jwt"),
W3C("w3c"),
SDJWT("vc+sd-jwt"),
ANONCREDS_OFFER("anoncreds/credential-offer@v1.0"),
ANONCREDS_REQUEST("anoncreds/credential-request@v1.0"),
ANONCREDS_ISSUE("anoncreds/credential@v1.0"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,7 @@ abstract class PrivateKey : Key() {
* Defines a method to fetch the public key of this private key
*/
abstract fun publicKey(): PublicKey

@Throws
abstract fun jca(): java.security.PrivateKey
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ abstract class PublicKey : Key() {
fun getValue(): ByteArray {
return this.raw
}

@Throws
abstract fun jca(): java.security.PublicKey
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const val DIDCOMM1 = "#didcomm-1"
const val DIDCOMM_MESSAGING = "DIDCommMessaging"
const val PRISM = "prism"
const val JWT_MEDIA_TYPE = "prism/jwt"
const val SDJWT_MEDIA_TYPE = "vc+sd-jwt"
const val PROTOCOL_TYPE = "ProtocolType"
const val GOAL_CODE = "goal_code"
const val WILL_CONFIRM = "will_confirm"
Expand Down
Loading

0 comments on commit cd3baf8

Please sign in to comment.