CryptoAPI a CommonCrypto con RC4

3

Ho un codice crittografico usato nella piattaforma Windows, che usa le funzioni API Crypto e ho bisogno di convertirlo in Common Crypto su OS X.

Essenzialmente il codice originale è questo, con il controllo degli errori rimosso per brevità: -

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);

Per quanto ho capito, questo è quello che sta succedendo: -

CryptAcquireContext - Get an object to handle the cryptography

CryptCreateHash - Create an MD5 hashing object

CryptHashData - Hash the input data with MD5

CryptDeriveKey, CryptDecrypt - Decode pData with RC4, using the key m_hKey

La dimensione di pszInputData è di 12 byte e l'array di output dell'oggetto hash MD5 è lo stesso su entrambe le piattaforme.

Per decodificare con RC4, eseguo le seguenti operazioni 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);

Test dell'output (matrice OutBuffer) da Common Crypto con un decoder RC4 online corrisponde, quindi questa è decodifica correttamente.

Tuttavia, l'output finale dal codice Windows in pData non corrisponde a RC4 decodificato in Common Crypto.

Ci sono dei passaggi che mi mancano o che non capisco con le chiamate all'API di Windows Crypto qui; perché le uscite differiscono?

(Si noti che non sto cercando commenti sulla sicurezza o difetti nell'uso di RC4)

    
posta TheDarkKnight 19.06.2015 - 16:47
fonte

1 risposta

2

Secondo CryptDeriveKey() documentazione , PAROLA SUPERIORE del parametro dwFlags specifica la dimensione della chiave desiderata in bit. Nel tuo caso dovrebbe generare chiavi a 40 bit (0x28), scartando efficacemente tutti tranne i primi cinque byte dell'uscita MD5.

Per ottenere un comportamento simile con CommonCrypto puoi provare questo:

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

EDIT:

In realtà, il codice precedente non è compatibile con CryptDeriveKey() . Risulta (dai vettori di test pubblicati nei commenti) che Windows utilizza ancora la chiave da 16 byte ma gli ultimi 11 byte sono impostati su zero (quindi, la lunghezza effettiva della chiave è ancora di 5 byte o 40 bit). Codice Python che produce lo stesso risultato del codice di 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())))

Output per me:

04021f02730101000000ff9b

Questo codice CommonCrypto dovrebbe funzionare:

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);
    
risposta data 19.06.2015 - 17:22
fonte

Leggi altre domande sui tag