Diferencia AES entre iPhone(Objective-c) y Java.
encryption (5)
¿Qué modo usa el iPhone con AES? No se enumera nada, por lo que quizás eso significa que no está utilizando el encadenamiento (BCE).
Sin embargo, en el lado de Java, está utilizando CBC, pero no está especificando un vector de inicialización. Eso está definitivamente mal. Si realmente está utilizando CBC, debe tener el IV que se usó durante el cifrado. El IV no es secreto; Puede ser enviado junto con el texto cifrado.
Si realmente está utilizando ECB, no hay IV, pero su Java especifica el modo incorrecto.
He estado arrancándome el pelo todo el día tratando de resolver esto ...
Tengo un cliente de object-c que se ejecuta en el iPhone y que se conecta a un servidor Java. El iPhone está cifrando datos usando AES, pero no puedo descifrarlos en el servidor. Estoy utilizando una frase de contraseña y un mensaje conocidos (cadena única) y estoy generando la matriz de bytes en el iPhone, generando una matriz de bytes de comparación en el servidor Java utilizando la misma clave y mensaje, pero las matrices de bytes son completamente diferentes (y por lo tanto no pueden ser decodificado en el lado de Java).
El cliente está utilizando la biblioteca CommonCrypto con la siguiente configuración ...
Los datos son un NSData
contiene la palabra "mensaje" usando dataUsingEncoding:NSASCIIStringEncoding
Key es un NSData
contiene la frase "1234567891123456" nuevamente usando la codificación como se NSData
arriba. El algoritmo es kCCAlgorithmAES128
opciones son kCCOptionsPKCS7Padding
(que creo que equivale a ECB en el servidor ?!)
El servidor está utilizando el siguiente código ...
byte[] key = "1234567891123456".getBytes();
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec k = new SecretKeySpec(key, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedData = c.doFinal("message".getBytes());
PERO los datos en encryptedData no coinciden con los que se generan en el código de object-c, las matrices de bytes son completamente diferentes.
¿Alguien puede ver algo obvio que estoy haciendo mal? Creo que las configuraciones son todas iguales ... :(
- ACTUALIZACIÓN - según lo solicitado ....
Ok así que aquí va ...
El cliente iPhone está encriptando la siguiente cadena "mensaje". Utiliza la clave "1234567891123456". Utiliza un vector de inicialización de "101010101010101010". Está utilizando AES128, con modo CBC (por lo que puedo decir) y opciones de kCCOptionsPKCS7Padding.
El resultado del cifrado (con codificación base64) es UHIYllDFAXl81ZM7OZPAuA ==
El servidor está cifrando la misma cadena, con la misma clave y el mismo vector de inicialización. Está utilizando la siguiente Cipher.getInstance ("AES / CBC / PKCS5Padding");
El resultado del cifrado (con codificación base64) es ALBnFIHysLbvAxjvtNo9vQ ==
Gracias.
- ACTUALIZACIÓN 2 - Según lo solicitado ...
Aquí está el código del iPhone ....
NSData *toencrypt = [@"message" dataUsingEncoding:NSASCIIStringEncoding];
NSData *pass = [@"1234567891123456" dataUsingEncoding:NSASCIIStringEncoding];
NSData *iv = [@"1010101010101010" dataUsingEncoding:NSASCIIStringEncoding];
CCCryptorStatus status = kCCSuccess;
NSData *encrypted = [toencrypt dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];
NSString *text = [NSString base64StringFromData:encrypted length:[encrypted length]];
La categoría NSData para cifrar viene de aquí ...
http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/
Por cierto, he comprobado las matrices de bytes que están en toencrypt, pass y iv y coinciden con las que están en el servidor.
Acabo de encontrar exactamente el mismo problema. Estoy usando CommonCrypto en el cliente iOS, usando la configuración:
NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];
El servidor utiliza Cipher.getInstance("AES/CBC/PKCS5Padding");
Con la misma clave y vector de inicialización que el cliente.
Después de golpear mi cabeza contra la pared durante las últimas horas, finalmente seguí el consejo de Jason y comprobé la rutina dataEncryptedUsingAlgorithm
e keyData
justo después de FixKeyLengths
. Resulta que mi clave de 128 bits se extendió a 192 bits con 0s añadidos al final. Después de arreglar esto, todo funciona correctamente. :)
Actualización: Mi respuesta se publicó hace casi 2 años, y este problema parece NSData+CommonCrypto solucionado en el último código NSData+CommonCrypto . Específicamente, esta fue la parte que causó el problema:
static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData )
{
NSUInteger keyLength = [keyData length];
switch ( algorithm )
{
case kCCAlgorithmAES128:
{
if ( keyLength <= 16 )
{
[keyData setLength: 16];
}
else if ( keyLength <= 24 )
{
[keyData setLength: 24];
}
else
{
[keyData setLength: 32];
}
break;
}
La primera verificación keyLength <= 16
no estaba allí antes.
Si todavía estás experimentando problemas ahora, probablemente sea algo más.
Basándose en sus muestras, el servidor lo está haciendo bien y el cliente no.
En cuanto a los datos, me imagino que la clave es incorrecta. Por favor, muéstrenos el código del iPhone, especialmente el código para ir de "1234567891123456" a su clave.
Esta no es mi área pero parece que en el cliente tienes PKCS7
pero en el servidor tienes PKCS5
.
Recientemente me encontré con esto en otro proyecto. El problema era que la clave era un byte demasiado largo para caber en el búfer de caracteres dentro del método dataEncryptedUsingAlgorithm
.
El problema era que el método getBytes
en la NSString
suave. Copiaría la mayor parte de la cadena en el búfer, pero como la clave era un byte demasiado larga, "marcaría" la operación como fallida al establecer el primer carácter en NUL
(carácter 0).
Ingrese a ese método en Xcode y vea cómo se ve su búfer key char [16]. Puede tener este mismo problema y tener los contenidos { 0, ''2'', ''3'', ''4'', ... }
.