Qt QSslSocket "The certificate is self-signed, and untrusted" - c++

i want to connect server with QSslSocket and on server i get soketSslError "The certificate is self-signed, and untrusted" , but i dont understand why i have this error.
On first step was generated file for server and client with openssl
$openssl req -new -newkey rsa:1024 -keyout ca.key -x509 -days 500 -out ca.crt
$openssl req -new -newkey rsa:1024 -keyout client01.key -out client01.csr
$openssl ca -config ca.config -in client01.csr -out client01.crt -batch
in c++ server / client
On server:
start server
if (listen(QHostAddress::Any,this->connectingPort)) {
std::cout<<"Server start on port: "<<this->connectingPort<<std::endl;
return true;
} else {
std::cout<<"Cant start server. "<<errorString().toStdString().c_str()<<std::endl;
return false;
}
incomingConnection
QFile keyFile("ca.key");
if (!keyFile.open(QIODevice::ReadOnly)) {
delete this->sslSocket;
qDebug()<<"Cant open file: "<<keyFile.fileName();
return false;
}
QByteArray pasp ="qwerty";
QSslKey key(keyFile.readAll(),QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,pasp);
if (key.isNull()) {
delete this->sslSocket;
qDebug()<<"key in file "<<keyFile.fileName()<<" is empty";
return false;
}
keyFile.close();
this->sslSocket->setPrivateKey(key);
this->sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
this->sslSocket->setLocalCertificate("ca.crt");
this->sslSocket->startServerEncryption();
on client side:
this->sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
QFile keyFile("client01.key");
if (!keyFile.open(QIODevice::ReadOnly)) {
delete this->sslSocket;
qDebug()<<"Cant open file: "<<keyFile.fileName();
return ;
}
QByteArray pasp ="qwerty";
QSslKey key(keyFile.readAll(),QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,pasp);
if (key.isNull()) {
delete this->sslSocket;
qDebug()<<"key in file "<<keyFile.fileName()<<" is empty";
return ;
}
keyFile.close();
this->sslSocket->setPrivateKey(key);
this->sslSocket->setLocalCertificate("client01.crt");
this->sslSocket->connectToHostEncrypted("192.168.0.10",1258);
if (!this->sslSocket->waitForEncrypted()) {
qDebug()<<"error: "<<sslSocket->errorString();
}
and when i connecting from client i get on server error
soket ssl error
"The certificate is self-signed, and untrusted"
"The certificate is self-signed, and untrusted"
socketError: QAbstractSocket::SocketError( 13 )
any idea what i do wrong?
UPDATE:
Qt Creator 3.0.1
Based on Qt 5.2.1 (GCC 4.8.2, 64 bit)

I suggest you try this on the server:
QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("your-certificate.pem"));
QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
QList<QSslError> expectedSslErrors;
expectedSslErrors.append(error);
this->sslSocket.ignoreSslErrors(expectedSslErrors);

probleb has been resolved
what i doen:
update version Qt for 5.5
and generated new ssl certificate:
openssl req -x509 -newkey rsa:1024 -keyout key.key -out key.pem -days 365 -nodes
in server:
sslServer.setSslLocalCertificate("key.pem");
sslServer.setSslPrivateKey("key.key");
sslServer.setSslProtocol(QSsl::TlsV1_2);
in client:
sslSocket.addCaCertificates("key.pem");

Related

OpenSSL encrypt list of files?

Is it possible to encrypt a list of files with OpenSSL command in Linux I tried the code below to run a the command on multiple files
(I'm using the command instead of coding because I'm not experienced and I could screw up the encryption)
ifstream Data("/home/kali/Desktop/filelist.txt"); // txt file contains files to encrypt
string cmd = "openssl aes-256-cbc -in ";
string files; // files scraped from filelist.txt will be stored here
string outarg = " -out ";
string outfile = "/home/kali/Desktop/Testdir/test.enc"; // encrypted files will all be named test.enc (openssl will rename by defualt)
string key = " -pass pass:testkey";
int main()
{
while (getline(Data, files)) // To get list of files to encrypt
{
cmd += files += outarg += outfile += key += "\n"; // Adding everything together using c_str()
}
printf(cmd.c_str()); // replaced with system()
}
Expected Output:
"openssl aes-256-cbc -in /home/kali/Desktop/Testdir/Passwords.txt -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey"
"openssl aes-256-cbc -in /home/kali/Desktop/Testdir/Images.zip -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey"
"openssl aes-256-cbc -in /home/kali/Desktop/Testdir/Documents.docx -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey"
Actual Output(1st is good but the other are messy):
openssl aes-256-cbc -in /home/kali/Desktop/Testdir/Passwords.txt -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey
/home/kali/Desktop/Testdir/src/Images.zip -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey
/home/kali/Desktop/Testdir/test.enc -pass pass:testkey
-pass pass:testkey
/home/kali/Desktop/Testdir/src/Documents.docx -out /home/kali/Desktop/Testdir/test.enc -pass pass:testkey
/home/kali/Desktop/Testdir/test.enc -pass pass:testkey
-pass pass:testkey

how to use http2 in loopback 4 application?

We are planning to implement http2 in a loopback 4 application. We had used http, socket servers but never http2.
What is the procedure to use http2 in my application?
Here's what you have to do in your existing app:
Step 1: Install spdy
npm i spdy
Step 2: Configure index.ts
Change your main function in src/index.ts with this:
import spdy from "spdy";
export async function main(options: ApplicationConfig = {}) {
// specify cert and key file paths for SSL
const serverOptions: spdy.ServerOptions = {
key: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-privkey.pem'),
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-cert.pem'),
),
};
// setting listenOnStart to false will not start the default httpServer
options.rest.listenOnStart = false;
// Replace YourApplication with your class
const app = new YourApplication(options);
await app.boot();
await app.start();
// create server
const server = spdy.createServer(serverOptions, app.requestHandler);
// to avoid process exit on warnings
server.on('warning', console.warn);
server.listen(3000, () => {
console.log('Listening on https://localhost:3000/');
});
return app;
}
All we're doing in the above code is, preventing the default http server from being started and starting the server using spdy with loopback's request handler app.requestHandler that will be used for all incoming request.
Check out this pastebin containing entire index.ts file content after the changes.
To generate certificate and keys for localhost use:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout localhost-privkey.pem -out localhost-cert.pem
You may need to allow self-signed certificates in Chrome as well for /explorer to work as expected.
And that's it, you can now run your app, and enjoy the power of http2 :)
Blog Post: https://shubham-web.medium.com/how-to-use-http2-in-loopback-4-applications-5e83881c7b38

Signing certificate by self signed CA

I have created selfsigned CA certificate on Ubuntu that runs on AWS . I have also created client and server certificates signed by current CA.
SSL connection is used by Mosquitto MQTT service. Unfortunatly I have Received fatal alert: unknown_ca error from client side when it tries to connect to server.
I was tested the same certificate generation procedure on my Raspberry Pi and SSL+MQTT works well.
Creating certificates:
# CA
openssl req -new -newkey rsa:2048 -keyout private/cakey.pem -out careq.pem -config ./openssl.cnf
openssl ca -create_serial -out cacert.pem -days 365 -keyfile private/cakey.pem -selfsign -config ./openssl.cnf -infiles careq.pem
# Server
openssl req -new -out server.csr -config openssl.cnf -newkey rsa:2048 -nodes -keyout server.key
openssl ca -config openssl.cnf -in server.csr -out server.crt
# Client
openssl req -new -out client.csr -config openssl.cnf -newkey rsa:2048 -nodes -keyout client.key
openssl ca -config openssl.cnf -in client.csr -out client.crt
openssl.cnf content:
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = . # Where everything is kept
certs = $dir/certsdb # Where the issued certs are kept
new_certs_dir = $certs # default place for new certs.
database = $dir/index.txt # database index file.
certificate = $dir/cacert.pem # The CA certificate
private_key = $dir/private/cakey.pem# The private key
serial = $dir/serial # The current serial number
RANDFILE = $dir/private/.rand # private random number file
crldir = $dir/crl
crlnumber = $dir/crlnumber # the current crl number
crl = $crldir/crl.pem # The current CRL
x509_extensions = usr_cert # The extentions to add to the cert
copy_extensions = copy
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha1 # which md to use.
preserve = no # keep passed DN ordering
policy = policy_match
[ policy_match ]
countryName = match # Must be the same as the CA
stateOrProvinceName = match # Must be the same as the CA
organizationName = match # Must be the same as the CA
organizationalUnitName = optional # not required
commonName = supplied # must be there, whatever it is
emailAddress = optional # not required
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
prompt = yes
default_bits = 2048
#default_keyfile = privkey.pem
distinguished_name = req_distinguished_name # where to get DN for reqs
attributes = req_attributes # req attributes
x509_extensions = v3_ca # The extentions to add to self signed certs
req_extensions = v3_req # The extensions to add to req's
string_mask = nombstr
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = California
localityName = Locality Name (eg, city)
localityName_default = Hawthorne
0.organizationName = Organization Name (eg, company)
0.organizationName_default = PhilNet
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = UN
commonName = Common Name (eg, YOUR name)
commonName_default = CN
commonName_max = 64
emailAddress_default = aaa#bbb.cc
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
[ usr_cert ]
basicConstraints=CA:false
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
#subjectAltName=email:move
subjectAltName = #alt_names
[alt_names]
IP.1 = 34.245.0.160
DNS.1 = ec2-34-245-0-160.eu-west-1.compute.amazonaws.com
[ usr_cert_has_san ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[ v3_req ]
subjectAltName=email:move
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
[ v3_ca_has_san ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
My Java web client uses paho library for MQTT communication:
public class TestMQTT4 {
public static void main(String[] args) {
System.out.println("Starting");
String serverUrl ="ssl://ec2-34-245-0-160.eu-west-1.compute.amazonaws.com:8887";
String path= "C:\\projects\\certs\\U\\CA6\\";
String caFilePath =path+"cacert.pem";
String clientCrtFilePath = path+ "client.crt";
String clientKeyFilePath = path+ "client.key";
String mqttUserName = "b";
String mqttPassword = "b";
MqttClient client;
try {
client = new MqttClient(serverUrl, "2");
MqttConnectOptions options = new MqttConnectOptions();
options.setUserName(mqttUserName);
options.setPassword(mqttPassword.toCharArray());
options.setConnectionTimeout(60);
options.setKeepAliveInterval(60);
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
SSLSocketFactory socketFactory = getSocketFactory(caFilePath,clientCrtFilePath, clientKeyFilePath, "aaabbb");
//SSLSocketFactory socketFactory = getSocketFactory3(caFilePath);
options.setSocketFactory(socketFactory);
System.out.println("starting connect the server...");
client.connect(options);
System.out.println("connected!");
Thread.sleep(1000);
client.subscribe("aaa",0);
client.disconnect();
System.out.println("disconnected!");
} catch (MqttException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static SSLSocketFactory getSocketFactory(final String caCrtFile,
final String crtFile, final String keyFile, final String password)
throws Exception {
Security.addProvider(new BouncyCastleProvider());
// load CA certificate
X509Certificate caCert = null;
FileInputStream fis = new FileInputStream(caCrtFile);
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
caCert = (X509Certificate) cf.generateCertificate(bis);
}
//System.out.println("load CA certificate certificate done :"+caCert);
// load client certificate
bis = new BufferedInputStream(new FileInputStream(crtFile));
X509Certificate cert = null;
while (bis.available() > 0) {
cert = (X509Certificate) cf.generateCertificate(bis);
}
//System.out.println("load client certificate done :"+cert);
// load client private key
PEMParser pemParser = new PEMParser(new FileReader(keyFile));
Object object = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
PrivateKey pk=null;
if (object instanceof PEMEncryptedKeyPair) {
KeyPair key;
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
System.out.println("Encrypted key - we will use provided password");
key = converter.getKeyPair(((PEMEncryptedKeyPair) object)
.decryptKeyPair(decProv));
pk = key.getPrivate();
} else
if (object instanceof PrivateKeyInfo)
{
System.out.println("got PrivateKeyInfo ");
pk = converter.getPrivateKey((PrivateKeyInfo) object);
System.out.println("algorithm "+pk.getAlgorithm() +" format " + pk.getFormat());
}else
if (object instanceof PEMKeyPair)
{
KeyPair key;
System.out.println("Unencrypted key - no password needed "+object.getClass().getName());
key = converter.getKeyPair((PEMKeyPair) object);
pk = key.getPrivate();
}
pemParser.close();
// CA certificate is used to authenticate server
KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
caKs.load(null, null);
caKs.setCertificateEntry("ca-certificate", caCert);
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} };
// client key and certificates are sent to server so it can authenticate
// us
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("certificate", cert);
ks.setKeyEntry("private-key", pk, password.toCharArray(),
new java.security.cert.Certificate[] { cert });
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray());
// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(kmf.getKeyManagers(), trustAllCerts, null);
return context.getSocketFactory();
}
}
Log:
...
....
*** CertificateVerify
Signature Algorithm SHA256withRSA
update handshake state: certificate_verify[15]
upcoming handshake states: client change_cipher_spec[-1]
upcoming handshake states: client finished[20]
upcoming handshake states: server change_cipher_spec[-1]
upcoming handshake states: server finished[20]
MQTT Con: 2, WRITE: TLSv1.2 Handshake, length = 264
update handshake state: change_cipher_spec
upcoming handshake states: client finished[20]
upcoming handshake states: server change_cipher_spec[-1]
upcoming handshake states: server finished[20]
MQTT Con: 2, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 74, 211, 43, 244, 29, 37, 34, 169, 164, 170, 51, 82 }
***
update handshake state: finished[20]
upcoming handshake states: server change_cipher_spec[-1]
upcoming handshake states: server finished[20]
MQTT Con: 2, WRITE: TLSv1.2 Handshake, length = 40
MQTT Con: 2, READ: TLSv1.2 Alert, length = 2
MQTT Con: 2, RECV TLSv1.2 ALERT: fatal, unknown_ca
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
MQTT Con: 2, called closeSocket()
MQTT Con: 2, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
MQTT Con: 2, called close()
MQTT Con: 2, called closeInternal(true)
MqttException (0) - javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
UPD
I found difference in Signature Algorithm in log file in good connection (Raspberry Pi) and bad one (Ubuntu on AWS)
Failed (Ubuntu on AWS)
*** CertificateVerify
Signature Algorithm SHA256withRSA
Good (Raspberry Pi)
*** CertificateVerify
Signature Algorithm SHA512withRSA
Why I have different signature algorithm? In moth cases identical commands was used to create and sign certificates.
Might it be problem while communicating with Java?
UPD
I did some changes accoding to comments and now my certificates works fine.
Certificates generation proedure:
openssl req -new -newkey rsa:2048 -keyout private/cakey.pem -out careq.pem -config ./openssl.cnf -extensions v3_ca_509 -reqexts v3_ca_req -subj "/C=US/ST=California/L=Hawthorne/O=PhilNet/CN=CA/"
openssl ca -create_serial -out cacert.pem -days 365 -keyfile private/cakey.pem -selfsign -config ./openssl.cnf -extensions v3_ca_509 -infiles careq.pem
openssl req -new -newkey rsa:2048 -keyout server.key -out server.csr -config openssl.cnf -reqexts v3_server_req -nodes -subj "/C=US/ST=California/L=Hawthorne/O=PhilNet/CN=Server/"
openssl ca -config openssl.cnf -in server.csr -out server.crt
openssl req -new -newkey rsa:2048 -keyout client.key -out client.csr -config openssl.cnf -reqexts v3_server_req -nodes -subj "/C=US/ST=California/L=Hawthorne/O=PhilNet/CN=Client/"
openssl ca -config openssl.cnf -in client.csr -out client.crt
openssl.cnf file:
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = . # Where everything is kept
certs = $dir/certsdb # Where the issued certs are kept
new_certs_dir = $certs # default place for new certs.
database = $dir/index.txt # database index file.
certificate = $dir/cacert.pem # The CA certificate
private_key = $dir/private/cakey.pem# The private key
serial = $dir/serial # The current serial number
RANDFILE = $dir/private/.rand # private random number file
crldir = $dir/crl
crlnumber = $dir/crlnumber # the current crl number
crl = $crldir/crl.pem # The current CRL
#x509_extensions = usr_cert # The extentions to add to the cert
copy_extensions = copy
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha1 # which md to use.
preserve = no # keep passed DN ordering
policy = policy_anything
[ policy_anything ]
countryName = match
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
prompt = yes
default_bits = 2048
attributes = req_attributes
#x509_extensions = v3_ca # The extentions to add to self signed certs
#req_extensions = v3_req # The extensions to add to req's
string_mask = nombstr
[ req_attributes ]
[ v3_ca_509 ]
basicConstraints = CA:true
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
[ v3_ca_req ]
basicConstraints = CA:true
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, keyCertSign
[ v3_server_req ]
basicConstraints=CA:false
subjectKeyIdentifier=hash
subjectAltName = #alt_names_server
[alt_names_server]
IP.1 = 34.245.0.159
DNS.1 = ec2-34-245-0-159.eu-west-1.compute.amazonaws.com
[ v3_client_req ]
basicConstraints=CA:false
subjectKeyIdentifier=hash
subjectAltName = #alt_names_client
[alt_names_client]
IP.1 = 192.168.1.103
DNS.1 = GM

OpenSSL: server cannot verify client certificate

I am working with a legacy OpenSSL wrapper, which I intend to extend with client certificates. This wrapper contains both server and client parts, but the issue is related only to server handshake part. The problem I am facing is that the server cannot get the certificate from client.
Here are the commands which I used to generate a pair of certificates for client and server:
1) Generate Certificate Authority:
openssl req -out ca.pem -new -x509
2) Generate server certificate:
openssl genrsa -out server.key 1024
openssl req -key server.key -new -out server.req
echo "00" > file.srl
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.pem
3) Generate client certificate:
openssl genrsa -out client.key 1024
openssl req -key client.key -new -out client.req
openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.pem
All of the certificates are placed in one folder
When I am trying to connect to server implemented by Wrapper using s_client, I got the following output:
$ openssl s_client -connect localhost:40912 -CAfile ca.pem -cert client.pem -key client.key -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL_connect:SSLv3 read server hello A
depth=1 C = RO, ST = Rootville, L = Rootbirgem, O = CA Limited, OU = Issuer, CN = Autorida, emailAddress = ca#ca.mil
verify return:1
depth=0 C = SR, ST = Serverstan, L = Serversaintsburg, O = Servers advanced productions, OU = Acceptors factory, CN = Servstian, emailAddress = server#internet.org
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read server session ticket A
3073885884:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1262:SSL alert number 48
3073885884:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
Certificate chain
0 s:/C=SR/ST=Serverstan/L=Serversaintsburg/O=Servers advanced productions/OU=Acceptors factory/CN=Servstian/emailAddress=server#internet.org
i:/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca#ca.mil
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDMzCCAhsCAQIwDQYJKoZIhvcNAQELBQAwgYkxCzAJBgNVBAYTAlJPMRIwEAYD
VQQIDAlSb290dmlsbGUxEzARBgNVBAcMClJvb3RiaXJnZW0xEzARBgNVBAoMCkNB
IExpbWl0ZWQxDzANBgNVBAsMBklzc3VlcjERMA8GA1UEAwwIQXV0b3JpZGExGDAW
BgkqhkiG9w0BCQEWCWNhQGNhLm1pbDAeFw0xNTEwMjcxNTA3MjlaFw0xNTExMjYx
NTA3MjlaMIG4MQswCQYDVQQGEwJTUjETMBEGA1UECAwKU2VydmVyc3RhbjEZMBcG
A1UEBwwQU2VydmVyc2FpbnRzYnVyZzElMCMGA1UECgwcU2VydmVycyBhZHZhbmNl
ZCBwcm9kdWN0aW9uczEaMBgGA1UECwwRQWNjZXB0b3JzIGZhY3RvcnkxEjAQBgNV
BAMMCVNlcnZzdGlhbjEiMCAGCSqGSIb3DQEJARYTc2VydmVyQGludGVybmV0Lm9y
ZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy6j9ZHv/xCOqrRUXbWTE2Xht
PRPf/70Rytri4McCyjT6AO/GrDlAfD815yZPqTssRWy13sJGczoM4CPOffR7ufQR
4oMfugbX0W6kqlN7K1VpPlqtm8fb2jei5K0+tXOb7UHox13b69y0kVvArfhcUqmE
SGllcB++/Se2IIdcCOECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA5Eot8mv6QXvG
jd8oeX/JmJzzPSOn6kGMRsyR06OnF4tALHo5EdHaTF4EBgylVuAIp7dBRrdHzU4y
XnsY+X8lPlFEUFsSEuheJmISJgKZ8GtlbjHkV2cgXFSsFeiiI6Gjzlj2aOzYQQHD
DtpOL4InjHgeDTv7JxtMZXRaQqSvIejVXki0d+FOP42H3GyqleYABDtPl7o3gOmh
b8I7aZaOj/qxR8J//nGjXmodGHmL+RKK3vJ3thgD5UWREdE87qygJ2sZEUvXsnhG
CTulJEdWShGw27xuYw26wCt2yo0VXLcYsMgJLOjUAEdW3k+TowTi4XmZN4MaudAp
KFMlb2y7jg==
-----END CERTIFICATE-----
subject=/C=SR/ST=Serverstan/L=Serversaintsburg/O=Servers advanced productions/OU=Acceptors factory/CN=Servstian/emailAddress=server#internet.org
issuer=/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca#ca.mil
---
Acceptable client certificate CA names
/C=RO/ST=Rootville/L=Rootbirgem/O=CA Limited/OU=Issuer/CN=Autorida/emailAddress=ca#ca.mil
---
SSL handshake has read 1101 bytes and written 2149 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-GCM-SHA384
Session-ID:
Session-ID-ctx:
Master-Key: 4CA603347F386EB0A723BCF1F07040E0C47FAD52AE9CBCC5DCB3D329D69C8E3FB31E994DC24FBA9E8312A476A8F08905
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1445977139
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
At the same time on server part SSL_accept returns -1, SSL_get_error then returns SSL_ERROR_SSL and ERR_print_errors_fp gives me a message
3080665920:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:3279:
I don't have any experience with cryptography or OpenSSL, so all of these errors seems really confusing for me. OpenSSL's documentation doesn't make things clear at all.
As far as I can see from s_client log, the problems is with certificates themselves, although I don't understand what exactly goes wrong. At the same time, I can successfully use these certificates with s_server application, so this is reproducible only with my implementation of server. It seems that my implementation is incomplete in some way, but I don't see a way how I can resolve the situation from here, most of the documents I found on the web avoid client certificates topic at all, and all of the error messages are cryptic.
Here's a a simplified code of the server (with omitted error checking, logging, timeouts, etc):
ctx_ = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_use_certificate_file(ctx_, config.cert_file.c_str(), SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx_, config.private_key.c_str(), SSL_FILETYPE_PEM);
if( !SSL_CTX_check_private_key(ctx_) )
{ /* never happens */ }
ssl_ = SSL_new(ctx_);
STACK_OF(X509_NAME)* list;
list = SSL_load_client_CA_file(config.client_ca_file.c_str());
SSL_set_client_CA_list(ssl_, list);
SSL_set_verify(ssl_, SSL_VERIFY_PEER, 0);
int flags = fcntl(fd_, F_GETFL, 0);
flags |= O_NONBLOCK;
if( fcntl(fd_, F_SETFL, flags) < 0 )
SSL_set_fd(ssl_, fd_);
while( /* not timeout */ )
{
int res = SSL_accept(ssl_);
if( res > 0) {break;}
ec = WaitAfterError(res, /* timeout */);
if( !ec.isSucceeded() )
{
return; // Returns here
}
}
Wait after error have the following implementation:
ErrorCode OpenSslWrapper::WaitAfterError( int res, long* ptimeout )
{
ErrorCode ec;
int ret = SSL_get_error(ssl_, res);
switch( ret )
{
case SSL_ERROR_WANT_READ:
WaitForFd(fd_, Consts::k_WaitRead, ptimeout);
return ec;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
WaitForFd(fd_, Consts::k_WaitWrite, ptimeout);
return ec;
case SSL_ERROR_SYSCALL:
if( !errno ) {return ec;}
case SSL_ERROR_SSL:
// Got message here:
ERR_print_errors_fp(stderr);
ec = ErrorCode::Fail;
return ec;
default:
ec = ERR_reason_error_string(ret);
return ec;
}
}
WaitForFd is just a simple wrapper over select.
The documentation for SSL_CTX_set_client_CA_list() says:
The CAs listed do not become trusted (list only contains the names, not the complete certificates); use SSL_CTX_load_verify_locations to additionally load them for verification.

SSL_CTX_use_PrivateKey_file() failed

I'm writing a client application on Windows that establishes an SSL connection to a server, and the server requests client certificate for authentication. The server provides me a .pfx file, then I use openssl command line tool to get the certificate and the private key like this:
openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
openssl pkcs12 -in filename.pfx -nocerts -out key.pem
after that, I try to load the certificate and the private key with functions from openssl as below, but SSL_CTX_use_PrivateKey_file() always failed, the error message is "error:0906D06C:PEM routines:PEM_read_bio:no start line", I can't figure it out why, can anyone give me some enlightenment?
Here is the code.
#include "openssl/ssl.h"
#include "openssl/err.h"
#include <stdio.h>
#include <string>
int InitClientCtx()
{
OpenSSL_add_ssl_algorithms();
SSL_CTX* m_pClientCtx;
m_pClientCtx = SSL_CTX_new(SSLv23_method());
if(!m_pClientCtx)
{
return -1;
}
::SSL_CTX_set_options(m_pClientCtx, SSL_OP_ALL); //for well-known bugs
int nRet = 0;
std::string sCertFilePath = "C:\\cert.pem";
nRet = SSL_CTX_use_certificate_chain_file(m_pClientCtx, sCertFilePath.c_str());
std::string sKeyPassWord = "123456";
SSL_CTX_set_default_passwd_cb_userdata(m_pClientCtx, (void*)(sKeyPassWord.c_str()));
std::string sKeyFilePath = "C:\\key.pem";
// this method returned 0, which means it failed.
nRet = SSL_CTX_use_PrivateKey_file(m_pClientCtx, sKeyFilePath.c_str(), SSL_FILETYPE_PEM);
SSL_load_error_strings();
unsigned long n = ERR_get_error();
char buf[1024];
printf("%s\n", ERR_error_string(n, buf));
nRet = SSL_CTX_check_private_key(m_pClientCtx);
if (nRet <= 0)
{
return -1;
}
/*std::string sCACertFilePath;
nRet = SSL_CTX_load_verify_locations(m_pClientCtx, sCACertFilePath.c_str(), NULL);*/
return 0;
}
int main()
{
InitClientCtx();
return 0;
};
In my case the error was because the PEM file did not contain both a key and a certificate.
Make sure your file contains both sections:
-----BEGIN PRIVATE KEY----- jhajk838383jks.....
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE----- yoe55wjcxnshre.....
-----END CERTIFICATE KEY-----
I catenated .key and .crt files I already had in my Apache configuration to make a .pem file.
The 'no start line' error is certainly misleading as you can have a perfectly good "BEGIN" line in your PEM file and still get the error.
The error error:0906D06C:PEM routines:PEM_read_bio:no start line is because in both the cert.pem as well as key.pem, don't start off with -----BEGIN CERTIFICATE----- and -----BEGIN ENCRYPTED PRIVATE KEY-----.
If you open up your cert.pem and key.pem in a text editor and yank off whatever is there before the BEGIN markers, you should be good.
When you create a certificate and a key pair using Certificate Signing Request, you won't get this additional information.
I've solved this problem myself. I generated the key.pem using OpenSSL for Windows, when the CMD prompts me to type in the pass phrase, I just typed a Enter since I needn't a pass phrase, but the key.pem was invalid(neither BEGIN nor END markers). When I generate the private key in Linux, the terminal prompts I must type a pass phrase and I do. Then I remove the key pass phrase using this command:
openssl rsa -in key.pem -out newkey.pem
After that, I open the key.pem in a text editor, it starts off with -----BEGIN RSA PRIVATE KEY----- and end up with -----END RSA PRIVATE KEY-----. And SSL_CTX_use_PrivateKey_file() just works fine!
Under openssl directory demo/openssl there is a client example.
Change:
meth = SSLv2_client_method();
in your case to:
meth = SSLv23_client_method();
Try this example and see where it fails.
Are you sure that the key password is 123456 ?
I had the same problem in NGINX while installing the SSL certificate and I resolved using the following step:
Go to the folder where you have your certificate and pem files
Open your ca-bundle.crt file and copy everything, sudo nano your fileName select all and copy. the file looks like
-----BEGIN CERTIFICATE----- MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
..........
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT
MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv
..........
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
..........
-----END CERTIFICATE-----
Open your pem file using sudo nano your fileName.pem
You will see some code like
-----BEGIN CERTIFICATE----- MIIGLzCCBRegAwIBAgIIWI4ndTQi3MwwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV
MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIF
oDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcy
-----END CERTIFICATE-----
After -----END CERTIFICATE----- paste all the code copied from ca-bundle.crt file and save it
Restart your Nginx server using following command sudo service nginx restart
The above steps worked for me in my Nginx and SSL configuration