// Enc012.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #include #include #define CERT_SUBJ_STR L"電子証明書の所有者名に変えてください" int _tmain(int argc, _TCHAR* argv[]) { HCRYPTPROV hProv; HCERTSTORE hStore; // CSPハンドルの取得 if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, NULL)) { if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { fprintf(stderr, "CryptAcquireContext error\n"); return 1; } } // 証明書ストアーのオープン hStore = CertOpenSystemStore( hProv, "MY"); if(!hStore) { fprintf(stderr, "CertOpenSystemStore error\n"); return 2; } // 自分の電子証明書の取り出し PCCERT_CONTEXT pcCert; char name[100]; pcCert = NULL; while(pcCert = CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, CERT_SUBJ_STR, pcCert)) { CertNameToStr(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &pcCert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, name, 100); printf("Name: %s\n", name); break; } if(!pcCert) { fprintf(stderr, "指定された電子証明書が見つかりませんでした。"); return 3; } // 暗号化の準備 PCCERT_CONTEXT recipients[1]; // 受取人の電子証明書 CRYPT_ALGORITHM_IDENTIFIER encAlg; // 暗号化のアルゴリズム CRYPT_ENCRYPT_MESSAGE_PARA encPara; // 暗号化のパラメーター recipients[0] = pcCert; // 受取人リストに電子証明書をセットする memset(&encAlg, 0, sizeof(encAlg)); encAlg.pszObjId = szOID_RSA_RC4; // 暗号化の方式として、RC4を設定 memset(&encPara, 0, sizeof(encPara)); encPara.cbSize = (DWORD)sizeof(encPara); encPara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; encPara.hCryptProv = hProv; // CSPのハンドル encPara.ContentEncryptionAlgorithm = encAlg; // データを暗号化するアルゴリズム // 暗号化 BYTE *pbCont = (BYTE*)"このデータを暗号化します。"; // 暗号化されるデータ DWORD cbCont = (DWORD)strlen((char*)pbCont) + 1; // データのサイズ BYTE *pbEncBlob; // 暗号化データの格納域 DWORD cbEncBlob; // 暗号化データのサイズ if(!CryptEncryptMessage( &encPara, // 暗号化パラメーター 1, // 受取人の数 recipients, // 受取人の証明書アレー pbCont, // 暗号化されるデータ cbCont, // そのサイズ NULL, // 暗号化データのサイズがわからないのでNULLを指定 &cbEncBlob)) // 暗号化データのサイズが戻される { fprintf(stderr, "暗号化に失敗しました。\n"); return 4; } // 暗号化データの格納領域を確保してから再度暗号化を実施 pbEncBlob = new BYTE [cbEncBlob]; if(!CryptEncryptMessage( &encPara, // 暗号化パラメーター 1, // 受取人の数 recipients, // 受取人の証明書アレー pbCont, // 暗号化されるデータ cbCont, // そのサイズ pbEncBlob, // 暗号化データの格納域ポインター &cbEncBlob)) // 暗号化データのサイズが戻される { fprintf(stderr, "暗号化に失敗しました。\n"); return 5; } printf("Data size = %d\n", cbEncBlob); // 復号の準備 HCERTSTORE certStores[1]; CRYPT_DECRYPT_MESSAGE_PARA decPara; DWORD cbDecMsg; BYTE *pbDecMsg; certStores[0] = hStore; memset(&decPara, 0, sizeof(decPara)); decPara.cbSize = sizeof(decPara); decPara.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; decPara.cCertStore = 1; decPara.rghCertStore = certStores; // 復号 if(!CryptDecryptMessage( &decPara, // パラメーター pbEncBlob, // 暗号化データの格納ポインター cbEncBlob, // 暗号化データのサイズ NULL, // データの大きさがわからないのでNULL &cbDecMsg, // 大きさが戻る NULL)) // 暗号化されたデータに含まれている電子証明書 { fprintf(stderr, "復号に失敗しました。\n"); return 6; } // 復号したデータを格納する領域を確保して再度復号 pbDecMsg = new BYTE [cbDecMsg]; if(!CryptDecryptMessage( &decPara, pbEncBlob, cbEncBlob, pbDecMsg, // 確保した格納域を指定 &cbDecMsg, NULL)) { fprintf(stderr, "復号に失敗しました。\n"); return 7; } printf("復号したデータは、「%s」です。\n", pbDecMsg); // 後始末 delete [] pbDecMsg; delete [] pbEncBlob; CertFreeCertificateContext(pcCert); CertCloseStore(hStore, 0); CryptReleaseContext(hProv, 0); return 0; }