c - Programmatically verify a X509 certificate and private key match -


i created rsa key pair using evp_aes_256_cbc() cipher. private key pem encoded , has passphrase. requires passphrase entered user.

here's create private key call:

//save private key     bio_priv = bio_new_file(full_asymkeyfilepath.c_str(), "a+");     if (pem_write_bio_rsaprivatekey(         bio_priv,   //bio handle         rsa,        //key handle         evp_aes_256_cbc(),      //cipher encoding format         pwd,        //password         pwd_len,            //password length         null,       //callback         null        //not sure         ) != 1) {             //report err     }  

then generated certificate , signed private key.

//sign certificate generated key     if (!x509_sign(cert, evpkey, evp_sha1())){         //report err     } 

later on, want verify certificate matches rsa key pair. when ssl_ctx_check_private_key(), i'm prompted input passphrase console.

is there way automatically input password don't prompted console?

//load server certificate, must called before ever calling use private key     if (ssl_ctx_use_certificate_file(context, full_certfilepath.c_str(), ssl_filetype_pem) == 0){   //load certs pem file ssl_ctx          //err     }      //load private key corresponding certificate     if (ssl_ctx_use_privatekey_file(context, full_asymkeyfilepath.c_str(), ssl_filetype_pem) == 0){ //load certs pem file ssl_ctx          //file type not pem or private key loaded before calling function. private key not match public key in certificate         //err     }      //verify certificate , private key match     if (!ssl_ctx_check_private_key(context)){  //<====== prompts me enter pass :(         //err     } 

programmatically verify x509 certificate , private key match. private key has pem passphrase

there 2 answers here. 1 certificate, , second private key. private key shown first because used validate certificate (so makes sense visit first).

also, important call *_check_key routines because openssl checks key encoded; , not check valid. see, example, private key generated openssl not satisfy n = p * q.


in openssl, use following verify the private key encoded:

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 null, there problem , err holds reason code. otherwise, have encoded private key (but not valid).

if key encoded, can check type of private key , validate 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 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, use following verify the certificate encoded:

file* file = fopen(...); x509* x509 = pem_read_x509(file, null, null, null); unsigned long err = err_get_error(); 

if x509 null, there problem , err holds reason code. otherwise, have encoded certificate (but not valid).

you can verify certificate with:

/* see above on validating private key */ evp_pkey* pkey = readprivatekey(...);  int rc = x509_verify(x509, pkey); err = err_get_error(); 

if rc != 1, there problem , err holds reason code. otherwise, have valid certificate , private key pair. if certificate valid, can't use err because err valid if there's problem.

if certificate signed issuer (for example, ca or intermediate), need use x509_store verify issuer's signature on certificate (a lot of error checking 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);  /* other object/functions owns 'lookup', i'm not sure (perhaps store) */ x509_lookup* lookup = x509_store_add_lookup(store, x509_lookup_file()); /* err = err_get_error(); // not set error codes. */ assert(lookup);      /* cannot load memory. no api!!! */ rc = x509_lookup_load_file(lookup, issuercertfilename, x509_filetype_pem); /* err = err_get_error(); // 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 @ https://www.openssl.org/docs/crypto/x509_store_ctx_get_error.html */ rc = x509_verify_cert(ctx); err = x509_store_ctx_get_error(ctx);  /* cleanup, return success/failure */ 

is there way automatically input password don't prompted console?

yes. use password callback in pem_read_privatekey. passwordcallback can provide password in buffer, or can prompt user , return password in buffer.

my password callback involved. performs single hash of raw password before passing on library. ensures "plain text" password not used (but not slow down customary attacks). yours can prompt user string, or can return hard coded string.

my password callback uses label. label allows me derive different keys depending on usage (even though same 'base' secret used). specifying different usage or label, different derivation of key bits. label provided through arg below, , can set ssl_ctx_set_default_passwd_cb_userdata.

using evp_md_ctx_ptr = std::unique_ptr<evp_md_ctx, decltype(&::evp_md_ctx_destroy)>;  int passwordcallback(char *buffer, int size, int rwflag, void *arg) {     unused(rwflag);      int rc;     unsigned long err;     ostringstream oss;      const char* label = (char*) arg;     size_t lsize = (label ? strlen(label) : 0);      securevector sv = config.getmasterkey();     assert(!sv.empty());     if (sv.empty())     {         ...         throw runtime_error(oss.str().c_str());     }      evp_md_ctx_ptr ctx(evp_md_ctx_create(), ::evp_md_ctx_destroy);     assert(ctx.get() != null);      const evp_md* hash = evp_sha512();     assert(hash != null);      rc = evp_digestinit_ex(ctx.get(), hash, null);     err = err_get_error();      assert(rc == 1);     if (rc != 1)     {         ...         throw runtime_error(oss.str().c_str());     }      rc = evp_digestupdate(ctx.get(), sv.data(), sv.size());     err = err_get_error();      assert(rc == 1);     if (rc != 1)     {         ...         throw runtime_error(oss.str().c_str());     }      if (label && lsize)     {         rc = evp_digestupdate(ctx.get(), label, lsize);         err = err_get_error();          assert(rc == 1);         if (rc != 1)         {             ...             throw runtime_error(oss.str().c_str());         }     }      int n = std::min(size, evp_md_size(hash));     if (n <= 0)         return 0;      rc = evp_digestfinal_ex(ctx.get(), (unsigned char*) buffer, (unsigned int*) &n);     err = err_get_error();      assert(rc == 1);     if (rc != 1)     {         ...         throw runtime_error(oss.str().c_str());     }      return n; } 

Comments

Popular posts from this blog

shopping cart - Page redirect not working PHP -

php - How to modify a menu to show sub-menus -

python - Installing PyDev in eclipse is failed -