Skip to content

Commit

Permalink
feat(prism-agent): generalize DIDSecretStorage trait (and implementat…
Browse files Browse the repository at this point in the history
…ions) to use JWK instead of OctetKeyPair
  • Loading branch information
bvoiturier committed Aug 22, 2023
1 parent 756dea7 commit 399cfaa
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package io.iohk.atala.mercury

import zio._

import com.nimbusds.jose.jwk.JWK
import io.iohk.atala.mercury.model.*
import com.nimbusds.jose.jwk.OctetKeyPair
import org.didcommx.didcomm.common.*
import org.didcommx.didcomm.secret.*
import org.didcommx.peerdid.core.PeerDIDUtils
import org.didcommx.didcomm.common._
import org.didcommx.didcomm.secret._
import zio.*

import scala.jdk.CollectionConverters.*

case class AgentPeerService(
val id: DidId,
val jwkForKeyAgreement: Seq[OctetKeyPair],
val jwkForKeyAuthentication: Seq[OctetKeyPair],
val jwkForKeyAgreement: Seq[JWK],
val jwkForKeyAuthentication: Seq[JWK],
) extends DidAgent

object AgentPeerService {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package io.iohk.atala.mercury

import org.didcommx.peerdid.*

import com.nimbusds.jose.jwk.*
import com.nimbusds.jose.jwk.gen.*
import io.circe._
import io.circe.syntax._
import io.circe.generic.semiauto._
import scala.jdk.CollectionConverters.*

import io.circe.*
import io.circe.generic.semiauto.*
import io.circe.syntax.*
import io.iohk.atala.mercury.model.DidId
import org.didcommx.peerdid.*

import scala.jdk.CollectionConverters.*

final case class PeerDID(
did: DidId,
jwkForKeyAgreement: OctetKeyPair,
jwkForKeyAuthentication: OctetKeyPair,
jwkForKeyAgreement: JWK,
jwkForKeyAuthentication: JWK,
) {
// def keyAgreement = PeerDID.keyAgreemenFromPublicJWK(jwkForKeyAgreement)
// def keyAuthentication = PeerDID.keyAuthenticationFromPublicJWK(jwkForKeyAuthentication)
Expand Down Expand Up @@ -71,26 +70,26 @@ object PeerDID {
def apply(endpoint: String) = new Service(s = endpoint)
}

def makeNewJwkKeyX25519: OctetKeyPair = new OctetKeyPairGenerator(Curve.X25519).generate()
def makeNewJwkKeyX25519: JWK = new OctetKeyPairGenerator(Curve.X25519).generate()

def makeNewJwkKeyEd25519: OctetKeyPair = new OctetKeyPairGenerator(Curve.Ed25519).generate()
def makeNewJwkKeyEd25519: JWK = new OctetKeyPairGenerator(Curve.Ed25519).generate()

def keyAgreemenFromPublicJWK(key: OctetKeyPair) = VerificationMaterialPeerDID[VerificationMethodTypeAgreement](
def keyAgreemenFromPublicJWK(key: JWK) = VerificationMaterialPeerDID[VerificationMethodTypeAgreement](
VerificationMaterialFormatPeerDID.JWK,
key.toPublicJWK,
VerificationMethodTypeAgreement.JSON_WEB_KEY_2020.INSTANCE
)

def keyAuthenticationFromPublicJWK(key: OctetKeyPair) =
def keyAuthenticationFromPublicJWK(key: JWK) =
VerificationMaterialPeerDID[VerificationMethodTypeAuthentication](
VerificationMaterialFormatPeerDID.JWK,
key.toPublicJWK,
VerificationMethodTypeAuthentication.JSON_WEB_KEY_2020.INSTANCE
)

def makePeerDid(
jwkForKeyAgreement: OctetKeyPair = makeNewJwkKeyX25519,
jwkForKeyAuthentication: OctetKeyPair = makeNewJwkKeyEd25519,
jwkForKeyAgreement: JWK = makeNewJwkKeyX25519,
jwkForKeyAuthentication: JWK = makeNewJwkKeyEd25519,
serviceEndpoint: Option[String] = None
): PeerDID = {
val did = org.didcommx.peerdid.PeerDIDCreator.createPeerDIDNumalgo2(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import io.iohk.atala.mercury.model.DidId
/** Represente a Decentralized Identifier with secrets keys */
trait DidAgent {
def id: DidId
def jwkForKeyAgreement: Seq[OctetKeyPair]
def jwkForKeyAuthentication: Seq[OctetKeyPair]
def jwkForKeyAgreement: Seq[JWK]
def jwkForKeyAuthentication: Seq[JWK]
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package io.iohk.atala.agent.walletapi.sql

import com.nimbusds.jose.jwk.OctetKeyPair
import com.nimbusds.jose.jwk.JWK
import doobie.*
import doobie.implicits.*
import io.iohk.atala.agent.walletapi.storage.DIDSecretStorage
import io.iohk.atala.mercury.model.DidId
import java.time.Instant
import java.util.UUID
import zio.*
import zio.interop.catz.*

import java.time.Instant
import java.util.UUID

class JdbcDIDSecretStorage(xa: Transactor[Task]) extends DIDSecretStorage {

case class InstantAsBigInt(value: Instant)
Expand All @@ -25,10 +26,10 @@ class JdbcDIDSecretStorage(xa: Transactor[Task]) extends DIDSecretStorage {

given didIdGet: Get[DidId] = Get[String].map(DidId(_))
given didIdPut: Put[DidId] = Put[String].contramap(_.value)
given octetKeyPairGet: Get[OctetKeyPair] = Get[String].map(OctetKeyPair.parse)
given octetKeyPairPut: Put[OctetKeyPair] = Put[String].contramap(_.toJSONString)
given jwkGet: Get[JWK] = Get[String].map(JWK.parse)
given jwkPut: Put[JWK] = Put[String].contramap(_.toJSONString)

override def getKey(did: DidId, keyId: String): Task[Option[OctetKeyPair]] = {
override def getKey(did: DidId, keyId: String): Task[Option[JWK]] = {
val cxnIO = sql"""
| SELECT
| key_pair
Expand All @@ -37,13 +38,13 @@ class JdbcDIDSecretStorage(xa: Transactor[Task]) extends DIDSecretStorage {
| did = $did
| AND key_id = $keyId
""".stripMargin
.query[OctetKeyPair]
.query[JWK]
.option

cxnIO.transact(xa)
}

override def insertKey(did: DidId, keyId: String, keyPair: OctetKeyPair): Task[Int] = {
override def insertKey(did: DidId, keyId: String, keyPair: JWK): Task[Int] = {
val cxnIO = (now: InstantAsBigInt) => sql"""
| INSERT INTO public.did_secret_storage(
| did,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.iohk.atala.agent.walletapi.storage

import com.nimbusds.jose.jwk.OctetKeyPair
import com.nimbusds.jose.jwk.JWK
import io.iohk.atala.mercury.model.DidId
import zio.*

/** A simple single-user DID key storage */
trait DIDSecretStorage {

/** PeerDID related methods. TODO: Refactor to abstract over PrismDID & PeerDID and merge methods */
def insertKey(did: DidId, keyId: String, keyPair: OctetKeyPair): Task[Int]
def insertKey(did: DidId, keyId: String, keyPair: JWK): Task[Int]

def getKey(did: DidId, keyId: String): Task[Option[OctetKeyPair]]
def getKey(did: DidId, keyId: String): Task[Option[JWK]]

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package io.iohk.atala.agent.walletapi.vault

import com.nimbusds.jose.jwk.OctetKeyPair
import com.nimbusds.jose.jwk.JWK
import io.iohk.atala.agent.walletapi.storage.DIDSecretStorage
import io.iohk.atala.mercury.model.DidId
import scala.util.Try
import zio.*
import scala.util.Failure

import scala.util.{Failure, Try}

class VaultDIDSecretStorage(vaultKV: VaultKVClient) extends DIDSecretStorage {

private val WALLET_PATH_PREFIX = "secret/default" // static <tenant-id> in signle-tenant mode

override def insertKey(did: DidId, keyId: String, keyPair: OctetKeyPair): Task[Int] = {
override def insertKey(did: DidId, keyId: String, keyPair: JWK): Task[Int] = {
val path = s"$WALLET_PATH_PREFIX/peer-dids/${did.value}/$keyId"
val kv = encodeOctetKeyPair(keyPair)
for {
Expand All @@ -23,21 +23,21 @@ class VaultDIDSecretStorage(vaultKV: VaultKVClient) extends DIDSecretStorage {
} yield 1
}

override def getKey(did: DidId, keyId: String): Task[Option[OctetKeyPair]] = {
override def getKey(did: DidId, keyId: String): Task[Option[JWK]] = {
val path = s"$WALLET_PATH_PREFIX/peer-dids/${did.value}/$keyId"
vaultKV.get(path).flatMap {
case Some(kv) => ZIO.fromTry(decodeOctetKeyPair(kv)).asSome
case None => ZIO.none
}
}

private def encodeOctetKeyPair(keyPair: OctetKeyPair): Map[String, String] = {
private def encodeOctetKeyPair(keyPair: JWK): Map[String, String] = {
Map("jwk" -> keyPair.toJSONString())
}

private def decodeOctetKeyPair(kv: Map[String, String]): Try[OctetKeyPair] = {
private def decodeOctetKeyPair(kv: Map[String, String]): Try[JWK] = {
kv.get("jwk") match {
case Some(jwk) => Try(OctetKeyPair.parse(jwk))
case Some(jwk) => Try(JWK.parse(jwk))
case None => Failure(Exception("A property 'jwk' is missing from KV data"))
}
}
Expand Down

0 comments on commit 399cfaa

Please sign in to comment.