Re: Work.ink's JWTs
This article is intended as a response to a blog post by a third party that's claiming that work.ink's authentication is insecure, which is not true.
Recently, a blog post has surfaced containing misinformation of work.ink's safety and integrity. This blog article is based on the claim that JWTs using HS256 are insecure, showing that the author of the article does not seem to have a basic understanding of cryptology and the concept of JWTs as a whole.
TL;DR / Conclusion can be found at the bottom of this article.
What is a JWT?
A JWT (JSON Web Token) is a compact, secure way to transport data between trusted parties through untrusted parties. The token can contain any data (at least if it is safe to show in public) that services use for authentication of e. g. a user. Moreover, a JWT contains a signature, used to verify the authenticity of the token. This signature is generated by a trusted party and can be checked only by a trusted party using a high-entropy secret key.
This is what a JWT looks like:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30The individual parts of the token are separated by dots. The parts are:
<Metadata about the Token>.<Actual Data that's shared with the trusted party>.<Signature>The Metadata as well as the actual data in the token are both base64 encoded JSON strings. This means, that this data can be decoded and would be the following for the example token:
// JWT Metadata
{
"alg": "HS256",
"typ": "JWT"
}
// Data
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}As you can see, this token is using the HS256 algorithm for the signature and is assigned to a user named John Doe that has admin rights.
Now to the part that makes this actually secure to use: The signature.
When a server generates a token a high-entropy (basically just really long) secret key is used to sign the token. This then results in the last part of the token.
You can learn more about JWTs on their official website.
The Signature
The signature can then be used by the same, or another, server that knows the secret key to validate the tokens authenticity. If you don't know the secret key, you can't fake a token. If the token's signature doesn't match the servers secret, the server will reject it.
Now you might be asking: But what about cracking the secret key?
That isn't really an option either as will be explained in the following:
The Basics of Signing
This is not a deep dive into cryptology and signing. There is much more to understand about this. This offers a nice overview over the topic as a whole.
As the author of the article doesn't seem to understand the basic concepts modern cryptology, I'll explain it here:
Signing something basically means taking the text contents of it and mangling that exact text through an algorithm to a point where you are not able to derive the secret key from it without impossibly high expense. In our case the algorithm used is HS256, which is the current standard for JWTs and is used by pretty much anyone using JWTs for authentication.
This works by first taking the text and the secret key and combining them using an algorithm. This then results in new data that would still be relatively easy to derive the secret key from. This data is then applied to a SHA256 function, creating a hash that is not possible to reverse to the secret key, as information needed to do that is partially gone and the expense of doing this to get a list of possible secrets is not possible to be supplied with our current, as well as future technology.
So let's have a look at work.ink's JWTs.
JWT on work.ink is secure
Work.ink uses a high entropy key. We won't tell you the exact length of it to keep it more secure, even though it wouldn't even be helpful as there are just to many possibilities for what it could be anyways. So let's assume we use a 64 character token. Each character has 62 possible values, if we assumed that we're only using the alphabet and numbers. This means that there are 62^64 possible tokens. In decimal that would be 5164973859965249179065154939717494269947658426266553960878244596268481614842987330263563657801857314603738370932736. That's an astronomically high number.
For comparison, there are roughly 10^23 grains of sand on earth, according to estimations. That's significantly less. As a decimal number: 100000000000000000000000.
As you can see, this wouldn't be fun to do with a pen and paper. But what about computers, even datacenters? Aren't they fast enough to do it, if we took the entire computing power of the world and used it for a single work.ink JWT?
Let's assume the entire world could test 10^25 Hashes/Second (that's a ridiculously overestimated number).
We can simply divide both values to see what happens: 62^64 / 10^25 = 2 * 1095^ Seconds. Let's see what that is in years: 10^95 / (60 * 60 * 24 * 365) = 6 * 10^87 Years. That's this many zeroes: 600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Years.
As you can see, while it is technically possible to crack a JWT, it is practically not possible to do. As another point of reference: The universe exists since 13800000000 Years. And to me at least, this already seems like a long time.
So, finally, we can finally say the claim that correctly implemented JWTs are easily crackable, as was hinted by the author in a message, is in fact not true.
But what if it suddenly was possible to do?
Then work.ink is the least of your worries. Every single website that uses OAuth (a widespread login standard) in the Login flow (e. g. Google, Microsoft, Meta, Instagram, Discord, ... as well as internal tools of Companies and Governments) could easily be hacked. Every time you see a Log in using ..., that's an OAuth login. Think about how often you have used one and where you used one already. That would be all gone.
And not only that. Everything using JWTs would be hackable. That could be literally anything. JWTs are wide-spread.
But what if the secret key gets leaked?
It doesn't. There are standards in place to prevent exactly this from happening used by by pretty much everyone that's building a distributed system. If the secret key actually gets leaked, the consequences would be catastrophic. Same thing is valid for every other company.
If a secret of a Google service got leaked, it would have the same consequences as for us. If the secret key of any service gets leaked, it would be the same disaster for every single company.
That's why on distributed systems like work.ink there are special secret stores in place, that keep such secrets safe from anything reading it, that doesn't need it. Those secret stores are the same used in any other distributes system like Google, Instagram, Discord, etc.
If you want to know more about how a secret store works, you can read more here in the Kubernetes docs.
TL;DR
It's not possible to crack HS256 JWTs with high entropy secrets. Work.ink uses a high-entropy secret. It's a literal standard. Everything is secure. The original blog post is basically saying: "If I knew your password, I could easily hack you."