How to protect a server's secret key on a browser? - javascript

In this use case, the server send an encypted blob to the browser and the the javascript on the browser subsequently requests the decryption key from the server and decrypts the blob to usable content.
Is there a way to protect this key on the browser from an attack by a bookmarklet or browser plugin or the user stepping through the javascript debugger on browser? Or atleast make it a slightly harder problem for the attacker.
Edit : the context of the problem is HTML Video DRM as specified in EME specifications. There is a ClearKey api that is part of this standard and does nor require closed source plugin from WideVine or FairPlay etc. But as multiple responses have pointed out, ClearKey cannot be protected. (which unfortunately means using propritory DRM plugins).

You can not guarantee the security of any data once it reaches the client.
There is just no way to do this. Once the client receives this, especially if they also receive the decryption key, they have full access to all the secrets within.
On a very simple scale, they can just drop some breakpoint or put some prints in the javascript console. If they want to get more advanced they can use tools like wireshark to see the data as it comes over the wire.
Now if you want to send them encrypted data that doesn't get decrypted, and it is strongly encrypted, then its not as bad. But if you're never going to decrypt it on their side, then what are you even sending it for?

Agree that it can't be done. You could do it with asymmetric encryption. But I would go back to why you're doing it - if the connection were SSL encrypted, there is no reason to do it.

Related

Sign webpage and JavaScript to protect against server manipulation

I would like to sign a whole webpage to protect against changes by a third party. Currently, end2end encryption with JavaScript does not make sense because an attacker with control over the server could change the code to send himself an unencrypted copy. For a user it is not possible to verify code he loads from the web is from the correct source.
Also with cloud and serverless becoming more popular you don't own the server anymore.
I know there is HTTPS and SRI but if the attacker has control over the server this offers no protection.
I would like to add a public key to the domain record like DKIM. The browser should only accept signed files with the correct signature.
All I found was XML Signature but I as far I can tell there is no browser support at all. Still, this is not what I am looking for.
Can someone point me in the right direction?
W3C Draft or something?

Verifying data that is encrypted in the browser

We have a file upload system that PGP encrypts data in the browser before it is sent to our servers. The files are then viewed by us in a specially designed local program. We decided this was the safest way to store that data. One downside to this we find in our own testing is that we can really upload anything at all, random strings etc., because we can't verify what that data is once encrypted without keeping our private keys on a server that is connected to the internet. It seems to me that this is a pretty big potential flaw, though I can't put my finger on exactly what could be done with it. Aside from sanitizing and checking data before viewing it, what can we do to mitigate the issue? Should we take another route entirely for protecting the data?
Edit: We realized the public key used to encrypt could simply be changed by an attacker and they'd have access to all files encrypted from that point. The current suggestion is to encrypt using hashed user password+salt generated at login time and then storing that key on another server (protected by master password) so that we too can view them. The issue of changing keys seems to be mitigated by this (though keys could plausibly be intercepted while being sent to the secure storage server).

Protecting JSON in Javascript?

I used jQuery Ajax to talk to php script, then it returns JSON. Then, the returned JSON Array Object is assigned to Javascript Variable var myJSON = ajaxReturn;
Normally the returned JSON values are not visible in Page Source or Javascript File, as it is rendered on the runtime only.
But when i open the tools like, Firebug and call that variable in console, like: alert(myJSON); the results are popping out. I do NOT want it to be as this is something secret data.
What is the best way to prevent/protect the JSON at Javascript side?
Everything sent to the client side is public, this is the nature of front end development and you can't change it. It is impossible to hide stuff from the user if he decides to take a peek.
If the purpose of your application is to store the JSON for client use, then you have no way of protecting it from being accessed. However you can do all modifications upon receiving the JSON and then discard it (not store it). Keep in mind that the request can still be intercepted the response can be read simply by using the networking tab of the browser developer tools.
What do you do with the JSON data? In all probability, you are feeding UI controls or subsequent calls to web services. So if you would protect (i.e., encrypt) the JSON, you would still need client-side decryption, and so your JSON would still be vulnerable -- as you can just do an alert(decryptedJSON) too.
There is no real, safe way to protect JSON if you have to be able to decipher the data in the browser.
You can of course protect the data while it is underway over the network by encrypting it, either using HTTPS or by explicitly encrypting the data server-side and then decrypting it using client-side JavaScript. But that does not protect it from being viewed in the browser.
A better option could be to encrypt and decrypt only on the server, if that fits your scenario. So you can get encrypted JSON data from a particular web service call, then feed that data into your next web service call where it gets decrypted on the server. That way, your client-side JavaScript doesn't need to decrypt, making your data safer. But if the purpose is to populate the UI, obviously this won't fit your needs.
You have just missed the game, Once you send the data from your server then its out of your limit. Because browser like firefox can do anything, So the point is everything which renders on the client is Public.
Even if there were some way to block Firefox from displaying the data in firebug, its easy for anyone to write their own web client that pretends to be a web browser and then they can do whatever they want with the data.
If you really want to hide json-data then dont send it using ajax-json. Use diffrent terminology or server-side programming.

practical use of cryptico.js

Cryptico seems like a super slick RSA encryption library.
cryptico.wwwtyro.net
In regards to JavaScript applications, suppose I want to send data to the client, have them do something to the data, and pass it back. How can I use RSA to ensure that the data clients send back to the server is not tampered with? Since JavaScript is easily reverse-engineered, is there any practical client-side application of cryptico?
Do you - by your example - mean that you want to hide from the user what his client is doing with the data? If so - it's impossible.
You should never trust any data which comes from the client.
If you send encrypted data to the client to process - you must assume that the user knows (or will know if he wants) the encryption key, otherwise it will be impossible to process. In other words there is no secure way to hide from the user what his client processes. Obfuscation - like you've noticed can always be cracked no matter what language you use.
I think that the most common and practical client-side application for this library would be encrypting user's data and sending them to server or vice-versa. There may be some cases you can't use SSL. Moreover, you can make -for example- an encrypted post on facebook which only your friend will be able to decrypt (because he knows the key).
There is a solution to what you seek (I'm sure there is more than one). My answer requires two non-conventional approaches to what we call a 'secure connection' and how you receive the 'client code'.
You need a physically pre-shared key that initiates a secure connection, and because it's pre-shared it doesn't have to be RSA, which then opens up speed opportunities and higher levels of encryption security for you.
Physically pre-share your client code in a similar manner, i.e., download the code from a cd in a magazine or from a pre-paid card sold in a market. This stops the MITM from sending you tampered and exploited clients, which ssl allows. Once client is known to be secure, and a real secure connection, mentioned in (1), is established, the client code can be updated.
With the combination of a pre-shared key that develops a secure connection and client code that can pass a checksum, you can achieve what you are after.
Ideally, we should have pre-shared secure connection keys available in the market now, but we don't. So, for you to do it alone, would require to implement something similar for you website specifically until people in this country get their act together with some real security. You would have to give them keys over your phone, through the mail, etc. And your client code would most likely have to be a browser extension to install it due to cross domain security issues.

How can I send data to a user that will persist between web page views, but which won't be resent to the server?

I want to send some data to a user after they log in to a web site, some kind of secret string for encryption.
I want to allow them to navigate around the web site, and I want to be able to use javascript on their machine to encrypt data before it's sent back to the server. Note: This will be in addition to using SSL.
I don't want to use cookies for this because they are sent to the server on each request.
So my aim is to have some data that will be sent across the wire only once for the whole session, but that when the user visits multiple pages, javascript will be able to access this secret. To be clear I never want to see the user's decrypted data, nor be able to.
Is this possible, maybe using HTML5 persistence or something? I need a cross-browser compatible solution please that will ideally work with IE6 (so that might shoot down any HTML5 magic).
Thanks
If you are worried about snooping, use HTTPS. It sounds like a pretty fragile encryption mechanism though, why not go more 'traditional'?
I'd doubt you can do this. A session is normally tied to a cookie (ie jsessionid), so to tie it to the "session" (ie you said "some data that will be sent across the wire only once for the whole session"), and have it available to the user, you need to put it in a cookie.
You can use localStorage on HTML5-supporting browsers (IE8, FF3+, Chrome, Safari 4+, Opera 9+). You can fall back to userData for IE6 and IE7. That gives you a guaranteed minimum of 64 KB of data on all platforms (minimum userData size).
There's a library that encapsulates the various strategies for storing data locally: PersistJS
I use this to store client-side state that doesn't need to be sent to the server with every request (e.g. resizable panel dimensions). I don't think it could offer any additional security though, because any attacker that can decrypt the SSL stream can get at your data, because they can observe all your javascript code.
You could use a RIA plug-in like Flash or Silverlight. Both have mechanisms for storing data locally w/o sending it back to the server on each request. Java might as well.
How about keeping the user on the secure page and sending the encrypted data back with ajax calls?
I also remember seeing a php script that would load a given page into an iframe based on some criteria. I think the example I saw was just a demo, where you selected a page from a select form. The page containing the iframe can be used to persist data.
I think i'll take inspiration from the banking world and perform all of the encryption on the server. I can think of a way that I could generate a private key from the user's password making it impossible for me to decrypt data without the user being logged in.
I don't think there's a robust solution to my initial question, but thanks for the responses.

Categories