Does appending randomness to a token before encrypting it, make it more secure?
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
Scenario:
- User requests page on my site
- Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
- Token is embedded into link on page
- When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them. Apart from allowing the same request to be replayed against the endpoint ad infinitum, this makes it more likely that someone will be able to break the token encryption (yes, I know this isn't likely, but it is possible).
To make the encryption even more resilient, my intention is to insert a high-quality random value - say a GUID - into the token before it is encrypted. The end result will be to introduce more entropy into the encryption process, meaning that for a given set of identical values that we care about (i.e. everything except the random value), the generated token will almost certainly differ. This random value will always be inserted in the same place and will always be the same length, so removing and throwing it away after the token is decrypted is trivial. Effectively, this is augmenting encryption with obfuscation.
It appears to my untrained eye that this is a relatively simple and safe solution to my problem, but is it, or am I just wasting my time and/or making things less secure and more complicated?
encryption obfuscation
add a comment |Â
up vote
5
down vote
favorite
Scenario:
- User requests page on my site
- Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
- Token is embedded into link on page
- When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them. Apart from allowing the same request to be replayed against the endpoint ad infinitum, this makes it more likely that someone will be able to break the token encryption (yes, I know this isn't likely, but it is possible).
To make the encryption even more resilient, my intention is to insert a high-quality random value - say a GUID - into the token before it is encrypted. The end result will be to introduce more entropy into the encryption process, meaning that for a given set of identical values that we care about (i.e. everything except the random value), the generated token will almost certainly differ. This random value will always be inserted in the same place and will always be the same length, so removing and throwing it away after the token is decrypted is trivial. Effectively, this is augmenting encryption with obfuscation.
It appears to my untrained eye that this is a relatively simple and safe solution to my problem, but is it, or am I just wasting my time and/or making things less secure and more complicated?
encryption obfuscation
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
1
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
Scenario:
- User requests page on my site
- Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
- Token is embedded into link on page
- When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them. Apart from allowing the same request to be replayed against the endpoint ad infinitum, this makes it more likely that someone will be able to break the token encryption (yes, I know this isn't likely, but it is possible).
To make the encryption even more resilient, my intention is to insert a high-quality random value - say a GUID - into the token before it is encrypted. The end result will be to introduce more entropy into the encryption process, meaning that for a given set of identical values that we care about (i.e. everything except the random value), the generated token will almost certainly differ. This random value will always be inserted in the same place and will always be the same length, so removing and throwing it away after the token is decrypted is trivial. Effectively, this is augmenting encryption with obfuscation.
It appears to my untrained eye that this is a relatively simple and safe solution to my problem, but is it, or am I just wasting my time and/or making things less secure and more complicated?
encryption obfuscation
Scenario:
- User requests page on my site
- Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
- Token is embedded into link on page
- When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them. Apart from allowing the same request to be replayed against the endpoint ad infinitum, this makes it more likely that someone will be able to break the token encryption (yes, I know this isn't likely, but it is possible).
To make the encryption even more resilient, my intention is to insert a high-quality random value - say a GUID - into the token before it is encrypted. The end result will be to introduce more entropy into the encryption process, meaning that for a given set of identical values that we care about (i.e. everything except the random value), the generated token will almost certainly differ. This random value will always be inserted in the same place and will always be the same length, so removing and throwing it away after the token is decrypted is trivial. Effectively, this is augmenting encryption with obfuscation.
It appears to my untrained eye that this is a relatively simple and safe solution to my problem, but is it, or am I just wasting my time and/or making things less secure and more complicated?
encryption obfuscation
asked Aug 30 at 14:23


Ian Kemp
1567
1567
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
1
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51
add a comment |Â
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
1
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
1
1
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
15
down vote
accepted
You don't need to add any randomness to an encrypted token. If it's properly encrypted, user has no way to infer anything about the encrypted data.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them.
This seems odd. Your encryption does not seem to use a secure standard. Otherwise every time you encrypted the same token, the cyphertext would change. You must use an IV, and never ever think about AES-ECB, that mode is broken and should not be used even to teach kids how AES works.
If you use industry standards, you will know about the Initialization Vector (IV). In rough terms, the IV is a value added to the process that changes the cyphertext, so even if you encrypt two identical plaintexts with the same key, the corresponding cyphertext will change.
The IV is the random data you are thinking about adding. It's already there.
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
add a comment |Â
up vote
4
down vote
Let's try to break this down:
Problem: replaying a token:
Apart from allowing the same request to be replayed against the endpoint ad infinitum
Usually auth tokens solve this problem by expiring the tokens: the encrypted data includes a datestamp (which has the side-effect of making each token unique) and the server will reject any token older than, say 15 minutes.
Problem: breaking crypto:
this makes it more likely that someone will be able to break the token encryption
I'm not an expert, but it would seem to me that you should use a random IV for each encryption, and include the IV with the cipher text as part of the token. This would both solve the cryptanalysis problem you're alluding to, and have the side-effect of making your tokens unique. (if you're not using random IVs, then you probably have much bigger problems on your hands)
Why not use a standard library to do this rather than going out of your depth to design your own encryption scheme? I would recommend JWT.
Finally, as a public service I need to correct this: GUIDs ARE NOT HIGH-QUALITY RANDOMNESS.
See Wikipedia/Universally_unique_identifier.
UUIDs / GUIDs are designed to be unique, they make no attempt to be unpredictable. There are 5 standard ways to derive a UUID; 4 of them are some combination of MAC address + hostname + timestamp. Version 4 UUIDs are pure random, but because UUIDs / GUIDs generation needs to be fast and non-blocking, they use non-cryptographic random number generators.
PLEASE DO NOT USE UUIDs / GUIDs AS A SOURCE OF CRYPTOGRAPHIC RANDOMNESS. Instead use /dev/random
in unix, SecureRandom
in java, or whatever the equivalent is in your OS / programming language
2
don't you mean/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.
– dandavis
Aug 30 at 18:45
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.random
is safer but may have performance issues,urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes/dev/random
and/dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.
– Mike Ounsworth
Aug 30 at 18:56
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
add a comment |Â
up vote
1
down vote
The solution that is used on my platform of choice is "encrypt/decrypt with managed IV (Initialization Vector)." What this means is that, upon encryption, the entire plain text is encrypted with a cryptographic secure IV, and then the IV is placed in base64-format before the beginning of the cipher text. Upon decryption, the IV is pulled off the front and used as the IV for the cipher text. This is all transparent to the developer. Note that it is perfectly safe to expose the IV, because decryption with the correct key but wrong IV will result in a failure condition. If your programming language has a similar feature, do use it; by having a random IV generated each time you encrypt something, you don't need to put any extra data in the plain text.
add a comment |Â
up vote
0
down vote
To me, this looks like an XY Problem.
The best way to protect a secret is not to tell anyone the secret. The token is generated server-side. The server already knows the data. And then you replay the token to the server, which contains only data the server already has. That is completely unnecessary.
Other answers have pointed out the quick, immediate fix for your encryption problem by using encryption with IVs. But the better solution would be to make this superfluous.
Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
Instead of encrypting those values, save them in a database. You can potentially, if you really must, still encrypt those values and then save them. But there is absolutely no need for these values to ever leave the server, even in encrypted form.
Then generate a truly random token (with a CSPRNG), and use that as a lookup-key. Send this token to the client.
Token is embedded into link on page
Use the random token you just generated for that.
When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
Instead of decrypting and parsing the values, you use the token to look them up in the database. Done. If you only stored the data encrypted, you still need to decrypt it, of course.
This also works if you have multiple servers. If the token is generated on Server A and send to Server B, have Server B use a secure connection to Server A and request the data via the token from Server A. In this scenario, too, the data is never sent to the client.
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings
Internal state should never leak from an implementation. This is already a code smell and a good hint that your architecture is flawed.
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
15
down vote
accepted
You don't need to add any randomness to an encrypted token. If it's properly encrypted, user has no way to infer anything about the encrypted data.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them.
This seems odd. Your encryption does not seem to use a secure standard. Otherwise every time you encrypted the same token, the cyphertext would change. You must use an IV, and never ever think about AES-ECB, that mode is broken and should not be used even to teach kids how AES works.
If you use industry standards, you will know about the Initialization Vector (IV). In rough terms, the IV is a value added to the process that changes the cyphertext, so even if you encrypt two identical plaintexts with the same key, the corresponding cyphertext will change.
The IV is the random data you are thinking about adding. It's already there.
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
add a comment |Â
up vote
15
down vote
accepted
You don't need to add any randomness to an encrypted token. If it's properly encrypted, user has no way to infer anything about the encrypted data.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them.
This seems odd. Your encryption does not seem to use a secure standard. Otherwise every time you encrypted the same token, the cyphertext would change. You must use an IV, and never ever think about AES-ECB, that mode is broken and should not be used even to teach kids how AES works.
If you use industry standards, you will know about the Initialization Vector (IV). In rough terms, the IV is a value added to the process that changes the cyphertext, so even if you encrypt two identical plaintexts with the same key, the corresponding cyphertext will change.
The IV is the random data you are thinking about adding. It's already there.
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
add a comment |Â
up vote
15
down vote
accepted
up vote
15
down vote
accepted
You don't need to add any randomness to an encrypted token. If it's properly encrypted, user has no way to infer anything about the encrypted data.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them.
This seems odd. Your encryption does not seem to use a secure standard. Otherwise every time you encrypted the same token, the cyphertext would change. You must use an IV, and never ever think about AES-ECB, that mode is broken and should not be used even to teach kids how AES works.
If you use industry standards, you will know about the Initialization Vector (IV). In rough terms, the IV is a value added to the process that changes the cyphertext, so even if you encrypt two identical plaintexts with the same key, the corresponding cyphertext will change.
The IV is the random data you are thinking about adding. It's already there.
You don't need to add any randomness to an encrypted token. If it's properly encrypted, user has no way to infer anything about the encrypted data.
The issue here is that, every time a particular user views a particular page, the same token will be generated for them.
This seems odd. Your encryption does not seem to use a secure standard. Otherwise every time you encrypted the same token, the cyphertext would change. You must use an IV, and never ever think about AES-ECB, that mode is broken and should not be used even to teach kids how AES works.
If you use industry standards, you will know about the Initialization Vector (IV). In rough terms, the IV is a value added to the process that changes the cyphertext, so even if you encrypt two identical plaintexts with the same key, the corresponding cyphertext will change.
The IV is the random data you are thinking about adding. It's already there.
edited Aug 31 at 1:27
answered Aug 30 at 14:43
ThoriumBR
16.4k44060
16.4k44060
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
add a comment |Â
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
Since OP says that he sees the same token generated, I guess it's not properly encrypted with an IV. In that case, maybe he should add it or change what he's using for encryption to something that does add it for him.
– JoL
Aug 30 at 17:42
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
When encrypting a large amount of data, the cost of storing or transmitting an IV with the encrypted data will be usually be small relative to the cost of storing or transmitting everything else. If the payload is small, however, the cost of the IV relative to the payload may be more significant.
– supercat
Aug 30 at 21:08
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
If you don't use an IV and the data is small and predictable, you will disclose your key. And as you have one single key on the server, losing that key means disaster...
– ThoriumBR
Aug 30 at 23:40
add a comment |Â
up vote
4
down vote
Let's try to break this down:
Problem: replaying a token:
Apart from allowing the same request to be replayed against the endpoint ad infinitum
Usually auth tokens solve this problem by expiring the tokens: the encrypted data includes a datestamp (which has the side-effect of making each token unique) and the server will reject any token older than, say 15 minutes.
Problem: breaking crypto:
this makes it more likely that someone will be able to break the token encryption
I'm not an expert, but it would seem to me that you should use a random IV for each encryption, and include the IV with the cipher text as part of the token. This would both solve the cryptanalysis problem you're alluding to, and have the side-effect of making your tokens unique. (if you're not using random IVs, then you probably have much bigger problems on your hands)
Why not use a standard library to do this rather than going out of your depth to design your own encryption scheme? I would recommend JWT.
Finally, as a public service I need to correct this: GUIDs ARE NOT HIGH-QUALITY RANDOMNESS.
See Wikipedia/Universally_unique_identifier.
UUIDs / GUIDs are designed to be unique, they make no attempt to be unpredictable. There are 5 standard ways to derive a UUID; 4 of them are some combination of MAC address + hostname + timestamp. Version 4 UUIDs are pure random, but because UUIDs / GUIDs generation needs to be fast and non-blocking, they use non-cryptographic random number generators.
PLEASE DO NOT USE UUIDs / GUIDs AS A SOURCE OF CRYPTOGRAPHIC RANDOMNESS. Instead use /dev/random
in unix, SecureRandom
in java, or whatever the equivalent is in your OS / programming language
2
don't you mean/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.
– dandavis
Aug 30 at 18:45
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.random
is safer but may have performance issues,urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes/dev/random
and/dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.
– Mike Ounsworth
Aug 30 at 18:56
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
add a comment |Â
up vote
4
down vote
Let's try to break this down:
Problem: replaying a token:
Apart from allowing the same request to be replayed against the endpoint ad infinitum
Usually auth tokens solve this problem by expiring the tokens: the encrypted data includes a datestamp (which has the side-effect of making each token unique) and the server will reject any token older than, say 15 minutes.
Problem: breaking crypto:
this makes it more likely that someone will be able to break the token encryption
I'm not an expert, but it would seem to me that you should use a random IV for each encryption, and include the IV with the cipher text as part of the token. This would both solve the cryptanalysis problem you're alluding to, and have the side-effect of making your tokens unique. (if you're not using random IVs, then you probably have much bigger problems on your hands)
Why not use a standard library to do this rather than going out of your depth to design your own encryption scheme? I would recommend JWT.
Finally, as a public service I need to correct this: GUIDs ARE NOT HIGH-QUALITY RANDOMNESS.
See Wikipedia/Universally_unique_identifier.
UUIDs / GUIDs are designed to be unique, they make no attempt to be unpredictable. There are 5 standard ways to derive a UUID; 4 of them are some combination of MAC address + hostname + timestamp. Version 4 UUIDs are pure random, but because UUIDs / GUIDs generation needs to be fast and non-blocking, they use non-cryptographic random number generators.
PLEASE DO NOT USE UUIDs / GUIDs AS A SOURCE OF CRYPTOGRAPHIC RANDOMNESS. Instead use /dev/random
in unix, SecureRandom
in java, or whatever the equivalent is in your OS / programming language
2
don't you mean/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.
– dandavis
Aug 30 at 18:45
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.random
is safer but may have performance issues,urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes/dev/random
and/dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.
– Mike Ounsworth
Aug 30 at 18:56
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
add a comment |Â
up vote
4
down vote
up vote
4
down vote
Let's try to break this down:
Problem: replaying a token:
Apart from allowing the same request to be replayed against the endpoint ad infinitum
Usually auth tokens solve this problem by expiring the tokens: the encrypted data includes a datestamp (which has the side-effect of making each token unique) and the server will reject any token older than, say 15 minutes.
Problem: breaking crypto:
this makes it more likely that someone will be able to break the token encryption
I'm not an expert, but it would seem to me that you should use a random IV for each encryption, and include the IV with the cipher text as part of the token. This would both solve the cryptanalysis problem you're alluding to, and have the side-effect of making your tokens unique. (if you're not using random IVs, then you probably have much bigger problems on your hands)
Why not use a standard library to do this rather than going out of your depth to design your own encryption scheme? I would recommend JWT.
Finally, as a public service I need to correct this: GUIDs ARE NOT HIGH-QUALITY RANDOMNESS.
See Wikipedia/Universally_unique_identifier.
UUIDs / GUIDs are designed to be unique, they make no attempt to be unpredictable. There are 5 standard ways to derive a UUID; 4 of them are some combination of MAC address + hostname + timestamp. Version 4 UUIDs are pure random, but because UUIDs / GUIDs generation needs to be fast and non-blocking, they use non-cryptographic random number generators.
PLEASE DO NOT USE UUIDs / GUIDs AS A SOURCE OF CRYPTOGRAPHIC RANDOMNESS. Instead use /dev/random
in unix, SecureRandom
in java, or whatever the equivalent is in your OS / programming language
Let's try to break this down:
Problem: replaying a token:
Apart from allowing the same request to be replayed against the endpoint ad infinitum
Usually auth tokens solve this problem by expiring the tokens: the encrypted data includes a datestamp (which has the side-effect of making each token unique) and the server will reject any token older than, say 15 minutes.
Problem: breaking crypto:
this makes it more likely that someone will be able to break the token encryption
I'm not an expert, but it would seem to me that you should use a random IV for each encryption, and include the IV with the cipher text as part of the token. This would both solve the cryptanalysis problem you're alluding to, and have the side-effect of making your tokens unique. (if you're not using random IVs, then you probably have much bigger problems on your hands)
Why not use a standard library to do this rather than going out of your depth to design your own encryption scheme? I would recommend JWT.
Finally, as a public service I need to correct this: GUIDs ARE NOT HIGH-QUALITY RANDOMNESS.
See Wikipedia/Universally_unique_identifier.
UUIDs / GUIDs are designed to be unique, they make no attempt to be unpredictable. There are 5 standard ways to derive a UUID; 4 of them are some combination of MAC address + hostname + timestamp. Version 4 UUIDs are pure random, but because UUIDs / GUIDs generation needs to be fast and non-blocking, they use non-cryptographic random number generators.
PLEASE DO NOT USE UUIDs / GUIDs AS A SOURCE OF CRYPTOGRAPHIC RANDOMNESS. Instead use /dev/random
in unix, SecureRandom
in java, or whatever the equivalent is in your OS / programming language
edited Aug 30 at 14:56
answered Aug 30 at 14:48


Mike Ounsworth
35.3k1384127
35.3k1384127
2
don't you mean/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.
– dandavis
Aug 30 at 18:45
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.random
is safer but may have performance issues,urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes/dev/random
and/dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.
– Mike Ounsworth
Aug 30 at 18:56
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
add a comment |Â
2
don't you mean/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.
– dandavis
Aug 30 at 18:45
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.random
is safer but may have performance issues,urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes/dev/random
and/dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.
– Mike Ounsworth
Aug 30 at 18:56
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
2
2
don't you mean
/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.– dandavis
Aug 30 at 18:45
don't you mean
/dev/urandom
? devs shouldn't use /random for anything unless you are an expert making your own crypto system, and even then; don't roll your own crypto.– dandavis
Aug 30 at 18:45
3
3
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.
random
is safer but may have performance issues, urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes /dev/random
and /dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.– Mike Ounsworth
Aug 30 at 18:56
@dandavis uuuggggg I'm not getting into this debate again. They both have pros and cons.
random
is safer but may have performance issues, urandom
is secure if your your system has been up for a while, is not an IoT device. etc. On most non-linux unixes /dev/random
and /dev/urandom
are symlinks to each other (ex. BSD, MacOS and iOS, Solaris (I think), AIX, etc). Personally I like FreeBSD's implementation better than linux's, but *shrug*. Basically: yes I know the difference, no I don't think they're significant enough to have yet another debate over.– Mike Ounsworth
Aug 30 at 18:56
1
1
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
heh, no debate needed; i think your comment provides the context the answer missed...
– dandavis
Aug 30 at 19:02
add a comment |Â
up vote
1
down vote
The solution that is used on my platform of choice is "encrypt/decrypt with managed IV (Initialization Vector)." What this means is that, upon encryption, the entire plain text is encrypted with a cryptographic secure IV, and then the IV is placed in base64-format before the beginning of the cipher text. Upon decryption, the IV is pulled off the front and used as the IV for the cipher text. This is all transparent to the developer. Note that it is perfectly safe to expose the IV, because decryption with the correct key but wrong IV will result in a failure condition. If your programming language has a similar feature, do use it; by having a random IV generated each time you encrypt something, you don't need to put any extra data in the plain text.
add a comment |Â
up vote
1
down vote
The solution that is used on my platform of choice is "encrypt/decrypt with managed IV (Initialization Vector)." What this means is that, upon encryption, the entire plain text is encrypted with a cryptographic secure IV, and then the IV is placed in base64-format before the beginning of the cipher text. Upon decryption, the IV is pulled off the front and used as the IV for the cipher text. This is all transparent to the developer. Note that it is perfectly safe to expose the IV, because decryption with the correct key but wrong IV will result in a failure condition. If your programming language has a similar feature, do use it; by having a random IV generated each time you encrypt something, you don't need to put any extra data in the plain text.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
The solution that is used on my platform of choice is "encrypt/decrypt with managed IV (Initialization Vector)." What this means is that, upon encryption, the entire plain text is encrypted with a cryptographic secure IV, and then the IV is placed in base64-format before the beginning of the cipher text. Upon decryption, the IV is pulled off the front and used as the IV for the cipher text. This is all transparent to the developer. Note that it is perfectly safe to expose the IV, because decryption with the correct key but wrong IV will result in a failure condition. If your programming language has a similar feature, do use it; by having a random IV generated each time you encrypt something, you don't need to put any extra data in the plain text.
The solution that is used on my platform of choice is "encrypt/decrypt with managed IV (Initialization Vector)." What this means is that, upon encryption, the entire plain text is encrypted with a cryptographic secure IV, and then the IV is placed in base64-format before the beginning of the cipher text. Upon decryption, the IV is pulled off the front and used as the IV for the cipher text. This is all transparent to the developer. Note that it is perfectly safe to expose the IV, because decryption with the correct key but wrong IV will result in a failure condition. If your programming language has a similar feature, do use it; by having a random IV generated each time you encrypt something, you don't need to put any extra data in the plain text.
answered Aug 30 at 18:01
phyrfox
3,8191120
3,8191120
add a comment |Â
add a comment |Â
up vote
0
down vote
To me, this looks like an XY Problem.
The best way to protect a secret is not to tell anyone the secret. The token is generated server-side. The server already knows the data. And then you replay the token to the server, which contains only data the server already has. That is completely unnecessary.
Other answers have pointed out the quick, immediate fix for your encryption problem by using encryption with IVs. But the better solution would be to make this superfluous.
Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
Instead of encrypting those values, save them in a database. You can potentially, if you really must, still encrypt those values and then save them. But there is absolutely no need for these values to ever leave the server, even in encrypted form.
Then generate a truly random token (with a CSPRNG), and use that as a lookup-key. Send this token to the client.
Token is embedded into link on page
Use the random token you just generated for that.
When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
Instead of decrypting and parsing the values, you use the token to look them up in the database. Done. If you only stored the data encrypted, you still need to decrypt it, of course.
This also works if you have multiple servers. If the token is generated on Server A and send to Server B, have Server B use a secure connection to Server A and request the data via the token from Server A. In this scenario, too, the data is never sent to the client.
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings
Internal state should never leak from an implementation. This is already a code smell and a good hint that your architecture is flawed.
add a comment |Â
up vote
0
down vote
To me, this looks like an XY Problem.
The best way to protect a secret is not to tell anyone the secret. The token is generated server-side. The server already knows the data. And then you replay the token to the server, which contains only data the server already has. That is completely unnecessary.
Other answers have pointed out the quick, immediate fix for your encryption problem by using encryption with IVs. But the better solution would be to make this superfluous.
Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
Instead of encrypting those values, save them in a database. You can potentially, if you really must, still encrypt those values and then save them. But there is absolutely no need for these values to ever leave the server, even in encrypted form.
Then generate a truly random token (with a CSPRNG), and use that as a lookup-key. Send this token to the client.
Token is embedded into link on page
Use the random token you just generated for that.
When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
Instead of decrypting and parsing the values, you use the token to look them up in the database. Done. If you only stored the data encrypted, you still need to decrypt it, of course.
This also works if you have multiple servers. If the token is generated on Server A and send to Server B, have Server B use a secure connection to Server A and request the data via the token from Server A. In this scenario, too, the data is never sent to the client.
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings
Internal state should never leak from an implementation. This is already a code smell and a good hint that your architecture is flawed.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
To me, this looks like an XY Problem.
The best way to protect a secret is not to tell anyone the secret. The token is generated server-side. The server already knows the data. And then you replay the token to the server, which contains only data the server already has. That is completely unnecessary.
Other answers have pointed out the quick, immediate fix for your encryption problem by using encryption with IVs. But the better solution would be to make this superfluous.
Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
Instead of encrypting those values, save them in a database. You can potentially, if you really must, still encrypt those values and then save them. But there is absolutely no need for these values to ever leave the server, even in encrypted form.
Then generate a truly random token (with a CSPRNG), and use that as a lookup-key. Send this token to the client.
Token is embedded into link on page
Use the random token you just generated for that.
When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
Instead of decrypting and parsing the values, you use the token to look them up in the database. Done. If you only stored the data encrypted, you still need to decrypt it, of course.
This also works if you have multiple servers. If the token is generated on Server A and send to Server B, have Server B use a secure connection to Server A and request the data via the token from Server A. In this scenario, too, the data is never sent to the client.
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings
Internal state should never leak from an implementation. This is already a code smell and a good hint that your architecture is flawed.
To me, this looks like an XY Problem.
The best way to protect a secret is not to tell anyone the secret. The token is generated server-side. The server already knows the data. And then you replay the token to the server, which contains only data the server already has. That is completely unnecessary.
Other answers have pointed out the quick, immediate fix for your encryption problem by using encryption with IVs. But the better solution would be to make this superfluous.
Server builds up token using various values, encrypts it (via an industry-standard algorithm, nothing homegrown) using a key only the server knows, and returns it as part of the page data
Instead of encrypting those values, save them in a database. You can potentially, if you really must, still encrypt those values and then save them. But there is absolutely no need for these values to ever leave the server, even in encrypted form.
Then generate a truly random token (with a CSPRNG), and use that as a lookup-key. Send this token to the client.
Token is embedded into link on page
Use the random token you just generated for that.
When client clicks that link, token is sent to server, decrypted and parsed and the values used to determine what to do
Instead of decrypting and parsing the values, you use the token to look them up in the database. Done. If you only stored the data encrypted, you still need to decrypt it, of course.
This also works if you have multiple servers. If the token is generated on Server A and send to Server B, have Server B use a secure connection to Server A and request the data via the token from Server A. In this scenario, too, the data is never sent to the client.
This is done because we need certain bits of information to be sent from the client to the server, but we don't want to leak those bits of information to the client because they would reveal details of the server's inner workings
Internal state should never leak from an implementation. This is already a code smell and a good hint that your architecture is flawed.
edited Sep 1 at 9:31
answered Sep 1 at 7:53
Polygnome
1015
1015
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsecurity.stackexchange.com%2fquestions%2f192731%2fdoes-appending-randomness-to-a-token-before-encrypting-it-make-it-more-secure%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
i would consider a standard approach like JWT, which includes space for your side-car meta
– dandavis
Aug 30 at 18:47
Which encryption algorithm do you use?
– Sjoerd
Aug 30 at 19:14
1
Why should the secret leave the server in the first place? Generate a random token. That one is given to the client. The secret data is stored on the server, with the token as lookup key. Client sends token to server. Server looks up values in database. A secret can't be compromised if you don't give it away.If the token is used on another server, make that server talk to the original server over an encrypted channel. If the client isn't supposed to have the data, don't give it to him.
– Polygnome
Aug 30 at 20:51