Make sure the file is a certificate or key.

I have a problem, I allow using certificate and private keys for uploading files. Now suppose I have a file whose extension is confused (changed knowingly or unknowingly) is said to break the system. I need to put validation in place, which can check and can tell me that this file is a valid certificate file or private key file or some other file.

What I was in: check -- BEGIN CERTIFICATE -- , -- BEGIN RSA PRIVATE KEY -- in the contents of the file .. Please tell me what I am, good, or is there another better solution to this problem.

thanks

+1
source share
1 answer

check and tell me that this file is a valid certificate file or private key file

I am going to answer this in C because OpenSSL is the C library. Others can translate it into pyOpenSSL , in which case they will probably have a better answer than mine.

There are two answers here. One for the certificate, the second for the private key. The private key is displayed first because it is used to verify the certificate (therefore, it makes sense to visit it first).

In addition, it is important to call the *_check_key , because OpenSSL only verifies that the key is well encoded; and he does not check whether he is valid. See For example, The private key generated by openssl does not satisfy n = p * q .


In OpenSSL, you must use the following to verify the private key:

 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); 

If pkey is NULL , then a problem has occurred, and err contains the reason code. Otherwise, you have a correctly encoded private key (but not necessarily a valid one).

PasswordCallback can simply provide a password in the buffer or request a user and return the password to the buffer. For more information about PasswordCallback see Downloading a PEM Certificate .

If the key is correctly encoded, you can check the type of private key and check it with the following.

 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 not part of OpenSSL. Here's how I implemented it:

 int EVP_PKEY_get_type(EVP_PKEY *pkey) { ASSERT(pkey); if (!pkey) return NID_undef; return EVP_PKEY_type(pkey->type); } 

In OpenSSL, the following is required to verify a certificate:

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

If x509 is NULL , then a problem has occurred, and err contains the reason code. Otherwise, you have a correctly encoded certificate (but not necessarily valid).

Then you can check the certificate:

 /* See above on validating the private key */ EVP_PKEY* pkey = ReadPrivateKey(...); int rc = X509_verify(x509, pkey); err = ERR_get_error(); 

If rc != 1 , then a problem has occurred, and err contains the reason code. Otherwise, you have a valid pair of certificates and private keys. If the certificate is valid, you cannot use err because err is only valid if a problem occurs.

If your certificate is signed by the issuer (for example, CA or intermediate), you need to use X509_STORE to verify the issuer's signature in your certificate (many verification errors are omitted):

 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 */ 
+2
source

All Articles