AES interoperabilidad entre .Neto y el iPhone?

Necesito para cifrar una cadena en el iPhone y lo envía a un .Web de la red de servicio para el descifrado. Soy capaz de cifrar/descifrar en el iPhone y con .Net, pero las cadenas cifradas desde el iPhone no se puede descifrar .Net. El error que me sale es «Relleno no es válida y no puede ser eliminado.»

El .Net de código es de:
http://blog.realcoderscoding.com/index.php/2008/07/dot-net-encryption-simple-aes-wrapper/

El iPhone código usa el código de ejemplo de: http://nootech.wordpress.com/2009/01/17/symmetric-encryption-with-the-iphone-sdk/

AFAIK mi clave de configuración son los mismos:

result.BlockSize = 128; //iPhone: kCCBlockSizeAES128
result.KeySize = 128; //kCCBlockSizeAES128
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7; //kCCOptionPKCS7Padding

He probado diferentes formas de generación de texto cifrado. hola/hello:

e0PnmbTg/3cT3W+92CDw1Q== en .Net

yrKe5Z7p7MNqx9+CbBvNqQ== en el iPhone

y «openssl enc -aes-128-cbc -nosalt -a-en hello.txt -pass pass:hola» genera: QA+Ul+r6Zmr7yHipMcHSbQ==

Actualización: He publicado el código de trabajo para esta aquí.

  • También traté de openSSL y no funciona bien: openssl enc -d -aes-128-cbc -a-en crypt.txt -pass pass:hola
  • Si pasa el nosalt argumento a openssl, se obtiene un tamaño similar, la codificación base64. Parece que el .Neto y el iPhone no están usando un explícito Vector de Inicialización (sal). Pero incluso entonces, openssl no puede decodificar bien. Me imagino que cada biblioteca tiene su propio predeterminado de sal?
  • hey, jefe, sé que esto es una vieja pregunta, pero estoy teniendo problemas de atm en el intento de implementar el código que has subido como creo que tengo una forma diferente de aplicar el cifrado de aes, yo uso IV, con una longitud de 16. Ya que soy nuevo con el objetivo , no estoy muy seguro de dónde longitud se establece.

3 Kommentare

  1. 16

    Al menos, está el uso de los diferentes vectores de inicialización (IV).

    • El .Net de código utiliza la clave para IV.

      private static AesCryptoServiceProvider GetProvider(byte[] key)
      {
          //Set up the encryption objects
          AesCryptoServiceProvider result = new AesCryptoServiceProvider();
          byte[] RealKey = Encryptor.GetKey(key, result);
          result.Key = RealKey;
          result.IV = RealKey;
          return result;
      }

      y

      private static byte[] GetKey(byte[] suggestedKey, AesCryptoServiceProvider p)
      {
          byte[] kRaw = suggestedKey;
          List kList = new List();
          for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8 )
          {
              kList.Add(kRaw[i % kRaw.Length]);
          }
          byte[] k = kList.ToArray();
          return k;
      }

      que probablemente deben ser: kList.Add(kRaw[(i /8) % kRaw.Length]);. De lo contrario, una clave cuya longitud % 8 == 0 se utiliza la misma letra en repetidas ocasiones, doh!

      Así, el IV (y clave) que utiliza .Net es: hleolhleolhleolh. Esto no es parte de la API, sino por el código de contenedor que usted señaló en (que tiene un grave error en el que…).

    • El iPhone de código utiliza 0 para IV.

      //Initialization vector; dummy in this case 0's.
      uint8_t iv[kChosenCipherBlockSize];
      memset((void *) iv, 0x0, (size_t) sizeof(iv));
    • openssl por defecto, se antepone al azar que se generan de sal (que es la razón por la que la salida es más largo!).

    Openssl de salida es más seguro ya que es anteponiendo al azar vector de inicialización. Parece que los primeros bytes de la base64 decodificado cadena es «Salado__». Usted también puede pedir openssl para no usar una sal (-nosalt) y /o proporcionar una vía INTRAVENOSA (iv).

    Esencialmente, openssl, .Net, y el iPhone utiliza la misma codificación, usted sólo tiene que tener cuidado de cómo inicializar la Api con la clave de cifrado y el vector de inicialización.

    • Gracias! Una vez que he cambiado el .Red para el uso de la clave correcta y 0 para el IV, el resultado es el mismo. ¿Qué debe hacer el IV estar bien? Es 0 OK? Sería más seguro si he utilizado algo más?
    • IV=0 es sólo aceptable si utiliza cada tecla sólo una vez. De lo contrario, debe utilizar un cambio de IV (un contador, un nonce o totalmente al azar IV). Uno de los riesgos con el uso de una estática IV es que el mismo texto claro generará el mismo texto cifrado cada vez, que se abre para muchos de los ataques.
    • Normalmente se utiliza un algoritmo de hash seguro para derivar la clave y el IV de la contraseña y al azar de sal. Por ejemplo, vea RFC 2898, que creo que utiliza HMACSHA1.
    • Gracias hombre, me ahorraría un montón de tiempo con su solución. Yo estaba tratando de interoperabilidad entre el iPhone y un servicio WCF. He utilizado tu código, sino que, además, necesitaba escribir el resultado NSData a una cadena base64, con el fin de meterlo en un sobre SOAP. He utilizado la función discutido aquí: stackoverflow.com/questions/882277/…
    • El GetKey código no es seguro. Usted no debe repetir bytes en una clave criptográfica, ni se debe eliminar bytes de ella. En lugar usted debe utilizar una Contraseña de Claves Basada en la Derivación de la Función (PBKDF, por ejemplo, PBKDF2) o Clave de Claves Basada en la Derivación de la Función (KBKDF, por ejemplo, hkdf).
    • Esta es una vieja respuesta, y en caso de que alguien está leyendo esto, IV debe ser impredecibles y, preferentemente, generado por un criptográficos generador de números aleatorios, para AES en modo CBC. Cero IV, estática IV, o un contador no es seguro cuando está en el modo CBC.

  2. 3

    En c#

    void test(){
       string ctB64 = encrypt("hola");
       Console.WriteLine(ctB64);  //the same as in objective-c
    }
    
    string encrypt(string input)
            {
                try
                {
                    //Create a new instance of the AesManaged class.  This generates a new key and initialization vector (IV).
                    AesManaged myAes = new AesManaged();
    
                    //Override the cipher mode, key and IV
                    myAes.Mode = CipherMode.CBC;
                    myAes.IV = new byte[16] { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; //must be the same as in objective-c
                    myAes.Key = Encoding.UTF8.GetBytes(“0123456789123456”);
                    //CipherKey;  //Byte array representing the key
                    myAes.Padding = PaddingMode.PKCS7;
    
                    //Create a encryption object to perform the stream transform.
                    ICryptoTransform encryptor = myAes.CreateEncryptor();
    
                    //perform the encryption as required...
                    MemoryStream ms = new MemoryStream();
                    CryptoStream ct = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
                    byte[] binput = Encoding.UTF8.GetBytes(input);
                    ct.Write(binput, 0, binput.Length);
                    ct.Close();
                    byte [] result = ms.ToArray();
                    return Convert.ToBase64String(result);
                }
                catch (Exception ex)
                {
                    //TODO: Log the error 
                    Console.WriteLine(ex);
                    throw ex;
                }
    
            }

    · En objective-c,
    agregar CocoaSecurity biblioteca de https://github.com/kelp404/CocoaSecurity

    #import "CocoaSecurity.h"
    #import "Base64.h"
    
    
    
    - (void) test{
     unsigned char bytes[] = { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; //must be the same as in c#
    
        NSData *iv = [NSData dataWithBytesNoCopy:bytes length:16 freeWhenDone:YES];
        NSData* key =   [@"0123456789123456" dataUsingEncoding:NSUTF8StringEncoding];
    
        CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:@"hola" key:key iv:iv];
       NSLog(@"%@", result.base64); //the same as in c#
    
    
        NSData *data = [NSData dataWithBase64EncodedString:result.base64];
        CocoaSecurityResult *result2 = [CocoaSecurity aesDecryptWithData:data key:key iv:iv];
    
        NSLog(@"%@", result2.utf8String); //show "hola"
    
    }
  3. 2

    ¿Estás seguro de que estás utilizando la misma clave AES en las pruebas? El OpenSSL ejemplo en tu post utiliza una contraseña que OpenSSL se deriva de una clave y una vía intravenosa (IV) (y probablemente utiliza una sal.

    Generar una clave aleatoria de 128 bits y especificar esta clave en formato hexadecimal a OpenSSL con:

    openssl enc -aes-128-cbc -a -in hello.txt -K KEY_IN_HEX -iv 0

    Que no se debe usar IV=0 en cualquier sistema de seguridad, pero para probar la interoperabilidad es ACEPTAR.

    • esto funciona para decodificar el iPhone muestra el uso de openssl. clave = 68656c6c6f (hola).
    • El uso de «hola» como clave la da sólo el 40 bits, de manera que los diferentes implantaciones de AES usará algún método para aumentar esta a 128 bits. Probablemente no utilizar el mismo método para esto… Intenta especificar un total de 128 bits (16 caracteres) primas clave.
    • Finalmente. Trabajó como un encanto. Muchas gracias.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea