ios - common - swift crypto




Importieren von CommonCrypto in einem Swift-Framework (8)

Wie importieren Sie CommonCrypto in ein Swift-Framework für iOS?

Ich verstehe, wie Sie CommonCrypto in einer Swift-App verwenden: Sie fügen #import <CommonCrypto/CommonCrypto.h> zum Bridging-Header hinzu.

Swift-Frameworks unterstützen jedoch keine Bridging-Header. Die documentation sagt:

Sie können externe Frameworks mit einer reinen Objective-C-Codebase, einer reinen Swift-Codebasis oder einer codierten Codebasis mit mehreren Sprachen importieren. Der Prozess zum Importieren eines externen Frameworks ist derselbe, unabhängig davon, ob das Framework in einer einzelnen Sprache geschrieben ist oder Dateien aus beiden Sprachen enthält. Stellen Sie beim Importieren eines externen Frameworks sicher, dass die Einstellung Builds für Modul definieren für das zu importierende Framework auf Ja festgelegt ist.

Sie können ein Framework mithilfe der folgenden Syntax in eine beliebige Swift-Datei in einem anderen Ziel importieren:

import FrameworkName

CommonCrypto funktioniert leider nicht. Das Hinzufügen von #import <CommonCrypto/CommonCrypto.h> zu dem Regenschirm-Header auch nicht.


@mogstad war so freundlich, @stephencelis Lösung in eine Cocoapod zu wickeln:

pod 'libCommonCrypto'

Die anderen verfügbaren Pods funktionierten nicht für mich.


Die modulmap-Lösungen können gut sein und sind robust gegenüber SDK-Änderungen, aber ich habe festgestellt, dass sie in der Praxis unpraktisch sind und nicht so zuverlässig sind, wie ich es gerne hätte, wenn ich anderen Dinge übergebe. Um es noch narrensicherer zu machen, ging ich einen anderen Weg:

Kopiere einfach die Header.

Ich weiß, zerbrechlich. Aber Apple ändert fast nie wesentliche Änderungen an CommonCrypto und ich lebe den Traum, dass sie es nicht in bedeutender Weise ändern werden, ohne auch CommonCrypto schließlich einen modularen Kopf zu machen.

Mit "kopiere die Header" meine ich, "schneide und füge alle benötigten Header in einen massiven Header in deinem Projekt ein, so wie es der Präprozessor tun würde." Ein Beispiel hierfür, das Sie kopieren oder anpassen können, finden Sie unter RNCryptor.h .

Beachten Sie, dass alle diese Dateien unter APSL 2.0 lizenziert sind. Bei diesem Ansatz werden die Copyright- und Lizenzhinweise absichtlich beibehalten. Mein Verkettungsschritt wird unter MIT lizenziert, und das gilt nur bis zur nächsten Lizenzbenachrichtigung).

Ich sage nicht, dass dies eine schöne Lösung ist, aber bisher scheint es eine unglaublich einfache Lösung für die Implementierung und Unterstützung gewesen zu sein.


Es ist sehr einfach. Hinzufügen

#import <CommonCrypto/CommonCrypto.h>

in eine .h-Datei (die Bridging-Header-Datei Ihres Projekts). Als Konvention können Sie es YourProjectName-Bridging-Header.h nennen.

Dann gehen Sie zu Ihrem Projekt Build Settings und suchen Sie nach Swift Compiler - Code Generation. Fügen Sie darunter den Namen Ihres Bridging-Headers zum Eintrag "Objetive-C Bridging Header" hinzu.

Sie sind fertig. In Ihrem Swift-Code sind keine Importe erforderlich. Alle öffentlichen Objective-C-Header, die in dieser Bridging-Header-Datei aufgelistet sind, sind für Swift sichtbar.


Etwas einfacher und robuster ist es, ein Aggregationsziel namens "CommonCryptoModuleMap" mit einer Run Script-Phase zu erstellen, um die Modulzuordnung automatisch und mit dem korrekten Xcode / SDK-Pfad zu generieren:

Die Run Script-Phase sollte diese Bash enthalten:

# This if-statement means we'll only run the main script if the CommonCryptoModuleMap directory doesn't exist
# Because otherwise the rest of the script causes a full recompile for anything where CommonCrypto is a dependency
# Do a "Clean Build Folder" to remove this directory and trigger the rest of the script to run
if [ -d "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap" ]; then
    echo "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap directory already exists, so skipping the rest of the script."
    exit 0
fi

mkdir -p "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap"
cat <<EOF > "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap/module.modulemap"
module CommonCrypto [system] {
    header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}
EOF

Wenn Sie Shell-Code und ${SDKROOT} , müssen Sie den Xcode.app-Pfad nicht fest codieren, was von System zu System variieren kann, insbesondere wenn Sie xcode-select , um zu einer Beta-Version zu wechseln, oder auf einem CI-Server, auf dem mehrere Versionen an nicht standardmäßigen Standorten installiert sind. Sie müssen das SDK auch nicht fest codieren, damit dies für iOS, MacOS usw. funktioniert. Sie müssen auch nichts im Quellverzeichnis Ihres Projekts haben.

Nachdem Sie dieses Ziel erstellt haben, müssen Sie Ihre Bibliothek / Ihr Framework davon abhängig machen, ob Sie ein Zielabhängigkeitselement verwenden:

Dadurch wird sichergestellt, dass die Modulzuordnung generiert wird, bevor Ihr Framework erstellt wird.

macOS note : Wenn Sie auch macOS unterstützen, müssen Sie der Build-Einstellung für Supported Platforms auf dem neuen Aggregatziel, das Sie gerade erstellt haben, macosx hinzufügen. macosx die macosx nicht in den korrekten Debug macosx mit dem Rest der Rahmenprodukte.

${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap Nächstes das übergeordnete Verzeichnis der ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap , ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap , zur ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap " ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap " im Abschnitt Swift ( SWIFT_INCLUDE_PATHS ) hinzu:

Denken Sie daran, eine $(inherited) Zeile hinzuzufügen, wenn Sie Suchpfade auf der Projekt- oder xcconfig-Ebene definiert haben.

Jetzt sollten Sie import CommonCrypto


Ich habe ein GitHub-Projekt gefunden, das CommonCrypto erfolgreich in einem Swift-Framework verwendet: SHA256-Swift . Auch dieser Artikel über das selbe Problem mit sqlite3 war nützlich.

Basierend auf dem oben genannten sind die Schritte:

1) Erstellen Sie ein CommonCrypto Verzeichnis innerhalb des Projektverzeichnisses. Innerhalb, erstellen Sie eine module.map Datei. Die Modulkarte ermöglicht es uns, die CommonCrypto-Bibliothek als Modul innerhalb von Swift zu verwenden. Sein Inhalt ist:

module CommonCrypto [system] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    link "CommonCrypto"
    export *
}

2) CommonCrypto in den Build-Einstellungen in Swift Compiler - CommonCrypto das CommonCrypto Verzeichnis den CommonCrypto ( SWIFT_INCLUDE_PATHS ).

3) Schließlich importieren Sie CommonCrypto in Ihre Swift-Dateien wie alle anderen Module. Beispielsweise:

import CommonCrypto

extension String {

    func hnk_MD5String() -> String {
        if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        {
            let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))
            let resultBytes = UnsafeMutablePointer<CUnsignedChar>(result.mutableBytes)
            CC_MD5(data.bytes, CC_LONG(data.length), resultBytes)
            let resultEnumerator = UnsafeBufferPointer<CUnsignedChar>(start: resultBytes, length: result.length)
            let MD5 = NSMutableString()
            for c in resultEnumerator {
                MD5.appendFormat("%02x", c)
            }
            return MD5
        }
        return ""
    }
}

Einschränkungen

Die Verwendung des benutzerdefinierten Frameworks in einem anderen Projekt schlägt missing required module 'CommonCrypto' Kompilierung fehl, da der Fehler das missing required module 'CommonCrypto' . Dies liegt daran, dass das CommonCrypto-Modul nicht im benutzerdefinierten Framework enthalten ist. Eine Problemumgehung besteht darin, Schritt 2 (Festlegen von Import Paths ) in dem Projekt zu wiederholen, das das Framework verwendet.

Die Modulkarte ist nicht plattformunabhängig (sie zeigt derzeit auf eine bestimmte Plattform, den iOS 8 Simulator). Ich weiß nicht, wie man den Header-Pfad relativ zur aktuellen Plattform macht.

Updates für iOS 8 <= Wir sollten den Zeilenlink "CommonCrypto" entfernen, um die erfolgreiche Kompilierung zu erhalten.

AKTUALISIEREN / BEARBEITEN

Ich habe den folgenden Erstellungsfehler erhalten:

ld: Bibliothek nicht gefunden für -lCommonCrypto für Architektur x86_64 clang: Fehler: Linker-Befehl ist fehlgeschlagen mit Exit Code 1 (benutze -v um den Aufruf zu sehen)

Es sei denn, ich habe den link "CommonCrypto" aus der von module.map Datei module.map . Sobald ich diese Zeile entfernt habe, hat es sich in Ordnung entwickelt.


Ich weiß, das ist eine alte Frage. Aber ich finde einen alternativen Weg, die Bibliothek im Swift-Projekt zu verwenden, was für diejenigen hilfreich sein könnte, die das in diese Antworten eingeführte Framework nicht importieren wollen.

Erstellen Sie in Swift-Projekt einen Objective-C-Bridging-Header, erstellen Sie in Objective-C die NSData-Kategorie (oder die benutzerdefinierte Klasse, die die Bibliothek verwenden soll). Der einzige Nachteil wäre, dass Sie den gesamten Implementierungscode in Objective-C schreiben müssen. Beispielsweise:

#import "NSData+NSDataEncryptionExtension.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (NSDataEncryptionExtension)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
    //do something
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
//do something
}

Und dann fügen Sie dies in Ihrem objektiven c-Bridging-Header hinzu

#import "NSData+NSDataEncryptionExtension.h"

Und dann in der Swift-Klasse:

public extension String {
func encryp(withKey key:String) -> String? {
    if let data = self.data(using: .utf8), let encrypedData = NSData(data: data).aes256Encrypt(withKey: key) {
        return encrypedData.base64EncodedString()
    }
    return nil
}
func decryp(withKey key:String) -> String? {
    if let data = NSData(base64Encoded: self, options: []), let decrypedData = data.aes256Decrypt(withKey: key) {
        return decrypedData.UTF8String
    }
    return nil
}
}

Es funktioniert wie erwartet.


Wenn Sie Hash-Algorithmen wie SHA, MD5 usw. verwenden, verwenden Sie nicht die sperrige CommonCrypto-Bibliothek. Suchen Sie stattdessen nach der speziellen Hashing-Bibliothek, nach der Sie suchen.

Zum Beispiel für MD5 können Sie mit SwiftHash gehen


WARNUNG: iTunesConnect reject möglicherweise Apps ab, die diese Methode verwenden.

Ein neues Mitglied in meinem Team hat versehentlich die Lösung einer der Top-Antworten gebrochen, also habe ich beschlossen, es in einem kleinen Wrapper-Projekt namens CommonCryptoModule zu konsolidieren. Sie können es manuell oder über Cocoapods installieren:

pod 'CommonCryptoModule', '~> 1.0.2'

Dann müssen Sie CommonCrypto das Modul, in dem Sie CommonCrypto benötigen, CommonCrypto :

import CommonCryptoModule

Hoffe, jemand anderes findet das nützlich.







commoncrypto