2012-10-03 3 views
1

Microsoft Crypto API에서 "인증서"을 사용하여 데이터를 암호화하는 방법은 무엇입니까? 오히려 대칭 암호화보다 내가 공개 -를 사용할 필요가 제외인증서를 사용하여 데이터를 암호화하는 방법은 무엇입니까?

keyBlob.hdr.bType := PLAINTEXTKEYBLOB; 
keyBlob.hdr.bVersion := CUR_BLOB_VERSION; 
keyBlob.hdr.reserved := 0; 
keyBlob.hdr.aiKeyAlg := CALG_AES_128; 
keyBlob.cbKeySize := 16; 
Move(data[0], keyBlob.key[0], 16); 


/* 
    Set ProviderName to either 
    providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider" 
    providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" //Windows XP and earlier 
*/ 
MS_ENH_RSA_AES_PROV_W: WideString = 'Microsoft Enhanced RSA and AES Cryptographic Provider'; 
providerName := MS_ENH_RSA_AES_PROV_W; 

CryptAcquireContextW(provider, nil, PWideChar(providerName), PROV_RSA_AES, CRYPT_VERIFYCONTEXT); 
CryptImportKey(provider, PByte(@keyBlob), sizeof(keyBlob), 0, 0, importedKey); 

mode := CRYPT_MODE_CBC; 
CryptSetKeyParam(importedKey, KP_MODE, @mode, 0); 

//CryptEncrypt encrypts in-place. Copy stuff to be encrypted into new byte buffer 
utf8PlainText := TCrypt.WideStringToUTF8(szPlainText); 
dataLen := Length(utf8PlainText); 
bufferLen := dataLen+16; //allocate a buffer larger than we need to hold the data we want to encrypt 
SetLength(data, bufferLen); 
Move(utf8PlainText[1], data[0], dataLen); 

if not CryptEncrypt(importedKey, 0, True, 0, @data[0], {var}dataLen, bufferLen) then 
begin 
    le := GetLastError; 
    if le = ERROR_MORE_DATA then 
    begin 
     /* 
     If the buffer allocated for pbData is not large enough to hold the encrypted data, 
     GetLastError returns ERROR_MORE_DATA and stores the required buffer size, 
     in bytes, in the DWORD value pointed to by pdwDataLen. 
     */ 
     bufferLen := dataLen; 
     SetLength(data, bufferLen); 
     CryptEncrypt(importedKey, 0, True, 0, @data[0], {var}dataLen, bufferLen); 
    end; 
    CryptDestroyKey(importedKey); 
    CryptReleaseContext(provider, 0); 
end; 

지금 내가 같은 일을 수행해야합니다


은 내가 AES 암호화를 사용하여 Microsoft 암호화 API를 사용하여 데이터를 암호화하는 방법을 알고 암호화 할 키 및 해독 할 개인 키가 포함됩니다.


: 그것은 대칭 암호화를위한 코드들 (15 개) 라인을 마련하기 위해 삼일했다. 나는 벽에 머리를 두드리는 일주일에 누군가 똑같은 일을 할 수 있기를 바라고있다. 나는 내가 설치해야한다고 생각하는 잘못된 길로 내려 간다. OpenSSL. 내가 채우기 만-최대 irrelavent 정크로 질문을하는 방법으로 코드 예제를 포함 : 내가 COM Objectsfrom native code

를 호출하려고하면, 더 나쁜. 하나의 행만 포함되어있는 경우 질문을 닫는 사람들이 있습니다.

답변

4

Microsoft Crypto API에는 인증서를 통한 비대칭 암호화 및 암호 해독을위한 고급 기능이 포함되어 있습니다. CryptEncryptessageCryptDecryptMessage을보십시오.

암호 해독의 경우 CERT_CONTEXT에 CERT_KEY_PROV_INFO_PROP_ID 속성이 있어야합니다.

나는 당신에게 사용의 예를들 수 있습니다

const wchar_t message[] = L"This is a simple test message."; 
PCCERT_CONTEXT hCert = NULL; 
HCERTSTORE hStore = NULL; 

static bool openCertStoreMY(CDialog *parent) 
{ 
    if(!hStore) 
    { 
     hStore = CertOpenSystemStore(NULL, L"MY"); 

     if(!hStore) 
     { 
      parent->MessageBox(L"Cannot open \"MY\"", L"Error", MB_ICONERROR); 
      return false; 
     } 
    } 

    return true; 
} 

void CTestDlg::OnEncryptClicked() 
{ 
    if(!hCert) 
    { 
     if(!openCertStoreMY(this)) 
      return; 

     hCert = CryptUIDlgSelectCertificateFromStore(hStore, GetSafeHwnd(), NULL, NULL, 0, 0, 0); 

     if(!hCert) 
      return; 
    } 

    CRYPT_ENCRYPT_MESSAGE_PARA params; 
    memset(&params, 0, sizeof(CRYPT_ENCRYPT_MESSAGE_PARA)); 
    params.cbSize = sizeof(CRYPT_ENCRYPT_MESSAGE_PARA); 
    params.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 
    params.ContentEncryptionAlgorithm.pszObjId = "2.16.840.1.101.3.4.1.2"; //AES128 

    DWORD msz; 
    DWORD cbMsg = sizeof(message); 
    const BYTE *pbMsg = (PBYTE)message; 
    if(!CryptEncryptMessage(&params, 1, &hCert, pbMsg, cbMsg, NULL, &msz)) 
     return; 

    PBYTE outBuf = new BYTE[msz]; 
    if(CryptEncryptMessage(&params, 1, &hCert, pbMsg, cbMsg, outBuf, &msz)) 
    { 
     FILE *fil = _wfopen(filename, L"wb"); 
     if(fil) 
     { 
      fwrite(outBuf, 1, msz, fil); 
      fclose(fil); 
      MessageBox(L"Complete"); 
     } 
     else 
      MessageBox(L"Cannot open file", L"Error", MB_ICONERROR); 
    } 

    delete [] outBuf; 
} 

void CTestDlg::OnDecryptClicked() 
{ 
    if(!openCertStoreMY(this)) 
     return; 

    CRYPT_DECRYPT_MESSAGE_PARA params; 
    params.cbSize = sizeof(CRYPT_DECRYPT_MESSAGE_PARA); 
    params.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; 
    params.cCertStore = 1; 
    params.rghCertStore = &hStore; 
    params.dwFlags = 0; 

    DWORD cbMsg; 
    PBYTE pbMsg; 

    FILE *fil = _wfopen(filename, L"rb"); 
    if(fil) 
    { 
     fseek(fil, 0 ,2); 
     cbMsg = ftell(fil); 
     fseek(fil, 0, 0); 
     pbMsg = new BYTE[cbMsg]; 

     fread(pbMsg, 1, cbMsg, fil); 
     fclose(fil); 
    } else { 
     MessageBox(L"Cannot open file", L"Error", MB_ICONERROR); 
     return; 
    } 

    DWORD msz; 
    if(!CryptDecryptMessage(&params, pbMsg, cbMsg, NULL, &msz, NULL)) 
    { 
     delete [] pbMsg; 
     return; 
    } 

    PBYTE outBuf = new BYTE[msz]; 
    if(CryptDecryptMessage(&params, pbMsg, cbMsg, outBuf, &msz, NULL)) 
     MessageBox((LPCWSTR)outBuf); 

    delete [] pbMsg; 
    delete [] outBuf; 
} 
관련 문제