-
Notifications
You must be signed in to change notification settings - Fork 557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SIP007 - Per-session subkey #42
Comments
LGTM. +1. I suggest to follow the naming convention |
@wongsyrone HKDF has two phases: extract and expand, which allows the input keying material to be weak. My understanding is that The protocol mostly stays the same. This SIP only changes how the cipher key is generated. @madeye I'm wondering if we should amend SIP004 to force the new design at least for AEAD ciphers since it's pretty new and AEAD ciphers are more vulnerable to nonce reuse. For stream ciphers, we definitely need the prefix. |
@riobard I'm fine with it. AEAD is still in pre-release stage, so I think we are safe now. |
@wongsyrone HKDF is very easy to implement. Here is one based on mbedtls: https://github.com/thomas-fossati/mbedtls/blob/2bf438d7d6906b753fe1ffe615eb2467353a1a78/library/hkdf.c |
@wongsyrone I think you mean "not that random" salt in broken clients? Yes, it's still a problem. |
Alright, I guess the right plan is to amend SIP004 with SIP007 and rewrite AEAD ciphers to use the new construction and provide additional stream ciphers. I'm not familiar with C, but in other higher-level languages like Go and Python, using HKDF is very simple. You can pick your own hash function. SHA1 is just a conservative choice. |
Updated the proposal to include guidance on the length of random salt. |
Actually it's an open pull request for mbedtls. Mbed-TLS/mbedtls#542 After reviewing the code, I think the implementation is very solid. |
It depends. If we don't have better library for HKDF, I'll directly implement it in shadowsocks, like what we are doing for PBKDF currently. |
I have implemented AEAD ciphers with subkey here https://github.com/riobard/go-shadowsocks2/tree/sip007 |
I applied similar treatment to derive a new subkey for each UDP packet with nonce setting to all zero. Also, I think it's pointless to retrofit the old stream ciphers with the session key. If people want better security, they should use AEAD ciphers anyway. Less compatibility headache. |
@riobard OK. Let's only apply this on AEAD. |
@madeye Could you please test the interoperability once you finish the changes in shadowsocks-libev? I think I've implemented this SIP correctly, but without another reference point, it's not guaranteed. Let me know if there's any problem. |
Thanks. I'm working on it. |
Don't remove original stream ciphers, not everyone think they need the extra security. PS: |
The new AEAD ciphers actually perform very well on modern devices. On my machines, AES-128-GCM gives me about 2x the throughput of AES-128-CTR and AES-128-CFB. I've actually written my own implementation of ShadowVPN (with some experimental changes) in Go. However, UDP traffic is heavily throttled on many ISPs, making it less viable for widespread adoption. That's why I'm back to Shadowsocks. |
One TCP connection with one tunnelled TCP connection would be better. And from my currently knowledge, no VPN supports this . AES-128-GCM is good, but I'm using AES-256-CFB now which is a silly choice made year ago before knowing more. And ChaCha20 with authentication is a little slower from the benchmark in the ss-libev issue #1173. Current Shadowsocks client on Windows is just a proxy front end, not very convenient in some case. And my router doesn't have TPROXY module for UDP redirection. This is my first motive to see how ShadowVPN works. And I think UDP with an auto BBR-like congestion control method is great and may help uploading on OSes which don't support BBR. KCP has too many parameters which need some tweak time. UDP may working better in some ISPs. But I don't have the capability to implement this. |
TCP over TCP is bad for performance. KCP basically moves the congestion control from kernel to userspace, making it easier for people to experiment. However this empowerment comes with great danger that selfish people would abuse available bandwidth and we all suffer as a result. That's why fairness is a core concern in TCP. |
Great! |
Fairness protocols in subscriber sides just save ISP's efforts to improve router design. |
I'm afraid the Internet doesn't work that way. The only thing to happen for sure is even worse QoS on all traffic. |
I wonder what convention. |
@Mygod Never mind. We don't need to change any cipher name now. All AEAD ciphers are forced to use per-session subkey. |
Hmm okay. However has the downside of this proposal been discussed? This proposal effectively introduces the risk of skey collisions and leaves a large space of nonce unused for most (if not all) of the time. |
With random salt at minimal 128-bit, the probability of session key collision is negligible. And you can always use 192 or 256-bit key (which will in turn use 192/256-bit salt). |
OK, so the server and client both use the same derived key, and with the same nounce? That is a key-nounce reuse vulnerability. If I don't get it wrong, the reuse is also present in old design, but as we are devising a brand new protocol here, it should fixed. The server and client should have different subkey by having different "info" argument. |
@netheril96 The two directions of one TCP stream are totally independent. It means their salts and subkeys are also generated from different random bytes. |
@madeye Is that also the case in the old protocol? Please update the documentation on the spec to clarify this, because I read it several times, and found no evidence of independent IVs in the design. |
|
Finalized in https://shadowsocks.org/en/spec/AEAD-Ciphers.html |
According to the spec https://shadowsocks.org/en/spec/AEAD-Ciphers.html |
Yes, because we do not have any associated data (yet). |
Exactly, |
Question from 2019: do we need to worry about the fact the key derivation uses SHA1, given that it's known to be broken? |
Well, it seems I found my answer: https://crypto.stackexchange.com/questions/26510/why-is-hmac-sha1-still-considered-secure HMAC-SHA1 seems to still be secure, which is what we seem to use. |
Background
As discussed in #36 and #40, currently Shadowsocks has a fundamental design flaw of potential key-nonce pair reuse. Specifically, we are using a long-term M-bit pre-shared key and N-bit random nonces, resulting in a (M+N)-bit key-nonce pair containing only N-bit randomness, where N is usually insufficient (N < 128).
#36 proposed to deprecate ciphers where N <= 96, which unfortunately eliminated many good ciphers like Chacha20 and Chacha20-Poly1305 where N=64. However the problem still exists, albeit at slightly lower probability. Even when N=96, there are practical concerns about the safety margin. Needless to say, we are operating against best practices and security recommendations.
#40 identified the design flaw and paved the way to this SIP.
Proposal
I propose to introduce a per-session subkey derived from the pre-shared master key using HKDF, and use the subkey to encrypt/decrypt in both stream ciphers and AEAD ciphers. Essentially it means we are moving from (M+N)-bit (PSK, nonce) pair to (M+N)-bit (HKDF(PSK, salt), nonce) pair. Because HKDF is a PRF, the new construction significantly expands the amount of randomness (from N to at least M where M is much greater than N), thus correcting the previously mentioned design flaw.
Additionally, because the pre-shared key is usually generated from a human-chosen text password of insufficient entropy, the result is not very strong. HKDF gives us the benefit of producing cryptographically strong derived keys even if the input master key is weak.
Details
Assuming we already have a user-supplied pre-shared master key PSK.
Function HKDF_SHA1 is a HKDF constructed using SHA1 hash. Its signature is
The "info" string argument allows us to bind the derived subkey to a specific application context.
For stream ciphers, the revised encryption scheme is:
Note that even with the above changes, the old approach using stream ciphers is still not secure. We encourage users to switch to AEAD ciphers as soon as possible.
For compatibility reasons, we will probably NOT adding per-session key to stream ciphers.
For AEAD ciphers, the revised encryption scheme is:
The text was updated successfully, but these errors were encountered: