Преобразовать NSData в строку?


122

Я храню закрытый ключ openssl EVP_PKEY как nsdata. Для этого я сериализую в поток байтов, используя приведенный ниже код.

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

где pkey имеет тип EVP_PKEY. Затем я сохраняю байты из буфера 'p' как NSData, используя строку, приведенную ниже

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

Теперь я конвертирую его в NSString, используя приведенный ниже код, но когда я печатаю его на консоли, он дает некоторые другие символы.

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

Может кто-нибудь помочь?

В основном я хочу сохранить EVP_PKEY в базе данных sqlite

я на правильном пути? Спасибо.


Что значит «другие персонажи»? В конце печатаются лишние символы, которых не должно быть, или просто печатаются совершенно другие символы, чем вы ожидаете?
— Tom Harrington

Это полностью отличается от того, чем оно должно быть,
— Зак

Вы уверены, что данные действительно закодированы в UTF-8? Я не знаком с i2d_PrivateKey, но ваши результаты показывают, что вы не используете правильную кодировку строк.
— Tom Harrington

@TOm: Спасибо. это было ASCIIEncoding. Теперь он работает нормально
— Zach

Нет, вы здесь не на правильном пути, и все ответы кажутся неверными. Вы должны использовать кодировку base64, если хотите преобразовать данные в NSDataформат NSString.
— Maarten Bodewes

Ответы:


260

Objective-C

Вы можете использовать (см. Справочник по классам NSString )

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

Пример:

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

Примечание : обратите внимание, что NSDataзначение должно быть действительным для указанной кодировки (UTF-8 в приведенном выше примере), в противном случае nilбудет возвращено:

Возвращает nil, если инициализация не удалась по какой-либо причине (например, если данные не представляют допустимые данные для кодирования).

Приор Свифт 3.0

String(data: yourData, encoding: NSUTF8StringEncoding)

Swift 3.0 и выше

String(data: yourData, encoding: .utf8)

См. String # init (data: encoding :) Ссылка


Спасибо за ответ. Я уже пробовал это безуспешно.
— Zach

26
О отладчике:po [[NSString alloc] initWithData:myData encoding:4]
— Берик

7
Как этот ответ может иметь множество положительных отзывов, даже если он NSDataможет содержать любое байтовое значение, в том числе вне диапазона UTF-8?
— Maarten Bodewes

2
Потому что люди, которые здесь, преобразуют ответ данных с сервера в строку.
— Necro

1
что, если NSData <strong> действительно </strong> содержит значения вне диапазона UTF-8?
— Зенничимаро

24

Предыдущий Swift 3.0:

String(data: yourData, encoding: NSUTF8StringEncoding)

Для Swift 4.0:

String(data: yourData, encoding: .utf8)

3

Я считаю, что ваш "P" как параметр dataWithBytes

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

должно быть "буф"

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

поскольку i2d_PrivateKey помещает указатель на выходной буфер p в конец буфера и ожидает дальнейшего ввода, а buf все еще указывает на начало вашего буфера.

Для меня работает следующий код, где pkey - указатель на 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);

Вы можете использовать онлайн-конвертер для преобразования ваших двоичных данных в базу 64 ( http://tomeko.net/online_tools/hex_to_base64.php?lang=en ) и сравнить их с закрытым ключом в вашем файле сертификата после использования следующей команды и проверка вывода mypkey.pem:

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

Я сослался на ваш вопрос и этот сайт функции EVP для своего ответа.



1

Простой способ преобразовать произвольные NSData в NSString - это закодировать их в формате base64.

NSString *base64EncodedKey = [keydata base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];

Затем вы можете сохранить его в своей базе данных для повторного использования позже. Просто декодируйте его обратно в NSData.


1

Swift 5 :

String(data: data!, encoding: String.Encoding.utf8)

Это просто измененная копия ответа pierre23, которая мне больше подходит - я обычно использовал эту страницу для копирования кода и мне приходилось изменять yourData на data! это требует времени. Теперь мы с вами копируем и вставляем без изменений.
— Александр Волков

Это не вопрос, связанный с Swift. Более того, образец кода в вопросе - это код Objective-C. И не в последнюю очередь принудительное развертывание кода из вашего кода может привести к неожиданным сбоям.
— Cristik

@Cristik Вопрос не помечен как Obj-C.
— Eiko

@AlexanderVolkov, вы можете добавить для этого фрагмент Xcode, это было бы даже быстрее, чем этот;)
— Cristik
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.