CryptoAPI a CommonCrypto con RC4

3

Tengo un código criptográfico utilizado en la plataforma Windows, que utiliza las funciones de la API de Crypto y necesito convertirlo para usar Common Crypto en OS X.

Esencialmente, el código original es este, con la verificación de errores eliminada por brevedad: -

CryptAcquireContext(&m_hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
CryptCreateHash(m_hProv, CALG_MD5 ,0, 0, &hHash);
CryptHashData(hHash,(LPBYTE)pszInputData, lstrlen(pszInputData)*sizeof(TCHAR), 0);

CryptDeriveKey(m_hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE | 0x00280000, &m_hKey);
CryptDecrypt(m_hKey, 0, bFinal, 0, pData, pdwDataSize);

Según tengo entendido, esto es lo que está sucediendo: -

  

CryptAcquireContext: obtenga un objeto para manejar la criptografía

     

CryptCreateHash - Crear un objeto hash MD5

     

CryptHashData: hash los datos de entrada con MD5

     

CryptDeriveKey, CryptDecrypt - Decodifica pData con RC4, usando la clave m_hKey

El tamaño de pszInputData es de 12 bytes y la matriz de salida del objeto hash MD5 es la misma en ambas plataformas.

Para decodificar con RC4, estoy haciendo lo siguiente con Common Crypto: -

CCCryptorRef cryptor = NULL;
CCCryptorCreate(kCCDecrypt, kCCAlgorithmRC4, 0,
                      (void*)m_hKey.data(), m_hKey.length(), NULL, &cryptor);

char outBuffer[12];
size_t outBytes;
CCCryptorUpdate(cryptor, (void*)pData, *pdwDataSize, outBuffer, 12, &outBytes);

Probando la salida (outBuffer array) de Common Crypto con un decodificador RC4 en línea, por lo que esta se decodifica correctamente.

Sin embargo, el resultado final del código de Windows en pData no coincide con el RC4 descodificado en Common Crypto.

¿Hay algunos pasos que faltan o no entiendo con las llamadas a la API de Windows Crypto? ¿Por qué difieren las salidas?

(Tenga en cuenta que no estoy buscando comentarios sobre la seguridad o fallas en el uso de RC4)

    
pregunta TheDarkKnight 19.06.2015 - 16:47
fuente

1 respuesta

2

Según CryptDeriveKey() documentación , el parámetro de PALABRA superior de dwFlags especifica el tamaño de clave deseado en bits. En su caso, debe generar claves de 40 bits (0x28), descartando de manera efectiva todos los primeros cinco bytes de la salida MD5.

Para lograr un comportamiento similar con CommonCrypto, puede intentar esto:

CCCryptorCreate(kCCDecrypt, kCCAlgorithmRC4, 0,
                      (void*)m_hKey.data(), 5, NULL, &cryptor);

EDITAR:

En realidad, el código anterior no es compatible con CryptDeriveKey() . Resulta (de los vectores de prueba publicados en los comentarios) que Windows todavía usa una clave de 16 bytes, pero los últimos 11 bytes se establecen en cero (por lo tanto, la longitud efectiva de la clave sigue siendo de 5 bytes o 40 bits). Código de Python que produce el mismo resultado que el código de Windows:

from Crypto.Cipher import ARC4
import binascii

KEY = "cfba3dd2ed"
DATA = "eb b9 bd 6f 5d 46 8d 17 c1 88 db 78"

key = binascii.unhexlify(KEY) + "\x00" * 11
rc4 = ARC4.new(key)
print binascii.hexlify(rc4.encrypt(binascii.unhexlify(DATA.replace(" ", "").strip())))

Salidas para mi:

04021f02730101000000ff9b

Este código CommonCrypto debería funcionar:

if (m_hKey.length() > 5) {    
    memset(m_hKey.data() + 5, 0, m_hKey.length() - 5);
}

CCCryptorCreate(kCCDecrypt, kCCAlgorithmRC4, 0,
                          (void*)m_hKey.data(), m_hKey.length(), NULL, &cryptor);
    
respondido por el Andrey 19.06.2015 - 17:22
fuente

Lea otras preguntas en las etiquetas