С Android 9 и API 28 провайдер Bouncy Castle («BC») больше не поддерживается, и попытка его использования приводит к NoSuchAlgorithmException
.Согласно официальному сообщению в блоге от Android, способ исправить это состоит в том, чтобы вообще не указывать поставщика.
Однако кажется, что поставщик по умолчанию ведет себя иначе, чем поставщик Bouncy Castle -в DECRYPT_MODE
метод getOuptputSize
возвращает другое значение для того же параметра.Приведенный ниже код показывает, что поставщик BC возвращает 35, а поставщик по умолчанию возвращает 51, когда запрашивает размер вывода зашифрованного буфера 51:
Cipher aesGCMCipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(AES_KEY_SIZE_IN_BITS, new byte[12]);
aesGCMCipher.init(Cipher.DECRYPT_MODE, aesSecretKey, gcmParameterSpec);
LOG.i("(Decrypt) BC provider output size: " + aesGCMCipher.getOutputSize(51));
Cipher defaultAesGCMCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec defaultGcmParameterSpec = new GCMParameterSpec(AES_KEY_SIZE_IN_BITS, new byte[12]);
defaultAesGCMCipher.init(Cipher.DECRYPT_MODE, aesSecretKey, defaultGcmParameterSpec);
LOG.i("(Decrypt) Default provider output size: " + defaultAesGCMCipher.getOutputSize(51));
// Ouptput:
(Decrypt) BC provider output size: 35
(Decrypt) Default provider output size: 51
Обратите внимание, что значения, возвращаемые в ENCRYPT_MODE
, являютсято же самое:
Cipher aesGCMCipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(AES_KEY_SIZE_IN_BITS, new byte[12]);
aesGCMCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, gcmParameterSpec);
LOG.i("(Encrypt) BC provider output size: " + aesGCMCipher.getOutputSize(35));
Cipher defaultAesGCMCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec defaultGcmParameterSpec = new GCMParameterSpec(AES_KEY_SIZE_IN_BITS, new byte[12]);
defaultAesGCMCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, defaultGcmParameterSpec);
LOG.i("(Encrypt) Default provider output size: " + defaultAesGCMCipher.getOutputSize(35));
// Output
(Encrypt) BC provider output size: 51
(Encrypt) Default provider output size: 51
Является ли код для определения размера выходного буфера неправильным и нуждается в перезаписи, или это ошибка в реализации, которая требует обходного пути?Прямо сейчас, поскольку возвращаемое значение неверно, выделенный буфер слишком велик, что приводит к повреждению сообщений (дополнительные байты добавляются к сообщению).Мне кажется, это ошибка, но я не решаюсь произвольно сократить последние 16 байтов, потому что, если ошибка будет исправлена, код снова будет регрессировать.