Crittografato NSData di NSString in obj-c?

Ho una applicazione per iPhone che consente di crittografare un immessi NSString utilizzando CCCrypt (AES256) e un testo in chiaro chiave. La stringa chiave e dato il metodo di crittografia che restituisce un NSData oggetto.

Richiesta di [description] dove ‘dati’ è la stringa crittografata dei dati fornisce una NSString come: “<0b368353 a707e7de 3eee5992 ee69827e e3603dc2 b0dbbc0b 861ca87d f39ce72a>” ma quando provo a convertire un NSString, ottengo “(null)”.

Ho bisogno di restituire un NSString per l’utente, che può essere utilizzato per decifrare indietro la stringa originale utilizzando lo stesso testo in chiaro chiave. Se la ‘descrizione’ di proprietà del NSData oggetto può restituire una stringa, c’è qualche modo sono in grado di produrre una NSString dal NSData oggetto senza avere “(null)”?

AGGIORNAMENTO: Grazie a Quinn, che suggerisce di utilizzare la codifica Base64 per produrre groviglio di corda. Da quello che ho capito, la codifica Base64 non semplicemente scambiare i caratteri, ma il personaggio di cambio dipende dalla posizione, quindi va bene così.

La mia unica preoccupazione è che voglio essere in grado di cifrare il messaggio con una “passphrase” e richiedono l’identico passphrase deve essere inserito quando l’confuso stringa deve essere decodificato – qualcuno può suggerire modi per implementare questa?

  • Ho aggiornato la mia risposta all’indirizzo di seguito. Sei corretto, Base64 non è un algoritmo di sostituzione — sostanzialmente si espande 3 byte 4 byte, quindi codificati i dati 1.37 x grande come la sua non codificato controparte. Fondamentalmente, ci vogliono da 3 a 8-bit pezzi e redivides in 4 blocchi 6 bit, quindi reinterpreta ognuno di quelli a 8 bit pezzi, la quale può essere facilmente rappresentato in ASCII. Wikipedia ha più dettaglio.
InformationsquelleAutor Boz | 2009-09-13

 

3 Replies
  1. 33

    Prima di tutto, NON utilizzare -[NSData description] per creare una NSString per tali scopi. (È meglio per il trattamento di -description come output di debug. Mi scuso se la mia risposta precedente ingannare voi, io ero semplicemente stampa la descrizione per dimostrare che il NSData possono essere cifrati e decifrati.) Invece, utilizzare NSString del -dataUsingEncoding: e -initWithData:encoding: metodi per la conversione tra NSData e NSString. Anche con questi, nota che AES-dati crittografati probabilmente non traducono bene in stringhe come-si — alcune sequenze di byte di non giocare bene, quindi è una buona idea per codificare i dati prima di creare la stringa.

    Vi suggerisco di provare La codifica Base64 il NSData, dal momento che i dati Base64 può sempre essere rappresentato come una stringa ASCII. (Naturalmente, se si esegue questa operazione, dovrete decodifica da Base64 prima di decifratura.)

    Ecco alcune risorse utili…


    Edit: stavo supponendo che ci si combina questo con la mia risposta a la tua domanda precedente sulla crittografia AES di NSString oggetti. Dati di codifica in Base64 non pongono restrizioni sui dati — può certamente essere AES-enrypted dati. Ecco cosa fare se si desidera solo la stringa di input e di output:

    • Di crittografia
      • Fornire il NSString essere crittografati, e la passphrase da utilizzare per la crittografia.
      • Convertire la stringa in un NSData e di eseguire la crittografia AES su di esso (vedi domanda precedente).
      • Base64 codifica il NSData, quindi creare e ritorno e NSString di codifica di output.
    • Decrittografia
      • Fornire crittografati stringa codificata, e la passphrase da utilizzare per decifrare.
      • Creare un NSData dalla prima stringa Base64-decodificare i dati.
      • Eseguire AES decrittografia dei dati, quindi creare e restituire una NSString.

    È davvero solo una questione di concatenamento le due parti insieme e in esecuzione in senso inverso la via d’uscita. Dalla mia risposta precedente, è possibile modificare encryptString:withKey: per eseguire l’ultimo passaggio e restituire una stringa, e cambiare decryptData:withKey: essere decryptString:withKey: e accettare i due stringhe. E ‘ abbastanza semplice.

    • +1 e Grazie per il link NSDataAdditions, molto utile!
    • Si prega di non segnalare altre risposte di persone, come Comunità Wiki durante la modifica. Non è quello che è.
    • Le FAQ stati che sono l’unico che in particolare ha accesso alla Comunità Wiki casella di controllo. La mia modifica può avere inavvertitamente fatto entrare in Comunità Wiki modalità, ma che era assolutamente involontario. Si prega di non accusare altre persone di fare cose che non può fare. Reference
    • Le mie scuse, non era colpa tua, dopo tutto. Non sapevo che una risposta converte automaticamente in CW se: “Il post è stato modificato dieci (10) volte dal proprietario originale.” Mi è capitato di vedere che si trattava di CW quando ho visto il tuo edit, ma è stato dopo il mio precedente modifica che è successo. Scusa per saltare alle conclusioni. 😛
    • Va tutto bene. Queste sono cose che accadono. Dopotutto, (anche se pensiamo di essere potenti maghi del computer) siamo solo umani.
    • La documentazione NSData .descrizione meramente stati A string that contains a hexadecimal representation of the object’s contents in a property list format. C’è nessun riferimento a questo deve essere utilizzato solo per scopi di debug. Se si lavora per un noto formato di dati, c’è un vero e proprio motivo per non usarlo? [Edit: Ah, forse ho bisogno di leggere questa risposta, in particolare nel contesto della domanda originale del re di dati crittografati.]

  2. 2

    Ho messo insieme un completo pacchetto di categorie per NSData e NSString per fornire la crittografia AES256 per le stringhe.

    Vedere la mia risposta su “originale” domanda per ulteriori dettagli.

  3. 0

    Ho simile requisito di cui ho bisogno per crittografare tutte le corde quando l’utente immette la password per accedere alla app, in modo che coloro che sono sensibili stringhe non rimangono in chiaro tutto il tempo. Quindi devo tenere quelle stringhe criptate e decifrare come quando richiedono soltanto.

    Era una semplice esigenza e volevo tenerlo leggero. Così ho creato un piccolo Obfuscator utilizzando sacco di informazioni utili condivisa da @RobNapier in una sua blog. Potrebbe essere d’aiuto per coloro che sono alla ricerca di una soluzione leggera con molto succosa commenti.

    importazione Fondazione 
    importazione CommonCrypto 
    //Un sottile involucro intorno interfacciamento 
    pubblica enum CrypticAlgo { 
    caso AlgoAES 
    caso AlgoDES

    func blockSize() -> Int {
        switch self {
        case .AlgoAES:
            return kCCBlockSizeAES128
        case .AlgoDES:
            return kCCBlockSizeDES
        }
    }
    
    func keySize() -> size_t {
        switch self {
        case .AlgoAES:
            return kCCKeySizeAES128
        case .AlgoDES:
            return kCCKeySizeDES
        }
    }
    
    func algo() -> UInt32 {
        switch self {
        case .AlgoAES:
            return CCAlgorithm(kCCAlgorithmAES)
        case .AlgoDES:
            return CCAlgorithm(kCCAlgorithmDES)
        }
    }
    

    }

    pubblica finale classe MGObfuscate {

    private var ivData: [UInt8]?
    private var derivedKey: Data?
    private let crypticAlgo: CrypticAlgo

    public init(password: String, salt: String, algo: CrypticAlgo) {
    //Quickly get the data to release the password string
    let passwordData
    = password.data(using: .utf8)!
    //
    //Rounds require for 1 sec delay in generating hash.
    //Salt is a public attribute. If attacker somehow get the drivedKey and try to crack
    //the password via brute force, The delay due to Rounds will make it frustrating
    //to get actual password and deter his/her efforts.
    //
    let rounds
    = CCCalibratePBKDF(CCPBKDFAlgorithm(kCCPBKDF2), password.count,
    salt
    .count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), Int(CC_SHA256_DIGEST_LENGTH), 1000)

    let saltData = salt.data(using: .utf8)!
    derivedKey
    = MGObfuscate.derivedKey(for: passwordData,
    saltData
    : saltData, rounds: rounds)
    self
    .crypticAlgo = algo
    var ivData
    = [UInt8](repeating: 0, count: algo.blockSize())
    //Random criptographically secure bytes for initialisation Vector
    let rStatus
    = SecRandomCopyBytes(kSecRandomDefault, ivData.count, &ivData)
    self
    .ivData = ivData
    // print(ivData)
    guard rStatus
    == errSecSuccess else {
    fatalError
    ("seed not generated \(rStatus)")
    }
    }

    @inline(__always) private static func derivedKey(for passwordData: Data, saltData: Data, rounds: UInt32) -> Data {
    var derivedData
    = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
    let result
    = derivedData.withUnsafeMutableBytes { (drivedBytes: UnsafeMutablePointer<UInt8>?) in
    passwordData
    .withUnsafeBytes({ (passwordBytes: UnsafePointer<Int8>!) in
    saltData
    .withUnsafeBytes({ (saltBytes: UnsafePointer<UInt8>!) in
    CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), passwordBytes, passwordData.count, saltBytes, saltData.count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), rounds, drivedBytes, Int(CC_SHA256_DIGEST_LENGTH))
    })
    })
    }
    if kCCSuccess != result {
    fatalError
    ("failed to generate hash for password")
    }
    return derivedData
    }

    private func runCryptic(operation: Int, inputData: Data, keyData: Data, ivData: Data) -> Data {
    let cryptLength
    = size_t(inputData.count + crypticAlgo.blockSize())
    var cryptData
    = Data(count: cryptLength)
    let keyLength
    = crypticAlgo.keySize()

    var bytesProcessed: size_t = 0
    let cryptStatus
    = cryptData.withUnsafeMutableBytes {cryptBytes in
    inputData
    .withUnsafeBytes { dataBytes in
    keyData
    .withUnsafeBytes { keyBytes in
    ivData
    .withUnsafeBytes{ ivBytes in
    CCCrypt(CCOperation(operation),
    crypticAlgo
    .algo(),
    CCOptions(kCCOptionPKCS7Padding),
    keyBytes
    , keyLength,
    ivBytes
    ,
    dataBytes
    , inputData.count,
    cryptBytes
    , cryptLength,
    &bytesProcessed)
    }
    }
    }
    }
    if cryptStatus == CCCryptorStatus(kCCSuccess) {
    cryptData
    .removeSubrange(bytesProcessed..<cryptData.count)
    } else {
    fatalError
    ("Error: \(cryptStatus)")
    }
    return cryptData
    }

    public func encriptAndPurge(inputString: inout String?) -> Data? {
    if let inputdata = inputString?.data(using: .utf8) {
    inputString
    = nil
    return runCryptic(operation: kCCEncrypt, inputData: inputdata, keyData: derivedKey!, ivData: Data(bytes: ivData!))
    }
    return nil
    }

    public func encript(inputString: String) -> Data {
    let inputdata
    = inputString.data(using: .utf8)!
    return runCryptic(operation: kCCEncrypt, inputData: inputdata, keyData: derivedKey!, ivData: Data(bytes: ivData!))
    }

    public func decript(data: Data, result: (String) -> Void) {
    let data
    = runCryptic(operation: kCCDecrypt, inputData: data, keyData: derivedKey!, ivData: Data(bytes: ivData!))
    result
    (String(data: data, encoding: .utf8)!)
    }

    public func purge() {
    ivData
    = nil
    derivedKey
    = nil
    }

    }

Lascia un commento