Konwertować NSData na ciąg?

122

Przechowuję klucz prywatny openssl EVP_PKEY jako nsdata. W tym celu serializuję do strumienia bajtów przy użyciu poniższego kodu

unsigned char *buf, *p;
int len;
len = i2d_PrivateKey(pkey, NULL);
buf = OPENSSL_malloc(len); 
p = buf;
i2d_PrivateKey(pkey, &p);

gdzie pkey jest typu EVP_PKEY. Następnie przechowuję bajty z bufora `` p '' jako NSData przy użyciu linii podanej poniżej

NSData *keydata = [NSData dataWithBytes:P length:len];

Teraz konwertuję go na NSString przy użyciu kodu podanego poniżej, ale kiedy drukuję go w konsoli, podaje kilka innych znaków.

NSString *content =[ NSString stringWithCString:[keydata bytes] encoding:NSUTF8StringEncoding];

Czy ktoś mógłby pomóc?

Zasadniczo chcę przechowywać EVP_PKEY w bazie danych sqlite

czy jestem na dobrej drodze? Dzięki.

Zach
źródło
Co masz na myśli mówiąc „inne postacie”? Czy na końcu drukuje dodatkowe znaki, których nie powinno tam być, czy po prostu drukuje zupełnie inne znaki, niż się spodziewasz?
Tom Harrington,
Jest zupełnie inny niż to, co ma być
Zach
Czy jesteś pewien, że dane są rzeczywiście zakodowane w UTF-8? Nie znam i2d_PrivateKey, ale Twoje wyniki sugerują, że nie używasz odpowiedniego kodowania ciągów.
Tom Harrington
@TOm: Dzięki. to było ASCIIEncoding. Teraz działa dobrze
Zach
Nie, nie jesteś na dobrej drodze i wszystkie odpowiedzi wydają się nieprawidłowe. Należy użyć kodowania base64 jeśli chcesz przekonwertować dane w NSDatacelu NSString.
Maarten Bodewes

Odpowiedzi:

260

Cel C

Możesz użyć (zobacz NSString Class Reference )

- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding

Przykład:

NSString *myString = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];

Uwaga : proszę zauważyć, że NSDatawartość musi być prawidłowa dla określonego kodowania (UTF-8 w powyższym przykładzie), w przeciwnym razie nilzostanie zwrócona:

Zwraca nil, jeśli inicjalizacja z jakiegoś powodu nie powiedzie się (na przykład jeśli dane nie reprezentują prawidłowych danych do zakodowania).

Wcześniejszy Swift 3.0

String(data: yourData, encoding: NSUTF8StringEncoding)

Swift 3.0 i nowsze

String(data: yourData, encoding: .utf8)

Zobacz String # init (data: encoding :) Reference

louiscoquio
źródło
Dziękuję za odpowiedź. Próbowałem już tego bez powodzenia.
Zach,
26
W debugerze:po [[NSString alloc] initWithData:myData encoding:4]
Berik
7
Jak ta odpowiedź może mieć wiele głosów za, mimo że NSDatamoże zawierać dowolną wartość bajtową, w tym te spoza zakresu UTF-8?
Maarten Bodewes
2
Ponieważ ludzie, którzy są tutaj, konwertują odpowiedź danych z serwera na łańcuch.
Necro
1
co się stanie, jeśli NSData <strong> rzeczywiście </strong> zawiera wartości spoza zakresu UTF-8?
Zennichimaro
24

Przed Swift 3.0:

String(data: yourData, encoding: NSUTF8StringEncoding)

Dla Swift 4.0:

String(data: yourData, encoding: .utf8)
pierre23
źródło
3

Uważam, że Twoje „P” jest parametrem dataWithBytes

NSData *keydata = [NSData dataWithBytes:P length:len];

powinno być „buf”

NSData *keydata = [NSData dataWithBytes:buf length:len];

ponieważ i2d_PrivateKey umieszcza wskaźnik do bufora wyjściowego p na końcu bufora i czeka na dalsze wejście, a buf nadal wskazuje początek bufora.

Poniższy kod działa dla mnie, gdzie pkey jest wskaźnikiem do EVP_PKEY:

unsigned char *buf, *pp;
int len = i2d_PrivateKey(pkey, NULL);
buf = OPENSSL_malloc(len); 
pp = buf;
i2d_PrivateKey(pkey, &pp);

NSData* pkeyData = [NSData dataWithBytes:(const void *)buf length:len];
DLog(@"Private key in hex (%d): %@", len, pkeyData);

Możesz użyć konwertera online, aby przekonwertować swoje dane binarne do bazy 64 ( http://tomeko.net/online_tools/hex_to_base64.php?lang=en ) i porównać je z kluczem prywatnym w pliku certyfikatu po użyciu następującego polecenia i sprawdzanie wyjścia mypkey.pem:

openssl pkcs12 -in myCert.p12 -nocerts -nodes -out mypkey.pem

Odwołałem się do twojego pytania i tej strony funkcji EVP, aby uzyskać odpowiedź.

aspergillusOryzae
źródło
2

Swift 3:

String(data: data, encoding: .utf8)
Travis M.
źródło
1

Prostym sposobem na przekonwertowanie dowolnych NSData na NSString jest zakodowanie ich w standardzie base64.

NSString *base64EncodedKey = [keydata base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];

Następnie możesz zapisać go w swojej bazie danych do późniejszego wykorzystania. Po prostu dekoduj go z powrotem do NSData.

Pałka policjanta
źródło
1

Swift 5 :

String(data: data!, encoding: String.Encoding.utf8)
Alexander Volkov
źródło
To tylko zmodyfikowana kopia odpowiedzi pierre23, która jest dla mnie lepsza - zwykle używałem tej strony do kopiowania kodu i musiałem zmodyfikować yourData do danych! to wymaga czasu. Teraz ja i ty kopiujemy i wklejamy bez modyfikacji.
Alexander Volkov
To nie jest pytanie związane ze Swiftem. Co więcej, przykładowy kod w pytaniu to kod Objective-C. I nie koniec, wymuszone rozpakowanie z kodu może prowadzić do nieoczekiwanych awarii.
Cristik,
@Cristik Pytanie nie jest oznaczone jako Obj-C.
Eiko
@AlexanderVolkov możesz dodać do tego fragment kodu Xcode, byłby jeszcze szybszy;)
Cristik