Creazione di firme digitali con Swift

Lo scopo principale di una firma digitale è verificare l'integrità di alcune informazioni. Per un semplice esempio, supponiamo che tu avessi un file che è stato trasferito sulla rete e vuoi controllare che l'intero file sia stato trasferito correttamente. In tal caso, si utilizzerà un checksum.

"Un checksum è un dato di piccole dimensioni derivato da un blocco di dati digitali allo scopo di rilevare errori che potrebbero essere stati introdotti durante la sua trasmissione o memorizzazione" - Wikipedia

Come deriviamo quel checksum? L'opzione migliore è usare un hash. Una funzione di hash prenderà una quantità variabile di dati e produrrà una firma di lunghezza fissa. Ad esempio, potremmo pubblicare un file insieme al suo hash online. Quando qualcuno scarica il file, può quindi eseguire la stessa funzione di hash sulla sua versione del file e confrontare il risultato. Se gli hash sono uguali, il file copiato o scaricato è lo stesso dell'originale. 

Un hash è anche una funzione a senso unico. Dato l'output risultante, non esiste un modo computazionalmente fattibile per invertire quell'hash per rivelare quale fosse l'input originale. SHA, Secure Hash Algorithm, è uno standard noto che fa riferimento a un gruppo di funzioni hash che hanno questa proprietà e altre, che le rendono utili per le firme digitali.

A proposito di SHA

SHA ha subito molte iterazioni da quando è stato pubblicato per la prima volta. Le prime e seconde iterazioni, SHA-0 e SHA-1, sono ora note per avere maggiori punti deboli. Non sono più approvati per implementazioni di sicurezza: in genere non dovrebbero essere utilizzati per applicazioni che si basano sulla sicurezza. Tuttavia, la famiglia SHA-2 include versioni chiamate SHA-256 e SHA-512, e queste sono considerate sicure. "256" e "512" si riferiscono semplicemente al numero risultante di bit prodotti. Per questo tutorial, utilizzeremo SHA-512.

Nota: un altro algoritmo di hash popolare più vecchio era MD5. Si è anche scoperto che presenta notevoli difetti.

L'utilizzo di SHA è ottimo per verificare se i dati sono stati accidentalmente corrotti, ma ciò non impedisce a un utente malintenzionato di manomettere i dati. Dato che un output hash è di dimensioni fisse, tutto ciò che un utente malintenzionato deve fare è capire quale algoritmo è stato utilizzato data la dimensione dell'output, modificare i dati e ricalcolare l'hash. Ciò di cui abbiamo bisogno sono alcune informazioni segrete aggiunte al mix durante l'hashing dei dati in modo che l'hacker non possa ricalcolare l'hash senza conoscere il segreto. Questo è chiamato Hash Message Authentication Code (HMAC).

HMAC

HMAC può autenticare un'informazione o un messaggio per assicurarsi che provenga dal mittente corretto e che le informazioni non siano state alterate. Uno scenario comune è quando parli con un server con un'API back-end per la tua app. Potrebbe essere importante autenticarsi per garantire che solo la tua app sia autorizzata a parlare con l'API. L'API avrebbe controllo di accesso a una risorsa specifica, come a / register_user endpoint. Il cliente avrebbe bisogno di cartello la sua richiesta al / register_user endpoint per usarlo con successo.

Quando si firma una richiesta, è prassi comune prendere parti selezionate della richiesta, come i parametri POST e l'URL, e unirle in una stringa. Prendere gli elementi concordati e metterli in un ordine particolare viene chiamato canonica. In HMAC, la stringa unita viene hash con la chiave segreta per produrre il firma. Invece di chiamarlo hash, usiamo il termine signature nello stesso modo in cui la firma di una persona nella vita reale viene utilizzata per verificare l'identità o l'integrità. La firma viene aggiunta alla richiesta del cliente come intestazione di richiesta (di solito anche denominata "Firma"). A volte una firma viene chiamata digest di messaggi, ma i due termini possono essere usati in modo intercambiabile.

Sul lato API, il server ripete il processo di unire le stringhe e creare una firma. Se le firme corrispondono, dimostra che l'app deve avere il possesso del segreto. Ciò dimostra l'identità dell'app. Poiché anche i parametri specifici della richiesta erano parte della stringa da firmare, garantisce anche l'integrità della richiesta. Impedisce ad un attaccante di eseguire un attacco man-in-the-middle, ad esempio, e di modificare i parametri della richiesta a proprio piacimento.

class func hmacExample () // Qualche esempio di URL ... let urlString = "https://example.com" let postString = "id = 123" let url = URL.init (string: urlString) var request = URLRequest (url: url!) request.httpMethod = richiesta "POST ".httpBody = postString.data (usando: .utf8) let session = URLSession.shared // Crea una firma let stringToSign = request.httpMethod! + "&" + urlString + "&" + postString print ("La stringa da firmare è:", stringToSign) se let dataToSign = stringToSign.data (usando: .utf8) let signingSecret = "4kDfjgQhcw4dG6J80QnvRFbtuJfkgitH6phkLN90" se let signingSecretData = signingSecret .data (usando: .utf8) let digestLength = Int (CC_SHA512_DIGEST_LENGTH) let digestBytes = UnsafeMutablePointer.allocare (capacità: digestLength) CCHmac (CCHmacAlgorithm (kCCHmacAlgSHA512), [UInt8] (signingSecretData), signingSecretData.count, [UInt8] (dataToSign), dataToSign.count, digestBytes) // output base64 consente hmacData = Dati (byte: digestBytes, count: digestLength) let signature = hmacData.base64EncodedString () print ("La firma HMAC in base64 è" + signature) // o l'output HEX lascia hexString = NSMutableString () per i in 0 ...  

In questo codice, il CCHmac la funzione accetta un parametro per il tipo di funzione di hash da utilizzare, insieme a due stringhe di byte e alle relative lunghezze: il messaggio e una chiave segreta. Per la massima sicurezza, utilizzare almeno una chiave a 256 bit (32 byte) generata da un generatore di numeri casuali protetto da crittografia. Per verificare che tutto funzioni correttamente sull'altro lato, eseguire l'esempio, quindi immettere la chiave segreta e il messaggio su questo server remoto e verificare che l'output sia lo stesso.

È inoltre possibile aggiungere un'intestazione di timestamp alla richiesta e una stringa di firma per rendere la richiesta più unica. Ciò può aiutare l'API a eliminare gli attacchi di riproduzione. Ad esempio, l'API potrebbe abbandonare la richiesta se il timestamp è di 10 minuti non aggiornato.

Sebbene sia opportuno attenersi alle versioni di SHA che sono sicure, si scopre che molte delle vulnerabilità delle versioni di SHA non sicure non si applicano a HMAC. Per questo motivo, potresti vedere SHA1 utilizzato nel codice di produzione. Tuttavia, da un punto di vista di pubbliche relazioni, può sembrare brutto se si deve spiegare perché, crittograficamente parlando, è giusto usare SHA1 in questo contesto. Molte delle debolezze di SHA1 sono dovute a ciò che viene chiamato attacchi di collisione. Gli auditor di codice oi ricercatori di sicurezza possono aspettarsi che il codice sia resistente alle collisioni, indipendentemente dal contesto. Inoltre, se si scrive codice modulare in cui è possibile scambiare la funzione di firma con un'altra in futuro, è possibile che si dimentichi di aggiornare le funzioni hash non sicure. Pertanto, continueremo ad attenerci a SHA-512 come nostro algoritmo di scelta.

Le operazioni della CPU HMAC sono veloci, ma uno svantaggio è il problema dello scambio di chiavi. Come facciamo a farci sapere a vicenda qual è la chiave segreta senza che venga intercettata? Ad esempio, forse la tua API dovrà aggiungere o rimuovere in modo dinamico più app o piattaforme da una whitelist. In questo scenario, le app dovrebbero essere registrate e il segreto dovrebbe essere passato all'app una volta completata la registrazione. È possibile inviare la chiave su HTTPS e utilizzare il blocco SSL, ma anche in questo caso si ha sempre la preoccupazione che in qualche modo la chiave venga rubata durante lo scambio. La soluzione al problema dello scambio di chiavi è generare una chiave che non ha mai bisogno di lasciare il dispositivo in primo luogo. Questo può essere realizzato utilizzando la crittografia a chiave pubblica, e uno standard molto popolare e accettato è RSA.

RSA

RSA sta per Rivest-Shamir-Adleman (gli autori del crittosistema). Si tratta di sfruttare la difficoltà di factoring del prodotto di due numeri primi molto grandi. RSA può essere utilizzato per la crittografia o l'autenticazione, anche se per questo esempio lo utilizzeremo solo per l'autenticazione. RSA genera due chiavi, una pubblica e una privata, che possiamo realizzare usando il SecKeyGeneratePair funzione. Quando viene utilizzato per l'autenticazione, la chiave privata viene utilizzata per creare la firma, mentre la chiave pubblica verifica la firma. Data una chiave pubblica, è computazionalmente irrealizzabile derivare la chiave privata.

Il prossimo esempio mostra ciò che Apple e tutte le più famose società di console di gioco usano quando distribuiscono il loro software. Diciamo che la tua azienda crea e consegna periodicamente un file che gli utenti trascinano nella porzione di condivisione dei file della tua app in iTunes. Assicurati che i file che invii non vengano mai manomessi prima di essere analizzati nell'app. La tua azienda manterrà e custodirà la chiave privata che utilizza per firmare i file. Nel pacchetto dell'app è presente una copia della chiave pubblica utilizzata per verificare il file. Dato che la chiave privata non viene mai trasmessa o inclusa nell'app, non è possibile per un utente malintenzionato essere in grado di firmare le proprie versioni dei file (a parte irrompere nell'azienda e rubare la chiave privata).

Noi useremo SecKeyRawSign per firmare il file. Sarebbe lento firmare l'intero contenuto del file usando RSA, quindi l'hash del file è firmato. Inoltre, i dati trasmessi a RSA dovrebbero essere sottoposti a hash prima della firma a causa di alcuni punti deboli di sicurezza.

@available (iOS 10.0, *) class FileSigner private var publicKey: SecKey? private var privateKey: SecKey? func generateKeys () -> String? var publicKeyString: String? // genera una nuova coppia di chiavi consente parametri: [String: AnyObject] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: 4096 come AnyObject,] let status = SecKeyGeneratePair (parametri come CFDictionary, & publicKey, & privateKey) // --- Salva qui la chiave --- // // Converti l'oggetto SecKey in una rappresentazione che possiamo inviare tramite la rete se stato == noErr && publicKey! = nil se let cfData = SecKeyCopyExternalRepresentation (publicKey !, nil) let data = cfData as Data publicKeyString = data.base64EncodedString () return publicKeyString func signFile (_ path: String) -> String? var signature: String? se let fileData = FileManager.default.contents (atPath: path) if (privateKey! = nil) // hash il messaggio lascia prima digestLength = Int (CC_SHA512_DIGEST_LENGTH) let hashBytes = UnsafeMutablePointer.allocate (capacity: digestLength) CC_SHA512 ([UInt8] (fileData), CC_LONG (fileData.count), hashBytes) // firma let blockSize = SecKeyGetBlockSize (privateKey!) // nel caso di RSA, il modulo è lo stesso del blocco size var signatureBytes = [UInt8] (ripetendo: 0, count: blockSize) var signatureDataLength = blockSize let status = SecKeyRawSign (privateKey !, .PKCS1SHA512, hashBytes, digestLength, & signatureBytes, & signatureDataLength) se stato == noErr let data = Data ( byte: signatureBytes, count: signatureDataLength) signature = data.base64EncodedString () return signature

In questo codice, abbiamo usato il CC_SHA512 funzione per specificare nuovamente SHA-512. (A differenza di HMAC, RSA diventa insicuro se la funzione di hash sottostante non è sicura.) Stiamo anche utilizzando 4096 come dimensione della chiave, che viene impostata dal kSecAttrKeySizeInBits parametro. 2048 è la dimensione minima consigliata. Questo per evitare che una potente rete di sistemi informatici rompa la chiave RSA (cracking intendo il factoring della chiave RSA, noto anche come fattorizzazione di un modulo pubblico). Il gruppo RSA ha stimato che le chiavi da 2048 bit potrebbero diventare illeggibili qualche tempo prima del 2030. Se vuoi che i tuoi dati siano al sicuro oltre quel tempo, allora è una buona idea scegliere una chiave più grande come 4096.

Le chiavi generate sono nella forma di SecKey oggetti. Un problema con l'implementazione di Apple SecKey è che non include tutte le informazioni essenziali che costituiscono una chiave pubblica, quindi non è un certificato X.509 codificato DER valido. Aggiungendo le informazioni mancanti nel formato per un'app iOS o OS X, anche le piattaforme lato server come PHP, richiede un po 'di lavoro e richiede di lavorare in un formato noto come ASN.1. Fortunatamente, questo è stato risolto in iOS 10 con nuovo SecKey funzioni per generare, esportare e importare chiavi. 

Il codice seguente mostra l'altro lato della comunicazione, la classe che accetta una chiave pubblica tramite SecKeyCreateWithData per verificare i file usando il SecKeyRawVerify funzione.

@available (iOS 10.0, *) class FileVerifier private var publicKey: SecKey? func addPublicKey (_ keyString: String) -> Bool var success = false se let keyData = Data.init (base64Encoded: keyString) let parameters: [String: AnyObject] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeyClass as String: kSecAttrKeyClassPublic , kSecAttrKeySizeInBits as String: 4096 come AnyObject, kSecReturnPersistentRef as String: true come AnyObject] publicKey = SecKeyCreateWithData (keyData come CFData, parametri come CFDictionary, nil) if (publicKey! = nil) success = true return success func verifyFile ( _ percorso: String, withSignature signature: String) -> Bool var success = false if (publicKey! = nil) if let fileData = FileManager.default.contents (atPath: path) se let signatureData = Data.init (base64Encoded : signature) // hash il messaggio prima lascia digerLength = Int (CC_SHA512_DIGEST_LENGTH) let hashBytes = UnsafeMutablePointer.allocare (capacità: digestLength) CC_SHA512 ([UInt8] (fileData), CC_LONG (fileData.count), hashBytes) // verificare let status = signatureData.withUnsafeBytes signatureBytes in ritorno SecKeyRawVerify (publicKey !, .PKCS1SHA512, hashBytes, digestLength, signatureBytes , signatureData.count) if status == noErr success = true else print ("Errore di verifica della firma") // - 9809: errSSLCrypto, etc return success

Puoi provare questo e verificare che funzioni con un semplice test come il seguente:

se #available (iOS 10.0, *) guard lascia plistPath = Bundle.main.path (forResource: "Info", ofType: "plist") else print ("Impossibile ottenere plist"); return let fileSigner = FileSigner () DispatchQueue.global (qos: .userInitiated) .async // RSA key gen può funzionare a lungo guard lascia publicKeyString = fileSigner.generateKeys () else print ("Errore di generazione chiave"); return // Torna al thread principale DispatchQueue.main.async guard let signature = fileSigner.signFile (plistPath) else print ("Nessuna firma"); return // Salva la firma sull'altra estremità lasciare che fileVerifier = FileVerifier () guard fileVerifier.addPublicKey (publicKeyString) else print ("La chiave non è stata aggiunta"); return let success = fileVerifier.verifyFile (plistPath, withSignature: signature) se successo print ("Signatures match!") else print ("Le firme non corrispondono") 

C'è uno svantaggio nella generazione delle chiavi RSA è lento! Il tempo per generare le chiavi dipende dalla dimensione della chiave. Sui dispositivi più recenti una chiave a 4096 bit richiede solo pochi secondi, ma se si esegue questo codice su un iPod Touch di quarta generazione, potrebbe essere necessario circa un minuto. Questo va bene se stai solo generando le chiavi alcune volte su un computer, ma cosa succede quando abbiamo bisogno di generare frequentemente chiavi su un dispositivo mobile? Non possiamo semplicemente abbassare la dimensione della chiave perché questo abbassa la sicurezza. 

Quindi qual è la soluzione? Bene, Elliptic Curve Cryptography (ECC) è un approccio emergente: una nuova serie di algoritmi basati su curve ellittiche su campi finiti. Le chiavi ECC sono di dimensioni molto più piccole e più veloci da generare rispetto alle chiavi RSA. Una chiave di soli 256 bit offre un livello molto alto di sicurezza! Per sfruttare l'ECC, non è necessario modificare molto codice. Possiamo firmare i nostri dati utilizzando lo stesso SecKeyRawSign funzione e quindi regolare i parametri per utilizzare Elliptic Curve Digital Signature Algorithm (ECDSA).

Suggerimento: per ulteriori idee sull'implementazione di RSA, puoi consultare il SwiftyRSA libreria helper, incentrata sulla crittografia e sulla firma dei messaggi.

ECDSA

Immagina il seguente scenario: un'app di chat consente agli utenti di inviare messaggi privati ​​tra loro, ma si vuole essere sicuri che un avversario non abbia cambiato il messaggio mentre si sta recando all'altro utente. Vediamo come potresti proteggere la loro comunicazione con la crittografia. 

Innanzitutto, ciascun utente genera una coppia di chiavi pubbliche e private sul proprio dispositivo mobile. Le loro chiavi private sono archiviate in memoria e non abbandonano mai il dispositivo, mentre le chiavi pubbliche vengono trasmesse l'una all'altra. Come prima, la chiave privata viene utilizzata per firmare i dati inviati, mentre la chiave pubblica viene utilizzata per la verifica. Se un utente malintenzionato dovesse acquisire una chiave pubblica durante il transito, tutto ciò che potrebbe essere fatto è verificare l'integrità del messaggio originale dal mittente. Un utente malintenzionato non può modificare un messaggio perché non ha la chiave privata necessaria per ricostruire la firma.

C'è un altro professionista nell'usare ECDSA su iOS. Possiamo fare uso del fatto che attualmente, i tasti della curva ellittica sono gli unici che possono essere memorizzati nell'enclave sicura del dispositivo. Tutte le altre chiavi sono memorizzate nel portachiavi che crittografa i suoi elementi nell'area di archiviazione predefinita del dispositivo. Su dispositivi che ne hanno uno, l'enclave sicura si trova separata dal processore e la memorizzazione delle chiavi è implementata nell'hardware senza accesso diretto al software. L'enclave sicura può memorizzare una chiave privata e operare su di essa per produrre l'output che viene inviato alla tua app senza mai esporre l'effettiva chiave privata caricandola in memoria!

Aggiungerò il supporto per la creazione della chiave privata ECDSA sull'enclave sicura aggiungendo il kSecAttrTokenIDSecureEnclave opzione per il kSecAttrTokenID parametro. Possiamo iniziare questo esempio con a Utente oggetto che genererà una coppia di chiavi al momento dell'inizializzazione.

@available (iOS 9.0, *) class User public var publicKey: SecKey? private var privateKey: SecKey? destinatario privato var: Utente? init (withUserID id: String) // se let access = SecAccessControlCreateWithFlags (nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, [.privateKeyUsage / *, .userPresence] UI di autenticazione per ottenere la chiave privata * /], nil) // Forza archivio solo se passcode o Touch ID impostato ... se let access = SecAccessControlCreateWithFlags (nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, [.privateKeyUsage], nil) // Mantieni la chiave privata sul dispositivo let privateTagString = "com.example.privateKey." + id lascia privateTag = privateTagString.data (usando: .utf8)! // Memorizza come Dati, non come String lascia privateKeyParameters: [String: AnyObject] = [kSecAttrIsPermanent as String: true come AnyObject, kSecAttrAccessControl as String: access come AnyObject, kSecAttrApplicationTag come String: privateTag come AnyObject,] let publicTagString = " com.example.publicKey." + id lascia publicTag = publicTagString.data (usando: .utf8)! // Data, not String let publicKeyParameters: [String: AnyObject] = [kSecAttrIsPermanent as String: false as AnyObject, kSecAttrApplicationTag as String: publicTag as AnyObject,] consente keyPairParameters: [String: AnyObject] = [kSecAttrKeySizeInBits as String: 256 as AnyObject , kSecAttrKeyType as String: kSecAttrKeyTypeEC, kSecPrivateKeyAttrs come stringa: privateKeyParameters come ANYOBJECT, kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave come ANYOBJECT, // Conservare in kSecPublicKeyAttrs Enclave sicuro come String: publicKeyParameters come ANYOBJECT] lasciare status = SecKeyGeneratePair (keyPairParameters come CFDictionary, e publicKey, e PrivateKey) if status! = noErr print ("Errore di generazione della chiave") // ... 

Successivamente, creeremo alcune funzioni di aiuto e di esempio. Ad esempio, la classe consentirà a un utente di avviare una conversazione e inviare un messaggio. Naturalmente, nella tua app, devi configurarlo per includere la tua configurazione di rete specifica.

 // ... private func sha512Digest (dati forData: Data) -> Data let len ​​= Int (CC_SHA512_DIGEST_LENGTH) let digest = UnsafeMutablePointer.allocare (capacità: len) CC_SHA512 ((dati come NSData) .bytes, CC_LONG (data.count), digest) return NSData (bytesNoCopy: UnsafeMutableRawPointer (digest), length: len) come Data public func initiateConversation (withUser user: User ) -> Bool var success = false if publicKey! = Nil user.receiveInitialization (self) destinatario = utente success = true return success public func receiveInitialization (_ user: User) recipient = user public func sendMessage (_ message: String) if let data = message.data (using: .utf8) let signature = self.signData (plainText: data) if signature! = nil self.recipient? .receiveMessage (message, withSignature: signature!)  public func receiveMessage (_ message: String, withSignature signature: Data) let signatureMatch = verifySignature (plainText: message.data (utilizzando: .utf8) !, signature: signature) if signatureMatch print ("Messaggio ricevuto. Signature Il messaggio è: ", messaggio) else print (" Messaggio ricevuto. Errore di firma. ") // ... 

Successivamente, faremo la firma e la verifica effettive. ECDSA, a differenza di RSA, non deve essere sottoposto a hash prima della firma. Tuttavia, se si volesse avere una funzione in cui l'algoritmo può essere facilmente scambiato senza apportare molte modifiche, allora è perfettamente corretto continuare a cancellare i dati prima di firmare.

 // ... func signData (plainText: Data) -> Data? guard privateKey! = nil else print ("Chiave privata non disponibile") return nil let digestToSign = self.sha512Digest (forData: plainText) let signature = UnsafeMutablePointer.allocate (capacità: 512) // 512 - overhead var signatureLength = 512 let status = SecKeyRawSign (privateKey !, .PKCS1SHA512, [UInt8] (digestToSign), Int (CC_SHA512_DIGEST_LENGTH), signature, & signatureLength) se stato! = noErr print ( "Firma fallita: \ (stato)") restituisce Data.init (byte: firma, conteggio: signatureLength) // ridimensiona alla dimensione effettiva della firma func verifySignature (plainText: Data, firma: Data) -> Bool guard destinatario? .publicKey! = nil else print ("Chiave pubblica del destinatario non disponibile") restituisce false let digestToVerify = self.sha512Digest (forData: plainText) let signedHashBytesSize = signature.count let status = SecKeyRawVerify (destinatario! .publicKey !, .PKCS1SHA512, [UInt8] (digestToVerify), Int (CC_SHA512_DIGEST_LENGTH), [UInt8] (firma come dati), signedHashBytesSize) stato restituito == noErr

Questo verifica il messaggio, così come l'"identificazione" di un utente specifico poiché solo quell'utente ha il possesso della propria chiave privata. 

Questo non significa che stiamo collegando la chiave con chi l'utente è nella vita reale - il problema di associare una chiave pubblica a un utente specifico è un altro dominio. Mentre le soluzioni non rientrano nell'ambito di questo tutorial, le popolari app di chat sicure come Signal e Telegram consentono agli utenti di verificare un'impronta digitale o un numero tramite un canale di comunicazione secondario. Allo stesso modo, Pidgin offre uno schema di domande e risposte in cui si pone una domanda che solo l'utente dovrebbe conoscere. Queste soluzioni aprono un intero mondo di dibattito su quale dovrebbe essere l'approccio migliore.

Tuttavia, la nostra soluzione crittografica verifica che il messaggio possa essere stato inviato solo da qualcuno che è in possesso di una chiave privata specifica.

Facciamo una semplice prova del nostro esempio:

se #available (iOS 9.0, *) lascia alice = User.init (withUserID: "aaaaaa1") lascia bob = User.init (withUserID: "aaaaaa2") let accept = alice.initiateConversation (withUser: bob) if (accettato ) alice.sendMessage ("Salve") bob.sendMessage ("Messaggio di prova") alice.sendMessage ("Un altro messaggio di prova")

OAuth e SSO

Spesso quando si lavora con servizi di terze parti, si noteranno altri termini di alto livello utilizzati per l'autenticazione, come OAuth e SSO. Mentre questo tutorial riguarda la creazione di una firma, spiegherò brevemente cosa significano gli altri termini.

OAuth è un protocollo per l'autenticazione e l'autorizzazione. Funge da intermediario per utilizzare l'account di qualcuno per servizi di terze parti e mira a risolvere il problema dell'autorizzazione selettiva all'accesso ai dati. Se accedi al servizio X tramite Facebook, una schermata ti chiede, ad esempio, se il servizio X è autorizzato ad accedere alle tue foto di Facebook. Ottiene ciò fornendo un token senza rivelare la password dell'utente.

Single sign-on, o SSO, descrive il flusso in cui un utente autenticato può utilizzare le stesse credenziali di accesso per accedere a più servizi. Un esempio di questo è il modo in cui il tuo account Gmail funziona per accedere a YouTube. Se nella tua azienda hai diversi servizi diversi, potresti non voler creare account utente separati per tutti i diversi servizi.

Conclusione

In questo tutorial, hai visto come creare firme usando gli standard più popolari. Ora che abbiamo coperto tutti i concetti principali, ricapitoliamo!

  • Usa HMAC quando hai bisogno di velocità e assicurati che la chiave segreta possa essere scambiata in modo sicuro.
  • Se le chiavi devono viaggiare attraverso una rete, è meglio usare RSA o ECDSA.
  • RSA è ancora lo standard più popolare. La sua fase di verifica è abbastanza veloce. Usa RSA se il resto del tuo team ha già familiarità o utilizza lo standard.
  • Se è necessario generare costantemente chiavi su un dispositivo lento, tuttavia, utilizzare ECDSA. Mentre la verifica ECDSA è un po 'più lenta della verifica RSA, ciò non è paragonabile ai molti secondi salvati su RSA per la generazione di chiavi.

Quindi è tutto per le firme digitali in Swift. Se avete domande, sentitevi liberi di mandarmi una linea nella sezione commenti, e nel frattempo date un'occhiata ad alcuni dei nostri altri tutorial sulla sicurezza dei dati e lo sviluppo di app in Swift!