Skip to content

Commit

Permalink
feat: complete the integration with anoncred and fixes (#820)
Browse files Browse the repository at this point in the history
Signed-off-by: FabioPinheiro <fabiomgpinheiro@gmail.com>
Signed-off-by: Fabio Pinheiro <fabiomgpinheiro@gmail.com>
Co-authored-by: Bassam <bassam.riman@iohk.io>
  • Loading branch information
FabioPinheiro and CryptoKnightIOG committed Dec 20, 2023
1 parent 87809c4 commit 15ff710
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 66 deletions.
9 changes: 7 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import org.scoverage.coveralls.Imports.CoverallsKeys.*
import sbtbuildinfo.BuildInfoPlugin.autoImport.*

// externalResolvers += "ScalaLibrary packages" at "https://maven.pkg.github.com/input-output-hk/anoncreds-rs" // use plugin"sbt-github-packages"

inThisBuild(
Seq(
organization := "io.iohk.atala",
Expand All @@ -10,7 +12,8 @@ inThisBuild(
releaseUseGlobalVersion := false,
versionScheme := Some("semver-spec"),
githubOwner := "input-output-hk",
githubRepository := "atala-prism-building-blocks"
githubRepository := "atala-prism-building-blocks",
resolvers += "Local Maven Repository" at "file://" + Path.userHome.absolutePath + "/.m2/repository",
)
)

Expand Down Expand Up @@ -420,7 +423,8 @@ val commonSetttings = Seq(
val overrides = licenseOverrides.value.lift
val depExclusions = licenseDepExclusions.value.lift
val originatingModule = DepModuleInfo(organization.value, name.value, version.value)
val resolution = DependencyResolution(new LicenseReportCustomDependencyResolution(ivyConfiguration.value, ivyModule.value))
val resolution =
DependencyResolution(new LicenseReportCustomDependencyResolution(ivyConfiguration.value, ivyModule.value))
license.LicenseReport.makeReport(
ivyModule.value,
resolution,
Expand Down Expand Up @@ -740,6 +744,7 @@ lazy val polluxAnoncreds = project
Compile / unmanagedResourceDirectories ++= Seq(
baseDirectory.value / "native-lib" / "NATIVE"
),
// libraryDependencies += "io.iohk.atala.prism.anoncredskmp" % "anoncreds-kmp-jvm" % "0.3.5-M2",
libraryDependencies ++= D_Pollux_AnonCreds.baseDependencies
)

Expand Down
6 changes: 1 addition & 5 deletions pollux/lib/anoncreds/README_anoncreds.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ Go into the folder `uniffi` and generate the file `anoncreds.kt`

Assuming uniffi_bindgen is install. Install with `cargo install uniffi_bindgen --version $(cargo pkgid uniffi | cut -f 2 -d '@')`

(Note you can also the run the script `build-release-linux.sh` in there)

Run the command `~/.cargo/bin/uniffi-bindgen generate src/anoncreds.udl --language kotlin -o ./wrappers/kotlin/anoncreds`

Replace the `anoncreds.kt` file in the `output-frameworks/anoncreds-jvm` project (`output-frameworks/anoncreds-jvm/src/main/uniffi/anoncreds/anoncreds.kt`)
Run the script `build-release-linux.sh` in there

Generate the Jar with `./gradlew jar` in the `output-frameworks/anoncreds-jvm` project

Expand Down
Binary file modified pollux/lib/anoncreds/anoncreds-jvm-1.0-SNAPSHOT.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
33 changes: 19 additions & 14 deletions pollux/lib/anoncreds/native-lib/helper_script_to_update.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
#!/usr/bin/env bash

# https://github.com/input-output-hk/anoncreds-rs/releases/download/0.4.0/library-darwin-aarch64-0ce097bbc9afa8a17a491248d75dcdf03f133dc4.tar.gz
RELEASES=https://github.com/input-output-hk/anoncreds-rs/releases/download/
VERSION=expose_presentation_methods_in_uniffi
SHA="16a7178ca979f7643788f6ebf8189131ab922a53"
VERSION="0.4.0"
SHA="0ce097bbc9afa8a17a491248d75dcdf03f133dc4"

mkdir NATIVE_new
mkdir NATIVE_new/darwin-aarch64
mkdir NATIVE_new/darwin-x86-64
mkdir NATIVE_new/linux-aarch64
mkdir NATIVE_new/linux-x86-64
rm -rf NATIVE/darwin-aarch64
rm -rf NATIVE/darwin-x86-64
rm -rf NATIVE/linux-aarch64
rm -rf NATIVE/linux-x86-64

wget -c $RELEASES/$VERSION/library-darwin-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/darwin-aarch64
wget -c $RELEASES/$VERSION/library-darwin-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/darwin-x86-64
wget -c $RELEASES/$VERSION/library-linux-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/linux-aarch64
wget -c $RELEASES/$VERSION/library-linux-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE_new/linux-x86-64
mkdir NATIVE/darwin-aarch64
mkdir NATIVE/darwin-x86-64
mkdir NATIVE/linux-aarch64
mkdir NATIVE/linux-x86-64

rename 'libanoncreds_uniffi.so' 'libuniffi_anoncreds.so' NATIVE_new/**/*.so
rename 'libanoncreds_uniffi.dylib' 'libuniffi_anoncreds.dylib' NATIVE_new/**/*.dylib
wget -c $RELEASES/$VERSION/library-darwin-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE/darwin-aarch64
wget -c $RELEASES/$VERSION/library-darwin-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE/darwin-x86-64
wget -c $RELEASES/$VERSION/library-linux-aarch64-$SHA.tar.gz -O - | tar -xz -C NATIVE/linux-aarch64
wget -c $RELEASES/$VERSION/library-linux-x86_64-$SHA.tar.gz -O - | tar -xz -C NATIVE/linux-x86-64

rename 'libanoncreds_uniffi.so' 'libuniffi_anoncreds_wrapper.so' NATIVE/**/*.so
rename 'libanoncreds_uniffi.dylib' 'libuniffi_anoncreds_wrapper.dylib' NATIVE/**/*.dylib


## TODO missing anoncreds-jvm-1.0-SNAPSHOT.jar
## run https://github.com/input-output-hk/anoncreds-rs/blob/main/uniffi/build-release-linux.sh
## copy jar from uniffi/output-frameworks/anoncreds-jvm/build/libs/anoncreds-jvm-1.0-SNAPSHOT.jar
## copy jar from uniffi/output-frameworks/anoncreds-jvm/build/libs/anoncreds-jvm-1.0-SNAPSHOT.jar
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.iohk.atala.pollux.anoncreds

import uniffi.anoncreds

import scala.jdk.CollectionConverters.*
import scala.language.implicitConversions

Expand All @@ -20,26 +18,26 @@ object AnoncredLib {
version: String, // SCHEMA_Version
attr_names: AttributeNames,
issuer_id: IssuerId, // ISSUER_DID
): SchemaDef = anoncreds.Schema.apply(name, version, attr_names.toSeq.asJava, issuer_id)
): SchemaDef = uniffi.anoncreds_wrapper.Schema.apply(name, version, attr_names.toSeq.asJava, issuer_id)

// issuer
def createCredDefinition(
issuer_id: String,
schema: SchemaDef,
tag: String,
supportRevocation: Boolean,
signature_type: anoncreds.SignatureType.CL.type = anoncreds.SignatureType.CL
signature_type: uniffi.anoncreds_wrapper.SignatureType.CL.type = uniffi.anoncreds_wrapper.SignatureType.CL
) = {
val credentialDefinition: anoncreds.IssuerCreateCredentialDefinitionReturn =
anoncreds
val credentialDefinition: uniffi.anoncreds_wrapper.IssuerCreateCredentialDefinitionReturn =
uniffi.anoncreds_wrapper
.Issuer()
.createCredentialDefinition(
schema.name,
schema: anoncreds.Schema,
schema: uniffi.anoncreds_wrapper.Schema,
issuer_id,
tag,
signature_type,
anoncreds.CredentialDefinitionConfig(supportRevocation)
uniffi.anoncreds_wrapper.CredentialDefinitionConfig(supportRevocation)
)

CreateCredentialDefinition(
Expand All @@ -54,7 +52,7 @@ object AnoncredLib {
credentialDefinition: CreateCredentialDefinition,
credentialDefinitionId: String
): CredentialOffer =
anoncreds
uniffi.anoncreds_wrapper
.Issuer()
.createCredentialOffer(
credentialDefinition.cd.schemaId, // string schema_id,
Expand All @@ -74,7 +72,7 @@ object AnoncredLib {
}
): CreateCrendentialRequest = {
val credentialRequest =
anoncreds
uniffi.anoncreds_wrapper
.Prover()
.createCredentialRequest(
entropy, // string? entropy,
Expand All @@ -94,8 +92,8 @@ object AnoncredLib {
metadata: CredentialRequestMetadata,
linkSecret: LinkSecretWithId,
credentialDefinition: CredentialDefinition,
): Unit = {
anoncreds
): Credential = {
uniffi.anoncreds_wrapper
.Prover()
.processCredential(
credential, // Credential,
Expand All @@ -118,16 +116,15 @@ object AnoncredLib {
// revocationStatusList : RevocationStatusList
// credentialRevocationConfig : CredentialRevocationConfig
): Credential = {

anoncreds
uniffi.anoncreds_wrapper
.Issuer()
.createCredential(
credentialDefinition, // CredentialDefinition cred_def,
credentialDefinitionPrivate, // CredentialDefinitionPrivate cred_def_private,
credentialOffer, // CredentialOffer cred_offer,
credentialRequest, // CredentialRequest cred_request,
attributeValues
.map(e => anoncreds.AttributeValues(e._1, e._2))
.map(e => uniffi.anoncreds_wrapper.AttributeValues(e._1, e._2))
.asJava, // sequence<AttributeValues> cred_values,
null, // RevocationRegistryId? rev_reg_id,
null, // RevocationStatusList? rev_status_list,
Expand All @@ -138,40 +135,67 @@ object AnoncredLib {
type SchemaId = String
type CredentialDefinitionId = String

// TODO FIX
// [info] uniffi.anoncreds.AnoncredsException$CreatePresentationException: Create Presentation: Error: Error: Invalid structure
// [info] Caused by: Predicate is not satisfied

def createPresentation(
presentationRequest: PresentationRequest,
credentials: Seq[Credential],
credentialRequests: Seq[CredentialAndRequestedAttributesPredicates],
selfAttested: Map[String, String],
linkSecret: LinkSecret,
schemas: Map[SchemaId, SchemaDef],
credentialDefinitions: Map[CredentialDefinitionId, CredentialDefinition],
): Presentation = {
anoncreds
.Prover()
.createPresentation(
presentationRequest,
credentials.map(e => e: uniffi.anoncreds.Credential).asJava, // sequence<Credential> credentials,
selfAttested.asJava, // record<string, string>? self_attested,
linkSecret, // LinkSecret link_secret,
schemas.view.mapValues(i => i: uniffi.anoncreds.Schema).toMap.asJava, // record<SchemaId, Schema> schemas,
credentialDefinitions.view.mapValues(i => i: uniffi.anoncreds.CredentialDefinition).toMap.asJava
// record<CredentialDefinitionId, CredentialDefinition> credential_definitions
): Either[uniffi.anoncreds_wrapper.AnoncredsException.CreatePresentationException, Presentation] = {
try {
Right(
uniffi.anoncreds_wrapper
.Prover()
.createPresentation(
presentationRequest, // uniffi.anoncreds
credentialRequests
.map(i => i: uniffi.anoncreds_wrapper.CredentialRequests)
.asJava, // sequence<Credential> credentials,
selfAttested.asJava, // record<string, string>? self_attested,
linkSecret, // LinkSecret link_secret,
schemas.view
.mapValues(i => i: uniffi.anoncreds_wrapper.Schema)
.toMap
.asJava, // record<SchemaId, Schema> schemas,
credentialDefinitions.view.mapValues(i => i: uniffi.anoncreds_wrapper.CredentialDefinition).toMap.asJava
// record<CredentialDefinitionId, CredentialDefinition> credential_definitions
)
)
} catch {
case ex: uniffi.anoncreds_wrapper.AnoncredsException.CreatePresentationException => Left(ex)
}
}

// TODO FIX
// uniffi.anoncreds.AnoncredsException$ProcessCredentialException: Verify Presentation: Error:
// Requested restriction validation failed for "{"sex": Some("M")}" attributes [$and operator validation failed.
// [$eq operator validation failed for tag: "attr::sex::value", value: "F" [Proof rejected: "attr::sex::value" values are different: expected: "F", actual: "M"]]]

// TODO FIX
// uniffi.anoncreds.AnoncredsException$ProcessCredentialException: Verify Presentation: Error: Requested restriction validation failed for "{"sex": Some("M")}" attributes [$and operator validation failed. [$eq operator validation failed for tag: "cred_def_id", value: "CRED_DEF_ID" [Proof rejected: "cred_def_id" values are different: expected: "CRED_DEF_ID", actual: "mock:uri3"]]]

// FIXME its always return false ....
def verifyPresentation(
presentation: Presentation,
presentationRequest: PresentationRequest,
schemas: Map[SchemaId, SchemaDef],
credentialDefinitions: Map[CredentialDefinitionId, CredentialDefinition],
): Boolean = {
anoncreds
uniffi.anoncreds_wrapper
.Verifier()
.verifyPresentation(
presentation, // Presentation presentation,
presentationRequest, // PresentationRequest presentation_request,
schemas.view.mapValues(i => i: uniffi.anoncreds.Schema).toMap.asJava, // record<SchemaId, Schema> schemas,
credentialDefinitions.view.mapValues(i => i: uniffi.anoncreds.CredentialDefinition).toMap.asJava
schemas.view
.mapValues(i => i: uniffi.anoncreds_wrapper.Schema)
.toMap
.asJava, // record<SchemaId, Schema> schemas,
credentialDefinitions.view.mapValues(i => i: uniffi.anoncreds_wrapper.CredentialDefinition).toMap.asJava
// record<CredentialDefinitionId, CredentialDefinition> credential_definitions
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.iohk.atala.pollux.anoncreds

import uniffi.anoncreds.{
import uniffi.anoncreds_wrapper.{
Nonce,
Credential as UniffiCredential,
CredentialRequests as UniffiCredentialRequests,
CredentialDefinition as UniffiCredentialDefinition,
CredentialDefinitionPrivate as UniffiCredentialDefinitionPrivate,
CredentialKeyCorrectnessProof as UniffiCredentialKeyCorrectnessProof,
Expand Down Expand Up @@ -257,6 +258,47 @@ object Credential {
}
}

// ****************************************************************************
case class CredentialAndRequestedAttributesPredicates(
credential: Credential,
requestedAttribute: Seq[String],
requestedPredicate: Seq[String],
)

object CredentialAndRequestedAttributesPredicates {
given Conversion[CredentialAndRequestedAttributesPredicates, UniffiCredentialRequests] with {
import uniffi.anoncreds_wrapper.RequestedAttribute
import uniffi.anoncreds_wrapper.RequestedPredicate
def apply(credentialRequests: CredentialAndRequestedAttributesPredicates): UniffiCredentialRequests = {
val credential = Credential.given_Conversion_Credential_UniffiCredential(credentialRequests.credential)
val requestedAttributes = credentialRequests.requestedAttribute.map(a => RequestedAttribute(a, true))
val requestedPredicates = credentialRequests.requestedPredicate.map(p => RequestedPredicate(p))
UniffiCredentialRequests(credential, requestedAttributes.asJava, requestedPredicates.asJava)
}
}

given Conversion[UniffiCredentialRequests, CredentialAndRequestedAttributesPredicates] with {
def apply(credentialRequests: UniffiCredentialRequests): CredentialAndRequestedAttributesPredicates = {
CredentialAndRequestedAttributesPredicates(
Credential.given_Conversion_UniffiCredential_Credential(credentialRequests.getCredential()),
credentialRequests
.getRequestedAttribute()
.asScala
.toSeq
.filter(e => e.getRevealed())
.map(e => e.getReferent()),
credentialRequests
.getRequestedPredicate()
.asScala
.toSeq
.map(e => e.getReferent())
)
}
}
}

//UniffiCredentialRequests

// ****************************************************************************

case class PresentationRequest(data: String)
Expand All @@ -277,12 +319,14 @@ object PresentationRequest {
case class Presentation(data: String)
object Presentation {
given Conversion[Presentation, UniffiPresentation] with {
def apply(presentation: Presentation): UniffiPresentation =
def apply(presentation: Presentation): UniffiPresentation = {
UniffiPresentation(presentation.data)
}
}

given Conversion[UniffiPresentation, Presentation] with {
def apply(presentation: UniffiPresentation): Presentation =
def apply(presentation: UniffiPresentation): Presentation = {
Presentation(presentation.getJson())
}
}
}
2 changes: 1 addition & 1 deletion pollux/lib/anoncredsTest/src/test/scala/Uniffy.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import uniffi.anoncreds.*
import uniffi.anoncreds_wrapper.*
object Uniffy extends App {
val prover = new Prover()
val seceret = prover.createLinkSecret();
Expand Down
Loading

0 comments on commit 15ff710

Please sign in to comment.