Зашифровать 8-байтовую строку/кодировать base64/максимальная длина 20 байт

Каков наилучший метод/подход для шифрования и кодирования base64 строки UTF с максимальным размером 20 байтов в target-c? Я склоняюсь к Blowfish из-за размера блока 8 байт.

Пожалуйста, предоставьте пример кода? Спасибо.


person bickster    schedule 03.02.2015    source источник
comment
Для этого вам придется пожертвовать некоторой безопасностью. Этого места недостаточно, чтобы втиснуть MAC и IV надлежащего размера. Увеличение допуска до 32 символов очень помогло бы.   -  person CodesInChaos    schedule 03.02.2015


Ответы (1)


Да.

DES, 3DES и Blowfish имеют размер блока 8 байтов, поэтому зашифрованный вывод будет 8 байтов, кодирование Base64 8 байтов приведет к 12 байтам.

AES имеет размер блока 16, поэтому 8 байтов + заполнение будут 16 байтами данных. Кодировка Base64 16 байтов приведет к 24 байтам, поэтому AES не будет работать.

Есть и другие проблемы, такие как режим CBC и iv, хорошая схема будет использовать случайный iv и передавать его с зашифрованным сообщением. Оставшиеся биты в Base64 можно использовать для передачи частичного iv. Но это уже мимо вопроса.

В настоящее время предпочтительным алгоритмом симметричного шифрования является AES. DES больше не рекомендуется для новой работы и имеет несколько известных слабых ключей. Blowfish также не рекомендуется, но многим он нравится и может быть лучше, чем DES.

Вот пример использования 8-байтовых данных с 64-битным ключом и без iv. 3DES можно использовать, заменив константы Blowfish на 3DES и 24-байтовый ключ. Это не рекомендуемое решение, хорошее решение должно учитывать использование, желаемую безопасность, ценность данных и потенциальных злоумышленников, среди прочего, таких как iv и ключ.

+ (NSData *)doCipher:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt
               error:(NSError **)error
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmBlowfish,
                       0,
                       symmetricKey.bytes,
                       kCCKeySizeMinBlowfish,
                       nil,
                       dataIn.bytes, dataIn.length,
                       dataOut.mutableBytes, dataOut.length,
                       &cryptBytes);

    if (ccStatus == kCCSuccess) {
        dataOut.length = cryptBytes;
    }
    else {
        if (error) {
            *error = [NSError errorWithDomain:@"kEncryptionError"
                                         code:ccStatus
                                     userInfo:nil];
        }
        dataOut = nil;
    }

    return dataOut;
}

Тест: я поместил вышеуказанный метод в имена классов Test.

uint8_t keyBytes[] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
NSData *key = [NSData dataWithBytes:keyBytes length:8];
uint8_t dateBytes[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
NSData *data = [NSData dataWithBytes:dateBytes length:8];
NSLog(@"data:   %@", data);

NSError *error;
NSData *encryptData = [Test doCipher:data iv:nil key:key context:kCCEncrypt error:&error];
NSString *encryptString = [encryptData base64EncodedStringWithOptions:0];
NSLog(@"encryptData:   %@", encryptData);
NSLog(@"encryptString: %@", encryptString);

NSData *decryptData = [Test doCipher:encryptData iv:nil key:key context:kCCDecrypt error:&error];
NSLog(@"decryptData:   %@", decryptData);

Выход:

data:          01020304 05060708
encryptData:   9e8ec0a8 71ab9d10
encryptString: no7AqHGrnRA=
decryptData    01020304 05060708
person zaph    schedule 03.02.2015
comment
Ok. Вы использовали библиотеку RNCryptor на iOS? Я пытаюсь настроить эту библиотеку для использования 8-байтовых блоков Blowfish, но вывод всегда 27 байт, а не 8 байт. - person bickster; 03.02.2015
comment
Просто используйте Common Crypto. RNCryptor — отличная библиотека и включает в себя настоящие функции безопасности, но вы не можете получить это в 20 байтах. См. справочный пример, добавленный к ответу. - person zaph; 03.02.2015
comment
Спасибо за пример кода. Почему в примере кода не используется iv? - person bickster; 03.02.2015
comment
IV добавляет безопасность к первому блоку. Это может или не может относиться к вашему случаю. Безопасность — это гораздо больше, чем заставить работать метод edncryption. - person zaph; 03.02.2015
comment
Как вы упомянули. Я мог бы использовать оставшиеся 6 байтов для случайного iv, который получает кодировку base64 и добавляется к зашифрованному сообщению. Верно? - person bickster; 03.02.2015
comment
DES — очень плохая идея, 56-битные ключи слишком малы. С другой стороны, 3DES имеет достойную безопасность (112 бит безопасности с 168-битным ключом). При использовании Blowfish используйте ключ длиной не менее 128 бит, а не 64-битный ключ. - person CodesInChaos; 03.02.2015
comment
@CodesInChaos Да, DES - плохой выбор, я не советовал этого делать. 3DES - разумное решение, я должен был добавить это к своему ответу, я его пересмотрю. - person zaph; 03.02.2015
comment
@bickster Да, вы можете упаковать 7 байт случайного ключа в 20 байтов Base64 для передачи на расшифровку. Просто сделайте один из байтов iv константой. - person zaph; 03.02.2015
comment
@Zaph, почему я должен сделать один из байтов константой? - person bickster; 03.02.2015
comment
Мне нужно изменить предыдущий комментарий, я написал: можно упаковать 7 байт случайного ключа, я хотел написать: можно упаковать 7 байт случайного iv - person zaph; 03.02.2015
comment
20-байтовая строка Base64 может содержать только 15 8-битных байтов, за вычетом 8 зашифрованных байтов остается только 7 байтов для содержания iv. Проблема заключается в 8-м байте iv, и один из способов - сделать его константой, которая по-прежнему оставляет 7 случайных байтов iv. - person zaph; 03.02.2015
comment
Понятно. Еще один вопрос. Я изменил код вашего примера, чтобы использовать 16-байтовый/128-битный ключ, а размер зашифрованного вывода остался прежним. Будет ли это лучше, чем 8-байтовый/64-битный ключ? - person bickster; 03.02.2015
comment
Размер ключа не связан с размером зашифрованного вывода. Выходной размер кратен размеру блока. Обычно достаточно 128-битного ключа. Но реальная проблема заключается в том, насколько хорош ключ? Как они будут разделены между двумя сторонами и как они будут защищены — это ключевые вопросы управления, которые нелегко реализовать. - person zaph; 03.02.2015