From d8e8a7fd1974f0d348eae1a9d44ddf62536c26bf Mon Sep 17 00:00:00 2001 From: Ivan Pagac Date: Fri, 10 Nov 2023 20:23:28 +0100 Subject: [PATCH 1/3] Added ios target with sample implementation of JWTCryptoProvider for MAC and Digital Signatures --- build.gradle.kts | 56 ++- gradle.properties | 6 + settings.gradle.kts | 1 + .../kotlin/id/walt/sdjwt/ByteArray+NSDAta.kt | 15 + .../DigitalSignaturesJWTCryptoProvider.kt | 37 ++ .../id/walt/sdjwt/HMACJWTCryptoProvider.kt | 40 ++ .../kotlin/id/walt/sdjwt/JWTClaimsSet.kt | 9 + .../kotlin/id.walt.sdjwt/SDJwtTestIOS.kt | 104 +++++ .../cinterop/waltid-sd-jwt-ios.def | 10 + waltid-sd-jwt-ios/build.gradle.kts | 28 ++ .../project.pbxproj | 375 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 14 + .../waltid-sd-jwt-ios/CryptoOperations.swift | 35 ++ .../waltid-sd-jwt-ios/Operations.swift | 116 ++++++ .../waltid_sd_jwt_ios-Bridging-Header.h | 1 + 17 files changed, 859 insertions(+), 3 deletions(-) create mode 100644 settings.gradle.kts create mode 100644 src/iosMain/kotlin/id/walt/sdjwt/ByteArray+NSDAta.kt create mode 100644 src/iosMain/kotlin/id/walt/sdjwt/DigitalSignaturesJWTCryptoProvider.kt create mode 100644 src/iosMain/kotlin/id/walt/sdjwt/HMACJWTCryptoProvider.kt create mode 100644 src/iosMain/kotlin/id/walt/sdjwt/JWTClaimsSet.kt create mode 100644 src/iosTest/kotlin/id.walt.sdjwt/SDJwtTestIOS.kt create mode 100644 src/nativeInterop/cinterop/waltid-sd-jwt-ios.def create mode 100644 waltid-sd-jwt-ios/build.gradle.kts create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.pbxproj create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios/CryptoOperations.swift create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios/Operations.swift create mode 100644 waltid-sd-jwt-ios/waltid-sd-jwt-ios/waltid_sd_jwt_ios-Bridging-Header.h diff --git a/build.gradle.kts b/build.gradle.kts index 2501079..c4b31ef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,6 @@ plugins { kotlin("multiplatform") version "1.9.20" - - id("org.jetbrains.kotlin.plugin.serialization") + kotlin("plugin.serialization") version "1.9.20" id("dev.petuska.npm.publish") version "3.4.1" `maven-publish` @@ -15,14 +14,16 @@ repositories { mavenCentral() } +@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) kotlin { jvm { - jvmToolchain(16) + jvmToolchain(18) withJava() testRuns["test"].executionTask.configure { useJUnitPlatform() } } + js(IR) { browser { commonWebpackConfig(Action { @@ -42,6 +43,36 @@ kotlin { } binaries.library() } + + listOf ( + iosArm64(), + iosX64(), + iosSimulatorArm64(), + + ).forEach { + val platform = when (it.name) { + "iosArm64" -> "iphoneos" + else -> "iphonesimulator" + } + + it.binaries.framework { + baseName = "shared" + } + + it.compilations.getByName("main") { + cinterops.create("id.walt.sdjwt.cinterop.ios") { + val interopTask = tasks[interopProcessingTaskName] + interopTask.dependsOn(":waltid-sd-jwt-ios:build${platform.capitalize()}") + + defFile("$rootDir/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def") + packageName("id.walt.sdjwt.cinterop.ios") + includeDirs("$rootDir/waltid-sd-jwt-ios/build/Release-$platform/include/") + + headers("$rootDir/waltid-sd-jwt-ios/build/Release-$platform/include/waltid_sd_jwt_ios/waltid_sd_jwt_ios-Swift.h") + } + } + } + val hostOs = System.getProperty("os.name") val isMingwX64 = hostOs.startsWith("Windows") val nativeTarget = when { @@ -94,6 +125,25 @@ kotlin { } val nativeMain by getting val nativeTest by getting + + val iosArm64Main by getting + val iosSimulatorArm64Main by getting + val iosX64Main by getting + val iosMain by creating { + dependsOn(commonMain) + iosArm64Main.dependsOn(this) + iosSimulatorArm64Main.dependsOn(this) + iosX64Main.dependsOn(this) + } + val iosArm64Test by getting + val iosSimulatorArm64Test by getting + val iosX64Test by getting + val iosTest by creating { + dependsOn(commonTest) + iosArm64Test.dependsOn(this) + iosSimulatorArm64Test.dependsOn(this) + iosX64Test.dependsOn(this) + } } publishing { diff --git a/gradle.properties b/gradle.properties index 9dcc3a7..fef2476 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,8 @@ kotlin.code.style=official kotlin.js.compiler=ir + +kotlin.native.osVersionMin.ios_x64 = 13.0 +kotlin.native.osVersionMin.ios_arm64 = 13.0 +kotlin.native.cacheKind=none + +kotlin.mpp.enableCInteropCommonization=true \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..e98eb06 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +include(":waltid-sd-jwt-ios") \ No newline at end of file diff --git a/src/iosMain/kotlin/id/walt/sdjwt/ByteArray+NSDAta.kt b/src/iosMain/kotlin/id/walt/sdjwt/ByteArray+NSDAta.kt new file mode 100644 index 0000000..9d8e172 --- /dev/null +++ b/src/iosMain/kotlin/id/walt/sdjwt/ByteArray+NSDAta.kt @@ -0,0 +1,15 @@ +package id.walt.sdjwt + +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.addressOf +import kotlinx.cinterop.pin +import platform.Foundation.NSData +import platform.Foundation.create + +@OptIn(ExperimentalForeignApi::class) +internal inline fun ByteArray.toData(offset: Int = 0, length: Int = size - offset): NSData { + require(offset + length <= size) { "offset + length > size" } + if (isEmpty()) return NSData() + val pinned = pin() + return NSData.create(pinned.addressOf(offset), length.toULong()) { _, _ -> pinned.unpin() } +} \ No newline at end of file diff --git a/src/iosMain/kotlin/id/walt/sdjwt/DigitalSignaturesJWTCryptoProvider.kt b/src/iosMain/kotlin/id/walt/sdjwt/DigitalSignaturesJWTCryptoProvider.kt new file mode 100644 index 0000000..1d8d414 --- /dev/null +++ b/src/iosMain/kotlin/id/walt/sdjwt/DigitalSignaturesJWTCryptoProvider.kt @@ -0,0 +1,37 @@ +import id.walt.sdjwt.JWTCryptoProvider +import id.walt.sdjwt.JwtVerificationResult +import id.walt.sdjwt.cinterop.ios.DS_Operations +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.serialization.json.JsonObject +import platform.Security.* +import kotlin.js.ExperimentalJsExport + +@ExperimentalJsExport +@OptIn(ExperimentalForeignApi::class) +class DigitalSignaturesJWTCryptoProvider(private val algorithm: String, private val key: SecKeyRef) : + JWTCryptoProvider { + override fun sign(payload: JsonObject, keyID: String?, typ: String): String { + + val result = DS_Operations.signWithBody( + body = payload.toString(), + alg = algorithm, + key = key, + typ = typ, + keyId = keyID + ) + + return when { + result.success() -> result.data()!! + else -> result.errorMessage() ?: "" + } + } + + override fun verify(jwt: String): JwtVerificationResult { + val result = DS_Operations.verifyWithJws(jws = jwt, key = key) + + return when { + result.success() -> JwtVerificationResult(result.success()!!) + else -> JwtVerificationResult(false, message = result.errorMessage() ?: "") + } + } +} \ No newline at end of file diff --git a/src/iosMain/kotlin/id/walt/sdjwt/HMACJWTCryptoProvider.kt b/src/iosMain/kotlin/id/walt/sdjwt/HMACJWTCryptoProvider.kt new file mode 100644 index 0000000..7f2ebe6 --- /dev/null +++ b/src/iosMain/kotlin/id/walt/sdjwt/HMACJWTCryptoProvider.kt @@ -0,0 +1,40 @@ +package id.walt.sdjwt + +import id.walt.sdjwt.cinterop.ios.* +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.addressOf +import kotlinx.cinterop.pin +import kotlinx.serialization.json.JsonObject +import platform.Foundation.NSData +import platform.Foundation.create +import kotlin.js.ExperimentalJsExport + +@ExperimentalJsExport +@OptIn(ExperimentalForeignApi::class) +class HMACJWTCryptoProvider(private val algorithm: String, private val key: ByteArray) : + JWTCryptoProvider { + override fun sign(payload: JsonObject, keyID: String?, typ: String): String { + + val result = HMAC_Operations.signWithBody( + body = payload.toString(), + alg = algorithm, + key = key.toData(), + typ = typ, + keyId = keyID + ) + + return when { + result.success() -> result.data()!! + else -> result.errorMessage() ?: "" + } + } + + override fun verify(jwt: String): JwtVerificationResult { + val result = HMAC_Operations.verifyWithJws(jws = jwt, key = key.toData()) + + return when { + result.success() -> JwtVerificationResult(result.success()!!) + else -> JwtVerificationResult(false, message = result.errorMessage() ?: "") + } + } +} \ No newline at end of file diff --git a/src/iosMain/kotlin/id/walt/sdjwt/JWTClaimsSet.kt b/src/iosMain/kotlin/id/walt/sdjwt/JWTClaimsSet.kt new file mode 100644 index 0000000..74c7eb6 --- /dev/null +++ b/src/iosMain/kotlin/id/walt/sdjwt/JWTClaimsSet.kt @@ -0,0 +1,9 @@ +package id.walt.sdjwt + +/** + * Expected class for JWT claim set in platform specific implementation. Not necessarily required. + */ +actual class JWTClaimsSet { + actual override fun toString(): String = "" + +} diff --git a/src/iosTest/kotlin/id.walt.sdjwt/SDJwtTestIOS.kt b/src/iosTest/kotlin/id.walt.sdjwt/SDJwtTestIOS.kt new file mode 100644 index 0000000..74d9785 --- /dev/null +++ b/src/iosTest/kotlin/id.walt.sdjwt/SDJwtTestIOS.kt @@ -0,0 +1,104 @@ +package id.walt.sdjwt + +import io.kotest.assertions.json.shouldMatchJson +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.maps.shouldContainKey +import io.kotest.matchers.maps.shouldNotContainKey +import io.kotest.matchers.shouldBe +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonPrimitive +import kotlin.test.Test + +class SDJwtTestIOS { + private val sharedSecret = "ef23f749-7238-481a-815c-f0c2157dfa8e" + + @Test + fun testSignJwt() { + val cryptoProvider = HMACJWTCryptoProvider("HS256", sharedSecret.encodeToByteArray()) + + val originalSet = mutableMapOf ( + "sub" to JsonPrimitive("123"), + "aud" to JsonPrimitive("456") + ) + + val originalClaimsSet = JsonObject(originalSet) + + // Create undisclosed claims set, by removing e.g. subject property from original claims set + val undisclosedSet = mutableMapOf ( + "aud" to JsonPrimitive("456") + ) + + val undisclosedClaimsSet = JsonObject(undisclosedSet) + + // Create SD payload by comparing original claims set with undisclosed claims set + val sdPayload = SDPayload.createSDPayload(originalClaimsSet, undisclosedClaimsSet) + + // Create and sign SD-JWT using the generated SD payload and the previously configured crypto provider + val sdJwt = SDJwt.sign(sdPayload, cryptoProvider) + // Print SD-JWT + println(sdJwt) + + sdJwt.undisclosedPayload shouldNotContainKey "sub" + sdJwt.undisclosedPayload shouldContainKey SDJwt.DIGESTS_KEY + sdJwt.undisclosedPayload shouldContainKey "aud" + sdJwt.disclosures shouldHaveSize 1 + sdJwt.digestedDisclosures[sdJwt.undisclosedPayload[SDJwt.DIGESTS_KEY]!!.jsonArray[0].jsonPrimitive.content]!!.key shouldBe "sub" + sdJwt.fullPayload.toString() shouldMatchJson originalClaimsSet.toString() + + sdJwt.verify(cryptoProvider).verified shouldBe true + } + + @Test + fun presentSDJwt() { + // parse previously created SD-JWT + val sdJwt = + SDJwt.parse("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0NTYiLCJfc2QiOlsiaGx6ZmpmMDRvNVpzTFIyNWhhNGMtWS05SFcyRFVseGNnaU1ZZDMyNE5nWSJdfQ.2fsLqzujWt0hS0peLS8JLHyyo3D5KCDkNnHcBYqQwVo~WyJ4RFk5VjBtOG43am82ZURIUGtNZ1J3Iiwic3ViIiwiMTIzIl0") + + // present without disclosing SD fields + val presentedUndisclosedJwt = sdJwt.present(discloseAll = false) + println(presentedUndisclosedJwt) + + // present disclosing all SD fields + val presentedDisclosedJwt = sdJwt.present(discloseAll = true) + println(presentedDisclosedJwt) + + // present disclosing selective fields, using SDMap + val presentedSelectiveJwt = sdJwt.present(SDMapBuilder().addField("sub", true).build()) + println(presentedSelectiveJwt) + + // present disclosing fields, using JSON paths + val presentedSelectiveJwt2 = sdJwt.present(SDMap.generateSDMap(listOf("sub"))) + println(presentedSelectiveJwt2) + + } + + @Test + fun parseAndVerify() { + // Create SimpleJWTCryptoProvider with MACSigner and MACVerifier + val cryptoProvider = HMACJWTCryptoProvider("HS256", sharedSecret.encodeToByteArray()) + val undisclosedJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0NTYiLCJfc2QiOlsiaGx6ZmpmMDRvNVpzTFIyNWhhNGMtWS05SFcyRFVseGNnaU1ZZDMyNE5nWSJdfQ.2fsLqzujWt0hS0peLS8JLHyyo3D5KCDkNnHcBYqQwVo~" + + // verify and parse presented SD-JWT with all fields undisclosed, throws Exception if verification fails! + val parseAndVerifyResult = SDJwt.verifyAndParse(undisclosedJwt, cryptoProvider) + + // print full payload with disclosed fields only + println("Undisclosed JWT payload:") + println(parseAndVerifyResult.sdJwt.fullPayload.toString()) + + // alternatively parse and verify in 2 steps: + val parsedUndisclosedJwt = SDJwt.parse(undisclosedJwt) + val isValid = parsedUndisclosedJwt.verify(cryptoProvider).verified + println("Undisclosed SD-JWT verified: $isValid") + + val parsedDisclosedJwtVerifyResult = SDJwt.verifyAndParse( + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0NTYiLCJfc2QiOlsiaGx6ZmpmMDRvNVpzTFIyNWhhNGMtWS05SFcyRFVseGNnaU1ZZDMyNE5nWSJdfQ.2fsLqzujWt0hS0peLS8JLHyyo3D5KCDkNnHcBYqQwVo~WyJ4RFk5VjBtOG43am82ZURIUGtNZ1J3Iiwic3ViIiwiMTIzIl0~", + cryptoProvider + ) + // print full payload with disclosed fields + println("Disclosed JWT payload:") + println(parsedDisclosedJwtVerifyResult.sdJwt.fullPayload.toString()) + } +} \ No newline at end of file diff --git a/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def b/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def new file mode 100644 index 0000000..b7823a8 --- /dev/null +++ b/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def @@ -0,0 +1,10 @@ +language = Objective-C +staticLibraries = libwaltid-sd-jwt-ios.a +libraryPaths.ios_simulator_arm64 = waltid-sd-jwt-ios/build/Release-iphonesimulator/ +libraryPaths.ios_x64 = waltid-sd-jwt-ios/build/Release-iphonesimulator/ +libraryPaths.ios_arm64 = waltid-sd-jwt-ios/build/Release-iphoneos/ + +linkerOpts = -L/usr/lib/swift +linkerOpts.ios_arm64 = -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos/ +linkerOpts.ios_simulator_arm64 = -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/ +linkerOpts.ios_x64 = -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/ diff --git a/waltid-sd-jwt-ios/build.gradle.kts b/waltid-sd-jwt-ios/build.gradle.kts new file mode 100644 index 0000000..c91a914 --- /dev/null +++ b/waltid-sd-jwt-ios/build.gradle.kts @@ -0,0 +1,28 @@ +listOf("iphoneos", "iphonesimulator").forEach { sdk -> + tasks.create("build${sdk.capitalize()}") { + group = "build" + + commandLine( + "xcodebuild", + "-project", "waltid-sd-jwt-ios.xcodeproj", + "-scheme","waltid-sd-jwt-ios", + "-sdk", sdk, + "-configuration","Release" + ) + workingDir(projectDir) + + inputs.files( + fileTree("$projectDir/waltid-sd-jwt-ios.xcodeproj") { exclude("**/xcuserdata") }, + fileTree("$projectDir/waltid-sd-jwt-ios") + ) + outputs.files( + fileTree("$projectDir/build/Release-${sdk}") + ) + } +} + +tasks.create("clean") { + group = "build" + + delete("$projectDir/build") +} diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.pbxproj b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b16e861 --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.pbxproj @@ -0,0 +1,375 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + B3C274D22AFE9B9E00862806 /* Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3C274D12AFE9B9E00862806 /* Operations.swift */; }; + B3DA814D2AFD023500F2BD06 /* CryptoOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DA814C2AFD023500F2BD06 /* CryptoOperations.swift */; }; + B3DA81562AFD05A500F2BD06 /* JOSESwift in Frameworks */ = {isa = PBXBuildFile; productRef = B3DA81552AFD05A500F2BD06 /* JOSESwift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + B3DA81472AFD023500F2BD06 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + B3C274D12AFE9B9E00862806 /* Operations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operations.swift; sourceTree = ""; }; + B3DA81492AFD023500F2BD06 /* libwaltid-sd-jwt-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libwaltid-sd-jwt-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B3DA814C2AFD023500F2BD06 /* CryptoOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoOperations.swift; sourceTree = ""; }; + B3DA81532AFD02CE00F2BD06 /* waltid_sd_jwt_ios-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "waltid_sd_jwt_ios-Bridging-Header.h"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B3DA81462AFD023500F2BD06 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B3DA81562AFD05A500F2BD06 /* JOSESwift in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B3DA81402AFD023500F2BD06 = { + isa = PBXGroup; + children = ( + B3DA814B2AFD023500F2BD06 /* waltid-sd-jwt-ios */, + B3DA814A2AFD023500F2BD06 /* Products */, + ); + sourceTree = ""; + }; + B3DA814A2AFD023500F2BD06 /* Products */ = { + isa = PBXGroup; + children = ( + B3DA81492AFD023500F2BD06 /* libwaltid-sd-jwt-ios.a */, + ); + name = Products; + sourceTree = ""; + }; + B3DA814B2AFD023500F2BD06 /* waltid-sd-jwt-ios */ = { + isa = PBXGroup; + children = ( + B3DA814C2AFD023500F2BD06 /* CryptoOperations.swift */, + B3DA81532AFD02CE00F2BD06 /* waltid_sd_jwt_ios-Bridging-Header.h */, + B3C274D12AFE9B9E00862806 /* Operations.swift */, + ); + path = "waltid-sd-jwt-ios"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B3DA81482AFD023500F2BD06 /* waltid-sd-jwt-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = B3DA81502AFD023500F2BD06 /* Build configuration list for PBXNativeTarget "waltid-sd-jwt-ios" */; + buildPhases = ( + B3DA81452AFD023500F2BD06 /* Sources */, + B3DA81462AFD023500F2BD06 /* Frameworks */, + B3DA81472AFD023500F2BD06 /* CopyFiles */, + B3C274CE2AFE13BA00862806 /* Copy bridging header */, + B3C274D02AFE474000862806 /* Copy products */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "waltid-sd-jwt-ios"; + packageProductDependencies = ( + B3DA81552AFD05A500F2BD06 /* JOSESwift */, + ); + productName = "waltid-sd-jwt-ios"; + productReference = B3DA81492AFD023500F2BD06 /* libwaltid-sd-jwt-ios.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B3DA81412AFD023500F2BD06 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + B3DA81482AFD023500F2BD06 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = B3DA81442AFD023500F2BD06 /* Build configuration list for PBXProject "waltid-sd-jwt-ios" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B3DA81402AFD023500F2BD06; + packageReferences = ( + B3DA81542AFD05A500F2BD06 /* XCRemoteSwiftPackageReference "JOSESwift" */, + ); + productRefGroup = B3DA814A2AFD023500F2BD06 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B3DA81482AFD023500F2BD06 /* waltid-sd-jwt-ios */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + B3C274CE2AFE13BA00862806 /* Copy bridging header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Copy bridging header"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "targetDir=${BUILT_PRODUCTS_DIR}/include/${PRODUCT_MODULE_NAME}/\nmkdir -p $targetDir\ncp ${DERIVED_SOURCES_DIR}/*-Swift.h ${targetDir}\n"; + }; + B3C274D02AFE474000862806 /* Copy products */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Copy products"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cp -r ${BUILT_PRODUCTS_DIR}/../* ./build\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B3DA81452AFD023500F2BD06 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B3DA814D2AFD023500F2BD06 /* CryptoOperations.swift in Sources */, + B3C274D22AFE9B9E00862806 /* Operations.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B3DA814E2AFD023500F2BD06 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + B3DA814F2AFD023500F2BD06 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + B3DA81512AFD023500F2BD06 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PROJECT_NAME)/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B3DA81522AFD023500F2BD06 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/$(PROJECT_NAME)/$(SWIFT_MODULE_NAME)-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B3DA81442AFD023500F2BD06 /* Build configuration list for PBXProject "waltid-sd-jwt-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B3DA814E2AFD023500F2BD06 /* Debug */, + B3DA814F2AFD023500F2BD06 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B3DA81502AFD023500F2BD06 /* Build configuration list for PBXNativeTarget "waltid-sd-jwt-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B3DA81512AFD023500F2BD06 /* Debug */, + B3DA81522AFD023500F2BD06 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + B3DA81542AFD05A500F2BD06 /* XCRemoteSwiftPackageReference "JOSESwift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/airsidemobile/JOSESwift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.4.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + B3DA81552AFD05A500F2BD06 /* JOSESwift */ = { + isa = XCSwiftPackageProductDependency; + package = B3DA81542AFD05A500F2BD06 /* XCRemoteSwiftPackageReference "JOSESwift" */; + productName = JOSESwift; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = B3DA81412AFD023500F2BD06 /* Project object */; +} diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..329aa01 --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "joseswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/airsidemobile/JOSESwift.git", + "state" : { + "revision" : "10ed3b6736def7c26eb87135466b1cb46ea7e37f", + "version" : "2.4.0" + } + } + ], + "version" : 2 +} diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios/CryptoOperations.swift b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/CryptoOperations.swift new file mode 100644 index 0000000..b1ab496 --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/CryptoOperations.swift @@ -0,0 +1,35 @@ +// +// waltid_sd_jwt_ios.swift +// waltid-sd-jwt-ios +// +// Created by Ivan Pagac on 09/11/2023. +// + +import Foundation +import JOSESwift + +@objc +public class HMAC_Operations: NSObject, Operations { + @objc + public static func sign(body: String, alg: String, key: Data, typ: String, keyId: String? = nil) -> SignResult { + return OperationsBase.sign(body: body, alg: alg, key: key, typ: typ) + } + + @objc + public static func verify(jws: String, key: Data) -> VerifyResult { + return OperationsBase.verify(jws: jws, key: key) + } +} + +@objc +public class DS_Operations: NSObject, Operations { + @objc + public static func sign(body: String, alg: String, key: SecKey, typ: String, keyId: String? = nil) -> SignResult { + return OperationsBase.sign(body: body, alg: alg, key: key, typ: typ) + } + + @objc + public static func verify(jws: String, key: SecKey) -> VerifyResult { + return OperationsBase.verify(jws: jws, key: key) + } +} diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios/Operations.swift b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/Operations.swift new file mode 100644 index 0000000..86cda5c --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/Operations.swift @@ -0,0 +1,116 @@ +// +// Operations.swift +// waltid-sd-jwt-ios +// +// Created by Ivan Pagac on 10/11/2023. +// + +import Foundation +import JOSESwift + +protocol Operations { + associatedtype KeyType + static func sign(body :String, alg: String, key: KeyType, typ: String, keyId: String?) -> SignResult + static func verify(jws: String, key: KeyType) -> VerifyResult +} + +@objc +public class SignResult: NSObject { + @objc + public var success: Bool { + errorMessage == nil + } + + @objc + public let data: String? + + @objc + public let errorMessage: String? + + private init(data: String? = nil, errorMessage: String? = nil) { + self.data = data + self.errorMessage = errorMessage + } + + static func with(success data: String) -> SignResult { + SignResult(data: data) + } + + static func with(failure message: String) -> SignResult { + SignResult(errorMessage: message) + } +} + +@objc +public class VerifyResult: NSObject { + @objc + public var success: Bool { + errorMessage == nil + } + + @objc + public let isValid: Bool + + @objc + public let errorMessage: String? + + private init(isValid: Bool = false, errorMessage: String? = nil) { + self.isValid = isValid + self.errorMessage = errorMessage + } + + static func with(isValid: Bool) -> VerifyResult { + VerifyResult(isValid: isValid) + } + + static func with(failure message: String) -> VerifyResult { + VerifyResult(errorMessage: message) + } +} + +class OperationsBase: NSObject, Operations { + public static func sign(body payload: String, alg: String, key: TKeyType, typ: String, keyId: String? = nil) -> SignResult { + do { + guard let signingAlgorithm = JOSESwift.SignatureAlgorithm(rawValue: alg) else { + return SignResult.with(failure: "Unknown signature algorithm") + } + + guard let signer = Signer(signingAlgorithm: signingAlgorithm, key: key) else { + return SignResult.with(failure: "Could not construct signer.") + } + + guard let payloadData = payload.data(using: .utf8) else { + return SignResult.with(failure: "Body not in UTF-8") + } + + var header = JWSHeader(algorithm: signingAlgorithm) + header.typ = typ + if let keyId { + header.kid = keyId + } + + let jws = try JWS(header: header, payload: Payload(payloadData), signer: signer) + return SignResult.with(success: jws.compactSerializedString) + } catch { + return SignResult.with(failure: "Could not perform Sign, reason: \(error.localizedDescription).") + } + } + + public static func verify(jws: String, key: TKeyType) -> VerifyResult { + do { + let jws = try JWS(compactSerialization: jws) + + guard let algorithm = jws.header.algorithm else { + return VerifyResult.with(failure: "JWS does not contain alg header or was not recognized. This header must be present and be valid.") + } + + guard let verifier = Verifier(verifyingAlgorithm: algorithm, key: key) else { + return VerifyResult.with(failure: "Could not construct verifier with the provided key.") + } + + return VerifyResult.with(isValid: jws.isValid(for: verifier)) + } catch { + return VerifyResult.with(failure: "Could not perform Verify, reason: \(error.localizedDescription)") + } + } +} diff --git a/waltid-sd-jwt-ios/waltid-sd-jwt-ios/waltid_sd_jwt_ios-Bridging-Header.h b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/waltid_sd_jwt_ios-Bridging-Header.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/waltid-sd-jwt-ios/waltid-sd-jwt-ios/waltid_sd_jwt_ios-Bridging-Header.h @@ -0,0 +1 @@ + From 050f203fc15db257e8a88f46986723357221f9bf Mon Sep 17 00:00:00 2001 From: Ivan Pagac Date: Mon, 13 Nov 2023 13:25:43 +0100 Subject: [PATCH 2/3] changed rootDir to projectDir in build.gradle so could be included from elsewhere --- build.gradle.kts | 6 +++--- waltid-sd-jwt-ios/build.gradle.kts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c4b31ef..ecd9061 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -64,11 +64,11 @@ kotlin { val interopTask = tasks[interopProcessingTaskName] interopTask.dependsOn(":waltid-sd-jwt-ios:build${platform.capitalize()}") - defFile("$rootDir/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def") + defFile("$projectDir/src/nativeInterop/cinterop/waltid-sd-jwt-ios.def") packageName("id.walt.sdjwt.cinterop.ios") - includeDirs("$rootDir/waltid-sd-jwt-ios/build/Release-$platform/include/") + includeDirs("$projectDir/waltid-sd-jwt-ios/build/Release-$platform/include/") - headers("$rootDir/waltid-sd-jwt-ios/build/Release-$platform/include/waltid_sd_jwt_ios/waltid_sd_jwt_ios-Swift.h") + headers("$projectDir/waltid-sd-jwt-ios/build/Release-$platform/include/waltid_sd_jwt_ios/waltid_sd_jwt_ios-Swift.h") } } } diff --git a/waltid-sd-jwt-ios/build.gradle.kts b/waltid-sd-jwt-ios/build.gradle.kts index c91a914..124151c 100644 --- a/waltid-sd-jwt-ios/build.gradle.kts +++ b/waltid-sd-jwt-ios/build.gradle.kts @@ -1,5 +1,5 @@ listOf("iphoneos", "iphonesimulator").forEach { sdk -> - tasks.create("build${sdk.capitalize()}") { + tasks.register("build${sdk.capitalize()}") { group = "build" commandLine( From f979b46fced84dc8a5b9113eca7c50aa8f939a5c Mon Sep 17 00:00:00 2001 From: Severin Stampler Date: Thu, 16 Nov 2023 10:48:42 +0100 Subject: [PATCH 3/3] fix: disable native ios build on non-mac os build machines --- build.gradle.kts | 67 +++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a17439c..62b4106 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,13 +45,22 @@ kotlin { } binaries.library() } - - listOf ( - iosArm64(), - iosX64(), - iosSimulatorArm64(), - - ).forEach { + val hostOs = System.getProperty("os.name") + val isMingwX64 = hostOs.startsWith("Windows") + val nativeTarget = when { + hostOs == "Mac OS X" -> macosX64("native") + hostOs == "Linux" -> linuxX64("native") + isMingwX64 -> mingwX64("native") + else -> throw GradleException("Host OS is not supported in Kotlin/Native.") + } + when(hostOs) { + "Mac OS X" -> listOf ( + iosArm64(), + iosX64(), + iosSimulatorArm64() + ) + else -> listOf() + }.forEach { val platform = when (it.name) { "iosArm64" -> "iphoneos" else -> "iphonesimulator" @@ -75,14 +84,6 @@ kotlin { } } - val hostOs = System.getProperty("os.name") - val isMingwX64 = hostOs.startsWith("Windows") - val nativeTarget = when { - hostOs == "Mac OS X" -> macosX64("native") - hostOs == "Linux" -> linuxX64("native") - isMingwX64 -> mingwX64("native") - else -> throw GradleException("Host OS is not supported in Kotlin/Native.") - } val kryptoVersion = "4.0.10" @@ -128,23 +129,25 @@ kotlin { val nativeMain by getting val nativeTest by getting - val iosArm64Main by getting - val iosSimulatorArm64Main by getting - val iosX64Main by getting - val iosMain by creating { - dependsOn(commonMain) - iosArm64Main.dependsOn(this) - iosSimulatorArm64Main.dependsOn(this) - iosX64Main.dependsOn(this) - } - val iosArm64Test by getting - val iosSimulatorArm64Test by getting - val iosX64Test by getting - val iosTest by creating { - dependsOn(commonTest) - iosArm64Test.dependsOn(this) - iosSimulatorArm64Test.dependsOn(this) - iosX64Test.dependsOn(this) + if (hostOs == "Mac OS X") { + val iosArm64Main by getting + val iosSimulatorArm64Main by getting + val iosX64Main by getting + val iosMain by creating { + dependsOn(commonMain) + iosArm64Main.dependsOn(this) + iosSimulatorArm64Main.dependsOn(this) + iosX64Main.dependsOn(this) + } + val iosArm64Test by getting + val iosSimulatorArm64Test by getting + val iosX64Test by getting + val iosTest by creating { + dependsOn(commonTest) + iosArm64Test.dependsOn(this) + iosSimulatorArm64Test.dependsOn(this) + iosX64Test.dependsOn(this) + } } }