I am not sure if my question / explanation was too long since I got no answer. The short question now is:
When using the
SSL_CTX_use_PrivateKey_file
function; why do I get
139923876902592:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539:
139923876902592:error:0906A065:PEM routines:PEM_do_header:bad decrypt:pem_lib.c:483:
139923876902592:error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib:ssl_rsa.c:669:
ERROR: Failed to set private key file /home/jocke/ca/intermediate/private/xxx.key.pem. ERROR:
when I give wrong password, and
39814590265024:error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch:x509_cmp.c:330:
ERROR: Failed to set private key file /home/jocke/ca/intermediate/private/xxx.key.pem. ERROR:
when I give the right password?
OLD POST:
Sorry for the layout here, but the tool said something was code but not formatted as code, but I had no idea what it was so I will "code" everything.
Ok jww, I thought I did that. Let me show exactly what I am doing and explain why I think I am right (even though I am obviously not):
1) Generate root CA key / certificate
Directory setup
mkdir ~/ca/
cd ~/ca
mkdir certs crl newcerts private
chmod 700 private
The index.txt file is where the OpenSSL ca tool stores the certificate database. Do not delete or edit this file by hand. It should now contain a line that refers to the intermediate certificate.
touch index.txt
echo 1000 > serial
Create ~/ca/openssl.cnf like "Root CA configuration file" below, and make sure dir value is correct
openssl genrsa -aes256 -out private/ca.key.pem 4096
chmod 400 private/ca.key.pem
WARNING: Whenever you use the req tool, you must specify a configuration file to use with the -config option, otherwise OpenSSL will default to /etc/pki/tls/openssl.cnf.
NOTE: Long expiry time, use 20 years (7300 days)
openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem
Verify certificate:
openssl x509 -noout -text -in certs/ca.cert.pem
ROOT CA PRIVATE KEY: ~/ca/private/ca.key.pem
ROOT CA CERTIFICATE: ~/ca/certs/ca.cert.pem
2) Generate intermediate CA key / certificate
Directory setup
mkdir ~/ca/indermediate
cd ~/ca/indermediate
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > ~/ca/intermediate/crlnumber
Create ~/ca/intermediate/openssl.cnf like "Intermediate CA configuration file" below and make sure dir value is correct
cd ~/ca
Create intermediate CA private key:
openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096
chmod 400 intermediate/private/intermediate.key.pem
Create certificate signing request (CSR): (MAKE SURE TO SPECIFY THE INTERMEDIATE CA CONF FILE!)
cd ~/ca
openssl req -config intermediate/openssl.cnf -new -sha256 -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem
Create intermediate CA certificate by using the root certificate and the CSR: (MAKE SURE TO SPECIFY THE ROOT CA CONF FILE!!!)
NOTE: Shorter expiry time, use 10 years (3650 days)
openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem
chmod 444 intermediate/certs/intermediate.cert.pem
Verify intermediate certificate:
openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem
INTERMEDIATE CA PRIVATE KEY: ~/ca/intermediate/private/intermediate.key.pem
INTERMEDIATE CA CERTIFICATE: ~/ca/intermediate/certs/intermediate.cert.pem
3) Create certificate chain file
When an application (eg, a web browser) tries to verify a certificate signed by the intermediate CA, it must also verify the intermediate certificate against the root certificate.
To complete the chain of trust, create a CA certificate chain to present to the application.
To create the CA certificate chain, concatenate the intermediate and root certificates together.
We will use this file later to verify certificates signed by the intermediate CA.
cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
chmod 444 intermediate/certs/ca-chain.cert.pem
CERTIFICATE CHAIN FILE: ~/ca/intermediate/certs/ca-chain.cert.pem
4) Sign server and client certificates
Sign certificates using the intermediate CA.
Create a key:
cd ~/ca/
openssl genrsa -aes256 -out intermediate/private/myinternetaddr.key.pem 2048
chmod 400 intermediate/private/myinternetaddr.key.pem
Create a certificate signing request (CSR):
openssl req -config intermediate/openssl.cnf -key intermediate/private/myinternetaddr.key.pem -keyform PEM -new -sha256 -out intermediate/csr/myinternetaddr.csr.pem
Create server certificate:
openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/myinternetaddr.csr.pem -out intermediate/certs/myinternetaddr.cert.pem
chmod 444 intermediate/certs/myinternetaddr.cert.pem
cat index.txt
FOR THE WEBMASTERS: The following line is considered as "code" - why? The similar lines above are not.
CLIENT PRIVATE KEY: ~/ca/intermediate/private/myinternetaddr.key.pem
CLIENT CERTIFICATE SIGNING REQUEST: ~/ca/intermediate/csr/myinternetaddr.csr.pem
CLIENT CERTIFICATE: ~/ca/intermediate/certs/myinternetaddr.cert.pem
Verify the certificate:
openssl x509 -noout -text -in intermediate/certs/myinternetaddr.cert.pem
Use the CA certificate chain file we created earlier (ca-chain.cert.pem) to verify that the new certificate has a valid chain of trust.
$ openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/myinternetaddr.cert.pem
intermediate/certs/myinternetaddr.cert.pem: OK
After this I then run the program, as below. As you can see I am using the certificate chain file (that is verified to have the server certificate - see bottom) with the corresponding private key file to the server certificate.
SSL_library_init();
SSL_METHOD const * method = SSLv3_server_method();
if (!method)
{
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
SSL_CTX * ctx = SSL_CTX_new(method);
if (!ctx)
{
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
if (!SSL_CTX_use_certificate_chain_file(ctx, "~/ca/intermediate/certs/ca-chain.cert.pem"))
{
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) private_key_file_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
if (SSL_CTX_use_PrivateKey_file(ctx, "~/ca/intermediate/private/myinternetaddr.key.pem", SSL_FILETYPE_PEM) != 1)
{
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
The password callback:
static int pem_passwd_cb(char * buf, int size, int rwflag, void * userdata)
{
char const * const password = (char const * const) userdata;
Logger & logger = Logger::get_instance();
logger << "Setting password to [" << password << "]";
logger.log_info();
strncpy(buf, (char *) password, size);
buf[size - 1] = '\0';
fprintf(stdout, "BUFLEN: %d\nBUF: [%s]\n", (int) strlen(buf), buf);
return strlen(buf);
}
Now, when having done the following I thought everything should be ok.
$ openssl req -config intermediate/openssl.cnf -key intermediate/private/myinternetaddr.key.pem -new -sha256 -out intermediate/csr/myinternetaddr.csr.pem
Enter pass phrase for intermediate/private/myinternetaddr.key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:SE
State or Province Name [England]:Sweden
Locality Name []:NA
Organization Name [Alice Ltd]:NA
Organizational Unit Name []:NA
Common Name []:Jocke
Email Address []:yyy@hotmail.com
$ openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/myinternetaddr.csr.pem -out intermediate/certs/myinternetaddr.cert.pem
Using configuration from intermediate/openssl.cnf
Enter pass phrase for ~/ca/intermediate/private/intermediate.key.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 4098 (0x1002)
Validity
Not Before: Aug 13 20:58:46 2016 GMT
Not After : Aug 23 20:58:46 2017 GMT
Subject:
countryName = SE
stateOrProvinceName = Sweden
localityName = NA
organizationName = NA
organizationalUnitName = NA
commonName = Jocke
emailAddress = yyy@hotmail.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
D5:D6:F4:38:24:18:41:F7:F0:29:9F:99:6C:D3:08:38:CE:35:B8:43
X509v3 Authority Key Identifier:
keyid:2C:EB:99:69:BE:00:EE:C2:FD:86:B7:CF:6C:AD:47:4E:65:AA:90:5A
DirName:/C=SE/ST=Sweden/L=/O=Joachim Person/CN=Joachim Person/emailAddress=xxx@gmail.com
serial:10:00
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Certificate is to be certified until Aug 23 20:58:46 2017 GMT (375 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
But apparently it is not - why?