2010-03-04 3 views
1

내 서버와 클라이언트간에 인증서 기반 인증을 사용하고 있습니다. 루트 인증서를 생성했습니다. 설치시 클라이언트는 새 인증서를 생성하고 루트 인증서를 사용하여 서명합니다. Windows API를 사용해야합니다. makecert와 같은 Windows 도구를 사용할 수 없습니다.루트 인증서를 사용하여 인증서에 서명하는 방법

지금까지 저장소에 루트 인증서를 설치할 수있었습니다. 코드 아래

X509Certificate2^certificate = gcnew X509Certificate2("C:\\rootcert.pfx","test123"); 
X509Store^store = gcnew X509Store("teststore",StoreLocation::CurrentUser); 
store->Open(OpenFlags::ReadWrite); 
store->Add(certificate); 
store->Close(); 

그런 다음

GetRootCertKeyInfo(){ 
    HCERTSTORE hCertStore; 
    PCCERT_CONTEXT pSignerCertContext=NULL; 
    DWORD dwSize = NULL; 
    CRYPT_KEY_PROV_INFO* pKeyInfo = NULL; 
    DWORD dwKeySpec; 
    if (!(hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER,L"teststore"))) 
    { 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
    } 
    pSignerCertContext = CertFindCertificateInStore(hCertStore,MY_ENCODING_TYPE,0,CERT_FIND_ANY,NULL,NULL); 

if(NULL == pSignerCertContext) 
{ 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
} 

if(!(CertGetCertificateContextProperty(pSignerCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize))) 
{ 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
} 

if(pKeyInfo) 
    free(pKeyInfo); 
if(!(pKeyInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize))) 
{ 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
} 


if(!(CertGetCertificateContextProperty(pSignerCertContext, CERT_KEY_PROV_INFO_PROP_ID, pKeyInfo, &dwSize))) 
{  
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
} 
return pKeyInfo; 
} 

그런 다음 마지막으로 인증서를 생성하고 위의 코드와 pKeyInfo

// Acquire key container 
if (!CryptAcquireContext(&hCryptProv, _T("trykeycon"), NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) 
{ 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 

    // Try to create a new key container 
    _tprintf(_T("CryptAcquireContext... ")); 
    if (!CryptAcquireContext(&hCryptProv, _T("trykeycon"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET)) 
    { 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
    return 0; 
    } 
    else 
    { 
    _tprintf(_T("Success\n")); 
    } 
} 
else 
{ 
    _tprintf(_T("Success\n")); 
} 

// Generate new key pair 
_tprintf(_T("CryptGenKey... ")); 
if (!CryptGenKey(hCryptProv, AT_SIGNATURE, 0x08000000 /*RSA-2048-BIT_KEY*/, &hKey)) 
{ 
    _tprintf(_T("Error 0x%x\n"), GetLastError()); 
    return 0; 
} 
else 
{ 
    _tprintf(_T("Success\n")); 
} 
//some code 
    CERT_NAME_BLOB SubjectIssuerBlob; 
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob)); 
SubjectIssuerBlob.cbData = cbEncoded; 
SubjectIssuerBlob.pbData = pbEncoded; 

// Prepare algorithm structure for self-signed certificate 
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; 
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm)); 
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA; 

// Prepare Expiration date for self-signed certificate 
SYSTEMTIME EndTime; 
GetSystemTime(&EndTime); 
EndTime.wYear += 5; 

// Create self-signed certificate 
_tprintf(_T("CertCreateSelfSignCertificate... ")); 

CRYPT_KEY_PROV_INFO* aKeyInfo; 
aKeyInfo = GetRootCertKeyInfo(); 
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, aKeyInfo, &SignatureAlgorithm, 0, &EndTime, 0); 

서명 문맥 내가 수 있어요을 얻기 위해 설치된 루트 인증서를 엽니 다 인증서를 만들지 만 루트 인증서로 서명 된 것으로 보이지는 않습니다. 나는 자체 서명 된 인증서는 당신이 여기에서 필요로하는 무슨 생각하지 않습니다 ..

감사 아시프

+0

Google이 나를 보냈습니다. 이렇게하면 루트 인증서의 개인 키가 클라이언트에 설치됩니다. 하지만 그건 옳지 않을 수 있습니다. 왜냐하면 1) 그게 미친 짓이며, 2) 누군가는 지난 6 년 동안 그것을 지적했을 것이기 때문에 나는 틀렸어 야합니다. 권리? – Fozi

답변

0

을 제가 한 것은 .. 어떤 도움을 크게 감상 할 수와 오른쪽 또는 아닙니다 알 수없는입니다. "루트"인증서로 서명 된 새로운 "클라이언트"인증서를 만들고 싶습니까? 나는 당신이 이것을하기 위해 CryptSignAndEncodeCertificate를 사용할 필요가 있다고 생각한다.

+0

예 .. 루트 인증서로 서명해야합니다. certcreateselfsigncertificate() 설명을 보면 내 루트 인증서로 서명하는 데 사용할 수 있습니다. 그러나 아직도 혼란 스럽습니다. 인증서 체인과 다른 루트 인증서로 서명합니다. 루트 인증서로 인증서에 서명하면 내 인증서에 다음과 같은 경로가 표시됩니다. 루트 인증서 __ | | ----- 내 인증서 .. 고마워요 Asif –

+0

또한 루트 인증서를 가지고있는 CryptSignAndEncodeCertificate 사용 방법에 대한 정보를 제게 알려주세요. 나는 창에 웹에 많은 도움을 찾을 수없는 내가 인증서를 생성 한 다음 내 루트 인증서로 서명 및 저장소에 설치하는 방법 .. .. 덕분에 많은 아시프 –

+0

나는 방법을 잘 모르겠어요 CertCreateSelfSignCertificate는 정확하게 작동하지만 일반적으로 자체 서명 인증서를 만들면 자체 서명 된 인증서입니다.루트 인증서로 서명 할 수있는 유일한 자체 서명 인증서는 루트 인증서입니다. 나는 CryptSignAndEncodeCertificate가 어떻게 작동하는지 모르지만, 당신이하려고하는 것에 대한 합리적인 후보자처럼 들린다. 파일로 내보내는 코드는 다음과 같습니다. http://hi.baidu.com/mingyuejingque/blog/item/8982f1ee5d00b22f2df53498.html – Luke

1

처음 몇 년 전에 저는 여러분이 요청한 전체 코드를 포함하는 제품을 작성했습니다 : 새로운 인증서를 생성하고 다른 루트 인증서와 관련하여 서명하십시오. 이 코드는 Microsoft CryptoAPI 만 사용합니다. 그러나 귀하의 문제가 실제로 발생했는지 여부에 대한 세부적인 답변을 제공하거나 알고 싶은 코드를 게시하기 전에 귀하의 질문은 1 개월 반입니다.

일반적으로 원하는대로 수행하려면 CertCreateSelfSignCertificate() 기능을 사용하지 말고 다른 CryptoAPI와 관련하여 인증서를 만들어야합니다. CertCreateSelfSignCertificate() 함수는 자체 서명 된 인증서를 만들고 서명하는 데에만 사용할 수 있습니다. 생성 한 다른 인증서로 인증서에 서명 할 수 없습니다. 게다가 CertCreateSelfSignCertificate() 함수는 생성 된 개인 키의 길이에 대해 엄격한 제한을 가지고 있습니다. 따라서 CertCreateSelfSignCertificate() 함수가 수동으로 수행하는 것과 동일한 것을 만들어야합니다. API 체인의 마지막 API 인 CryptSignAndEncodeCertificate()은 다른 질문에 Luke에게 쓴 글입니다.

또한 큰 용의자가 있습니다. 인증서 체인을 만드는 목적이 올바른 방법이 아닙니다. 인증을 위해서만이 작업을 수행해야하는 경우 클라이언트 측에서 인증서를 만들 필요가 없습니다. 노래 한 메시지로도 충분할 것 같습니다. 키 쌍 대신에 하나의 인증서를 사용하는 것은 일부 용도 (예 : 코드 서명 및 데이터 암호화가 아닌 경우에만 사용)를 위해 키 해지 또는 키 제한과 같은 기능이 필요한 경우입니다.

인증 기반 인증을 구현해야하는 경우 클라이언트 컴퓨터의 인증서를 만들어 서버 컴퓨터로 보내고 서버 컴퓨터에서 클라이언트 인증서를 사용해야합니다. 서버 컴퓨터에서만 개인 인증서를 보유 할 수 있기 때문에 루트 인증서의 키.

인증서 등록 API과 관련하여 요구 사항을 구현할 수도 있습니다. 그것은 당신이 요구 한 것이 아니지만, 당신의 주요 문제를 해결할 수 있습니다.

: "양방향 인증"으로 실현하려는 개념이나 개념이 잘못되었거나 이해가되지 않습니다.

  1. 모든 클라이언트에서 서버로 전송 루트 클라이언트 인증서를 계획하는 방법 및시기를 이해하지 못합니다.
  2. 클라이언트 인증서를 클라이언트 루트 CA에 서명하려면 클라이언트의 루트 CA 인증서 (!!! ???)의 개인 키를 클라이언트에 보관해야합니다.
  3. 서버에 루트 CA 인증서와 같은 클라이언트에 대한 확인 된 정보가없는 경우 클라이언트의 인증을 위해 클라이언트 인증서를 실제로 사용할 수없는 것보다. 인증서가있는 클라이언트는 "허가"됩니다.
  4. 클라이언트 인증서가없는 표준 SSL을 사용하면 항상 동일한 클라이언트와 통신 할 수 있습니다. 따라서 클라이언트 루트 CA 전송 문제를 해결하지 않으면 표준 (클라이언트 인증서없이) SSL에서보다 많은 보안을 달성 할 수 없습니다.
  5. 서버와 클라이언트간에 표준 통신 프로토콜을 사용하지 않으려 고 시도한 것처럼 보입니다. 그 대신 새로운 프로토콜을 도입하려고합니다. 그것은 입니다. VERY 위험! 암호 전문가가 아닌 경우 만 안전한 것으로 보이는 프로토콜을 인식 할 수 있습니다. 개인 키 보유와 클라이언트에서 서버 또는 공개 키로의 공개 키 전송과 같은 "SMALL"문제는 매우 중요한 암호화 주제입니다. 거기에서 해결할 다른 암호화 프로토콜이 있습니다. 따라서이 분야에 새로운 것을 구현하려고하지 마십시오!
  6. 왜 클라이언트 인증서를 사용하고 싶은지 한 번 더 생각해보십시오. 실제로 클라이언트 인증을 구현하고 있습니까? 예를 들어, 표준 SSL에서는 모든 클라이언트가 동일한 클라이언트와 항상 통신하고 있으며 세션에 대해 생성 된 임의의 nonces 및 대칭 키만 사용할 수 있습니다. 클라이언트 당 또는 세션 당 인증서를 생성 하시겠습니까?

더 많은 질문을 쓸 수 있습니다. 당신이 자신의 인증서 기반의 통신 프로토콜을 구현한다면 나는 당신이 개념을 이해하기 전에 내 권고안을 내놓는데 큰 문제가있다.

+0

감사합니다. 이에 대한 통찰력을 주셔서 감사합니다. 우리는 무엇을 성취하려고 하는가 : 서버와 클라이언트간에 인증서 기반 인증을 설정해야합니다. SSL 설정시, 서버는 자신의 인증서 (개인 CA 또는 루트 인증서에 의해 서명 됨)를 보내야하며 클라이언트가 인증서를 보내길 기대해야합니다. 이제 서버와 클라이언트 모두 개인 인증서가 신뢰할 수있는 인증서로 설치됩니다. 내가해야 할 일은 서버와 클라이언트의 설치시에 새로운 인증서를 만들고 비공개 신뢰할 수있는 CA로 서명해야합니다. –

+0

비대칭 키 쌍을 사용하는 암호화로 양방향 인증을 시도합니다. 즉시 클라이언트 인증서를 만들고 서버에 보내고 서명 한 다음 SSL 핸드 셰이크에 사용하는 것이 좋습니다. 그러나 우리가 양방향 인증을 원한다면이 모델을 어떻게 가져야하는지 확신합니다. MS Crypto API를 사용하는 것에 대한 힌트를 줄 수 있다면 좋겠지 만, Windows에 대한 나의 싫어함과 함께 나는 이것을 창에서 수행해야한다. –

관련 문제