TLS Session Resumption via Pre-Shared Key (PSK) in Node.js - node.js

Currently the TLS Session Resumption documentation for Node.js only covers two methods (Session IDs and Session Tickets) both of which are obsoleted in the TLS 1.3 spec. In practice I've found that Filezilla is not utilizing either of these methods over TLS 1.3 when the server is configured to handle them.
That was confirmed to me by a Filezilla team member, they only utilize the Pre-Shared Key method as specified in TLS 1.3.
Which brought me to the PSK docs, which are sadly even more sparse and dated than the session resumption docs. They don't even cover exchanging a PSK during the handshake and instead focus on out of band PSK. I've been digging through the Node source but am not finding anything very helpful since most of this stuff is in the deps -> OpenSSL and my skills at deciphering C are not great.
It is quite possible that my question is not suitable for this medium, if so I understand if it is closed. That said, my question is simply: Can PSK based session resumption be achieved in Node.js at all at this point and if so, what would that flow look like?

Related

Signal voice/video encryption scheme

I am trying to figure out how Signal messenger audio/video encryption works.
I have read the blog post
https://signal.org/blog/signal-video-calls-beta/
and the RFC for DTLS-SRTP
https://tools.ietf.org/html/rfc5764
what I don't understand is how the DTLS handshake is actually made.
My first question is where does it feed the initial certificates does it uses the identity keys for both parties to negotiate the TLS session ?
It uses webrtc for android, with eliptic curves, and looking into the source code I can see it uses, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA or if compiled with boringssl TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. So any ideea how is compiled ? The sources for webrtc, where it works with the encryption algorithms are in
https://chromium.googlesource.com/external/webrtc/+/5647a2cf3db888195c928a1259d98f72f6ecbc15/webrtc/base/opensslstreamadapter.cc.
Thank you.

Websocket Security

I am looking to implement web (angular) and iPhone apps using WebSockets to communicate with our server. In the past using HTTP requests we have used hashes using the request data, url, timestamp etc to authenticate and secure the requests.
As far as I am aware we can't send headers with WebSockets requests therefore I am wondering how I can secure each request.
Does anyone have any ideas or good practices?
To secure your messages, use WebSockets over SSL/TLS (wss:// instead of ws://). Don't roll your own crypto.
Concerning authentication. The big difference between HTTP and WebSockets is that HTTP is a stateless protocol and WebSockets is not.
With HTTP you have to send headers (cookies, tokens, whatever) with each request. With WebSockets you establish a connection. In the first interactions you can authenticate the client and for the remainder of the connection you know the client is authenticated.
The people at Heroku have described a pattern where the client authenticates using HTTP, gets a ticket and then sends that ticket as a first message over the WebSocket connection. See https://devcenter.heroku.com/articles/websocket-security
I agree with the SSL/TLS wss:// connection. Always use encrypted traffic. There are several ways to implement a authentication. See here:
http://simplyautomationized.blogspot.com/2015/09/5-ways-to-secure-websocket-rpi.html
Most to all examples use python or nodejs and are directed for the Raspberry Pi but the general concepts are good ideas to consider. There are links in the post to a SocketRocket helper library that allows you to insert authentication into the auth header (SocketShuttle).
Having secure communication with server includes authenticating both parties to each other. If you need to channel different users with different authentication credentials through one communication channel (which is a rare idea nowadays), you'll need separate authentication. Otherwise, you just need to come up with key distribution scheme (so that your apps know public keys of your server and your server has a protocol of getting acquanted to public keys of clients, there are plenty of patterns for this).
To do that, there is a choice gradient a bit wider than SSL or your own crypto (try to avoid writing your own crypto at any cost).
For webserver-to-browser part of stack, SSL is your only choice, however it shouldn't be considered as a good safety measure, each year unfolds more and more vulnerabilities, cipher degradation cases and trust problems. It carries 20 years of baggage of bad engineering decisions and urgent fixes, so if you can get something better - it's worth doing so. Still, it's much better than nothing for the regular webs.
In your mobile app you could easily use one of a number of cryptographic libraries providing secure session messaging with server with significantly higher security guarantees, no reliance:
https://github.com/mochtu/libsodium-ios, libsodium-ios, an ios wrapper for NaCl, one of the best modern cryptographic libraries, which has lots of novel implementations to ECC cryptography, is highly praised in academic circles and written by a madman keen to have best performance under all circumstances (in short: I adore it :) ).
Themis, a project I'm a contributor in, we have very ObjC-friendly iOS version of our library, and a handy tutorial on doing secure traffic over websockets in iOS: https://www.cossacklabs.com/building-secure-chat
You should secure your connection with SSL/TLS and use https over http and wss over ws. For having auhentication/authorization, you can add query params to the websocket connections and also add something like username/passwprd.
For instanse :
wss://example.com/path?username=password=anotherParam=99ace112-dd56-427e-ba3d-9dd23e9c7551
yes, in js you cant add your arbitrary header, but you are allowed to add protocols and Sec-WebSocket-Protocol header to your webocket connections and on the server-side authenticate/authorize users based on websocket protocols

Node TLS Ticket Reestablish Connection

I am doing experimenting in nodejs. I'm trying to use a TLS Ticket to resume a TLS Session. So I will make a client save off the TLS Ticket after successful connection. After shut down I would like it to use the same TLS ticket to reestablish the TLS connection.
I have found the node tls command tlsSocket.getTLSTicket() however I am not sure how to use it to reestablish a connection because it's "Useful only for debugging".
What i want is the ability to get the TLSTicket from the client and manually validate it against a TLSTicketKey in a server in nodejs.
Thanks
After spending way more time than I should have, these are what I found:
There doesn't seem to be any API or exposed JavaScript functions that would allow you to validate TLSTickets.
Reusing sessions via session tickets works out-of-the box, the implementation is completely transparent for your node.js
https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/
However, as you will see in the link, it is possible to manually handle sessions with a session store (which obviously defeats the purpose of TLS tickets).
Node uses the following function provided by OpenSSL to do Ticket processing.
SSL_CTX_set_tlsext_ticket_key_cb - set a callback for session ticket processing
Full Details: https://github.com/joyent/node/blob/d13d7f74d794340ac5e126cfb4ce507fe0f803d5/deps/openssl/openssl/doc/ssl/SSL_CTX_set_tlsext_ticket_key_cb.pod
It's done from here: https://github.com/joyent/node/blob/master/src/node_crypto.cc
Node does not emit resumeSession when it receives valid TLS ticket.
The following GitHub issue describes why and is an easy reference to Node's TLS ticket implementation details.
https://github.com/joyent/node/issues/5872

Preshared keys (TLS-PSK-WITH-AES-256-CBC-SHA) with node.js server

I'm trying to implement a server that can field a request from a very constrained client that wants to handshake using pre-shared keys (PSK) using the cryptosuite TLS-PSK-WITH-AES-256 with a node.js server. I can't seem to find any samples or documentation that talks about how you'd set this up. Is this cryptosuite supported by node.js? If so, how does one go about configuring the options for the https server to accept these connections and verify them?
Although tls.getCiphers() claims to support psk-aes256-cbc-sha, it appears that support is not actually implemented.
Someone did submit a pull request implementing PSK several years ago, but it apparently went stale and was never merged.
To get PSK working, you'll have to manually apply the changes from the old PR to the current version of node and create a custom build.

Cryptography and Authentication via TLS with Web of Trust in Java

For a program I am writing, I would like to use TLS (or something similar) to encapsulate my application's protocol. This will minimize both the amount of work I have to do as well as the number of vulnerabilities I could accidentally create.
My program is designed to be peer-to-peer although one or more servers provide some services to help one user locate another (it registers IP address/port combos) but do little else. I want to make this system very fault-tolerant so having these servers act as a Certificate Authority is unacceptable because a compromise of a server or its key would affect too many users. Therefore I plan on using a Web of Trust.
The main problem with using TLS is that the original TLS 1.2 specification (RFC 5246) does not provide for using OpenPGP certificates. It seems to be very x.509 centric. RFC 6091, which obsoletes RFC 5081 and extends RFC 5246, makes provisions for an extension to TLS that does what I want. The problem is that I don't think BouncyCastle implements this extension and I can't find a Java crypto library that does. I also don't want to write my own / contribute to BC because I'm really bad at not making mistakes and I'm also very lazy.
Another problem with this is that BouncyCastle provides "a light weight client-side TLS API" but because this software is P2P, a server-side API is also necessary so that I can use TLS by making it believe that the peer originating the connection is the client. I'm pretty sure that once the handshake is complete that it's the same.
Questions:
Is there any way that I can still use TLS (which I highly doubt)? Is there a protocol like TLS that is designed for P2P, or at least can function in this way (like I believe TLS can), but can work with an OpenPGP certificate? If neither is the case, should I pursue the idea explained in this question and implement my own layer taking concepts from TLS?
Links to RFCs: RFC 5246 and RFC 6091
The only library that I know to support RFC 6091 (i.e. TLS with openpgp certificates) is GnuTLS but I don't know whether you can use something like that in Java. Alternatively you could replicate the SSH semantics, where you store the public keys of your peers using self-signed
X.509 certificates.
In TLS, the X.509 parts are actually handled as opaque blobs:
The server sends its certificate (and some helper certificates, if it wishes so) as (a list of) opaque string(s) of bytes (a three-byte length, followed by the encoded certificate as arbitrary bytes).
When the server asks for public key client authentication, it sends a list of "names" which are supposed to be the encoded X.500 names of the root CA the server will recognize -- there again, opaque blobs (two-byte length).
The client, when (if) it sends a certificate (chain), uses the same format than the server.
As TLS is defined, both client and server are supposed to use the peer public key, which they get in any way they see fit and that's mostly out of scope of the TLS specification: the certificates exchanged over the wire are considered as mere helpers. So there would be no problem in actually sending OpenPGP encoded public keys in those blobs, as long as both client and server expect it -- and since you control code on both, this should be no issue.
Your problem then "simply" becomes a matter of making a TLS implementation accept to hand you the blobs without choking on them. I know of no existing Java-only TLS implementation which will fit the bill, so you may have to write a bit of code -- but I urge you not to fiddle with TLS protocol details except processing of the certificate blobs. Those things are subtle and weaknesses are sooo easy to create...
As far as I know, the Sun/Oracle JSSE implementation only deals with X.509 TrustManagers (which you can customize to handle certain extensions, but would still expect a structurally valid X.509 certificate.
It might be possible to use Java's security API to implement RFC 6091, but I'm not sure how. It's definitely more work than just tweaking the TrustManagers, as you would have to go deeper into Java's implementation of TLS.
Alternatively, if it's for a bespoke server, you could re-use the key material from PGP certificates into X.509 certificates and put the initial PGP certificate (with all its signatures) as a blob in a custom X.509 extension (as it's more or less done here). The problem here would be interoperability, since such an extension wouldn't be a standard. Implementing a TrustManager in Java that is able to understand extension is definitely feasible, and you wouldn't need to dig into the internals of Java's TLS stack, you'd only have to deal with custom TrustManagers to initialize your SSLContexts.

Resources