|
|
Joined: Dec 2002
Posts: 3,896
Hoopy frood
|
OP
Hoopy frood
Joined: Dec 2002
Posts: 3,896 |
Hello all, I am currently looking into possibly adding FiSH encryption support to mIRC. FiSH has been discussed on the forums before, however I have never used it myself, so it is somewhat new to me. As a first step, I used the source code for FiSH 10 by flakes at https://github.com/flakes/mirc_fish_10 to compile a .lib for use by mIRC to see how that would work out. Note: If anyone knows how I can contact flakes, please let me know, as I could not find contact details. FiSH 10 integration notes: 1) While the FiSH 10 source code is freely usable, some functions are GPL. I initially tested everything with the GPL code in place to make sure it was working correctly. The GPL functions have now been replaced with non-GPL code. 2) Some of the FiSH 10 code uses APIs deprecated in OpenSSL 3.x. I tested these as-is to make sure FiSH was working correctly. I then updated all code to use non-deprecated APIs, which took a fair bit of work and testing. 3) Blowfish is no longer supported by default in OpenSSL 3.x. so OpenSSL had to be recompiled with support for weak ciphers. It would make sense to move to AES256CBC/GCM but this would break compatibility. 4) Removed the injection/hook-related code. 5) Added the calls _OnIncomingIRCLine() and _OnOutgoingIRCLine() to the incoming and outgoing line parsing functions in mIRC, allowing them to work more or less in the same place as the FiSH 10 injection code, ie. just before/after the send()/recv() calls are made. For testing purposes, made changes to allow the beta to work with the fish_10.mrc script without requiring changes to the script: 6) /dll and $dll now check if fish_inject.dll or fish_10.dll are being called and simulate / redirect them to the equivalent FiSH 10 functions in mIRC, including calls to LoadDLL and UnloadDLL. Having confirmed it is all working, this raises a few questions: 7) The main issue holding me back from adding support for this is that it needs to be usable by non-techies. This means that once DH keys are exchanged, the user must be guided/reminded/required, in the same way as eg. Pidgin, to confirm that they have authenticated before continuing to chat, since MITM on an IRC server would be trivial. On most platforms, authentication is through manual verification of a shared secret/password/safety number/etc. On IRC, users will need to make direct contact to do this, possibly confirmed in-client, eg. socialist millionare protocol, in the same way that Pidgin visually marks a chat window as "unverified", until users manually authenticate, and then marks the window as "private". 8) If I decide not to add support for it, I could add various plugin APIs that eg. enable a FiSH DLL to parse incoming and outgoing lines, so it would no longer need to inject or hook into mIRC. 9) The FiSH key exchange currently uses DH 1080 bits. This is not good enough nowadays and should probably be changed to DH X25519. Increasing the key size would break backward compatibility. There are FiSH implementations that use X25519 and ChaCha20-Poly1305 (instead of AESGCM) for authenticated encryption. As I have not used FiSH before, I'd be happy to receive feedback and suggestions from existing users. Can FiSH 10 be improved? What changes have you made to your FiSH 10 script to enhance it? Perhaps these can be integrated. In any case, this is just experimental for now and there are no definitive plans. I may release a beta with the above changes at some point.
Last edited by Khaled; 11/03/26 07:05 AM.
|
|
|
|
|
Joined: Feb 2011
Posts: 481
Pan-dimensional mouse
|
Pan-dimensional mouse
Joined: Feb 2011
Posts: 481 |
Try flakes email is in the git logs?
``` commit 9b7b98e6370f4f4c6c07901fb5e70383918da18e (HEAD -> master, origin/master, origin/HEAD) Author: flakes <emailaddress> Date: Sat Jul 8 08:45:57 2023 +0200
New release for mIRC 7.73+ with OpenSSL 3.0 ```
Last edited by Khaled; 07/03/26 01:15 PM. Reason: Thanks!
|
|
|
|
|
Joined: Dec 2002
Posts: 3,896
Hoopy frood
|
OP
Hoopy frood
Joined: Dec 2002
Posts: 3,896 |
A quick update on this: I haven't received a reply from flakes, however their last update to FiSH 10 was in 2023, so it may be that they are no longer updating it. There have been a large number of FiSH projects for different clients over the years, a few of which are on github. One of them, mIRC FiSH 11, written in Rust, is a modern update that uses X25519 and ChaCha20-Poly1305. Unfortunately, I couldn't get it to work. I also noticed that some (perhaps older?) FiSH implementations of blowfish CBC are not compatible with each other. I have continued updating/testing the FiSH 10 source code. Functions for AES-GCM and ChaCha20-Poly1305 authenticated encryption have been added, as well as X25519 key exchange and Socialist Millionare Protocol. However, these have not yet been integrated into FiSH 10, eg. DH1080 currently uses events such as DH1080_INIT, DH1080_FINISH, etc. and +OK as a prefix to blowfish encrypted text. It is likely new events will be needed, such as X25519_INIT, X25519_FINISH, etc. and +AES and +CHA as prefixes to encrypted text. Extending FiSH 10 to support these will need some significant changes to the FiSH 10 code. For the Socialist Millionare Protocol, I would need to add new events as it has several separate steps of back and forth between two parties to authenticate a secret. Users still need to share that secret out-of-band. I also expect to update the fish_10.mrc script to handle these changes. Once I have verified everything is working, I will likely add native FiSH events/menus/dialogs to mIRC to mimick the script. If you try out Pidgin with OTR, you'll get an idea of how it would work. Using OTR would have been a possibility but it is LGPL, so mIRC cannot link to it statically. This means it would need to be included as a separate DLL, something that I have avoided with mIRC so far. That said, it has not been updated in many years and OTR4 is in draft and development seems to have stalled some time ago. Update: libotr also has a GPL libgcrypt dependency which would take a fair bit of work to replace with OpenSSL. The development of IRCSRP also seems to have stopped a long time ago. This is going to take a fair bit of work, so if you have ideas/comments/suggestions, now is probably the time to make them :-)
Last edited by Khaled; 24/03/26 06:39 PM.
|
|
|
|
|
Joined: Mar 2026
Posts: 1
Mostly harmless
|
Mostly harmless
Joined: Mar 2026
Posts: 1 |
Dear Khaled, in January, I was messing around for several days with Mircryption, which was a non-dll-inject/exe-patch-solution to integrate Blowfish-Channel-En-/Decryption, PM-en-/Decryption and DH1080-key-exchange (as well as the older DH1024) into mIRC. It didn't work with scripts using on_text events etc. (in case of encrypted texts) but integrated its own Signals: on *:SIGNAL:MircryptionSignalAll: {
;$1 = event type (input,text,query,notice,action,join,topic,part,kick,quit,nick,mode)
;$2 = target ($chan)
;$3 = speaker ($nick)
;$4 = is $true if text was encrypted or $false if plaintext
;$5- = decrypted text
;/echo TRAPPED MircryptionSignalAll: event: $1 , target: $2 , speaker: $3 , encrypted: $4, firstword = $5, text: $5-as well as /esay and /emsg to make scripts send encrypted. (maybe also /enotice?) The compatibility to glftpd's sitebot pzs-ng was so horribly broken, that it refused to send any texts to me or even invite me... This sitebot can switch between 3 different blowfish implementations, so it might also be worth taking a look how they do it? I couldn't find a proper "Standard" telling how the key exchange and message en- and decryption should be done properly. I just found statements like "we do it as implemented by them, because they were first." It looks like, as long as we stay with ECB, all works fine. When it comes to CBC, Mircryption uses DH1080_INIT_cbc <pubKey>, but Fish uses DH1080_INIT <pubKey> CBC. They TELL that they want to use CBC. While other implementations just exchange it as it was ECB (default) mode. And then default to CBC. And detect encrypted messages of style "+OK *<encryptedBytes>===...=" (so starting with *, ending with =s) as CBC. You can find a summary of my findings in the issue I created in their repo. My suggestions would be: - If you want to integrate other key exchange methods than DH1080, use other Notices. - If other implementations already use some, use those (or at least make you implementation being able to detect and answer properly to those), for compatibility reasons. - Don't make your users download OpenSSL from somewhere and use the cryptographic implementations from there. better ship it with your Installer. OpenSSL seems to like to just drop compatibility for old Algorithms, when they are no longer secure enough. While users tend to disable cryptography, when it doesn't work. It took me some time to find a version that still works with FTPServers using 0.98, as well with those using the latest - It would be nice to have a "flag" in the events telling if a text was encrypted or not. Like $4 in MircryptionSignalAll. - Fish_10 uses a message text suffix to tell "this was encrypted". Mircryption uses different nickname brackets, which I prefer (I once had white brackets for usual messages, green for encrypted ones) - When you're not sure which new algorithms you would like mIRC to use, mozillla's recommendations and BSI-TR-02102-2 are a good resource (can you just pipe the 2nd one through deepl?) - Make it backwards compatible. What I mean: When another client doesn't react to your key exchange, use a weaker one and maybe warn the user ("weak key exchange"). If a user answers with ECB finish to a CBC init, just use the ECB one. If he starts texting without the * (cbc indication), just decrypt it and warn. There are already too many implementations that make problems when interacting with each other and the user then just disables it because he doesn't know what's wrong But that's just my limited view on the topic, you're the boss 
|
|
|
|
|
Joined: Dec 2002
Posts: 3,896
Hoopy frood
|
OP
Hoopy frood
Joined: Dec 2002
Posts: 3,896 |
Thanks for your feedback and suggestions, much appreciated 👍
|
|
|
|
|
Joined: Dec 2002
Posts: 3,896
Hoopy frood
|
OP
Hoopy frood
Joined: Dec 2002
Posts: 3,896 |
FiSH/SMP update/notes/observations:
FiSH uses NOTICE for the key exchange, so it needs both NOTICE and PRIVMSG to work. I can understand why this was chosen at the time but if I was going to implement it today, for an IRC client, just using a PRIVMSG would make more sense and perhaps CTCP, which was designed for direct client-to-client messages to distinguish them from normal messages. OTR, for example, sends a PRIVMSG with the ?OTR? prefix, so everything takes place in the same message context. This format could then also have been used in DCC Send/Chat.
Another issue is that a NOTICE is usually meant to get attention. An unrecognized CTCP message is often just printed quietly in the server window. If a non-keyexchange/encryption supporting client receives an unrecognized NOTICE, this will be a lot more annoying than a CTCP message. This is important because one of the FiSH features that can be enabled is to send a key exchange request automatically if a user tries to message you and you do not have keys set up for them.
Another issue is that with the current protocol, the initiating client sends DH1080_INIT and the receiving client sends DH1080_FINISH. For any number of reasons, the initiating client may reject the DH_1080_FINISH, causing the key exchange to fail, but only they will know this. The receiving client can only assume that everything went well. It would have made sense for the initiating client to send one more DH1080_FINISH as a final confirmation. From a user point of view, the initiating client will print "*** Key exchange: successful" or "*** Key exchange: fail". The receiving client can only display "*** Key exchange: sent reply" without confirmation of success. That said, at worst (assuming this wasn't an intentional failure/downgrade forced by an MITM), the receiving client will send encrypted messages that the sending client cannot decrypt.
FiSH uses named events DH1080_INIT / DH1080_FINISH for key exchange. To add a new key exchange method, we have to add more named events, eg. X25519_INIT / X25519_FINISH (like some newer FiSH implementations). It might have been better to use a generic named event such as FISH_INIT/FISH_FINISH which could then be used to negotiate both key exchange and encryption methods. Or just an OTR-style prefix like ?FiSH?. As it is, I have added new X25519_INIT / X25519_FINISH events. But this means that we will need to add even more events if we want to add new key exchange / encryption methods. Ideally, FiSH would be updated to use a new, forward-looking key exchange / encryption protocol but this would break backward compatibility.
One other option is to just extend DH1080_INIT. We can avoid adding more events and just treat the DH1080_INIT / DH1080_FINISH as generic events. A client can send DH1080_INIT as usual but append tags, such as X25519 CHAHCA20-POLY1305 AES-GCM, to the message, just like "CBC" is appended currently. If a client wants to use a particular encryption method, it includes its tag in the reply to DH1080_FINISH. If it wants to use a different key exchange method, it can restart the key exchange by replying with DH1080_INIT X25519, and the initiating client will resend DH1080_INIT with an X25519 key. As far as I can see, this should be fully backward compatible while supporting new key exchange / encryption methods. At the cost of being a bit of a hack :-]
SMP notes:
Socialist Millionare Protocol (SMP) requires five steps of back and forth messages and I had to choose to use either NOTICEs or PRIVMSGs. Ideally, this would have used CTCP PRIVMSGs but seeing as FiSH uses NOTICE for key exchange, I have opted for NOTICE as well. One thing to note is that FiSH encrypts PRIVMSGs by default post-key exchange but not NOTICEs. Technically, SMP does not need to be encrypted. I created new events SMP_INIT / SMP_REPLY / SMP_FINISH. SMP uses the group 2 1536-bit prime from RFC 3526, which is 192-bytes long. During the SMP exchange between clients, each message can be much longer the standard 512 byte limit. So this requires multiple NOTICEs per message, each containing part of the encoded message, that are assembled at the end of that sequence to be used in that SMP computation step. Since SMP requires five steps, each of which need 2-5 NOTICEs to transmit the full line, the total number of NOTICEs sent can be fifteen or more. That's... not great.
Note that this is different to how OTR uses SMP. OTR first creates private/public DSA keys that it then uses to establish long-term identification of parties and binding/signing of the initial session (Trust On First Use) and securing the SMP (if the user chooses to use it by verifying a secret) to prevent MITM. In mIRC's case, we are not generating private/public keys and the SMP is not secure - an MITM could simply pass it unchanged between parties to make us think they are not there. What SMP does, even with MITM, is verify a shared secret. I could add support for DSA keys but, at that point, I would essentially be re-inventing OTR. Considering that I was only planning on adding support for FiSH...
An alternative to SMP: CPace, which is a recommended modern balanced PAKE, that integrates authentication with key exchange, and requires fewer messages/steps than SMP. A user supplies a password, the key exchange is initiated, the other user supplies a password, if they match, both key exchange and authentication complete and the keys are secure. The difference here is that users are required to perform password authentication from the start. With OTR, authentication with SMP is optional after key exchange, to make the process user-friendly. Technically, we could still implement this as 1) perform a normal DH1080 key exchange without password authentication, which is susceptible to MITM and then 2) allow password authentication using CPace which guarantees secure keys.
Perhaps establishing a well thought out, standardised protocol for key exchange / encryption negotiation for IRC clients might be something for IRCv3.
Using SMP/CPace leads to another issue: these require the receiving client to answer a question to complete verification. A dialog suddenly popping up in your client on request from another user is probably not a good idea, so this needs to be implemented in a way that can't be spammed but is easy for non-techies to use. The developers of OTR already went through this entire process and published papers about it. The Pidgin OTR plugin adds visual cues/buttons to the chat window to let a user know that their chat is/is not secure/verified. I have intentionally tried to keep mIRC's GUI/windows minimalist / unencumbered by visual weight (which admittedly is not user-friendly - I expect most users have to be told that they can find window settings in the System menu), so adding a secure/verify visual button/cue to a query/chat window is going to be a challenge - there is no point in adding it if it isn't at least a little bit annoying and doesn't stand out. Users have to know that their session, even though encrypted, is actually not secure.
In any case, I am currently working on a CPace implementation.
Last edited by Khaled; 29/03/26 06:57 PM.
|
|
|
|
|