partire con iOS 10, si è in realtà possibile importare chiavi private PEM senza convertirle in PKCS # 12 (che è un formato contenitore universale per tutto ciò che riguarda la crittografia) e quindi anche senza usare OpenSSL sulla linea di comando o collegando staticamente le app con esso . Su macOS è persino possibile dal 10.7 utilizzando una funzione diversa da quelle menzionate qui (ma finora non esiste per iOS). Esattamente come descritto di seguito funzionerà anche su macOS 10.12 e successivi.
Per importare un certificato, è abbastanza per mettere a nudo solo le
-----BEGIN CERTIFICATE-----
e
-----END CERTIFICATE-----
linee, quindi eseguire la decodifica base64 sopra i dati rimasti, il risultato è un certificato in formato Der Standard , che può essere semplicemente inviato a SecCertificateCreateWithData()
per ottenere un SecCertificateRef
. Funziona sempre, anche prima di iOS 10.
Per importare una chiave privata, potrebbe essere necessario un po 'di lavoro extra. Se la chiave privata è incapsulata con
-----BEGIN RSA PRIVATE KEY-----
quindi è molto facile. Anche in questo caso, la prima e l'ultima riga devono essere rimosse, i dati rimanenti devono essere decodificati in base64 e il risultato è una chiave RSA nel formato PKCS # 1.Questo formato può contenere solo chiavi RSA ed è direttamente leggibile, basta inserire i dati decodificati in SecKeyCreateWithData()
per ottenere un SecKeyRef
. Il dizionario attributes
solo bisogno le seguenti coppie chiave/valore:
kSecAttrKeyType
: kSecAttrKeyTypeRSA
kSecAttrKeyClass
: kSecAttrKeyClassPrivate
kSecAttrKeySizeInBits
: CFNumberRef
con allora il numero di bit nella chiave (ad esempio 1024, 2048, etc.) Se non si sa, questa informazione può essere letta dai dati della chiave grezza, che sono dati ASN.1 (è un po 'oltre lo scopo di questa risposta, ma fornirò alcuni link utili di seguito su come analizzare tale formato). Questo valore è forse facoltativo! Nei miei test non era effettivamente necessario impostare questo valore; se assente, l'API ha determinato il valore da solo ed è stato sempre impostato correttamente in seguito.
Nel caso la chiave privata è avvolto da -----BEGIN PRIVATE KEY-----
, dati quindi le base64 codificato non è in PKCS # 1 formato ma in PKCS # 8 formato, tuttavia, questo è solo un container più generico che può anche contenere chiavi non RSA ma per chiavi RSA i dati interni di tale contenitore è uguale PKCS # 1, quindi si può dire per le chiavi RSA PKCS # 8 è PKCS # 1 con un'intestazione supplementare e tutto ciò che devi fare è rimuovere l'intestazione aggiuntiva. Basta rimuovere i primi 26 byte dei dati decodificati di base64 e hai di nuovo PKCS # 1. Sì, è davvero così semplice.
Per ulteriori informazioni sui formati PKCS # x nelle codifiche PEM, have a look at this site. Per ulteriori informazioni sul formato ASN.1, here's a good site for that. E se hai bisogno di un parser ASN.1 semplice ma potente e interattivo per giocare con diversi formati, uno che può leggere direttamente i dati PEM, così come ASN.1 in base64 e hexdump, try this site.
Molto importante: Quando si aggiunge una chiave privata al portachiavi, che è stato creato come sopra, si prega di essere consapevole del fatto che una chiave privata come non contiene un hash chiave pubblica, ma un hash chiave pubblica è importante perché portachiavi API per creare un'identità (SecIdentityRef
), poiché l'utilizzo dell'hash della chiave pubblica è il modo in cui l'API trova la chiave privata corretta appartenente a un certificato importato (uno SecIdentityRef
è solo un SecKeyRef
di una chiave privata e un SecCertificateRef
di un cert che forma una combinazione oggetto ed è l'hash della chiave pubblica, che li lega insieme). Pertanto, quando pianifichi di aggiungere la chiave privata al portachiavi, assicurati di impostare manualmente un hash della chiave pubblica, altrimenti non sarai mai in grado di ottenere un'identità e senza di essa non puoi utilizzare l'API portachiavi per attività come la firma o la decrittografia dati. L'hash della chiave pubblica deve essere memorizzato in un attributo denominato kSecAttrApplicationLabel
(nome stupido, lo so, ma in realtà non è un'etichetta e nulla che l'utente possa mai vedere, controlla la documentazione). Ad es .:
OSStatus error = SecItemAdd(
(__bridge CFDictionaryRef)@{
(__bridge NSString *)kSecClass:
(__bridge NSString *)kSecClassKey,
(__bridge NSString *)kSecAttrApplicationLabel:
hashOfPublicKey, // hashOfPublicKey is NSData *
#if TARGET_OS_IPHONE
(__bridge NSString *)kSecValueRef:
(__bridge id)privateKeyToAdd, // privateKeyToAdd is SecKeyRef
#else
(__bridge NSString *)kSecUseItemList:
@[(__bridge id)privateKeyToAdd], // privateKeyToAdd is SecKeyRef
#endif
},
&outReference // Can also be NULL,
// otherwise reference to added keychain entry
// that must be released with CFRelease()
);
penso che troverai la tua risposta qui: http://stackoverflow.com/questions/1595013/iphone-how-to-create-a-seckeyref-from-a-public-key-file-pem –