Реализация AES GCM с тегом аутентификации в Java

Я использую аутентификацию AES GCM в своем проекте Android, и она отлично работает. Но возникают некоторые проблемы с тегом аутентификации при сравнении с тегом генерации openssl API. Пожалуйста, найдите код Java ниже:

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
byte[] iv = generateRandomIV();
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
int outputLength = cipher.getOutputSize(data.length); // Prepare output buffer
byte[] output = new byte[outputLength];
int outputOffset = cipher.update(data, 0, data.length, output, 0);// Produce cipher text
outputOffset += cipher.doFinal(output, outputOffset);

Я использую openssl для того же в iOS и генерирую тег аутентификации, используя приведенный ниже код.

NSMutableData* tag = [NSMutableData dataWithLength:tagSize];
EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, [tag length], [tag mutableBytes])

В java или надувном замке невозможно получить точный тег аутентификации, который возвращает openssl, и вы можете помочь мне решить эту проблему. Спасибо


person user3656812    schedule 26.05.2014    source источник
comment
Можете уточнить, в чем именно проблема? Вам нужно настроить длину тега или вы хотите получить значение тега из шифра?   -  person Oleg Estekhin    schedule 26.05.2014
comment
Спасибо Олегу Эстехину. Я пытаюсь получить значение тега из шифра так же, как сгенерированный тег openssl.   -  person user3656812    schedule 26.05.2014


Ответы (1)


В Java тег к сожалению добавляется в конец зашифрованного текста. Вы можете настроить размер (в битах, используя число, кратное 8), используя GCMParameterSpec. Поэтому вы можете получить его, используя Arrays.copyOfRange(ciphertext, ciphertext.length - (tagSize / Byte.SIZE), ciphertext.length), если вы действительно этого хотите.

К сожалению, тег не должен помещаться в конец, и это портит онлайн-характер дешифрования GCM — требуется внутренняя буферизация вместо возможности напрямую вернуть открытый текст. С другой стороны, тег автоматически проверяется при расшифровке.

person Maarten Bodewes    schedule 14.10.2014
comment
Я только что обнаружил, что шифр AES/GCM будет поддерживать постоянно растущий внутренний буфер, который рано или поздно перерастет пространство кучи памяти Java для действительно больших операций дешифрования. Шифр, выполняющий расшифровку, запишет 0 байтов во время вызовов update() и, наконец, doFinal() выведет все декодированные буферизованные байты. Это печально во многих отношениях. Например, Cipher.update(ByteBuffer, ByteBuffer) требует, чтобы целевой буфер имел емкость не меньше, чем у Cipher.getOutputSize(), иначе будет выброшено исключение ShortBufferException. Cipher.getOutputSize() постоянно увеличивается... [см. следующий комментарий] - person Martin Andersson; 13.11.2014
comment
... заявленный требуемый размер (по мере роста внутреннего буфера), вынуждающий мое приложение также выделять все большие и большие целевые байтовые буферы, несмотря на то, что Cipher.update() никогда не записывает ни одного байта в выделенные байтовые буферы: '( Я думаю, что решение для Я здесь, чтобы разделить файлы на куски по 1 МБ либо в прямой памяти, либо на диске, а затем склеить куски вместе, как только весь процесс будет завершен.Я не крипто-парень, но вы говорите, что текущий дизайн Java несовершенен. Если бы это можно было сделать по-другому, то уж точно так, как доказывает мой собственный любительский опыт.[см. следующий комментарий] - person Martin Andersson; 13.11.2014
comment
Но! Поправьте меня, если я ошибаюсь - а я должен быть - не так ли, что MAC является хэшем всех входных байтов? Тогда, конечно, реализация должна помнить все байты, чтобы вычислить MAC? Это объясняет, почему MAC или тег аутентификации в данном случае помещается в конец зашифрованного текста, и это объясняет внутреннюю буферизацию? Пожалуйста, уточните этот вопрос, если хотите, потому что он очень важен для меня и, возможно, для многих других. Спасибо, owlstead! Ты удивительный. - person Martin Andersson; 13.11.2014
comment
Вместо этого попробуйте использовать код поставщика надувных замков. Он должен буферизовать только максимальный размер тега, если я не ошибаюсь. Вы должны использовать открытый текст только после проверки MAC, но GCM использует CTR внутри, должно быть легко сохранить открытый текст перед его использованием. - person Maarten Bodewes; 13.11.2014
comment
Готово. См. http://stackoverflow.com/q/26920906/1268003. - person Martin Andersson; 14.11.2014