Выполнение AES / GCM en Android. AES – algoritmo simétrico azul… | de Somethingtoldme | NOP :: Matiz de programación Octubre 2020

Junto con una serie de problemas, asociados con la finalización del cifrado y cifrado AES de Android,

TL; DR: aquí es posible encontrar una solución preparada. Si es necesario mostrarle IV y AAD en la calidad de los datos iniciales, en viaje de negocios y equipo, difícil de hacer la creación de la llave. ¡A partir de ahora, ten cuidado de esta forma!

API API API API Идея состояла в том, что в устройствах с аппаратным криптопроцессором наше программное обеспечение должно использовать его для шифрования и расшифровки, а в остальных устройствах обращаться к существующей библиотеке. A los efectos de este objetivo, se necesitaba una API abstracta y general, que se puede utilizar para ocultar el entorno criptográfico. El cifrado y el desmontaje cumplirían con AES en modo GCM.

Como y sisegundooh otros Я encontré un seguimiento promedio:

const val TAG_LENGTH = 16

fun encrypt(key: SecretKey, message: ByteArray): Pair<ByteArray, ByteArray> {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val iv = cipher.iv.copyOf()
val ciphertext = cipher.doFinal(message)
return Pair(iv, ciphertext)
}

fun decrypt(key: SecretKey, iv: ByteArray, message: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
cipher.init(Cipher.DECRYPT_MODE, key, spec)
return cipher.doFinal(message)
}

El problema era con qué no coincidían los parámetros de entrada y salida, que se utilizaban con urgencia.

  • aceptar iv C aad en la calidad de los parámetros de entrada;
  • regresar tag en la calidad de la exportación;
  • aceptar aad C tag en la calidad de los parámetros iniciales.

El desarrollo del AES GCM no afecta estándar? ¿Cómo pueden ser posibles estas diferencias?

Suelte esta sección si está familiarizado con las señales iv, aad C tag.

Vector de iniciación iv (Abreviación de Vector de inicialización) es utilizado por todos los parámetros en el momento de su uso cifrados en la nube. Necesita una garantía de lo necesario para encriptar a uno y a los que son uno de ellos y que lo lamentan mucho. iv nunca usé nada.

Con otra pagina, aad C tag usado solo en automatizado (en adelante, «AEAD», abreviado como «Cifrado autenticado con datos asociados»), como AES en modo GCM:

  • tag – это выходные данные процедуры шифрования, которые затем передаются в процедуру расшифровки для проверки подлинности зашифрованного текста (он должен быть сгенерирован с тем же ключом, который использовался для расшифровки).
  • aad presenta «Datos de autenticación adicionales» y proporciona una señal de entrada para los procesos de cifrado y cifrado, que tag.

Además, no existe una solución única para todas las soluciones mencionadas anteriormente. Según cada parámetro, se requiere su enfoque:

Empecemos por lo muy simple. De acuerdo Documentación de Java:

Si se utiliza un modo AEAD como GCM / CCM, se agrega al archivo de cifrado.

Próximo discurso: método Cipher.doFinal() (en modo GCM) agregado tag al final del texto cifrado durante el cifrado y se comprueba, se lee con el final, al descifrar. Lo siguiente se puede escribir de la siguiente manera:

const val TAG_LENGTH = 16

class EncryptionOutput(val iv: ByteArray,
val tag: ByteArray,
val ciphertext: ByteArray)

fun encrypt(key: SecretKey, message: ByteArray): EncryptionOutput {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val iv = cipher.iv.copyOf()
val result = cipher.doFinal(message)
val ciphertext = result.copyOfRange(0, result.size - TAG_LENGTH)
val tag = result.copyOfRange(result.size - TAG_LENGTH, result.size)
return EncryptionOutput(iv, tag, ciphertext)
}

fun decrypt(key: SecretKey, iv: ByteArray, tag: ByteArray, ciphertext: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
cipher.init(Cipher.DECRYPT_MODE, key, spec)
return cipher.doFinal(ciphertext + tag)
}

Teoría de acuerdo, aad datos, que están exentos del suministro Documentación de Java, en el que encontramos el método Cipher.updateAAD(byte[] src).

No creo lo que se describió en la descripción de este método, que puede sustentarse en base a esta pregunta, que es una pregunta. aad: cuando se le pide que lo cambie en cifrado o descifrado, el descifrado no es necesario con la excepción AEADBadTagException, indicando qué automatización no se llevó a cabo.

Al usar el método Cipher.updateAAD(byte[] src) para divisiones aad, que verá la siguiente imagen:

const val AAD_LENGTH = 16
const val TAG_LENGTH = 16

class EncryptionOutput(val iv: ByteArray,
val aad: ByteArray,
val tag: ByteArray,
val ciphertext: ByteArray)

fun encrypt(key: SecretKey, message: ByteArray): EncryptionOutput {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val iv = cipher.iv.copyOf()
val aad = SecureRandom().generateSeed(AAD_LENGTH)
cipher.updateAAD(aad)
val result = cipher.doFinal(message)
val ciphertext = result.copyOfRange(0, result.size - TAG_LENGTH)
val tag = result.copyOfRange(result.size - TAG_LENGTH, result.size)
return EncryptionOutput(iv, aad, tag, ciphertext)
}

fun decrypt(key: SecretKey, iv: ByteArray, aad: ByteArray, tag: ByteArray, ciphertext: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
cipher.init(Cipher.DECRYPT_MODE, key, spec)
cipher.updateAAD(aad)
return cipher.doFinal(ciphertext + tag)
}

Invertir la percepción de lo establecido aad en calidad salida procedimientos de cifrado. Siempre leeré más tarde. El código anterior muestra la base que recomendaría a todos los que lean la API sin seguridad para

Hemos dejado un detalle más, que no proporciona nuestra segunda biblioteca criptobiótica: vector iniciador Entrada en el método de cifrado, y no en la salida.

Por supuesto, con la ayuda de la clase. GCMParameterSpec Se puede completar lo siguiente:

const val TAG_LENGTH = 16

class EncryptionOutput(val tag: ByteArray,
val ciphertext: ByteArray)

fun encrypt(key: SecretKey, iv: ByteArray, aad: ByteArray, message: ByteArray): EncryptionOutput {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
cipher.init(Cipher.ENCRYPT_MODE, key, spec)
cipher.updateAAD(aad)
val result = cipher.doFinal(message)
val ciphertext = result.copyOfRange(0, result.size - TAG_LENGTH)
val tag = result.copyOfRange(result.size - TAG_LENGTH, result.size)
return EncryptionOutput(tag, ciphertext)
}

fun decrypt(key: SecretKey, iv: ByteArray, aad: ByteArray, tag: ByteArray, ciphertext: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
cipher.init(Cipher.DECRYPT_MODE, key, spec)
cipher.updateAAD(aad)
return cipher.doFinal(ciphertext + tag)
}

Cuando se le solicite, complete la siguiente sección: java.security.InvalidAlgorithmParameterException: Caller-provided IV not permitted, que suele ser público: Android no invita a mostrar y usar IV.

¿Por qué? Esto se introduce en API 23 y está indicado por la garantía, que exige que el método IV se utilice como tal. Lo siguiente está atascado en lo siguiente: IV no sigue el uso del uno y la clave, que es lo que significa

Por eso lo cuento mejor para generalizar aad внутри процедуры шифрования: чтобы избежать предоставления фиксированных значений вызывающим метото Внутренняя генерация ключа гарантирует то, что он будет случайным.

Sobre ti, como y yo en efecto difícil de presentar iv (C aad) en la calidad de los parámetros iniciales, que es una de las formas. Cuando use la clave AES, use el método setRandomizedEncryptionRequired()pedir explícitamente que se presenten soluciones de Android iv en la calidad de los datos iniciales. De esta forma, el método de generación de claves será el siguiente:

fun generateAesKey(): SecretKey {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
val kgps = KeyGenParameterSpec.Builder("my_aes_key", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
// Так мы получим разрешение
.setRandomizedEncryptionRequired(false)
.build()
keyGenerator.init(kgps)
return keyGenerator.generateKey()
}

Usa este método solo en eso, si sabes exactamente lo que estás haciendo! Olvidar, que iv (C aad) regular y suficientemente coordinados para la versión específica del uso.

Las API de Java y Android permiten la implementación de AES GCM, que son compatibles con otros criptosistemas. ¿Cual es la causa?

Además, es posible solucionar lo siguiente, para que los desarrolladores de estas API las hayan resuelto de tal forma:

  • Completamente curioso, cuál es el propósito de la inclusión tag en el resultado Cipher.doFinal(), era una API JCE en toda regla. Cipher.doFinal() regresó byte[] en el flujo de muchos años, independientemente del cifrado, por lo que decidieron quedarse solos
  • Y mi punto de vista, hubiera sido mejor si fuera aad era parte de la estructura GCMParameterSpecNo sugiero que me falte la causa, que se usa en la calidad del método. Cipher. Uno es yo puedo confirmar lo que se muestra en la documentación en cuanto a qué marca aad se usa cuando el método desafiante no lo demuestra.
  • И, наконец, IV: мне нравится подход Android (IOS) обеспечивающий безопасные значения по умолчанию для крип Тех, кто не разбирается в шифровании, количество вариантов, предоставляемых другими API (такими как JCE) может напугать, поэтому хорошая практика – предоставлять по la creación de las variantes más seguras.

Lea también:

Léanos en Telegrama, VK C Ендекс.Дзен

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *