2015-10-04 3 views
1

J'ai écrit le programme qui crypte/déchiffre la mémoire tampon de longueur personnalisée. Le chiffrement se termine bien; mais mon code de décryptage décrypte les données une seule fois à n'importe quelle position du tampon, ce qui correspond aux entrées du bloc. Le déchiffrement des autres blocs se termine par NTE_BAD_DATA.CryptoAPI RSA: CryptDecrypt décrypte seulement une fois, après est venu NTE_BAD_DATA

Avez-vous des suggestions pourquoi cela se produit-il?

Voici mon code de cryptage:

void CWinRSA::FinishEncrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbEcrData, size_t& rnEcrSize) const 
{ 
    if (m_hProvider == NULL) 
    { 
     throw ("Cannot encrypt data with wrong provider!!"); 
    } 

    if (m_hKey == NULL) 
    { 
     throw ("Cannot encrypt data with a wrong key!!"); 
    } 

    size_t nBlockLength = GetBlockLength(); 
    size_t nPaddingSize = nBlockLength - 11; 

    size_t nRemain = nDataSize % nBlockLength; 
    size_t nBlockProcess = (nDataSize/nPaddingSize + (nRemain != 0 ? 1 : 0)); 

    size_t nResultSize = nBlockProcess * nBlockLength; 

    (*ppcbEcrData) = new char[nResultSize]; 

    DWORD dwBufferLength = nBlockLength; 
    DWORD dwDataLength; 

    for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++) 
    { 
     memcpy((*ppcbEcrData) + (iBlock * nBlockLength), 
      pcbRawData + (iBlock * nPaddingSize), nPaddingSize); 

     dwDataLength = nPaddingSize; 

     if (!CryptEncrypt(m_hKey, NULL, FALSE, 0, 
      (BYTE*)((*ppcbEcrData) + (iBlock * nBlockLength)), 
      &dwDataLength, dwBufferLength)) 
     { 
      throw ("Cannot encrypt data!!"); 
     } 
    } 

    memcpy((*ppcbEcrData) + ((nBlockProcess - 1) * nBlockLength), 
     pcbRawData + ((nBlockProcess - 1) * nPaddingSize), (nRemain ? nRemain : nPaddingSize)); 

    dwDataLength = (nRemain ? nRemain : nPaddingSize); 

    if (!CryptEncrypt(m_hKey, NULL, TRUE, 0, 
     (BYTE*)((*ppcbEcrData) + ((nBlockProcess - 1) * nBlockLength)), 
     &dwDataLength, dwBufferLength)) 
    { 
     throw ("Cannot encrypt data!!"); 
    } 

    rnEcrSize = nResultSize; 
} 

le décryptage:

void CWinRSA::FinishDecrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbDecData, size_t& rnDecSize) const 
{ 
    if (m_hProvider == NULL) 
    { 
     throw ("Cannot decrypt data with wrong provider!!"); 
    } 

    if (m_hKey == NULL) 
    { 
     throw ("Cannot decrypt data with a wrong key!!"); 
    } 

    size_t nBlockLength = GetBlockLength(); 

    if ((nDataSize % nBlockLength) != 0) 
    { 
     throw ("Cannot decrypt data!! Probably data is corrupted!!"); 
    } 

    size_t nPaddingSize = nBlockLength - 11; 
    size_t nBlockProcess = nDataSize/nBlockLength; 

    size_t nResultSize = nBlockProcess * nPaddingSize; 

    (*ppcbDecData) = new char[nResultSize]; 

    DWORD dwDataLength; 

    char* pcbComputeResult = new char[nBlockLength]; 

    for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++) 
    { 
     memcpy(pcbComputeResult, pcbRawData + (iBlock * nBlockLength), nBlockLength); 

     if (!CryptDecrypt(m_hKey, NULL, FALSE, 0, (BYTE*)pcbComputeResult, &dwDataLength)) 
     { 
      throw ("Cannot decrypt data!!"); 
     } 

     memcpy((*ppcbDecData) + (iBlock * nPaddingSize), pcbComputeResult, nPaddingSize); 
    } 

    memcpy(pcbComputeResult, pcbRawData + ((nBlockProcess - 1) * nBlockLength), nBlockLength); 

    if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength)) 
    { 
     DWORD dwError = GetLastError(); 

     throw ("Cannot decrypt data!!"); 
    } 

    memcpy((*ppcbDecData) + ((nBlockProcess - 1) * nPaddingSize), pcbComputeResult, nPaddingSize); 

    rnDecSize = ((nBlockProcess - 1) * nPaddingSize) + dwDataLength; 

    delete[] pcbComputeResult; 
    pcbComputeResult = NULL; 
} 

Répondre

0

J'ai trouvé une réponse. Je dois initialiser dwDataLength avec la longueur du bloc en octets avant tous les appels de décryptage.

dwDataLength = nBlockLength; 

if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength)) 
{ 
    DWORD dwError = GetLastError(); 

    throw ("Cannot decrypt data!!"); 
} 

méthode de décryptage Tout

void CWinRSA::FinishDecrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbDecData, size_t& rnDecSize) const 
{ 
    if (m_hProvider == NULL) 
    { 
     throw ("Cannot decrypt data with wrong provider!!"); 
    } 

    if (m_hKey == NULL) 
    { 
     throw ("Cannot decrypt data with a wrong key!!"); 
    } 

    size_t nBlockLength = GetBlockLength(); 

    if ((nDataSize % nBlockLength) != 0) 
    { 
     throw ("Cannot decrypt data!! Probably data is corrupted!!"); 
    } 

    size_t nPaddingSize = nBlockLength - 11; 
    size_t nBlockProcess = nDataSize/nBlockLength; 

    size_t nResultSize = nBlockProcess * nPaddingSize; 

    (*ppcbDecData) = new char[nResultSize]; 

    DWORD dwDataLength; 

    char* pcbComputeResult = new char[nBlockLength]; 

    for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++) 
    { 
     memcpy(pcbComputeResult, pcbRawData + (iBlock * nBlockLength), nBlockLength); 

     dwDataLength = nBlockLength; 

     if (!CryptDecrypt(m_hKey, NULL, FALSE, 0, (BYTE*)pcbComputeResult, &dwDataLength)) 
     { 
      throw ("Cannot decrypt data!!"); 
     } 

     memcpy((*ppcbDecData) + (iBlock * nPaddingSize), pcbComputeResult, nPaddingSize); 
    } 

    memcpy(pcbComputeResult, pcbRawData + ((nBlockProcess - 1) * nBlockLength), nBlockLength); 

    dwDataLength = nBlockLength; 

    if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength)) 
    { 
     throw ("Cannot decrypt data!!"); 
    } 

    memcpy((*ppcbDecData) + ((nBlockProcess - 1) * nPaddingSize), pcbComputeResult, nPaddingSize); 

    rnDecSize = ((nBlockProcess - 1) * nPaddingSize) + dwDataLength; 

    delete[] pcbComputeResult; 
    pcbComputeResult = NULL; 
} 
1

RSA n'est pas destiné à être utilisé de cette façon. Ce n'est vraiment pas un chiffrement par bloc (ou un chiffrement de flux, d'ailleurs). Je comprends qu'il n'a pas vraiment d'utilisation cryptologique sauf pour un seul message "court", donc je ne suis pas étonné que la bibliothèque échoue après un décryptage d'une clé.

Si vous devez protéger une taille arbitraire de données, utilisez RSA pour échanger une clé symétrique contre un chiffrement de flux ou de bloc (comme AES).

+2

En ligne de principe, il _can_ être utilisé comme un chiffrement par bloc, mais il est ni l'utilisation prévue, ni les conséquences sur la sécurité de FAISANT, ont été explorés. –