I've recently been experimenting with the OpenSSL API in C, and I'm confused about a few of the setup functions, as well as certain concepts in Public Key cryptography overall.
I understand, in general, how Public Key cryptography works. You have a Public Key which is available to everyone, and then both server and client have a Private Key which is secret, and which is necessary to decrypt the messages.
However, I'm a bit confused as to when you actually need a Public key. Would a web browser, for example, need a Public Key? I would think not, since it seems that in most use cases, only a server (not a client) would need a Public Key. If both server and client have a public key, which one is used?
Adding to my confusion, is the fact that the OpenSSL API defines a function SSL_CTX_use_PrivateKey_file(), but there is no corresponding SSL_CTX_use_PublicKey_file(). In my experiments, I wrote a simple web client that connects to an https website and downloads a file. It works fine, and no Public Key was needed. I simply created a Private Key using the OpenSSL command line tools, and then called SSL_CTX_use_PrivateKey_file() in my program.
But, if I were writing a server, as opposed to a client, wouldn't I need a Public Key? And if so, why do I not see anything like use_PublicKey_file in the OpenSSL API?
In a TLS/SSL connection, a public key is supplied as part of a certificate that is used to authenticate one party - the certificate ties an identity to a particular public key. The server side always supplies a certificate (public key), because the server side must always prove its identity to the client.
It is also possible for the client to supply a certificate, if it wants to prove its identity (and it has a suitable certificate) - in your web browser example, it's usually the case that a client certificate isn't supplied, but it is possible. Some web sites do use client certificates for authentication.
If a public key is used, the corresponding private key must be used too - the keys come as a pair. The corresponding function to supply the public key is SSL_CTX_use_certificate() - the public key is part of the certificate. Supplying one without the other is pointless - in your client example, you could have omitted the call to SSL_CTX_use_PrivateKey_file() entirely.
In general, private keys are for decryption, public keys are for encryption and verification.
I'm not that familiar with the OpenSSL C interfaces, but my guess is that you're not actually doing anything with the key you loaded from the file. The download routine you're using is pulling down the web server's cert, verifying it's signature against a known chain of signing authorities, and then negotiating tls (shared cipher) encryption stream.
In other words, for HTTPS, the public key encryption is only used for your computer to verify the authenticity of the server prior to stream cipher negotiation. Once that's complete, both parties will have a shared key and the everything is encrypted using regular crypto.
The TLS RFC has all the gory details.
Keys come in pairs -- for every public key, there's a corresponding private key and for every private key there's a corresponding public key. So it makes no sense at all to talk about THE private key or THE public key -- instead you need to specify WHICH key you are talking about.
In a 'normal' (non-client-authenticated) SSL connection, there is one key-pair, the server's key pair. The server knows its own private key and the client needs to know the server's public key, which usually comes in the form of a certificate which is signed by some certificate authority's private key. So when the client first connects to the server, the first thing the server does is send its public key certificate (so the client has it). The client authenticates the certificate using the CA's public key (which needs to be built in or pre-loaded.) Then the client makes a 'secret' (a random number) and encrypts it with the server's public key and sends it to the server which can decrypt it with its private key. That secret is then used to seed a key for a symmetric cipher that is used for further communication.
In an authenticated SSL connection, both the client and server have private keys and provide their certificates (with the corresponding public keys) across the connection before establishing the secure connection.
Public keys are usually not required for the client. The client will generate a random public key during the handshake so that the server can encrypt messages that only the client can decrypt, but the lifetime of this public key is the same as the connection's lifetime.
As a client, in order to get a public key of a server, you will use a certificate SSL_CTX_use_certificate_file. The certificate contains the public key and is usually validated by a trusted certificate issuer. This guarantees for the client the authencity of the server, as long as you trust the certificate issuer. Web browsers are delivered with a set of trusted certificate issuers so they can validate certificates that they will download.
Related
I am attempting to create a C# application that connects to a PostgreSQL database using SSL with client certificate and key files similar in functionality to the PGAdmin UI, but the documentation for this in NPGSQL is lacking and I cannot find any examples. The documentation states that it "works just like on .NET's SSLStream", but I am not seeing any correlation between the two. Has anyone created a connection using this method that can possibly provide some help?
I am facing the same situation. Documentation certainly needs to describe usage explicitly on how to supply cert, key and CA files if needed to the connection string or connection builder, and how the ProvideClientCertificatesCallback can actually supply back cert, key and CA files.
Nov 2018: I got below sample code to work for self-signed certs:
var connection = new NpgsqlConnection(connectionStringBuilder.ConnectionString);
connection.ProvideClientCertificatesCallback += clientCerts => this.GetMyClientCertificates(clientCerts);
private void GetMyClientCertificates(X509CertificateCollection clientCerts)
{
clientCerts.Add(<supply an instance of X509Certificate2 here>);
}
You need to have SSL=true in your connection stream, and then provide a ProvideClientCertificatesCallback on your NpgsqlConnection before opening it (like SSLStream).
I want to use some API data to build a front app in angularjs 1. For that I have to decrypt the data first using AES128 and use it then send encrypt data to API. I can use crypto.js for that task but then the key will be visible to anyone.
Is their any secure way of doing this?
Thanks
For that you need to use angular-crypto.js for more information please refer this
github repository...encryption and decryption
Here what we can us
You have to modify API so that it will generate pair of keya: public key and private key. This public key will be given to angular code where it will be able to encrypt using this public key. Encrypted data will be send to API where it will use private key to decrypt it. This is the most secure way to do it where it encrypted data will not be able to be decrypted without secret private key.
There're some more ways to enhance security such as using hash functions and digital signatures
My current program(on windows) loads private key from a text file using SSL_CTX_use_PrivateKey_file and creates SSL connection to server.
Now I need to take the private key from windows certificate store.
OpenSSL don't seem to access windows cert store directly, please let me know how to do that?
I want to login with a file that contains digital certificate of someone, first registers with certificate contents that is base64 format, and when registering it will encrypt the content of certificate and save into database and when login with this file, i want to login with that data matched by decrypted way, pls help how to do this? And also when i encrypt each time file content saved with different characters, is it possible to save 3323 characters in database? pls help.....
// controller
$main_file = $request->file;
//$con = $main_file->getClientOriginalName();
$con = file_get_contents($main_file->getRealPath());
$files = Crypt::encrypt($con);
dd($files);
$file = Input::file('file')->getClientOriginalName();
$contents = File::get($main_file);
dd($contents);
Now to authenticate with this saved encrypted data, what is the possible way to save the encrypted 3322 characters in database, i am really in a stuck. can anyone help me...the main task is to login with file contents..thanks...
Sounds like you're trying to implement some kind of shared private key authentication. It's not clear why you want to do that (more on that later), but it sounds like a bad idea right from the start because you are immediately confronted with a difficult problem: how do you get the private key from the client to the server in a secure way?
A better way to do it would be a private/public key system, similar to the sort of thing SSH does when you set up passwordless login. Basically (very basically - I'm not an expert) the idea is that the client generates a private/public key pair and then sends the public key to the server. On authentication, the private key is used to encrypt a message. This encrypted message is sent to the server, where the public key is used to decrypt it. If the correct message was received, then the client is authenticated.
Rather than having some sort of shared certificate, I'd recommend following this model. That way you don't have to share sensitive information (the client's private key) with the server.
Ultimately, you need to think about why you want to do this.
You think this will be more convenient for clients? Well, for SSH, it certainly is more convenient to log in this way, because SSH has a mechanism for automatically encrypting and passing messages in a secure way. For HTTP? Not so much. The user is going to need to generate a file then use an upload form just to log in. Passwords are much quicker and easier.
You think it will be more secure? The way you've described it (a shared private key) will probably be less secure because you somehow have to get the private key from the client to the server without it being compromised - remember, if the private key is compromised, anyone can impersonate the client. The way SSH does it is more secure because the private key never leaves the client.
Ultimately, I think you can probably get what you're looking for with a) strictly enforced password complexity rules and b) HTTPS.
If security on your site is so important that you cannot rely on HTTPS and complex passwords, then you should probably be looking at a more comprehensive solution that will encrypt all traffic between the client and the server, such as a VPN (virtual private network).
I am stuck to retrieve the Key_block generated after the SSL handshake. I implemented a simple Client.cpp/Server.cpp program that is working well for exchanging encrypted data.
I would like to retrieve the key_block because I want to re-use it and perform my own encryption in another communication, but without having another handshake again.
I tried :
ssl->s3->tmp.key_block
but it retrieves an empty string (?!) and of course
ssl->s3->tmp.key_block_length
retrieves 0 value.
I call these methods just after SSL_accept(ssl) succeeds.
Once I've been able to catch this key_block, I'll need to find the encryption function used by SSL_write(...)
Hope you hear me, because the openSSL doc seems encrypted to my eyes.. =)
XY problem. You don't need this. Just open another SSL connection to the same target and it should re-use the same SSL session and therefore the same session master secret. Maybe even the same session key, but what do you care, as long as it's secure? You seem to be just trying to avoid a second full SSL handshake, but you can do that by suitable configuration at the client.