前言 使用程序去安装根证书的目的是:使用自签的证书给软件进行签名,安装根证书之后,电脑就会信任该自签名软件,不会进行拦截。当然可以的话,掏钱买证书比较好。我见过有些软件会安装根证书,但都是key驱动或者CA厂家。安装根证书需要用户手动点击确定按钮,就好比你是否同意我们的协议。
以下的证书都是cer证书,base64内容。其他格式可以转成cer格式
证书的安装 证书安装需要几个步骤,
1. 读取证书内容
2. 解析证书内容,并得到证书上下文
3. 添加或删除以及判断证书是否安装
读取证书内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 char * readFile (int * len) { int length = 0 ; ifstream file ("localhost.cer" ) ; if (!file.is_open()) { std ::cout << "open file fail" << endl ; } file.seekg(0 , std ::ios::end); length = file.tellg(); file.seekg(0 , std ::ios::beg); char * buffer = new char [length]; file.read(buffer, length); file.close(); *len = length; return buffer; }
解析证书并得到证书上下文 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 PCCERT_CONTEXT DecodeCert (LPBYTE lpCertData, ULONG ulDataLen) { PCCERT_CONTEXT pCertContext = NULL ; ULONG ulFlag = CRYPT_FIRST; ULONG ulContainerNameLen = 512 ; CHAR csContainerName[512 ] = { 0 }; BOOL bFoundContainer = FALSE; if (!lpCertData || ulDataLen == 0 ) { return pCertContext; } HCERTSTORE hCertStore = NULL ; CRYPT_DATA_BLOB dataBlob = { ulDataLen, lpCertData }; DWORD pdwContentType = CERT_QUERY_CONTENT_CERT; CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &dataBlob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, NULL , &pdwContentType, NULL , NULL , &hCertStore, NULL , (const void **)&pCertContext); if (NULL == hCertStore) { return NULL ; } if (pCertContext == NULL ) { pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext); } if (hCertStore) { CertCloseStore(hCertStore, 0 ); hCertStore = NULL ; } return pCertContext; }
添加证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 bool SaveCert (BYTE* cert, int length) { bool ret = false ; PCCERT_CONTEXT pCertContext = NULL ; pCertContext = DecodeCert(cert, length); HCERTSTORE hRootCertStore = CertOpenSystemStore(NULL , L"ROOT" ); if (hRootCertStore != NULL && pCertContext != NULL ) { ret = CertAddCertificateContextToStore(hRootCertStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING,NULL ); CertCloseStore(hRootCertStore, 0 ); CertFreeCertificateContext(pCertContext); } return ret; }
需要注意,Windows会弹出对话框,类似于以下图:
判断是否有证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 bool HasCert (BYTE* cert, int length) { bool ret = false ; PCCERT_CONTEXT pCertContext = NULL ; pCertContext = DecodeCert(cert,length); if (pCertContext != NULL ) { HCERTSTORE hRootCertStore = CertOpenSystemStore(NULL , L"ROOT" ); if (hRootCertStore != NULL ) { PCCERT_CONTEXT certcontext = CertFindCertificateInStore(hRootCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0 , CERT_FIND_EXISTING, pCertContext, NULL ); if (certcontext != NULL ) { ret = true ; CertFreeCertificateContext(certcontext); } } CertFreeCertificateContext(pCertContext); } return ret; }
删除根证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 bool DeleteCert (BYTE* cert, int length) { bool ret = true ; PCCERT_CONTEXT pCertContext = NULL ; pCertContext = DecodeCert(cert, length); if (pCertContext != NULL ) { HCERTSTORE hRootCertStore = CertOpenSystemStore(NULL , L"ROOT" ); if (hRootCertStore != NULL ) { PCCERT_CONTEXT certcontext = CertFindCertificateInStore(hRootCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0 , CERT_FIND_EXISTING, pCertContext, NULL ); if (certcontext != NULL ) { ret = CertDeleteCertificateFromStore(certcontext); int error = GetLastError(); std ::cout << error << endl ; } } CertFreeCertificateContext(pCertContext); } return ret; }
同安装证书一样,Windows会弹出对话框让用户确认:
结尾 好久之前写的代码了,以前因为项目需要给用户电脑安装根证书,但是后来发现不需要了,公司有现成的付费代码签名证书。