Skip to content

Commit

Permalink
fix:key id for jwt and sdjwt
Browse files Browse the repository at this point in the history
Signed-off-by: mineme0110 <shailesh.patil@iohk.io>
  • Loading branch information
mineme0110 committed Oct 29, 2024
1 parent 228f07b commit 9b74fbf
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,13 @@ object CredentialServiceError {
StatusCode.NotFound,
s"A key with the given purpose was not found in the DID: did=${did.toString}, purpose=${verificationRelationship.name}"
)

final case class MultipleKeysWithSamePurposeFoundInDID(
did: PrismDID,
verificationRelationship: VerificationRelationship
) extends CredentialServiceError(
StatusCode.BadRequest,
s"A key with the given purpose was found multiple times in the DID: did=${did.toString}, purpose=${verificationRelationship.name}"
)
final case class InvalidCredentialRequest(cause: String)
extends CredentialServiceError(
StatusCode.BadRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class CredentialServiceImpl(
claims = attributes,
thid = thid,
UUID.randomUUID().toString,
"domain",
"domain", // TODO remove the hardcoded domain
IssueCredentialOfferFormat.JWT
)
record <- createIssueCredentialRecord(
Expand Down Expand Up @@ -559,8 +559,8 @@ class CredentialServiceImpl(
private[this] def getKeyId(
did: PrismDID,
verificationRelationship: VerificationRelationship,
ellipticCurve: EllipticCurve
): UIO[KeyId] = {
keyId: Option[KeyId]
): UIO[PublicKey] = {
for {
maybeDidData <- didService
.resolveDID(did)
Expand All @@ -569,15 +569,25 @@ class CredentialServiceImpl(
.fromOption(maybeDidData)
.mapError(_ => DIDNotResolved(did))
.orDieAsUnmanagedFailure
keyId <- ZIO
.fromOption(
didData._2.publicKeys
.find(pk => pk.purpose == verificationRelationship && pk.publicKeyData.crv == ellipticCurve)
.map(_.id)
)
.mapError(_ => KeyNotFoundInDID(did, verificationRelationship))
.orDieAsUnmanagedFailure
} yield keyId
matchingKeys = didData._2.publicKeys.filter(pk => pk.purpose == verificationRelationship)
result <- (matchingKeys, keyId) match {
case (Seq(), _) =>
ZIO.fail(KeyNotFoundInDID(did, verificationRelationship)).orDieAsUnmanagedFailure
case (Seq(singleKey), None) =>
ZIO.succeed(singleKey)
case (multipleKeys, Some(kid)) =>
ZIO
.fromOption(multipleKeys.find(_.id.value.endsWith(kid.value)))
.mapError(_ => KeyNotFoundInDID(did, verificationRelationship))
.orDieAsUnmanagedFailure
case (multipleKeys, None) =>
ZIO
.fail(
MultipleKeysWithSamePurposeFoundInDID(did, verificationRelationship)
)
.orDieAsUnmanagedFailure
}
} yield result
}

override def getJwtIssuer(
Expand All @@ -586,34 +596,46 @@ class CredentialServiceImpl(
keyId: Option[KeyId] = None
): URIO[WalletAccessContext, JwtIssuer] = {
for {
issuingKeyId <- getKeyId(jwtIssuerDID, verificationRelationship, EllipticCurve.SECP256K1)
ecKeyPair <- managedDIDService
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingKeyId)
issuingPublicKey <- getKeyId(jwtIssuerDID, verificationRelationship, keyId)
jwtIssuer <- managedDIDService
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingPublicKey.id)
.flatMap {
case Some(keyPair: Secp256k1KeyPair) => ZIO.some(keyPair)
case _ => ZIO.none
case Some(keyPair: Secp256k1KeyPair) => {
val jwtIssuer = JwtIssuer(
jwtIssuerDID.did,
ES256KSigner(keyPair.privateKey.toJavaPrivateKey, keyId),
keyPair.publicKey.toJavaPublicKey
)
ZIO.some(jwtIssuer)
}
case Some(keyPair: Ed25519KeyPair) => {
val jwtIssuer = JwtIssuer(
jwtIssuerDID.did,
EdSigner(keyPair, keyId),
keyPair.publicKey.toJava
)
ZIO.some(jwtIssuer)
}
case _ => ZIO.none
}
.someOrFail(KeyPairNotFoundInWallet(jwtIssuerDID, issuingKeyId, "Secp256k1"))
.someOrFail(
KeyPairNotFoundInWallet(jwtIssuerDID, issuingPublicKey.id, issuingPublicKey.publicKeyData.crv.name)
)
.orDieAsUnmanagedFailure
Secp256k1KeyPair(publicKey, privateKey) = ecKeyPair
jwtIssuer = JwtIssuer(
jwtIssuerDID.did,
ES256KSigner(privateKey.toJavaPrivateKey, keyId),
publicKey.toJavaPublicKey
)
} yield jwtIssuer
}

private def getEd25519SigningKeyPair(
jwtIssuerDID: PrismDID,
verificationRelationship: VerificationRelationship
verificationRelationship: VerificationRelationship,
keyId: Option[KeyId] = None
): URIO[WalletAccessContext, Ed25519KeyPair] = {
for {
issuingKeyId <- getKeyId(jwtIssuerDID, verificationRelationship, EllipticCurve.ED25519)
issuingPublicKey <- getKeyId(jwtIssuerDID, verificationRelationship, keyId)
ed25519keyPair <- managedDIDService
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingKeyId)
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingPublicKey.id)
.map(_.collect { case keyPair: Ed25519KeyPair => keyPair })
.someOrFail(KeyPairNotFoundInWallet(jwtIssuerDID, issuingKeyId, "Ed25519"))
.someOrFail(KeyPairNotFoundInWallet(jwtIssuerDID, issuingPublicKey.id, issuingPublicKey.publicKeyData.crv.name))
.orDieAsUnmanagedFailure
} yield ed25519keyPair
}
Expand All @@ -635,7 +657,7 @@ class CredentialServiceImpl(
keyId: Option[KeyId]
): URIO[WalletAccessContext, JwtIssuer] = {
for {
ed25519keyPair <- getEd25519SigningKeyPair(jwtIssuerDID, verificationRelationship)
ed25519keyPair <- getEd25519SigningKeyPair(jwtIssuerDID, verificationRelationship, keyId)
} yield {
JwtIssuer(
jwtIssuerDID.did,
Expand Down Expand Up @@ -1148,6 +1170,8 @@ class CredentialServiceImpl(
statusListRegistryUrl: String,
): ZIO[WalletAccessContext, RecordNotFound | CredentialRequestValidationFailed, IssueCredentialRecord] = {
for {
_ <- ZIO.log(s"!!! *****generateJWTCredential*****JWT********** Handling recordId via Kafka queue $recordId")

record <- getRecordWithState(recordId, ProtocolState.CredentialPending)
issuingDID <- ZIO
.fromOption(record.issuingDID)
Expand All @@ -1163,7 +1187,7 @@ class CredentialServiceImpl(
.orElse(ZIO.dieMessage(s"Offer credential data not found in record: ${recordId.value}"))
preview = offerCredentialData.body.credential_preview
claims <- CredentialService.convertAttributesToJsonClaims(preview.body.attributes).orDieAsUnmanagedFailure
jwtIssuer <- getJwtIssuer(longFormPrismDID, VerificationRelationship.AssertionMethod)
jwtIssuer <- getJwtIssuer(longFormPrismDID, VerificationRelationship.AssertionMethod, record.keyId)
jwtPresentation <- validateRequestCredentialDataProof(maybeOfferOptions, requestJwt)
.tapError(error =>
credentialRepository
Expand Down Expand Up @@ -1243,7 +1267,11 @@ class CredentialServiceImpl(
case ZValidation.Success(log, header) => ZIO.succeed(header)
case ZValidation.Failure(log, failure) =>
ZIO.fail(VCJwtHeaderParsingError(s"Extraction of JwtHeader failed ${failure.toChunk.toString}"))
ed25519KeyPair <- getEd25519SigningKeyPair(longFormPrismDID, VerificationRelationship.AssertionMethod)
ed25519KeyPair <- getEd25519SigningKeyPair(
longFormPrismDID,
VerificationRelationship.AssertionMethod,
record.keyId
)
sdJwtPrivateKey = sdjwt.IssuerPrivateKey(ed25519KeyPair.privateKey)
jsonWebKey <- didResolver.resolve(jwtPresentation.iss) flatMap {
case failed: DIDResolutionFailed =>
Expand Down

0 comments on commit 9b74fbf

Please sign in to comment.