The remote certificate is invalid according to the validation procedure - NET Core WebAPI - asp.net-core

I'm struggling when putting together two ASP.Net Core application talk to each other using HTTPS.
Before setting up the web api, I first generated the HTTPS correspondent certificates through a development private PKI. This is the code to build the client and server certificates. I believe that the PKI part of the code is not relevant for now.
#!/usr/bin/env bash
printf "SET ENVIRONMENT\n\n"
export ca_dir=$HOME/CA
root_ca_config_path=$ca_dir/root-ca/root-ca.conf
sub_ca_config_path=$ca_dir/sub-ca/sub-ca.conf
server_config_path=$ca_dir/server/server_config.conf
client_config_path=$ca_dir/client/client_config.conf
pass=$ca_dir/pass/pass.aes256
printf "CREATED CLIENT FOLDER\n\n"
mkdir -p $ca_dir/client/{certs,private,csr}
printf "CREATED SERIAL\n\n"
openssl rand -hex 16 > $ca_dir/ca-chain/ca-chain.srl
cat << EOF > $server_config_path
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = #alt_names
[ alt_names ]
# Be sure to include the domain name here because Common Name is not so commonly honoured by itself
DNS.1 = localhost
IP.1 = 127.0.0.1
[ req ]
# Options for the req tool, man req.
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
[ req_distinguished_name ]
countryName = BR
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organization Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = BR
stateOrProvinceName_default = Brazil
0.organizationName_default = ElectricStone Ltd
organizationalUnitName_default = FakeProvider
commonName_default = localhost
EOF
cat << EOF > $client_config_path
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
subjectAltName = #alt_names
[ req ]
# Options for the req tool, man req.
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
[ req_distinguished_name ]
countryName = BR
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organization Unit Name
commonName = Common Name
emailAddress = Email Address
countryName_default = BR
stateOrProvinceName_default = Brazil
0.organizationName_default = ElectricStone Ltd
organizationalUnitName_default = eCommerce
commonName_default = localhost
[ alt_names ]
# Be sure to include the domain name here because Common Name is not so commonly honoured by itself
DNS.1 = localhost
IP.1 = 127.0.0.1
EOF
printf "CREATING SERVER PRIVATE KEY...\n\n"
openssl genrsa -out $ca_dir/server/private/netwebapp.key 2048
printf "CREATING CLIENT PRIVATE KEY...\n\n"
openssl genrsa -out $ca_dir/client/private/netwebappclient.key 2048
printf "CREATING A SERVER SIGNING REQUEST...\n\n"
openssl req -config $server_config_path -passin file:$pass -key $ca_dir/server/private/netwebapp.key \
-new -sha256 -out $ca_dir/server/csr/netwebapp.csr
printf "CREATING A CLIENT SIGNING REQUEST...\n\n"
openssl req -config $client_config_path -passin file:$pass -key $ca_dir/client/private/netwebappclient.key \
-new -sha256 -out $ca_dir/client/csr/netwebappclient.csr
printf "CREATING THE SERVER CERTIFICATE...\n\n"
openssl x509 -req -in $ca_dir/server/csr/netwebapp.csr -passin file:$pass \
-CA $ca_dir/ca-chain/ca-chain.crt \
-CAkey $ca_dir/sub-ca/private/sub-ca.key \
-CAserial $ca_dir/ca-chain/ca-chain.srl \
-out $ca_dir/server/certs/netwebapp.crt -days 365 -sha256 -extfile $server_config_path
printf "CREATING THE CLIENT CERTFICATE...\n\n"
openssl x509 -req -in $ca_dir/client/csr/netwebappclient.csr -passin file:$pass \
-CA $ca_dir/ca-chain/ca-chain.crt \
-CAkey $ca_dir/sub-ca/private/sub-ca.key \
-CAserial $ca_dir/ca-chain/ca-chain.srl \
-out $ca_dir/client/certs/netwebappclient.crt -days 365 -sha256 -extfile $client_config_path
After I had generate the certificates I was able to test their effectiveness through respectively openssl commands:
# Testing the server certificate
sudo openssl s_server -accept 443 -www -key $ca_dir/server/private/netwebapp.key \
-CAfile $ca_dir/sub-ca/certs/sub-ca.crt \
-cert $ca_dir/server/certs/netwebapp.crt
# Testing the client certificate
openssl s_client -connect localhost:443 -servername localhost \
-cert /home/dggt/CA/client/certs/netwebappclient.crt \
-key /home/dggt/CA/client/private/netwebappclient.key \
-CAfile /home/dggt/CA/root-ca/certs/ca.crt \
-showcerts
Those test command produced this output at client side:
CONNECTED(00000006)
depth=2 C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone Root CA
verify return:1
depth=1 C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone SUB CA
verify return:1
depth=0 C = BR, ST = Brazil, O = ElectricStone Ltd, OU = FakeProvider, CN = localhost
verify return:1
---
Certificate chain
0 s:C = BR, ST = Brazil, O = ElectricStone Ltd, OU = FakeProvider, CN = localhost
i:C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone SUB CA
-----BEGIN CERTIFICATE-----
################################## Output suppressed ##################################
-----END CERTIFICATE-----
1 s:C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone SUB CA
i:C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone Root CA
-----BEGIN CERTIFICATE-----
################################## Output suppressed ##################################
-----END CERTIFICATE-----
---
Server certificate
subject=C = BR, ST = Brazil, O = ElectricStone Ltd, OU = FakeProvider, CN = localhost
issuer=C = BR, ST = Brazil, O = ElectricStone Ltd, CN = ElectricStone SUB CA
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3378 bytes and written 381 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 5D3176780DE3404A9E246E026D875B0B81A3EFE9EB7B2F17D24E3565DB42E1AE
Session-ID-ctx:
Resumption PSK: E9D6B7E66063C4969C203A153A3E60E1131095E2AE1569AE04673BA9F1FA90974ACE42D5B902ABE8A5760218AD2959FF
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
################################## Output suppressed ##################################
Start Time: 1605522448
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 5B8E394EBEBEBC7FD2617EA0695CD9C2E0B8F4ED733F628CA28A5190AB4D27BA
Session-ID-ctx:
Resumption PSK: F536C3428049C2DD6F9496D14E516B30611D2D7056AE6B87445F6328B4B1577093FDA3D4A6AC9D00F30F7725B6925A9E
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
################################## Output suppressed ##################################
Start Time: 1605522448
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
DONE
So far so good. However at ASP.NET Core side the thing get complicated.
Afterwards some research, at one of my API, I configured the built-in Kestrel web server to work with HTTPS by the following code:
Program.cs
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.Extensions.Hosting;
namespace BogusProvider
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel((context, options) =>
{
var certificateConfig = context.Configuration.GetSection("Certificate");
var certFileName = certificateConfig["FileName"];
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER")))
{
// Insert a Docker entry coming from user-secrets when development in container
certFileName = certificateConfig["Docker"];
}
var certPassword = certificateConfig["Password"];
// Configure the Url and ports to bind to
// This overrides calls to UseUrls and the ASPNETCORE_URLS environment variable, but will be
// overridden if you call UseIisIntegration() and host behind IIS/IIS Express
// When development in container, use ListenAnyIP method
options.ConfigureHttpsDefaults(adapterOptions =>
{
adapterOptions.CheckCertificateRevocation = false;
adapterOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
});
options.ListenAnyIP(5002, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
listenOptions.UseHttps(certFileName, certPassword);
listenOptions.UseConnectionLogging("FakerHttpsConnection");
});
}).UseStartup<Startup>();
});
}
}
I also installed the Microsoft.AspNetCore.Authentication.Certificate package in order to setup the certificate authentication in the ASP.NET Core machinery.
This is a snippet of code at Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// Others services suppressed
}
With all this code running, I get 'connection refused' when either requesting through the browser (after I have installed the client certificate alongside its private key password and the Sub CA by browser settings) or the other Web API when requesting through HttpClient.
This is my HttpClient code:
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2("/home/dggt/CA/client/certs/netwebappclient.pfx",
"pa$$worD_1"));
return new HttpClient(handler) {BaseAddress = new Uri("https://localhost:5002/fake/")};
This the gist of the error message at console:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
System Specs:
OS: Ubuntu 20.04
Net Info:
SDK: 3.1.404
Runtime: Microsoft.AspNetCore.App 3.1.10
Any idea of what I might be doing wrong? Any help is welcome!

Related

jose-jwt can generate JWT token via private key, but failed to valid token via RSA public key

I was trying to implement JWT authentication based on jose-jwt for .NET, I can generate JWT token by RSA private key successfully, and pass checking on https://jwt.io debugger, but I'm getting stuck on validating the token with RSA public key by the following error message:
RsaUsingSha alg expects key to be of AsymmetricAlgorithm type.
Here is my steps and code snippets:
create PKCS#12 and certificate file
openssl x509 -signkey jwt-auth-private.key -in jwt-auth-csr.csr -req -days 365 -out jwt-auth-certificate.crt
openssl pkcs12 -inkey jwt-auth-private.key -in jwt-auth-certificate.crt -export -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out jwt-auth-pkcs12.pfx
Create JWT token with RSA private key (It works)
var pfxFilePath = string.Format("{0}\\{1}", baseDir, "jwt-auth-pkcs12.pfx");
var cipher = "private-key-cipher";
var privateKey = new X509Certificate2(pfxFilePath, cipher, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet).PrivateKey as RSACryptoServiceProvider;
var payload = new Dictionary<string, object>()
{
{ "sub", "mr.x#contoso.com" },
{ "exp", 1300819380 }
};
token = Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.RS256);
Valid token with public key (Failed)
var crtFilePath = string.Format("{0}\\{1}", baseDir, "jwt-auth-certificate.crt");
var cipher = "private-key-cipher";
var publicKey = new X509Certificate2(crtFilePath, cipher).GetPublicKey();
var data = Jose.JWT.Decode(token, publicKey);
When I tried to decode token, I got an error message:
RsaUsingSha alg expects key to be of AsymmetricAlgorithm type.
I had no idea on how to find what's wrong, please help. thanks.
Remark: It looks like that the .crt and .pfx file had no issues, cause if I use JWT.NET instead of jose-jwt libs, I can decode the token successfully in the same way.

SSL implementation with Tungstenite: SSL alert number 42

I created a working WebSocket server with async_tungstenite and async_std.
I now want to add SSL using async_native_tls.
If I understood correctly, this crates provides a function accept which takes a TcpStream, handles the TLS handshake and provides a TlsStream<TcpStream> which should behave like a TcpStream but handles the encryption and decryption behind the scene.
To test the server, I created a self-signed certificate.
Based on that, here is how the code handling new TCP connections evolved:
async fn accept_connection(stream: TcpStream, addr: SocketAddr) {
//Websocket stream
let accept_resut = async_tungstenite::accept_async(stream).await;
if let Err(err) = accept_resut {
println!(
"Error while trying to accept websocket: {}",
err.to_string()
);
panic!(err);
}
println!("New web socket: {}", addr);
}
async fn accept_connection(stream: TcpStream, addr: SocketAddr) {
//Open tls certificate !should be done one time and not for each connection!
let file = File::open("identity.pfx").await.unwrap();
let acceptor_result = TlsAcceptor::new(file, "glacon").await;
if let Err(err) = acceptor_result {
println!("Error while opening certificate: {}", err.to_string());
panic!(err);
}
let acceptor = acceptor_result.unwrap();
//Get a stream where tls is handled
let tls_stream_result = acceptor.accept(stream).await;
if let Err(err) = tls_stream_result {
println!("Error during tls handshake: {}", err.to_string());
panic!(err);
}
let tls_stream = tls_stream_result.unwrap();
//Websocket stream
let accept_resut = async_tungstenite::accept_async(tls_stream).await;
if let Err(err) = accept_resut {
println!(
"Error while trying to accept websocket: {}",
err.to_string()
);
panic!(err);
}
println!("New web socket: {}", addr);
}
With this implementation, I now call from a webpage
const sock = new WebSocket('wss://localhost:8020');
This results in the error:
Error while trying to accept websocket:
IO error: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate:../ssl/record/rec_layer_s3.c:1543:SSL alert number 42
thread 'async-std/runtime' panicked at 'Box<Any>', src/main.rs:57:9
It seems like the handshake was successful as the error does not occur during the acceptor.accept. The error states that the certificate is not valid so here is how I created my self-signed certificate.
The openssl version is 1.1.1f
# Create a key
openssl req -nodes -new -key server.key -out server.csr
# Create the self-signed certificate
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
# Convert the certificate to pfx format
openssl pkcs12 -export -out identity.pfx -inkey server.key -in server.crt
I thought that this problem had to do with security feature from the browser as the "SSL alert number 42" seems to come from the client. I tried to disable this option in Firefox settings
Query OCSP responder servers to confirm the current validity of certificates
I also tried to add my server.crt to the Authorities of the certificate manager.
Neither of these worked.
The problem came from the security features of Firefox.
Firefox detects that the certificate is not signed by an authority and sends back an error.
It seems like adding the certificate to the known authorities does not work.
To avoid this issue, I found this thread which indicates that an exception should be added for the address and port of your development Websocket server.
Go to Settings > Certificates > View Certificates > Servers > Add Exception...
Type in your local server (for me localhost:8020).
Add exception.

openssl ca vs openssl x509 (the openssl ca command doesn't register the same on certificate?)

what is the difference between openssl ca and openssl x509 commands? I'm using it to create and sign my root-ca, intermed-ca and clients certificates, but the openssl ca command does not register the cellphone and emailAddress on the certificates while openssl x509 does.
openssl x509:
openssl x509 -req \
-in client.req.pem \
-out client.cert.pem -signkey client.privkey.pem \
-CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -days 365
openssl ca:
openssl ca \
-in client.req.pem \
-out client.cert.pem \
-extensions client_ext \
-startdate `date +%y%m%d000000Z -u -d -2day` \
-enddate `date +%y%m%d000000Z -u -d +1years+1day`
My ca.cnf
CA_HOME = .
RANDFILE = $ENV::CA_HOME/private/.rnd
#oid_section = new_oids
# XMPP address Support
#[ new_oids ]
#xmppAddr = 1.3.6.1.5.5.7.8.5
#dnsSRV = 1.3.6.1.5.5.7.8.7
# Default Certification Authority
[ ca ]
default_ca = intermed_ca
# Intermediate Certification Authority
[ intermed_ca ]
dir = $ENV::CA_HOME
certs = $dir/certs
serial = $dir/intermed-ca.serial
database = $dir/intermed-ca.index
new_certs_dir = $dir/newcerts
certificate = $dir/intermed-ca.cert.pem
private_key = $dir/private/intermed-ca.key.pem
default_days = 730 # Two years
crl = $dir/crl/intermed-ca.crl
crl_dir = $dir/crl
crlnumber = $dir/intermed-ca.crlnum
name_opt = multiline, align
cert_opt = no_pubkey
copy_extensions = copy
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
preserve = no
email_in_dn = no
policy = policy
unique_subject = no
#
# Distinguished Name Policy
[ policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
#
# Distinguished Name Policy for Personal Certificates
[ user_policy ]
countryName = supplied
stateOrProvinceName = optional
localityName = supplied
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = supplied
#xmppAddr = optional # Added to SubjAltName by req
#
# Intermediate CA request options
[ req ]
default_bits = 3072
default_keyfile = private/intermed-ca.key.pem
encrypt_key = yes
default_md = sha256
string_mask = utf8only
utf8 = yes
prompt = no
req_extensions = req_ext
distinguished_name = distinguished_name
subjectAltName = subject_alt_name
#
# Intermediate CA Request Extensions
[ req_ext ]
subjectKeyIdentifier = hash
subjectAltName = #subject_alt_name
#
# Distinguished Name (DN)
[ distinguished_name ]
countryName = BR
stateOrProvinceName = mystate
localityName = mycity
organizationName = domain.com
organizationalUnitName = P&D
commonName = domain.com.br Intermediate Certification Authority
emailAddress = my.email#domain.com
#
# Server Certificate Extensions
[ server_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
issuerAltName = issuer:copy
authorityInfoAccess = #auth_info_access
crlDistributionPoints = crl_dist
#
# Client Certificate Extensions
[ client_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
issuerAltName = issuer:copy
authorityInfoAccess = #auth_info_access
crlDistributionPoints = crl_dist
#
# User Certificate Extensions
[ user_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, clientAuth, emailProtection
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
issuerAltName = issuer:copy
authorityInfoAccess = #auth_info_access
crlDistributionPoints = crl_dist
#
# CRL Certificate Extensions
[ crl_ext ]
authorityKeyIdentifier = keyid:always
issuerAltName = issuer:copy
#
# Certificate Authorities Alternative Names
[ subject_alt_name ]
URI = http://ca.domain.com/
email = contato#domain.com
#
# Certificate download addresses for the intermediate CA
[ auth_info_access ]
caIssuers;URI = http://ca.domain.com/certs/domain.com_Intermediate_Certification_Authority.cert.pem
#
# CRL Download address for the intermediate CA
[ crl_dist ]
fullname = URI:http://ca.domain.com/crl/domain.com_Intermediate_Certification_Authority.crl
Reference
https://roll.urown.net/ca/ca_root_setup.html
From the man page for ca(1) (ca(1ssl) or similar on some systems), emphasis added:
POLICY FORMAT
The policy section consists of a set of variables corresponding to certificate DN fields. If the value is "match" then the field value must match the same field in the CA certificate. If the value is "supplied" then it must be present. If the value is "optional" then it may be present. Any [DN] fields not mentioned in the policy section are silently deleted, unless the -preserveDN option is set[,] but this can be regarded more of a quirk than intended behaviour.
And later:
BUGS
...
Any [DN] fields in a request that are not present in a policy are silently deleted. This does not happen if the -preserveDN option is used. To enforce the absence of the EMAIL field within the DN, as suggested by RFCs, regardless [of] the contents of the request'[s] subject[,] the -noemailDN option can be used. The behaviour should be more friendly and configurable.
And although these only mention the commandline option -preserveDN, elsewhere it (incompletely) describes this related configuration item:
preserve
the same as -preserveDN
To be exact, if preserve is yes it overrides the policy and retains all DN fields (in order), as (correctly) documented for -preserveDN, but your posted file has preserve = no.
I also notice you specified -extensions in your ca but not in your x509. ca can put extensions in the cert from the config file if you specify commandline option -extensions OR config item x509_extensions (which your posted file doesn't) AND ALSO can copy extensions from the CSR (if any, which you don't indicate) if you specify config item copy_extensions (which you do). x509 can put extensions only from a config file (never the CSR) and only if you specify on commandline -extfile file and optionally -extensions section. This will produce a very important difference in your certs, likely more important than email and phone# in subject, and is already covered by other Qs like https://security.stackexchange.com/questions/150078/missing-x509-extensions-with-an-openssl-generated-certificate and https://unix.stackexchange.com/questions/371997/creating-a-local-ssl-certificate

Openssl Errors on port change

Very simple question. I'm trying to us OpenSSL in Ruby to connect to a service, but getting errors.
When I use the following command:
openssl s_client -ssl3 -showcerts -connect example.com:443 -tls1 -cipher 'DHE-RSA-AES256-SHA' -nbio_test -state
It works great! The cert shows up with all the correct information.
But when I do:
openssl s_client -ssl3 -showcerts -connect example.com:13902 -tls1 -cipher 'DHE-RSA-AES256-SHA' -nbio_test -state
I get the following errors:
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:error in SSLv3 write client hello B
write W BLOCK
SSL_connect:SSLv3 write client hello B
SSL3 alert read:fatal:handshake failure
SSL_connect:failed in SSLv3 read server hello A
140735228511072:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1275:SSL alert number 40
140735228511072:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1408456884
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
The only thing that changed between the two commands is the port. The other flags were copied directly from the successful request. In other words I first did openssl s_client -showcerts -connect example.com:443 and then copied the ssl version, tls version, and cipher into the second two commands.
Is this a problem with openssl or the certificate? And if it is a problem with the certificate, how do I fix it? (and what is it?)
PS. I was able to connect in Java just fine using the following code, but still have to find a Ruby way:
public static void main(String[] args) throws NoSuchAlgorithmException,
KeyManagementException, IOException {
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) {
}
} };
final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
URL url = new URL("https://example.com:13902");
URLConnection con = url.openConnection();
final Reader reader = new InputStreamReader(con.getInputStream());
final BufferedReader br = new BufferedReader(reader);
String line = "";
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
Figured it out. Was specifying both tls1 and ssl3. Needed to just specify tls1. Thanks Aria!

cannot use any protocol besides SSLv23 in python2 ssl wrapper with self-signed certificate

I generated my self-signed certificate with open ssl
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem
I am using python2, and this is my server code:
import socket, ssl
bindsocket = socket.socket()
bindsocket.bind(('localhost', 10023))
bindsocket.listen(5)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile="cert.pem",
ssl_version=ssl.PROTOCOL_SSLv23)
try:
data = connstream.read()
print data
finally:
connstream.write('hi this is server')
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
this code works well, my client can get 'hi this is server' successfully. however, when i changed the ssl_version from ssl.PROTOCOL_SSLv23 to ssl.PROTOCOL_TLSv1 or ssl.PROTOCOL_SSLv3, there will be an error:
ssl.SSLError: [Errno 1] _ssl.c:504: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
if i changed ssl_versiton to ssl.PROTOCOL_SSLv2:
ssl.SSLError: [Errno 1] _ssl.c:504: error:1406B0CB:SSL routines:GET_CLIENT_MASTER_KEY:peer error no cipher
this is my client code, I hope this may help to generate the issue:
import socket, ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="cert.pem",
cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('localhost', 10023))
ssl_sock.write('hi this is client')
data = ssl_sock.read()
print data
ssl_sock.close()
I can not understand what's wrong with these. how could I use protocols other than SSLv23?
Have you ever considered that the keyfile is needed for server side while certfile is not for client side?
Slightly modified your code here, hope it could help.
#Server side:
import socket, ssl
bindsocket = socket.socket()
bindsocket.bind(('localhost', 10023))
bindsocket.listen(5)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.wrap_socket(newsocket,
keyfile='key.pem',
server_side=True,
certfile="cert.crt",
ssl_version=ssl.PROTOCOL_SSLv23)
try:
data = connstream.read()
print data
finally:
connstream.write('hi this is server')
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
#Client side:
import socket, ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s,
ca_certs="cert.crt",
cert_reqs=ssl.CERT_REQUIRED
)
ssl_sock.connect(('localhost', 10023))
ssl_sock.write('hi this is client')
data = ssl_sock.read()
print data`enter code here`
ssl_sock.close()