2017-02-20 21 views
1

Мои методы шифрования java и объектива c производят разные выходы - AES128, режим CBC.AES128 CBC-шифрование в Java и Object C, дающее разные выходы

ключ: YnA+lracf9xaiJO1oA/bTQ==
мкв: 190Dt3MNeL32o9Kd37HZlQ==
Обычный текст: text to encrypt

Java выход: mHZpz52LOK2K76t3B/EUuA==
Obj C выход: Fb0D46H4tN+ukgI05x/Dbg==

Java код:

public static String AESEncrypt(String text, String key, String iv) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    byte[] keyBytes = new byte[16]; 
    byte[] b = key.getBytes("UTF-8"); 
    int len = b.length; 
    if (len > keyBytes.length) 
     len = keyBytes.length; 
    System.arraycopy(b, 0, keyBytes, 0, len); 

    byte[] keyBytesiv = new byte[16]; 
    byte[] biv = iv.getBytes("UTF-8"); 
    int leniv = biv.length; 
    if (leniv > keyBytesiv.length) 
     leniv = keyBytesiv.length; 
    System.arraycopy(biv, 0, keyBytes, 0, len); 
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv); 

    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 

    byte[] results = cipher.doFinal(text.getBytes("UTF-8")); 
    BASE64Encoder encoder = new BASE64Encoder(); 
    return encoder.encode(results); 
} 

Цель код C

+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSData *)key iV:(NSData *) iv { 

    NSUInteger dataLength = [data length]; 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, 
             kCCAlgorithmAES128, 
             kCCOptionPKCS7Padding, 
             [key bytes], 
             kCCBlockSizeAES128, 
             [iv bytes], 
             [data bytes], 
             dataLength, 
             buffer, 
             bufferSize, 
             &numBytesEncrypted); 
    if (cryptStatus == kCCSuccess) { 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    free(buffer); 
    return nil; 
} 
+1

Вы должны base64 дешифровать ключ и IV, а также проверить 'arraycopy's, есть ошибка в второй. – matt

+0

IV должен быть непредсказуемым (чтение: случайное). Не используйте статический IV, потому что это делает шифр детерминированным и, следовательно, не семантически безопасным. Злоумышленник, который наблюдает за зашифрованным текстом, может определить, когда тот же префикс сообщения был отправлен раньше. IV не секрет, поэтому вы можете отправить его вместе с зашифрованным текстом. Обычно это просто добавляется к зашифрованному тексту и разрезается перед расшифровкой. –

+0

Лучше аутентифицировать ваши зашифрованные тексты, чтобы атаки, такие как [padding oracle attack] (http://crypto.stackexchange.com/q/18185/13022), невозможны. Это можно сделать с помощью аутентифицированных режимов, таких как GCM или EAX, или с помощью схемы [encrypt-then-MAC] (http://crypto.stackexchange.com/q/202/13022). –

ответ

0

Я смог решить проблему по java-коду благодаря предложениям выше. Вот код Java, который работал для меня, чтобы достичь режима AES128 CBC как на Java и Objective C

public static String AESEncrypt(String text, String key, String iv) throws Exception { 

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    byte[] keyBytes = new byte[16]; 
    byte[] b = new BASE64Decoder().decodeBuffer(key); 
    int len = b.length; 
    if (len > keyBytes.length) 
     len = keyBytes.length; 
    System.arraycopy(b, 0, keyBytes, 0, len); 

    byte[] keyBytesiv = new byte[16]; 
    byte[] biv = new BASE64Decoder().decodeBuffer(iv); 
    int leniv = biv.length; 
    if (leniv > keyBytesiv.length) 
     leniv = keyBytesiv.length; 
    System.arraycopy(biv, 0, keyBytesiv, 0, len); 

    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv); 

    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 

    byte[] results = cipher.doFinal(text.getBytes("UTF-8")); 
    BASE64Encoder encoder = new BASE64Encoder(); 
    return encoder.encode(results); 
} 
4

Есть два подхода к таким вопросам, как это, которые могут быть объединены:

  • В качестве проверки вменяемости, пытаются расшифровать зашифрованный текст и посмотреть, если он соответствует оригиналу, на обоих языках ,

  • Попробуйте использовать другую библиотеку (третью) и сравните ее с первыми двумя значениями.

Так что я попытался дешифрования зашифрованного с онлайновым инструментом, и может восстановить исходный текст («текст для шифрования») с целью вывода C. Это показывает, что с кодом Java что-то не так. Я подозреваю, что это может быть связано с тем, что вход (ключ, iv) закодирован в base64, тогда как, похоже, он обрабатывается просто как кодировка UTF-8 (вызов getBytes()).

Смежные вопросы