Closed delphius closed 9 months ago
TLS encrypted is already implemented in a separated beta test branch with TLS. I'm planning to importing it to the main branch when we have a stable version (before making it public).
The issue is I still don't know how we should provide TLS.
webui-2
, webui-2-tls
. And the user can choose between them.However, this will need updating all the build scripts and all CI. So, let's add it at the end but not now.
TLS encrypted is already implemented in a separated beta test branch with TLS. I'm planning to importing it to the main branch when we have a stable version (before making it public).
I see! Lightweight in the name of the library will be slightly heavier due to OpenSSL :)
So, let's add it at the end but not now.
Of course, this question just lay on the surface and it was worth asking now
Thank you for pointing this out @delphius 👍 We should start a discussion on which approach we should take. 1 or 2.
The issue is I still don't know how we should provide TLS.
For me, the issue of tls support is not a question of a separate version of the library, but in general a question of complex security of the tool that I rely on during development, so for me this question is not worth it at all, I choose option 1
Me too, I vote for 1
. My point is that WebUI should provide only encrypted communication.
If it will require additional file, I vote for makig it optional and enabled with the API.
If it will significantly increase the library size, I even more vote for it to be optional and use a shared library.
If only websocket data exchange needs to be encrypted I guess I vote for using libsodium instead of openssl.
If it will require additional file, I vote for makig it optional and enabled with the API.
In any case, I agree that for good, this is not a question of the build option of the program, this support should be inside and should be optional.
If it will significantly increase the library size, I even more vote for it to be optional and use a shared library.
two files .dll for Windows (total 5 MB), built-in support for almost all Linux distributions (3.x+) with static linking, it should be significantly less
If only websocket data exchange needs to be encrypted I guess I vote for using libsodium instead of openssl.
Yes, we just need to transfer the ws connection to the wss connection and this is not a reason to pull whole cryptolib with us
So if everything is happening on the same machine, what is this encryption for?
I agree @fibodevy, this is why I spent time implementing TLS, but then I threw it in another Branche.
The only scenario TLS comes in handy is when your project has a password, and you use webui_get_url()
to let a user connect from another machine. Then TLS is a must, but WebUI is a GUI library designed to use a local web browser as UI in a local machine. And if the attacker already has access to the local machine, he can change the local certificate or read the keyboard events... TLS is for remote communication, and WebUI is for local communication.
However, we should do more research and vote at the end.
On the other hand, all processes and interactions take place within the same operating system and on localhost, so the question may not be very relevant.
I said this from the very beginning, that in the context of working on a local machine, it generally makes no sense. But we discussed it and came to the same conclusions.
For myself, I conceptually realized that the only way to guarantee data security is to use the browser only for input/output via the api from the programming language with all correctness checks and so on on the server (language) side, perceiving the browser side as a hostile environment
So, since everything runs on localhost, encryption with TLS makes no difference.
I mean, TLS works on higher layer, the browser decrypts it. If you have access to the browser, and you do, then the traffic is almost transparent for you. Simplest method is devtools and just look at incoming WS messages.
Encryption would be required if there was a danger that a third party was watching the traffic. And there is no third party, there is only WebUI and the user. On the same machine.
I mentioned libsodium
because that can be used to add real security to the communication.
libsodium can work at a lower layer, in WebUI JS and as a shared library, or static linked, but I would prefer this functionality as an addon. Lightweight
is really important.
two files .dll for Windows (total 5 MB), built-in support for almost all Linux distributions (3.x+)
libsodium is less than 0.3 MB
libsodium has ready to use mechanism to exchange async keys, then using those keys exhange actual symmetric encryption key. libsodium uses ChaCha20
(and its variants), many sources say its better than AES. Its fast, its not hardware boosted but really fast. Implementation of ChaCha20 is really small, I mean implementation from scratch, you can fit in 50 lines of code. But along with symmetric encryption you need the keys exchange mechanism, assymetric, so full libsodium lib is needed.
AFAIK TLS uses ChaCha20 among other algos.
The user would see some encrypted meaningless data, 99% of them will give up at at this point. Remaining 1%, well, its their machine, you cant be 100% sure.
For myself, I conceptually realized that the only way to guarantee data security is to use the browser only for input/output via the api from the programming language with all correctness checks and so on on the server (language) side, perceiving the browser side as a hostile environment
Imho thats obvious. You send only the data you want the user to see. And never trust the input, always validate.
I will add here that I think the text editor example
is poorly designed. Its fully written in JS, the only job for the executable is to open the browser. JS should communicate with the app to open the file, read, save, close etc. All the logic should be inside executable. This example shows improper usage of WebUI.
One last thing, in the branch with TLS if you dont provide certificate yourself, it generates 2K self signed cert. How long does it take? 5s? 10s? Kinda long before window shows up. Elliptic curve async keys are generated instantly. Another point for libsodium.
But I wouldnt do it right now, lets release 2.4.0 and think about encryption for next release.
I mean, TLS works on higher layer, the browser decrypts it. If you have access to the browser, and you do, then the traffic is almost transparent for you. Simplest method is devtools and just look at incoming WS messages.
Only if we cram the entire browser side into webasm in the future and a separate direct encryption channel without a browser is implemented
Encryption would be required if there was a danger that a third party was watching the traffic. And there is no third party, there is only WebUI and the user. On the same machine.
There is always a third party :)))))) Or it will definitely appear sooner or later and you need to be fully armed
Lightweight
is really important.
This is actually a killer feature of the library
libsodium has ready to use mechanism to exchange async keys, then using those keys exhange actual symmetric encryption key.
We should probably be talking about implementing TLS 1.3 with the minimum possible amount of code while maintaining the security level
libsodium uses
ChaCha20
(and its variants)
Its a fork of NaCl from djb it implements aes/aegis/chacha20
many sources say its better than AES
This is a controversial statement, rather ChaCha20 provides AES-comparable cryptographic strength at a much higher speed without hardware support. And AES has been and remains the world standard with the widest possible support and implementation.
AFAIK TLS uses ChaCha20 among other algos.
Just the same, Google once pushed it to ensure that its browsers work on mobile devices without hardware support. And now it's in TLS 1.3 only because if there is a critical vulnerability in AES, then there will be somewhere to jump painlessly for a while. All other things being equal, AES will be used with or without hardware support.
Implementation of ChaCha20 is really small, I mean implementation from scratch, you can fit in 50 lines of code. But along with symmetric encryption you need the keys exchange mechanism, assymetric,
Yes, there is much more needed to implement the minimum set of TLS 1.3:
So as they say: The first rule of cryptography club is: never invent a cryptography system yourself The second rule of cryptography club is: never implement a cryptography system yourself
so full libsodium lib is needed.
Exactly.
This example shows improper usage of WebUI
I also don't quite agree, this example involves imagination and makes you evaluate the potential scale, implementation details and security issues, this is the second question in this case
Elliptic curve async keys are generated instantly. Another point for libsodium.
Technically, this can be implemented using any modern reliable crypto library, but the requirement of lightness in combination with the lowest-level implementation of libsodium should give a good effect.
But I wouldnt do it right now, lets release 2.4.0 and think about encryption for next release.
I completely agree
How about we implement ChaCha20
+ Poly1305
(symmetric)?
Lets release 2.4.0 first and then we will discuss security, no rush here, its just about preventing data tampering by the user.
I suggest doing #243, then release. Either send chunked data with JS, or merge data in C (per websocket connection). I guess holding websocket data buffer per connection is easier, and release the data (call handler) if its size reaches the packet length.
How about we implement
ChaCha20
+Poly1305
(symmetric)?
Two questions arise. Firstly, how will a shared secret be generated, which will be used to generate the gamma for the cipher in chacha for both sides (otherwise, why encrypt and spend resources at all if we can just mask), and secondly, how to transmit the generated information about the shared secret, or simply use a secure generation function like curve25519
Lets release 2.4.0 first and then we will discuss security, no rush here, its just about preventing data tampering by the user.
This is just a discussion, not a call to action. For example, I will not help with the c library itself, although I understand a little about the implementation of cryptographic functions.
how will a shared secret be generated
Probably randen-rng is enough.
how to transmit the generated information
After we implemented the Token Secured Requests commit, I can say that only the legit UI can see webui.js
. Which contain the secret token, and in future will also contain the secret generated key.
Probably randen-rng is enough.
This is only enough for the client or server to individually generate some random initial vector or number with some level of cryptographic strength. I mean a shared secret for both the client and the server at the same time.
After we implemented the Token Secured Requests commit, I can say that only the legit UI can see
webui.js
. Which contain the secret token, and in future will also contain the secret generated key.
This is a question of the origin of chicken and egg :) Any wsS connection can only be established on top of an already established secure connection, so token transfer and any such things are already happening inside a secure communication channel.
The only option other than this is hand-to-hand common secret transfer (for example, in the form of a protected parameter when launching the browser, or static/dynamic common secret in webui.js). But in my opinion it must be implemented with widely used standard cryptoprimitive
We all agreed that the best way to secure data transfer between UI and the backend application is through TLS (Already implemented in a separate test branch). But we also agree that implementing TLS involves the OpenSSL library as a third-party dependency, and the statically linked apps will still need the OpenSSL dynamic library. So, to avoid all those TLS complexities and pushed by the idea that WebUI works only on the same local machine, we decided to implement a custom, simple, non-complicated encryption data exchange between UI and backend through non-encrypted WebSocket protocol.
Right now, an attacker with a simple TCP sniffer can detect the Token when running the WebUI app, but using this Token won't work for the attacker because the WebUI app already used it. If we add TLS in the future, it will be even better, as the Token exchange will be done in an encrypted tunnel. So, the attacker should have access to the UI source (Dev-tool) to get the Token... even though the Token is already useless because it's already used.
The Token is safe to be transferred in a non-secured tunnel. Still, it's not a good idea to exchange the secret key in a non-secured tunnel, especially for symmetric cryptography... however, we could start with a simple private key exchange generated by the WebUI (backend) only. We move to another more complex way to make both the backend and UI create the key at the same time. But if the process is more complicated than we taught, let's use TLS and fix this forever.
I'm not a cryptography expert, so all I said is a personal suggestion; it can be correct or wrong.
I'm not a cryptography expert, so all I said is a personal suggestion; it can be correct or wrong.
Everything we talked about and discussed absolutely fits into the scheme intended for implementation. The only difference is in the tasks solved by the proposed security tools:
The only subtlety is that authentication is carried out BEFORE the establishment of a secure connection, during mutual checks and approvals of the parameters of the secure connection (the so-called handshake). I haven't looked at the goals and implementation of the token mechanism in webui yet, but as far as I know, a third-party channel or method is usually used to get a token (OTP). And if its transmission over an open channel is secure and fits into the authentication scheme, then we have implemented (or planned for implementation) all the necessary mechanisms and exactly in the order that provides reasonable sufficient security
And finally, do not forget that secure message transmission is a separate protocol on top of websockets, which requires its own message formats (handshake and session records), as well as processing on both sides (message parsing, errors handling)
But the good news is that the entire implementation of the listed list can really be put in 1k lines of code
I see, thank you @delphius, so the big picture is using Curve25519 + ChaCha20 + Poly1305 in C and JavaScript.
ChaCha20
Useless. Easy key leak and can't authenticate the other parties.ChaCha20 + Poly1305
Useless. Key gets exchanged in plain text.ChaCha20 + Poly1305 + Curve25519
Okay. But need time to implement in C and JS. And it won't be as secure as OpenSSL (HTTPS).Honestly, Using OpenSSL dynamic lib will be less headache, quicker, easier, more secure and still our best option.
ChaCha20
Easy key leak
This is just a mechanism for turning plain text into a cryptographic ciphertext, it does not affect key leakage in any way, it is not intended to solve the problem of preventing leakage or key distribution. The main problem with chacha20, as with any other symmetric encryption algorithm, is that it requires the use of the SAME keys on both sides, while the mechanism for generating and transmitting them between the parties must be secure to prevent leakage (alternatively, they can be transmitted in some other way between the parties)
and can't authenticate the other parties.
The tasks of both chacha20 and poly1305 is not to authenticate the other parties, poly1305 only ensures the immutability of the ciphertext (in the simplest case, as well as the integrity of the open linked data that can be transmitted together with the message), like, for example, md5 hash for files
ChaCha20 + Poly1305
Useless. Key gets exchanged in plain text.
If the keys are not transmitted through an open channel, but in an alternative way (well, if of course it exists), then this bundle is already quite enough
ChaCha20 + Poly1305 + Curve25519
Okay. But need time to implement in C and JS.
This is a bundle that provides a sufficient level of security, used in modern protocols and their implementations, invented and developed specifically for a simpler and more efficient implementation by the famous DJB Only one task remains unsolved by this bundle is authentication of the parties to a secure exchange (sertificate/token/OTP/etc)
- And it won't be as secure as OpenSSL (HTTPS).
It will provide exactly the same level of security of the transmitted information as OpenSSL, since it uses exactly the same set of cryptoprimitives, but the level of resistance to possible attacks, including through side channels, will be lower, due to the fact that the implementation of attack-resistant algorithms and their implementations is the goal and the highest priority of all crypto libraries without exception, and they are constantly being tested and refined by a large community of both developers themselves and business representatives using them to ensure the security of transmitted information, as well as enutziasts exploring the capabilities and durability of such algorithms and most importantly their implementations
Honestly, Using OpenSSL dynamic lib will be less headache, quicker, easier, more secure and still our best option.
The implementation of the specified limited set of cryptoprimitives + protocol is no more complicated than the implementation of the websocket protocol, which was performed on the webui server side. Alternatively, we can implement a switchable socket interceptor, both for the internal implementation and for openssl
p.s. I apologize for misunderstanding some nuances, I am not a native speaker and use a translator
This is just a mechanism for turning plain text into a cryptographic ciphertext
I know, but I meant using ChaCha20 alone is useless as we will share the key in plain text, which basically means the key is leaked... but yes, of course, ChaCha20 is not designed to solve this issue in the first place.
poly1305 is not to authenticate the other parties
I didn't know that. I taught Poly1305 is to verify and authenticate the other parties... Thank you for clarifying this 👍
It will provide exactly the same level of security of the transmitted information as OpenSSL
Except authentication of the parties as you said earlier, it remains unsolved.
is no more complicated than the implementation of the websocket protocol
I'm more worried on the JavaScript implementation, I don't know if there is a stable robust ChaCha20, Poly1305 and Curve25519 JavaScript libraries online.
I apologize for misunderstanding some nuances, I am not a native speaker and use a translator
Don't worry, understandable, you are all good 👍
Except authentication of the parties as you said earlier, it remains unsolved.
Authentication of the parties is performed BEFORE the establishment of a secure connection, only after authentication of the parties there is a transition to encryption, so technically authentication has no effect on the process of secure transmission itself. If authentication was unsuccessful, then the secure connection is simply NOT established and is reset by the party that identified problems with the authentication of the opposite party
But the task of verifying the authenticity of the connection side is relevant within the framework of connection security in general, in most cases, of course, authentication of the called party by the calling party, since almost all such protocols have the client-server format
ChaCha20 + Poly1305 + Curve25519
As @delphius explained this is a complete set and is really secure and battle tested. ChaCha20 is just encryption, Poly1305 is a hash, like md5, and Curve25519 is the elliptic curve i mentioned some time ago. All this is inside libsodium. Its designed in a way you dont make a mistake. libsodium is even included in PHP since ~7, pre-compiled. (yes its fork of NaCl, but NaCl is unfinished)
@hassandraga I can guarantee you, you can have HTTPS and some tokens to ensure webui.js is loaded once, and it will be trivial to get actual source od webui.js.
In the case od WebUI, HTTPS does not make sense AT ALL, really. Do what you want, in 1 day I will write an app to listen the traffic between WebUI <> browser.
You can protect the communication to some extent.
webui.js
can be downloaded once, right? And if there is a page refresh, then new token is generated and webui.js can be downloaded again, right? If no connection to WS = webui.js can be downloaded, once, right? (dont have time to look at the source now)
In this case, I would use this token as key for ChaCha20. It just needs to be 32 bytes. This is really ENOUGH. It will discourage most ppl from trying further.
If you dont want to use Poly1305 with ChaCha20, its ok, any hash will be ok, its just to ensure nobody touched the encrypted data "on the fly". Its not even required in this case, but you can add some SHA3 and it will be ok.
Any encryption "good enough" will be just good enough. Since its all on localhost, if someone really wants to tamper with the traffic, he will, no matter what encryption you implement.
This above is really simple and IMHO "enough", but, here is the second part, to make it even more difficult. Above method will only require you to include some very low in size implementation of ChaCha20. The below, will require libsodium.
One thing to worry about is that token used as key will be transmitted as PLAIN TEXT. BTW I will mention here: I consider TLS as "PLAIN TEXT" too, since its on the same machine AND the browser takes care of it. So anything can see the token. And here comes the "assymetric key exchange system" from libsodium.
Instead of using token as encryption key, you make different key and "do some magic" that is ready to use in libsodium to exchange the "symmetric key".
TLS = no protection at all (ON THE SAME MACHINE) Internal encryption = some protection
@delphius libsodium can be static linked in Pascal, so no worries, I will show you how to do it like I showed you how to static link WebUI 😃
@hassandraga Its available as shared lib, static lib, and pure 100% JS code.
But if using such big library, and its only 0.3 MB, not huge OpenSSL, I still would like to get this as an ADDON. Or make it default built-in and an option to DISABLE it to keep WebUI really "lightweight". For me lightweight is super mega important, what is taking 200 KB anyway? Civet? Or some included C std libs?
In this case, I would use this token as key for ChaCha20
This is also the first thing that came to my mind when I read about the open one-time authentication code that is being transmitted. Although this will essentially be equated to a key leak, but it will be ideal for the task of just masking traffic.
Moreover, the implementation of a full-fledged protocol is not required, it is enough to pass a websocket message through chacha20 and decrypt it on the other side, so we will get rid of the complexity of the protocol over the protocol.
The implementation of message authentication in such a configuration is absolutely meaningless and only a waste of resources (imho)
Instead of using token as encryption key, you make different key and "do some magic" that is ready to use in libsodium to exchange the "symmetric key".
since key premutations are carried out by both sides according to a well-known algorithm and the transmitted public shared initial secret is not tied to an irreversible function, this is also a rather pointless undertaking in fact, well, only if in order to obtain a symmetric encryption key with sufficient cryptographic strength from the crypto material source, but this also will not have any effect on security, except how to solve the problem of disguise
libsodium can be static linked in Pascal, so no worries, I will show you how to do it like I showed you how to static link WebUI
I would prefer just TLS 1.3 implemented on pure Pascal :)
it will be trivial to get actual source od webui.js
I agree, at the end of the day, WebUI apps are using web technologies, so UI
source code and webui.js
source code is visible in the browser.
in 1 day I will write an app to listen the traffic
I'm sure you can 👍
can be downloaded, once, right?
I never tried to protect WebUI apps from a manual "Human" attack, I mean, from someone actually using the machine. Whatever we do, there is always a way, especially for a web app... but instead, I tried to stop/prevent or at least make it harder for an automated unwanted script from talking to the backend. That's it. And I hope the latest Token implementation does the job.
It will discourage most ppl from trying further
That what I wished for by using the token for automated unwanted scripts
TLS = no protection at all (ON THE SAME MACHINE) Since its all on localhost, if someone really wants to tamper with the traffic, he will, no matter what encryption you implement
Let's all agree on this. It will be an excellent ground to make a final decision from. So, why add more complexity and compute time to encrypt and decrypt data in a project that whatever we do will be cracked because it's a localhost web app? And if someone wants the TLS encryption, we can simply add a new compile argument to produce the webui-2-secure
library that uses OpenSSL.
pass a websocket message through chacha20 and decrypt it on the other side
Let's make webui-2
a plain text non-encrypted library, small and fast as possible. And webui-2-secure
a fully TLS encrypted communication library using OpenSSL. What do you think guys?
I would prefer just TLS 1.3 implemented on pure Pascal :)
Even better if WebUI-Secure does this for Pascal, and all other wrappers :)
Let's make webui-2 a plain text non-encrypted library, small and fast as possible. And webui-2-secure a fully TLS encrypted communication library using OpenSSL. What do you think guys?
TLS will protect from seeing the traffic by the sniffers, and protecting the token. So maybe also add encryption of websocket messages using the token as the key? So the messages cant be seen in devtools.
Im ok with 2 versions, TLS and no TLS.
I have an idea where TLS will be actually required, but its for later 🙃
Good. I will implement TLS.
Even better if WebUI-Secure does this for Pascal, and all other wrappers :)
Yes, shure :)
I meant that today, as far as I know, there are no full-fledged TLS implementations in pure Pascal, otherwise I would not have to make my own Pascal TLS PoC https://github.com/delphius/fpmtls
I have an idea where TLS will be actually required, but its for later
Solid riddles :)
TLS is fully implemented. By default, WebUI generate a self-signed certificate, so browsers may show a warning. But user can use his own trusted certificate if needed. webui_set_tls_certificate(certificate_pem, private_key_pem)
.
Also, I updated the TLS code to support OpenSSL 3.x.
Since the library implements a scheme of not purely intra-process, but inter-process interaction via websockets (over tcp/ip), then in industrial use the question arises of protecting the transmitted data (ssl/tls/etc) within the means provided by the library. Has someone already solved this issue or approached at least conceptually?
On the surface lies the option of using an alternative secure connection over any protocol between the program and the browser, but then some of the meaning embedded in the library is lost. By leaving the connection unprotected, we endanger the reading/manipulation of the transmitted data between the frontend and the backend
On the other hand, all processes and interactions take place within the same operating system and on localhost, so the question may not be very relevant. Who thinks what?