// Sign.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, "指定された電子証明書が見つかりませんでした。\n"); return 3; } // 電子署名の準備 CRYPT_SIGN_MESSAGE_PARA sigPara; memset(&sigPara, 0, sizeof(sigPara)); sigPara.cbSize = sizeof(sigPara); sigPara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; sigPara.pSigningCert = pcCert; sigPara.HashAlgorithm.pszObjId = szOID_RSA_MD5; sigPara.HashAlgorithm.Parameters.cbData = NULL; sigPara.cMsgCert = 1; sigPara.rgpMsgCert = &pcCert; // メッセージ(署名されるデータ) BYTE *pbMessage = (BYTE*)"電子署名されるデータです。"; DWORD cbMessage = (DWORD)strlen((char*)pbMessage)+1; const BYTE *messageArray[] = {pbMessage}; DWORD msgSizeArray[1]; msgSizeArray[0] = cbMessage; // 電子署名 BYTE *pbSignedMsgBlob; DWORD cbSignedMsgBlob; if(!CryptSignMessage( &sigPara, // 署名のパラメーター FALSE, // 署名にメッセージを含める 1, // メッセージの数 messageArray, // メッセージの配列 msgSizeArray, // メッセージサイズの配列 NULL, // 署名データのサイズがわからないので &cbSignedMsgBlob)) // 署名データのサイズが戻る { fprintf(stderr, "Error: CryptSignMessage\n"); return 4; } printf("Data size = %d\n", cbSignedMsgBlob); // 領域を確保して2回目のコール pbSignedMsgBlob = new BYTE [cbSignedMsgBlob]; if(!CryptSignMessage( &sigPara, FALSE, 1, messageArray, msgSizeArray, pbSignedMsgBlob, // 署名データの格納領域 &cbSignedMsgBlob)) { fprintf(stderr, "Error: CryptSignMessage\n"); return 5; } /* * 署名を検証します。 */ // 署名検証の準備 CRYPT_VERIFY_MESSAGE_PARA vrfyPara; memset(&vrfyPara, 0, sizeof(vrfyPara)); vrfyPara.cbSize = sizeof(vrfyPara); vrfyPara.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // 署名の検証 BYTE *pbDecodedMsgBlob; DWORD cbDecodedMsgBlob; if(!CryptVerifyMessageSignature( &vrfyPara, // 検証のパラメーター 0, // 最初の署名を検証 pbSignedMsgBlob, // 署名されたデータのポインター cbSignedMsgBlob, // 署名されたデータのサイズ NULL, // デコードされたメッセージ &cbDecodedMsgBlob, // デコードされたメッセージの大きさ NULL)) // 署名を検証した証明書 { fprintf(stderr, "Error: CryptVerifyMessageSignature\n"); return 6; } // 領域を確保して、2回目のコール pbDecodedMsgBlob = new BYTE [cbDecodedMsgBlob]; if(!CryptVerifyMessageSignature( &vrfyPara, 0, pbSignedMsgBlob, cbSignedMsgBlob, pbDecodedMsgBlob, // デコードされたメッセージ &cbDecodedMsgBlob, NULL)) { fprintf(stderr, "Error: CryptVerifyMessageSignature\n"); return 7; } printf("Verified Data is \"%s\"\n", pbDecodedMsgBlob); // 後始末 delete [] pbDecodedMsgBlob; delete [] pbSignedMsgBlob; CertFreeCertificateContext(pcCert); CertCloseStore(hStore, 0); CryptReleaseContext(hProv, 0); return 0; }