2010-01-05 15 views
9

Đây là câu hỏi tiếp theo cho question 1072540, 'WinVerifyTrust to check for a specific signature?'.Làm cách nào để xác minh rằng việc tổ chức của tôi đã ký một cửa sổ nhị phân đáng tin cậy?

Tôi muốn viết một hàm C++ Hãy gọi nó là 'TrustedByUs' có dạng:

bool TrustedByUs(std::string pathToBinary, std::string pathToPublicKey) 

Ý tưởng là chúng tôi cung cấp chức năng này một đường dẫn đến một .dll nhị phân hoặc file .exe đã được ký với chữ ký số. Chuỗi 'pathToPublicKey' là đường dẫn đến khóa công khai của chứng chỉ ký kết cụ thể của chúng tôi.

Sử dụng mã trong http://support.microsoft.com/kb/323809 thật dễ dàng để xác minh rằng tệp 'pathToBinary' thực tế được hệ điều hành tin cậy.

Bây giờ tôi ở cùng vị trí với người viết câu hỏi 1072540, tôi biết hệ điều hành tin tưởng người ký nhị phân này, nhưng tôi muốn biết khóa RSA của tổ chức của tôi có phải là ký hiệu nhị phân hay không.

KB323809 cho biết cách trích xuất chuỗi từ chứng chỉ được nhúng trong tệp nhị phân của chúng tôi. Ví dụ này cho thấy cách trích xuất các chuỗi từ chứng chỉ ký trong hàm GetProgAndPublisherInfo của nó, nhưng tôi không thoải mái bằng cách sử dụng một chuỗi khớp để verfiy chứng chỉ.

Điều tôi muốn làm là trích xuất khóa công khai từ chữ ký được nhúng và so sánh khóa công khai với khóa công khai tương ứng với khóa riêng đã ký tệp nhị phân của tôi ngay từ đầu.

Tài liệu về CryptMsgGetParam cho biết tham số CMSG_SIGNER_CERT_ID_PARAM 'Trả về thông tin trên một người ký thư cần thiết để xác định khóa công khai của người ký'. Tôi thành công trong việc nhận được số sê-ri của chứng chỉ với khóa này. Mã của tôi trông như thế này:

// Get message handle and store handle from the signed file. 
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, 
    L"C:\\Program Files\\MySignedProgram.exe", 
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, 
    CERT_QUERY_FORMAT_FLAG_BINARY, 
    0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL); 

// Get the public key information about the signer 
// First get the size 
DWORD dwCertIdSize(0); 
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 
    0, NULL, &dwCertIdSize); 
BYTE* pCertId = new BYTE(dwCertIdSize); 
::ZeroMemory(pCertId,dwCertIdSize); 

// Now get the cert info 
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 
    0, (PVOID)pCertId, &dwCertIdSize); 

if(fResult) 
{  
    CERT_ID* pId = (CERT_ID*)pCertId; 
    pId->HashId; 
    pId->dwIdChoice; 
    pId->IssuerSerialNumber; // Valid serial number (reversed) 
    pId->KeyId; 
    _tprintf("pid\n"); 
} 

này gần với những gì tôi muốn, nhưng thực sự tôi muốn sử dụng khóa công khai ký giấy chứng nhận để xác minh rằng các mục tiêu đã ký tập tin nhị phân được trong thực tế tạo ra với công chúng đặc biệt của tôi/cặp khóa riêng.

Sử dụng cờ CMSG_ENCRYPTED_DIGEST mã này thành công:

// Get digest which was encrypted with the private key 
DWORD digestSize(0); 
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, NULL, &digestSize); 

BYTE* pDigest = new BYTE[digestSize]; 

// Next CryptMsgGetParam call succeds, 
// pDigest looks valid, can I use this to confirm my public key 
// was used to sign MySignedProgram.exe ? 
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, pDigest, &digestSize); 

Bottom line câu hỏi: Căn cứ vào thông tin chứng phát hiện bởi CryptQueryObject, những gì kỹ thuật tôi nên sử dụng để đảm bảo rằng các tập tin mục tiêu là trong thực tế đã ký sử dụng khóa riêng tương ứng với khóa công khai có sẵn cho tôi khi mã trên thực thi?

Trả lời

7

Thay vào đó, bạn muốn thay đổi CMSG_SIGNER_INFO_PARAM.

Bạn có thể sử dụng điều này để có được toàn bộ giấy chứng nhận bằng cách nhìn lên chứng chỉ trong kho chứng chỉ được trả về bởi CryptQueryObject:

CryptMsgGetParam(hMsg, 
       CMSG_SIGNER_INFO_PARAM, 
       0, 
       NULL, 
       &dwSignerInfo); 
PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO) malloc(dwSignerInfo); 
CryptMsgGetParam(hMsg, 
       CMSG_SIGNER_INFO_PARAM, 
       0, 
       pSignerInfo, 
       &dwSignerInfo); 

PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore, 
              ENCODING, 
              0, 
              CERT_FIND_SUBJECT_CERT, 
              (PVOID)pSignerInfo, 
              NULL); 
// Compare with your certificate: 
// - check pCertContext->pbCertEncoded (length is pCertContext->cbCertEncoded) 

// *OR* 
// Compare with your public-key: 
// - check pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm and 
// pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey 
+0

Cảm ơn Rasmus, nhưng tôi vẫn còn một chút bối rối. Đường dẫn CMSG_SIGNER_INFO không bao gồm thành viên SubjectPublicKeyInfol. –

+0

Xin lỗi, tôi đã trộn lẫn CMSG_SIGNER_INFO và cấu trúc CERT_INFO. Câu trả lời nên được corrext ngay bây giờ. –

+0

Cảm ơn Rasmus, tôi cũng đã tìm thấy api CertGetNameString với cờ CERT_NAME_SIMPLE_DISPLAY_TYPE cũng hữu ích trong dự án này. –

Các vấn đề liên quan