Как получить ключ из объекта NSData в массив ключей/iv для Crypto++?

Я пытаюсь создать класс-оболочку Objective-C для некоторых криптографических операций, которые будут использовать библиотеку Crypto++. У меня есть несколько вопросов,

Это код, который я использую

- (void)testSerpentEncryptonMechanism
{
     byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];

    ::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
    ::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );

    NSString *andThisShalBeEncrypted = @"Serpentine and black...";

    NSLog(@"will encrypt %@",andThisShalBeEncrypted);

    NSString *encrypted = [self encryptWithSerpentString:andThisShalBeEncrypted withKey:key];

    NSLog(@"encrypted:%@",encrypted);

    NSString *decrypted = [self decryptWithSerpentString:encrypted withKey:key andIV:iv];

    NSLog(@"decrypted: %@",decrypted);


}

- (NSString *)encryptWithSerpentString:(NSString *)plaintext withKey:(byte[])keyArray
{
    std::string ptext = [plaintext UTF8String];
    std::string ciphertext;

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];

    ::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
    ::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );

    CryptoPP::Serpent::Encryption serpentEncryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcSerpentEncryptor (serpentEncryptor, iv);

    CryptoPP::StreamTransformationFilter stfSerpentEncryptor(cbcSerpentEncryptor, new CryptoPP::StringSink (ciphertext));
    stfSerpentEncryptor.Put( reinterpret_cast<const unsigned char*>( ptext.c_str() ), ptext.length() + 1);
    stfSerpentEncryptor.MessageEnd();

    std::string finalCT;
    CryptoPP::StringSource base64Encoder (ciphertext, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(finalCT)));



    return @(finalCT.c_str());
}

- (NSString *)decryptWithSerpentString:(NSString *)ciphertext withKey:(byte[])keyArray andIV:(byte[])initializationVector
{
    std::string ctext;
    std::string plaintext;

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];

//    ::memset( key, &keyArray , CryptoPP::Serpent::MAX_KEYLENGTH );
//    ::memset( iv, (byte[])initializationVector, CryptoPP::Serpent::BLOCKSIZE );

    ::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
    ::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );

    // decode from base64
    std::string encoded = [ciphertext UTF8String];
    CryptoPP::StringSource base64Encoder (encoded, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(ctext)));


    CryptoPP::Serpent::Decryption serpentDecryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcSerpentDecryptor (serpentDecryptor, iv);

    CryptoPP::StreamTransformationFilter stfSerpentDecryptor(cbcSerpentDecryptor, new CryptoPP::StringSink (ctext));// crash
    stfSerpentDecryptor.Put( reinterpret_cast<const unsigned char*>( ctext.c_str() ), ctext.length() + 1);
    stfSerpentDecryptor.MessageEnd();


    return @(ctext.c_str());
}

1) Как передать ключ/IV в качестве параметров метода? Смотрите закомментированный код, он не работает...

2) Я получаю вылет при попытке расшифровать

libc++abi.dylib: завершение с необработанным исключением типа CryptoPP::InvalidCiphertext: StreamTransformationFilter: длина зашифрованного текста не кратна размеру блока

Почему? Я думал, что расшифровка была автоматической, и шифрование соответствующим образом дополнит открытый текст... Я также хотел бы добавить HMAC к методам... Это будет добавлено после шифрования и проверено перед расшифровкой, верно?


person user1028028    schedule 28.11.2013    source источник
comment
Хотите знать, почему вы выбрали Serpent.   -  person zaph    schedule 28.11.2013
comment
Очень высокий запас прочности...   -  person user1028028    schedule 28.11.2013
comment
Интересно. Только что проверил с моим экспертом по крипто-доменам: AES — лучший выбор и лучший выбор для неустаревшего использования. 3DES, когда требуется совместимость с DES. Я предполагаю, что у вашего эксперта есть веская причина для выбора Змея.   -  person zaph    schedule 28.11.2013
comment
@NoOneInParticular Где недостатки в криптографии? На самом деле не в выборе алгоритма шифрования (при условии, что ничего действительно глупого). Атака заключается в использовании, недостатках в коде, недостатках в обработке/распределении ключей, аутентификации, протоколе и, наконец, в людях. Кто такие злоумышленники: те, для кого ценность данных больше, чем стоимость взлома криптографии, и те, у кого есть резиновые шланги. Найдите ценность своих данных для других, потратьте достаточно, чтобы защитить их. Очень важно, чтобы ваш код был либо написан, либо проверен экспертом в области криптографии — я так и делаю.   -  person zaph    schedule 29.11.2013
comment
AES не лучший выбор... это просто самый распространенный выбор... змей - лучший алгоритм, когда дело доходит до безопасности...   -  person user1028028    schedule 29.11.2013
comment
Алгоритм шифрования — это не то, что будет атаковано, даже АНБ не атакует AES, Serpent или 3DES строгим перебором. Дополнительный код для соединения C++ с Objective-C — хорошая цель, но чем больше кода, тем он сложнее, тем лучше для злоумышленника. Ключ, находящийся в памяти, также является потенциальной целью, и его трудно обойти, если вы используете NSString и/или NSData. AES имеет преимущество в производительности благодаря поддержке аппаратных инструкций, но это, вероятно, не будет иметь существенного значения, если не будет выполняться много шифрования.   -  person zaph    schedule 29.11.2013
comment
Я знаю, я думаю об использовании очень сложной техники управления ключами памяти (Шнайер называет это bjoom, странное название, но хорошая идея). И я думаю о том, чтобы сделать интерфейс Obective-C - C++ настолько маленьким, насколько это возможно... возможно, этот код будет использоваться и на Android, поэтому было бы хорошо иметь один и тот же криптографический код во всех приложениях.   -  person user1028028    schedule 29.11.2013
comment
Кстати... будет ли уровень безопасности приложения намного лучше, если я буду использовать обфускацию/анти-отладку кода Cryptanium?   -  person user1028028    schedule 29.11.2013
comment
Замечательную книгу о том, как использовать криптографию, см. в статье «Инженерия криптографии: принципы проектирования и практическое применение» Нильса Фергюсона, Брюса Шнайера и Тадаёси Коно. Еще один стандартный справочник (и его можно загрузить бесплатно): Руководство по прикладной криптографии (My у нас с женой есть печатная версия).   -  person zaph    schedule 29.11.2013
comment
Я читаю Криптографическую инженерию. Великая Книга. Также читайте Прикладная криптография и Современная криптография...   -  person user1028028    schedule 29.11.2013


Ответы (1)


Чтобы получить отступы, вы должны сделать это самостоятельно или иметь API, поддерживающий стандартные отступы, такие как PKCS7. Базовое шифрование, за исключением потоковых шифров, блочное, на нижнем уровне должны быть полные блоки. Некоторые API более высокого уровня обеспечивают заполнение.

Я передаю ключи, iv и данные as NSData * и получаю доступ к байтам как data.bytes.
Для выходных данных шифра:

NSMutableData  *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
// ...
                   dataOut.mutableBytes,
                   dataOut.length,
                   &cryptBytes
// ...
dataOut.length = cryptBytes;

Я бы сделал вызов API похожим на:

- (NSString *)encryptWithSerpentText:(NSString *)text key:(NSData *)key iv:(NSData *)iv;

Mac хорош, но как вы его проверите. Лучше всего изучить лучшие практики аутентификации.

Для HMAC просто используйте библиотеку CommonCrypto, поставляемую Apple. CommonCrypto также поддерживает: AES128, DES, 3DES, CAST, RC4 и Blowfish, но не Serpent.

Наконец, чтобы заставить все работать, регистрируйте каждый шаг, как на сервере, так и на клиенте, таким образом можно найти шаг, который не работает с неправильными данными. В этом случае прямая версия C++ против гибридной версии Objective-C/C++.

person zaph    schedule 28.11.2013
comment
Ну, Crypto++ выполняет заполнение... Но когда я добираюсь до метода расшифровки, он, кажется, отсутствует... Я думаю, что это как-то связано с UTF8String... - person user1028028; 28.11.2013
comment
Для примера использования NSData и шифрования. - person zaph; 28.11.2013
comment
Вопрос в том, как мне получить ключ из объекта NSData в массив key/iv (типа byte)... - person user1028028; 28.11.2013
comment
Вы можете использовать memcpy с data.out и data.length. Вы также можете использовать [data getBytes:&byteArray length:data.length]; data.out - это просто указатель на char. Objective-C — это строго надмножество C. - person zaph; 28.11.2013