Począwszy iOS 10, to jest rzeczywiście możliwe importowanie kluczy prywatnych PEM bez konwersji na PKCS # 12 (co jest bardzo uniwersalnym formatem kontenera dla wszystkiego związanego z kryptografią), a więc również bez użycia OpenSSL w linii poleceń lub statycznego łączenia aplikacji z nim . Na MacOS jest to nawet możliwe od 10,7 przy użyciu innej funkcji niż te wymienione tutaj (ale jak dotąd nie istnieje dla iOS). Dokładnie opisany poniżej sposób będzie działał także na macOS 10.12 i później.
Aby zaimportować certyfikat, to wystarczy, aby tylko pozbawić
-----BEGIN CERTIFICATE-----
i
-----END CERTIFICATE-----
linii, a następnie uruchomić dekodowanie base64 nad danymi w lewo, wynik jest certyfikat w standardowym formacie DER , który może być po prostu podany do SecCertificateCreateWithData()
, aby uzyskać SecCertificateRef
. To zawsze działało, także przed iOS 10.
Aby zaimportować klucz prywatny, może być wymagana dodatkowa praca. Jeśli klucz prywatny jest opakowany za pomocą
-----BEGIN RSA PRIVATE KEY-----
to bardzo łatwo. Ponownie, pierwsza i ostatnia linia musi zostać usunięta, pozostałe dane muszą zostać zdekodowane w base64, a wynikiem jest klucz RSA w formacie PKCS # 1.Ten format może przechowywać tylko klucze RSA i jest bezpośrednio czytelny, po prostu podaj zdekodowane dane do SecKeyCreateWithData()
, aby uzyskać SecKeyRef
. Słownik attributes
wystarczy następujące pary kluczy/wartości:
kSecAttrKeyType
: kSecAttrKeyTypeRSA
kSecAttrKeyClass
: kSecAttrKeyClassPrivate
kSecAttrKeySizeInBits
: CFNumberRef
z wówczas liczba bitów w kluczu (np 1024, 2048, etc.) Jeśli nie jest znana, ta informacja może zostać odczytana z surowych danych klucza, które są danymi ASN.1 (nieco wykracza to poza zakres tej odpowiedzi, ale poniżej podam kilka przydatnych linków o tym, jak przeanalizować ten format). Ta wartość jest opcjonalna! W moich testach nie było potrzeby ustawiania tej wartości; jeśli nie było, API sam ustaliło tę wartość i zawsze było ustawione poprawnie później.
W przypadku, gdy klucz prywatny jest owinięty przez -----BEGIN PRIVATE KEY-----
, następnie base64 zakodowane dane nie są na # 1 formacie PKCS ale w PKCS # 8 formatu, jednak jest to tylko bardziej ogólnych kontenerów Wewnętrzne dane tego kontenera są równe PKCS # 1, więc można powiedzieć, że dla kluczy RSA PKCS # 8 to PKCS # 1 z dodatkowym nagłówkiem i wszystko, co musisz zrobić, to rozebrać ten dodatkowy nagłówek. Po prostu usuń pierwsze 26 bajtów dekodowanych danych base64 i ponownie uzyskaj numer PKCS # 1. Tak, to naprawdę takie proste.
Aby uzyskać więcej informacji o formatach PKCS # x w kodowaniu PEM, have a look at this site. Aby dowiedzieć się więcej o formacie ASN.1, here's a good site for that. A jeśli potrzebujesz prostego, ale potężnego i interaktywnego parsera ASN.1 online do zabawy w różnych formatach, takiego, który może bezpośrednio odczytać dane PEM, a także ASN.1 w base64 i hexdump, try this site.
Bardzo ważne: Przy dodawaniu klucz prywatny do pęku kluczy, który został utworzony jak powyżej, należy pamiętać, że taki klucz prywatny nie zawiera klawisz krzyżyka publicznego, jeszcze klawisz krzyżyka publiczny jest ważne dla ich keychain Interfejs API do utworzenia tożsamości (SecIdentityRef
), ponieważ używanie klucza publicznego jest funkcją sprawdzania przez interfejs API właściwego klucza prywatnego należącego do zaimportowanego certyfikatu (SecIdentityRef
to tylko SecKeyRef
klucza prywatnego i SecCertificateRef
certyfikatu tworzący kombinację obiekt i jest to skrót klucza publicznego, który wiąże je razem). Jeśli więc zamierzasz dodać klucz prywatny do pęku kluczy, upewnij się, że ustawiłeś ręcznie klucz publiczny, w przeciwnym razie nigdy nie będziesz w stanie uzyskać dla niego tożsamości, a bez tego nie będziesz mógł używać keychain API do zadań takich jak podpisywanie lub odszyfrowywanie. dane. Hash klucza publicznego musi być przechowywany w atrybucie o nazwie kSecAttrApplicationLabel
(głupia nazwa, wiem, ale tak naprawdę nie jest to etykieta i nic, czego użytkownik nigdy nie zobaczy, sprawdź dokumentację). Np .:
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()
);
myślę, że znajdziesz tu odpowiedź: http://stackoverflow.com/questions/1595013/iphone-how-to-create-a-seckeyref-from-a-public-key-file-pem –