diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bf273af..c75543d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,7 +19,7 @@ on: required: true type: boolean swift: - description: Publish a swift version (cocoapods) + description: Publish a swift version (swift package) default: true required: true type: boolean @@ -186,42 +186,35 @@ jobs: - name: Setup rust run: | rustup target add aarch64-apple-ios - rustup target add x86_64-apple-ios - cargo install cargo-lipo + rustup target add x86_64-apple-darwin + rustup target add aarch64-apple-ios-sim + rustup target add aarch64-apple-darwin - name: Setup version id: version run: | - VERSION=$(grep -E "^\s*s\.version" Slauth.podspec \ - | awk -F"[\"\']" '{print $2}') + VERSION=$(grep -E "^version\s*=" Cargo.toml | head -1 | awk -F'"' '{print $2}') echo "version=$VERSION" >> $GITHUB_OUTPUT - - name: Run build.sh + - name: Generate package run: sh wrappers/swift/build.sh - - name: Package Pod + - name: Package Swift Package run: | VERSION=${{ steps.version.outputs.version }} - # locate all .a libraries under any release folder - AFILES=$(find target -type f -path '*/release/*.a') - zip -r Slauth-$VERSION.zip \ - Slauth.podspec \ - LICENSE \ - wrappers/swift/classes \ - slauth.h \ - $AFILES - echo "PACKAGE=Slauth-$VERSION.zip" >> $GITHUB_ENV + mv package Slauth-$VERSION + zip -r Slauth-$VERSION.zip Slauth-$VERSION - - name: Upload artifact + - name: Upload package uses: actions/upload-artifact@v4.3.6 with: - name: Cocoapods - path: Slauth-${{ steps.version.outputs.version }}.zip + name: swift-zip + path: ./Slauth-${{ steps.version.outputs.version }}.zip - name: Install Cloudsmith CLI run: pip install --upgrade cloudsmith-cli - name: Push package to Cloudsmith - run: cloudsmith push cocoapods devolutions/swift-public Slauth-${{ steps.version.outputs.version }}.zip + run: cloudsmith push swift devolutions/swift-public Slauth-${{ steps.version.outputs.version }}.zip --name Slauth --version ${{ steps.version.outputs.version }} --scope devolutions env: CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} diff --git a/.gitignore b/.gitignore index 7253f42..5c2a566 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,7 @@ android/NDK/ .gradle local.properties wrappers/android/build -build/ \ No newline at end of file +build/ +libslauth.xcframework/ +.swiftpm/ +package/ diff --git a/Cargo.toml b/Cargo.toml index 49acfba..4beb458 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,20 +69,20 @@ serde_cbor = { version = "0.11", optional = true } webpki = { version = "0.22", optional = true, features = ["alloc"] } bytes = { version = "1.10", optional = true } http = { version = "1.3", optional = true } -uuid = { version = "1.16", optional = true } -ed25519-dalek = { version = "2.1.1", features = [ +uuid = { version = "1.18", optional = true } +ed25519-dalek = { version = "2.2.0", features = [ "rand_core", "pkcs8", ], optional = true } p256 = { version = "0.13.2", optional = true } -indexmap = { version = "2.9.0", features = ["serde"], optional = true } +indexmap = { version = "2.12.0", features = ["serde"], optional = true } [target.'cfg(target_os = "android")'.dependencies] jni = { version = "0.21.1", optional = true } [target.'cfg(target_arch="wasm32")'.dependencies] -wasm-bindgen = { version = "0.2.100" } -js-sys = "0.3.77" +wasm-bindgen = { version = "0.2.104" } +js-sys = "0.3.81" # FIXME: https://docs.rs/getrandom/0.2.2/getrandom/#webassembly-support # let `getrandom` know that JavaScript is available for our targets # `getrandom` is not used directly, but by adding the right feature here @@ -92,7 +92,7 @@ getrandom = { version = "0.2", features = ["js"] } serde-wasm-bindgen = "0.6.5" [target.'cfg(target_arch="wasm32")'.dev-dependencies] -wasm-bindgen-test = "0.3.50" +wasm-bindgen-test = "0.3.54" [target.'cfg(not(target_arch="wasm32"))'.dev-dependencies] saphir = { version = "3.1.0", git = "https://github.com/richerarc/saphir.git", tag = "v3.1.0", features = [ @@ -104,7 +104,7 @@ async-stream = ">= 0.3, < 0.3.4" # 0.3.4 and up currently break saphir [dev-dependencies] serde_json = "1.0" serde_cbor = "0.11" -uuid = "1.16" +uuid = "1.18" rand = "0.9" bytes = "1.10" diff --git a/Slauth.podspec b/Slauth.podspec deleted file mode 100644 index 509d00a..0000000 --- a/Slauth.podspec +++ /dev/null @@ -1,19 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'Slauth' - s.version = '0.7.19' - s.summary = 'A Swift wrapper around Slauth Rust crate' - s.description = <<-DESC -TODO: Add long description of the pod here. - DESC - - s.homepage = 'https://github.com/Devolutions/Slauth.git' - s.license = { :type => 'MIT', :file => './LICENSE' } - s.author = { 'Devolutions' => 'lfauvel@devolutions.net' } - s.source = { :git => 'https://github.com/Devolutions/Slauth.git', :tag => s.version.to_s } - - s.swift_version = '5.0' - s.ios.deployment_target = '16.0' - - s.source_files = 'wrappers/swift/classes/**/*', 'slauth.h' - s.vendored_libraries = 'target/universal/release/*.a', 'target/x86_64-apple-ios/release/*.a', 'target/aarch64-apple-ios/release/*.a' -end diff --git a/src/oath/mod.rs b/src/oath/mod.rs index 05bb099..66ef90e 100644 --- a/src/oath/mod.rs +++ b/src/oath/mod.rs @@ -1,3 +1,5 @@ +//Have to allow deprecated because hmac crate hasn't been updated yet to GenericArray 1.0 +#[allow(deprecated)] use hmac::{ digest::{generic_array::GenericArray, FixedOutputReset, InvalidLength, OutputSizeUser}, Mac, SimpleHmac, @@ -47,6 +49,7 @@ impl MacHashKey { } } +#[allow(deprecated)] pub(crate) enum HmacShaResult { RSHA1(GenericArray::OutputSize>), RSHA256(GenericArray::OutputSize>), diff --git a/src/u2f/client/mod.rs b/src/u2f/client/mod.rs index 4e8de83..d5dd2ef 100644 --- a/src/u2f/client/mod.rs +++ b/src/u2f/client/mod.rs @@ -68,7 +68,11 @@ pub mod client { let mut data = Vec::with_capacity(64); + + //Allowing deprecated because hmac library hasn't updated yet + #[allow(deprecated)] data.extend_from_slice(challenge_param.as_slice()); + #[allow(deprecated)] data.extend_from_slice(application_parameter.as_slice()); let raw_req = RawRequest { @@ -133,7 +137,11 @@ pub mod client { let mut data = Vec::new(); + + //Allow deprecated pending rust crypto generic_array removal + #[allow(deprecated)] data.extend_from_slice(challenge_param.as_slice()); + #[allow(deprecated)] data.extend_from_slice(application_parameter.as_slice()); data.push(signing_key.key_handle.len() as u8); data.extend_from_slice(signing_key.key_handle.as_bytes()); diff --git a/src/webauthn/proto/tpm.rs b/src/webauthn/proto/tpm.rs index dfac4dc..6197844 100644 --- a/src/webauthn/proto/tpm.rs +++ b/src/webauthn/proto/tpm.rs @@ -123,10 +123,14 @@ impl TPM { let (scheme, hashed) = match self.alg.into() { CoseAlgorithmIdentifier::RS1 => ( Pkcs1v15Sign::new::(), + //Allow deprecated pending rust crypto generic_array removal + #[allow(deprecated)] sha1::Sha1::digest(self.cert_info.as_slice()).as_slice().to_vec(), ), CoseAlgorithmIdentifier::RSA => ( Pkcs1v15Sign::new::(), + //Allow deprecated pending rust crypto generic_array removal + #[allow(deprecated)] sha2::Sha256::digest(self.cert_info.as_slice()).as_slice().to_vec(), ), _ => return Err(Error::TpmError(TpmError::SignatureHashInvalid(self.alg))), diff --git a/src/webauthn/server/mod.rs b/src/webauthn/server/mod.rs index e05bb6b..1b777e9 100644 --- a/src/webauthn/server/mod.rs +++ b/src/webauthn/server/mod.rs @@ -234,6 +234,9 @@ impl CredentialCreationVerifier { } else { hasher.update(get_default_rp_id(&self.origin)); } + + //Allow deprecated pending rust crypto generic_array removal + #[allow(deprecated)] if attestation.auth_data.rp_id_hash != hasher.finalize().as_slice() { return Err(Error::CredentialError(CredentialError::Rp)); } @@ -601,6 +604,8 @@ impl CredentialRequestVerifier { } else { hasher.update(get_default_rp_id(&self.origin)); } + //Allow deprecated pending rust crypto generic_array removal + #[allow(deprecated)] if auth_data.rp_id_hash != hasher.finalize_reset().as_slice() { return Err(Error::CredentialError(CredentialError::Rp)); } diff --git a/wrappers/swift/Package.swift b/wrappers/swift/Package.swift new file mode 100644 index 0000000..64bddde --- /dev/null +++ b/wrappers/swift/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version: 5.10 +import PackageDescription + +let package = Package( + name: "Slauth", + platforms: [ + .iOS(.v16) + ], + products: [ + .library( + name: "Slauth", + targets: ["Slauth"] + ) + ], + targets: [ + .systemLibrary( + name: "SlauthFFI", + path: "ffi" + ), + .binaryTarget( + name: "libslauth", + path: "libslauth.xcframework" + ), + .target( + name: "Slauth", + dependencies: [ + "SlauthFFI", + "libslauth" + ], + path: "classes" + ) + ] +) diff --git a/wrappers/swift/build.sh b/wrappers/swift/build.sh index 9713b30..abce44e 100755 --- a/wrappers/swift/build.sh +++ b/wrappers/swift/build.sh @@ -1,4 +1,28 @@ -cargo lipo --release -mv target/universal/release/libslauth.a target/universal/release/libslauth_universal.a -mv target/x86_64-apple-ios/release/libslauth.a target/x86_64-apple-ios/release/libslauth_x86.a -mv target/aarch64-apple-ios/release/libslauth.a target/aarch64-apple-ios/release/libslauth_arm64.a \ No newline at end of file +#!/bin/bash +set -e + +rm -rf ./package + +# Build Rust libraries for iOS targets +cargo build --target aarch64-apple-ios --release +cargo build --target aarch64-apple-ios-sim --release +cargo build --target aarch64-apple-darwin --release +cargo build --target x86_64-apple-darwin --release + +lipo target/x86_64-apple-darwin/release/libslauth.a target/aarch64-apple-darwin/release/libslauth.a -create -output target/libslauth.a + +mkdir package +mkdir ./package/headers +cp slauth.h ./package/headers + +# Create XCFramework +xcodebuild -create-xcframework \ + -library target/aarch64-apple-ios/release/libslauth.a -headers ./package/headers \ + -library target/aarch64-apple-ios-sim/release/libslauth.a -headers ./package/headers \ + -library target/libslauth.a -headers ./package/headers \ + -output ./package/libslauth.xcframework + +cp wrappers/swift/Package.swift ./package +cp -R wrappers/swift/classes ./package +cp -R wrappers/swift/ffi ./package + diff --git a/wrappers/swift/classes/Hotp.swift b/wrappers/swift/classes/Hotp.swift index 966477f..2710a06 100644 --- a/wrappers/swift/classes/Hotp.swift +++ b/wrappers/swift/classes/Hotp.swift @@ -8,6 +8,10 @@ import Foundation +#if canImport(SlauthFFI) +import SlauthFFI +#endif + public class Hotp: NSObject, RustObject { var raw: OpaquePointer diff --git a/wrappers/swift/classes/SlauthUtils.swift b/wrappers/swift/classes/SlauthUtils.swift index 519fe45..c6eccc5 100644 --- a/wrappers/swift/classes/SlauthUtils.swift +++ b/wrappers/swift/classes/SlauthUtils.swift @@ -1,5 +1,9 @@ import Foundation +#if canImport(SlauthFFI) +import SlauthFFI +#endif + public class SlauthUtils { public static func convertPkcs8ToPrivateKey(pkcs8String: String) -> String { let cString = pkcs8_to_custom_private_key(pkcs8String) @@ -14,4 +18,4 @@ public class SlauthUtils { free(cString) return pkcs8String } -} \ No newline at end of file +} diff --git a/wrappers/swift/classes/Totp.swift b/wrappers/swift/classes/Totp.swift index e223e91..03a333a 100644 --- a/wrappers/swift/classes/Totp.swift +++ b/wrappers/swift/classes/Totp.swift @@ -8,6 +8,10 @@ import Foundation +#if canImport(SlauthFFI) +import SlauthFFI +#endif + public class Totp: NSObject, RustObject { var raw: OpaquePointer diff --git a/wrappers/swift/classes/U2f.swift b/wrappers/swift/classes/U2f.swift index 7f2b6c2..4097143 100644 --- a/wrappers/swift/classes/U2f.swift +++ b/wrappers/swift/classes/U2f.swift @@ -7,6 +7,10 @@ import Foundation +#if canImport(SlauthFFI) +import SlauthFFI +#endif + public class WebRequest : RustObject { var raw: OpaquePointer diff --git a/wrappers/swift/classes/WebAuthnCreationResponse.swift b/wrappers/swift/classes/WebAuthnCreationResponse.swift index 52f87f5..97bae33 100644 --- a/wrappers/swift/classes/WebAuthnCreationResponse.swift +++ b/wrappers/swift/classes/WebAuthnCreationResponse.swift @@ -1,6 +1,10 @@ import Foundation import AuthenticationServices +#if canImport(SlauthFFI) +import SlauthFFI +#endif + @available(iOS 15.0, *) public class WebAuthnCreationResponse: NSObject { diff --git a/wrappers/swift/classes/WebAuthnRequestResponse.swift b/wrappers/swift/classes/WebAuthnRequestResponse.swift index 268efc1..81a428e 100644 --- a/wrappers/swift/classes/WebAuthnRequestResponse.swift +++ b/wrappers/swift/classes/WebAuthnRequestResponse.swift @@ -1,3 +1,9 @@ +import Foundation + +#if canImport(SlauthFFI) +import SlauthFFI +#endif + @available(iOS 15.0, *) public class WebAuthnRequestResponse: NSObject, RustObject { diff --git a/wrappers/swift/ffi/framework.modulemap b/wrappers/swift/ffi/framework.modulemap new file mode 100644 index 0000000..9289f8f --- /dev/null +++ b/wrappers/swift/ffi/framework.modulemap @@ -0,0 +1,6 @@ +framework module SlauthFFI { + umbrella header "../headers/slauth.h" + + export * + module * { export * } +} diff --git a/wrappers/swift/ffi/module.modulemap b/wrappers/swift/ffi/module.modulemap new file mode 100644 index 0000000..d1eab87 --- /dev/null +++ b/wrappers/swift/ffi/module.modulemap @@ -0,0 +1,4 @@ +module SlauthFFI [system] { + header "../headers/slauth.h" + export * +}