2014-03-14 1 views
1

문제가 있습니다. 인증서 및 개인 키 파일을 업로드하는 데 익숙합니다. 이제 확장명이 엉망인 파일이 있다고 가정합니다. (고의로 또는 무의식적으로) 시스템을 해독하라는 말을합니다. 확인이 가능한 곳에서 유효성 검사를 수행하고 주어진 파일이 유효한 인증서 파일인지 또는 해당 파일이 유효한 인증서 파일인지 개인 키 파일 또는 다른 파일 ..파일이 인증서 또는 키인지 확인하십시오.

내가 무엇을 했는가 : 파일 내용에 -- BEGIN CERTIFICATE --, -- BEGIN RSA PRIVATE KEY --을 확인하는 중 ... 제게 무엇이 좋은지 말해 주시거나,이 문제에 대한 다른 좋은 해결책이 있습니다. ..

감사

답변

2

확인하고, 지정된 파일이 유효한 인증서 파일 또는 개인 키 FIL 것을 말해 줄 수 e

OpenSSL은 C 라이브러리이므로 C로 대답하겠습니다. 다른 사람들은 이것을 pyOpenSSL으로 번역 할 수 있습니다.이 경우 아마 내 것보다 더 나은 답을 얻을 수 있습니다.

두 가지 답변이 있습니다. 하나는 인증서 용이고 두 번째는 개인 키용입니다. 비공개 키는 인증서의 유효성을 검사하는 데 사용되므로 먼저 표시됩니다 (먼저 방문하는 것이 좋습니다).

또한 OpenSSL은 키가 잘 인코딩되었는지 확인하기 때문에 *_check_key 루틴을 호출해야합니다. 실제로 유효한지 확인하지 않습니다. 예를 들어, Private key generated by openssl does not satisfy n = p * q을 참조하십시오.


는 OpenSSL을, 당신은하여 개인 키를 확인하려면 다음을 사용합니다 : NULL입니다

FILE* file = fopen(...); 
EVP_PKEY* pkey = PEM_read_PrivateKey(file, NULL, PasswordCallback, NULL); 
unsigned long err = ERR_get_error(); 

if(pkey) 
    EVP_PKEY_free(pkey); 

pkey 경우,이 문제이고 err이 이유 코드를 보유하고 있습니다. 그렇지 않으면 올바르게 인코딩 된 개인 키가 있습니다 (그러나 반드시 유효하지는 않음).

PasswordCallback은 단순히 버퍼에 암호를 제공하거나 사용자에게 프롬프트하고 버퍼에 암호를 반환 할 수 있습니다. PasswordCallback에 대한 자세한 내용은 Loading a PEM format certificate을 참조하십시오.

키가 올바르게 인코딩 된 경우 개인 키 유형을 확인하고 다음을 사용하여 유효성을 검사 할 수 있습니다.

int type = EVP_PKEY_get_type(pkey); 
switch (type) 
{ 
case EVP_PKEY_RSA: 
case EVP_PKEY_RSA2: 
    RSA* rsa = EVP_PKEY_get1_RSA(pkey); 
    rc = RSA_check_key(rsa); 
    ASSERT(rc); 
    RSA_free(rsa); 

    break; 

case EVP_PKEY_DSA: 
case EVP_PKEY_DSA1: 
case EVP_PKEY_DSA2: 
case EVP_PKEY_DSA3: 
case EVP_PKEY_DSA4: 
    DSA* dsa = EVP_PKEY_get1_DSA(pkey); 
    rc = DSA_check_key(dsa); 
    ASSERT(rc); 
    DSA_free(dsa); 

    break; 

case EVP_PKEY_DH: 
    DH* dh = EVP_PKEY_get1_DH(pkey); 
    rc = DH_check_key(dh); 
    ASSERT(rc); 
    DH_free(dh); 

    break; 

case EVP_PKEY_EC: 
    EC_KEY* ec = EVP_PKEY_get1_EC_KEY(pkey); 
    rc = EC_KEY_check_key(ec); 
    ASSERT(rc); 
    EC_KEY_free(ec); 

    break; 

default: 
    ASSERT(0); 
} 

EVP_PKEY_get_type은 OpenSSL의 일부가 아닙니다. x509NULL입니다

FILE* file = fopen(...); 
X509* x509 = PEM_read_X509(file, NULL, NULL, NULL); 
unsigned long err = ERR_get_error(); 

경우이 문제가 있었고 err이 원하는 분야

int EVP_PKEY_get_type(EVP_PKEY *pkey) 
{ 
    ASSERT(pkey); 
    if (!pkey) 
     return NID_undef; 

    return EVP_PKEY_type(pkey->type); 
} 

OpenSSL을, 당신이 (가) 인증서를 확인하려면 다음을 사용합니다 : 여기에 내가 그것을 구현 방법 이유 코드. 그렇지 않으면 올바르게 인코딩 된 인증서가 있습니다 (그러나 반드시 유효하지는 않음).

/* See above on validating the private key */ 
EVP_PKEY* pkey = ReadPrivateKey(...); 

int rc = X509_verify(x509, pkey); 
err = ERR_get_error(); 

rc != 1 경우, 문제가 있었고 err이 이유 코드를 보유 :

당신은 다음과 인증서를 확인할 수 있습니다. 그렇지 않으면 유효한 인증서와 개인 키 쌍이 있습니다. 인증서가 유효하면 err을 사용할 수 없습니다. err은 문제가있는 경우에만 유효하기 때문입니다. 인증서가 (예를 들어, CA 또는 중간)이, 당신은 당신의 인증서 발급자의 서명을 확인하기 위해 X509_STORE를 사용할 필요가 발행자에 의해 서명 된 경우

(오류를 많이 생략 검사) :

const char* serverCertFilename = ...; 
const char* issuerCertFilename = ...;  

X509_STORE* store = X509_STORE_new(); 
ASSERT(store); 

static const long flags = X509_V_FLAG_X509_STRICT | X509_V_FLAG_CHECK_SS_SIGNATURE 
     | X509_V_FLAG_POLICY_CHECK; 
rc = X509_STORE_set_flags(store, flags); 
err = ERR_get_error(); 
ASSERT(rc); 

/* Some other object/functions owns 'lookup', but I'm not sure which (perhaps the store) */ 
X509_LOOKUP* lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 
/* err = ERR_get_error(); // Does not set error codes. */ 
ASSERT(lookup);  

/* Cannot load this from memory. No API!!! */ 
rc = X509_LOOKUP_load_file(lookup, issuerCertFilename, X509_FILETYPE_PEM); 
/* err = ERR_get_error(); // Does not set error codes. */ 
ASSERT(rc); 

X509_STORE_CTX* ctx = X509_STORE_CTX_new(); 
ASSERT(ctx); 

X509* serverCert = ReadCertifcate(serverCertFilename); 
ASSERT(serverCert); 

rc = X509_STORE_CTX_init(ctx, store, serverCert, NULL); 
ret = err = ERR_get_error(); 
ASSERT(rc); 

/* Error codes at https://www.openssl.org/docs/crypto/X509_STORE_CTX_get_error.html */ 
rc = X509_verify_cert(ctx); 
err = X509_STORE_CTX_get_error(ctx); 

/* Do cleanup, return success/failure */