I am interested in having something that I encrypt using a public key on a LAMPhp server, decrypted using the appropriate private key on the web client (firefox at least, best if it is standard javascript)
Note that what I want to do is -not- merely to have an encrypted connection using SSL/https. Or even to use browser-based client certificates as a login/access control method. I know how to do both of those things. What I want to do is more like emailing with gpg keys. I want to be able to create a short message that I will encrypt with a users public key that -only they- can decrypt using their private key. What I am looking for is not the privacy achieved automatically by ssl, but the ability to allow only particular users to decrypt messages. I know I can easily do this with gpg or perhaps SMIME, and perhaps that is the best way, but I would prefer a web-based alternative.
Firefox etc have a certificate stores, and I know that the private keys held there are unlikely to be exportable into javascript for obvious security reasons, but I would assume there is some way to -use- the certificates from javascript calls to decrypt something..
The reason I would like to do this, is that I need a secure method to give a randomly generated password to a particluar administrator. I am trying to implement full database translucency and public key cryptography seems like an important part of that effort. But this is one use-case that I am having trouble addressing without this kind of ability.
So on the php side I would use the openssl encryption calls like so...
<?php
$browsers_public_key = get_it_from_the_browser_via_apache_maybe();
openssl_public_encrypt($data,$encrypted_ends_up_here,$browsers_public_key);
echo "<html><head>
<script type='javascript'>
function decrypt_textarea(){
??
}
</script>
</head>
<body><textarea id='decrypt_me'> $encrypted_ends_up_here </textarea>
<div id='where_the_plaintext_goes'> </div>
</body> </html>";
?>
Note that I have found via stackedoverflow many fine javascript encrypton libraries... but I actually want to use keys imported into Firefox as per MyOpenId.com or CaCert.org
Does anyone know if this is possible?
Thanks,
-FT
It's been a while since you asked this question, but if you or anyone else is looking for a potential solution to this problem or a similar one, they should check out the JavaScript Forge project:
http://github.com/digitalbazaar/forge/blob/master/README
This project has an SSL implementation in JavaScript that will allow you to include a client-side certificate when communicating with Apache. You can also manually do RSA decryption using the associated private key (which you have access to in JavaScript).
For instance, the JavaScript could get/post to the server and include its client-side certificate. Apache could read this certificate, use the public key to encrypt whatever data is appropriate, and then return that data to the client. The client could then use its private key (in JavaScript) and decrypt the information and do something with it. This extra encryption is probably not even be necessary, however, if your server can authenticate the client-side certificate as the appropriate recipient of the secret you're trying to pass.
The Forge project also has the APIs to build a system for importing/exporting keys and certificates to/from Firefox or other browsers (if this is still a requirement for some reason). A little help from openssl might be necessary to get the keys/certs in the correct format for import/export (pem => pkcs12), but an example of how some of this works can be found in a JavaScript-based demonstration of WebID. WebID is a client-side certificate-based authentication system:
WebID management demo: https://webid.digitalbazaar.com/manage/
WebID authentication demo: https://payswarm.com/webid-demo/
Note that the SSL certificates for the above sites are self-signed and will require temporary exceptions to be added to your browser to view them. The sites do not require you to enter any personal information, they are for demonstration purposes only. However, if you go to the first link, you can generate keys in-browser (it uses Forge JavaScript to do this) and then you can see the private key and certificate that were generated, in PEM format, in the list at the top of the page. The key and certificate are persisted via Flash local storage.
Nearly 100% (if not that) of the source for the WebID management site is viewable since it is mostly JavaScript. Also, the Forge project itself (see the github link) is opensource.
Now that I understand what you're saying, I can give you a firm answer :)
The best I can tell you is that you can't get decent encryption in the way you're looking to do it. Private key encryption (namely RSA) uses very, very, very large numbers to do encryption. Using small numbers is very simple to crack computationally (there are only so many prime numbers) and the numbers get big extraordinarily quickly. Basically, with RSA, you need to take large numbers and raise them to large exponents. JavaScript is able to support quite large numbers, but you'll hit a wall with performance. With a 512-bit key, encryption of a few kilobytes can take up to a few seconds, while decryption can take seconds to minutes to do. The reason JS is so slow is simply because it's not a compiled language. Sure, you could decrease the key size, but anything larger than a couple kilobytes and you've got a problem.
Also, RSA is inherently insecure in a web page because the private key is transmitted alongside the data to be decrypted (unless it was transferred earlier), which enables anyone that receives the page to decrypt the data.
I'm going to assume that you're looking to do this because you want to obfuscate some code from your user or a client, so I'm going to recommend that you check out XOR encryption. Granted, it's nowhere near as secure as RSA, but it uses principles that can be very secure if used properly. For instance, if you use a random key that's used only once and has the same length as your data/code (an one-time pad), your encryption is "uncrackable". Even better, XOR encryption is FAST. Here are some resources:
http://guymal.com/mycode/xor_js_encryption/
http://javascript.internet.com/passwords/xor-encryption4.html
Hope you have luck with what you're trying to do!
I am searching exactly the same thing you do and wanted to use php's openssl-functions, too.
I was happy to see that on the phpside everything was working great with private/public key (encrypt/decrypt) and now wanted to find a way to use privatekey on clientside as you do.
!!!
IF you will find anything please let me know by email:
pki (at) life.de
!!!
And for the performance aspect:
You would encrypt the big parts with symetric encryption and only the decryption key with the public key of the client to excahnge it. So you dont't need to enrypt many kb.
But it seems to be an dead end with firefox, but with IE and ActiveX it seems possible with
CAPICOM (I had not much read about it now).
hxxp://geekswithblogs.net/shahed/archive/2007/05/03/112232.aspx
But for JavaScript/PHP have a look at (and read all comments at FAQ and other pages,too!In future maybe bidirectional communication was mentioned):
hxxp://www.jcryption.org/
hxxp://www.zend.com//code/codex.php?ozid=1323&single=1
Pure Javascript Public/Privatekey encryption
hxxp://shop-js.sourceforge.net/crypto2.htm
A helful FireFox-Addon for PKI:
hxxps://addons.mozilla.org/en-US/firefox/addon/4471
hxxp://www.mozilla.org/projects/security/pki/nss/tools/index.html
PHP with OpenSSL on Serverside / .NET on CLientside
hxxp://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html
Javascript OpenPGP
hxxp://www.hanewin.net/encrypt/
PS: stupid mechanism prevents me posting links ...
You don't handle SSL in your PHP. SSL is handled by the web server automatically. If you're using Apache, here's a simple tutorial:
http://www.debian-administration.org/article/Setting_up_an_SSL_server_with_Apache2
The idea is that you write your code like normal, and when the user accesses your site using https, the server automatically encrypts the connection. On the client side, the browser is capable of using the private keys that it already has to automagically decrypt the connection and present the code to the user agent.
Hope this helps!
Related
My Requirement
I am making a website which will have mobile version as well. So, I am making it API centric. Now I want to make my API secure without the complexities of OAuth because the security I need is quite simple. I don't want anyone with access to the api links to be able to access my data.
So, I came across this article http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/ which is quite amazing and cleared most of my doubts.
Right now, I am trying to recreate whatever is there in the article. I am using Laravel 5 framework for PHP for development.
I want to make sure that the API is being used by the mobile app and the web version only and no one else.
I have seen api links like
example.com/fetchallinformation&publicKey=<something>&Hashkey?<some_hash_key>
Now, I understand that this key is generated by using hash_hmac() function in php.
My Approach
I have a table where I am storing the publicKey and privateKey for my api users
That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.
In the server side, I take the publicKey and the Hash. I retrieve the private key from the table corresponding to the publicKey and has them and check if the resulting hash is same as the hash send by the client
If it is same, then I give permission to them, else, I don't.
My Confusion
I am not sure if this is the right way to do this.
Can we get the data that has been used to generate the hash using hash_hmac() by decrypting the hash?
That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.
Close, but not quite. As you just described it, a user with a given public key would send the same hmac with every request. That's no better than "username and password."
Side note: if you aren't using https, you're already insecure and whatever else you do to secure the site is of relatively little value.
The point of generating an hmac signature is that it not only authenticates the user as being in possession of the secret key, it also authenticates the specific request as being made by that user and being made during a specific window of time. Two different requests back to back should have a different hmac. One request today and an identical request tomorrow should also have a different hmac. Otherwise, you're in for replay attacks. This means information about the current time or expiration time of the signature, and information about the request itself, must be included in the information that's passed through the hmac algorithm or you're not accomplishing much.
For any given request, by a specific user, at a specific time, there can only be one possible valid signature. HMAC is not reversible, so you can't take the signature apart at the server end and figure out the attributes of the request.
Of course, of you're thinking about embedding that secret key in your app, remember that such tactics can be relatively trivial to reverse-engineer.
Is it a viable authentication mechanism? Of course. As the article points out, Amazon Web Services uses hmac signatures on their APIs, and they have a massive potential attack surface... but does that mean you will implement it in a meaningfully secure fashion? Not necessarily. There is always someone more clever, devious, and determined than you can imagine.
Even Amazon apparently realizes that their Signature Version 2 is not as strong as it could be, so they now have Signature Version 4, which has a much more complex algorithm, including several rounds of hashing and generation of an intermediate "Signing Key" that is derived from your secret, the current date, the specific AWS service, AWS region, and other attributes. Regions where Amazon S3 was first deployed in 2014 or later don't have support for the original Sig V2 at all -- and it seems like it can only be security-consciousness that drove that decision, since the old algorithm is computationally less expensive, by far.
Use caution in rolling your own security mechanisms.
If you are primarily trying to avoid the learning curve with OAuth, which I agree is quite annoying at first, you could be on a fool's errand.
If this method works for you it should definitely be fine, and undoubtedly it is secure.
Regarding decryption - HMAC is not supposed to be decrypted due to its nature (hash). HMAC is considered to be very secure and you should have no problems with it. You can read a bit more about How and when do I use HMAC? [SE Security]
I want to make sure that the API is being used by the mobile app and the web version only and no one else.
This is a problem that neither OAuth nor AWS-style signature authentication really help with. Both are about authenticating users, not applications. You can certainly implement either approach if you have a bunch of time to sink into it, but in both cases you're going to need to embed a "secret" in your apps, and once you give that app to a user your secret's not really a secret any more...
There's no great way to do what you're looking for. If someone's going to take the time to reverse-engineer your app to learn about how to directly hit the underlying API, anything else you do client-side to "authenticate" the calling application can be reverse-engineered as well.
I'd recommend not even bothering, and spending the time you save polishing your app so no one wants to bypass it and hit your API directly. :)
In a typical web scenario, a website user will come along, use a website, fill out a form, and transmit the data to the server for storage in the database. Now let's say we needed to ensure their address was encrypted as it was top secret, and only those with access to the back end of the website should be able to see what that address was - this is reasonably easy to achieve right? We would just store an encryption key server-side which would be used to generate the encrypted data, store the data in the DB, and we would just use the key again to decrypt it.
Now supposing someone at the hosting company were to browse the files on your server - they could very easily get access to this encryption key, and then use it to decrypt any data they wanted, since all addresses in the database have been encrypted with the same key!
I am just trying to cover every base with the new security model, and in a "trust no one" policy I am looking at ways of stopping the hosting company from getting at the data too.
So does anyone have any suggestions to prevent those with server access from obtaining the key and decrypting data? Would password salting help in any way, or would they still be able to decrypt data quite easily.
I can't think of a way around the issue. Does anyone have any suggestions to solve this particular problem?
Encrypt and decrypt in the browser everything sent to the host. Use a passphrase entered on the client to do the cryptography, and never send the passphrase to the host. There's a fuller description at Host-proof Hosting
I guess that's a risk when it comes to shared hostings. I'm using amazon aws for most of my projects and linode for my personal blog. Both solutions are in the model "you are your own sysadmin" and nobody peeks in your machines.
If I was in your shoes, I'd use mcrypt with a variable key. For example, whe username field of the same row. This way, for the data to be compromised, the intruder would need to get access to both your database and source code to figure out how to decrypt the data. At that point your problem would be far worse than a mere information leak.
Well mostly hosting companies have access to all databases and files that is bad really bad.
Few years ago I did some experimenting with encryption and decryption.
The best way would be to have personal servers, but that isn't cheap.
Example RC4 encryption requires key to crypt data. Now tricky part is to make that key also encrypted with some other encryption like BASE 64 , ATOM 128. This wont make it be 100% secure
But It will be really hard to decrypt data.
I hope you can understand me.
Cheers :)
btw point is there is no 100% secure data.
If you don't need to be able to decrypt the data online, this is an ideal situation for public-key cryptography. In particular, a sealing API. For example, using libsodium (PHP 7.2):
Encryption
$store_me = sodium_crypto_box_seal($plaintext, $box_publickey);
sodium_memzero($plaintext);
Decryption
$plaintext = sodium_crypto_box_seal_open($stored_msg, $box_keypair);
If, however, you do need to be able to decrypt the data from the webserver, then anyone who accesses the webserver can just pilfer the keys and decrypt your data. No cryptography algorithm can stop someone with the keys from decrypting messages.
Always start with a threat model.
I have a application (made in Delphi) that contains a Authentication system (login & password).
This system is in PHP, and the application get results from PHP using HTTP GET method.
The system returns 'OK' if login and password are correct, and 'NO' if not correct.
Like this...
procedure Check;
var
x: string;
begin
x:=Get('www.mywebsite.com/auth.php?user=xxxxxx&pass=zzzzzz');
if x='OK' then
UnlockFeatures
else
MessageBox(0,'You're not VIP','Error',0);
end;
Well, it works fine, but it is very easy to circumvent this system with sniffers, packet editor or proxy.
So, I want to get some information (in PHP) that changes every time, and that could be possible get the same information by my application.
What can I do?
I don't need codes. Just tips, suggestions, please...
Thanks...
Generally i suggest you not to try to outsmart everyone and invent brand new bicycle - you'd 99% fail with some stupid error making your approach completely insecure. There were a lot of precedences like DVD encryption or Win95 security. You'd better try some industry-approved mechanics, that for years been tested for security, that should have readymade implementations for both Delphi and PHP. Few are
TLS (https:// protocol) http://en.wikipedia.org/wiki/Transport_Layer_Security - that would give no protection from MITM attacks, but it sounds exactly what you asked and would require least possible change.
You may try implementing SSO via integrated windows authentication if you server would support that
You may try setting up OpenID or OAuth environments. Generally their v.1 would be simpler than v.2
You may try to bail out of HTTP and use XMPP/Jabber authentication - they take security seriously and libraries for PHP and Delphi exist. Though it should not be much more secure than just using TLS, you may hope that dumb attackers would not be prepared for non-HTTP protocols (there is not internet outside Facebook and such).
You may use Bluetooth-like approach to make special connection("handshake") once (when both client and servers are controlled) just to make special "tokens" interchanged and stored. That is a generic trait to use "controlled environment" to make 1st connection and use some tokens to prove "we had met before" on later connections using generic challenge/response trait. Those tokens should be unique for each client-user-server combinations! If you'd make one server-global clients-shared set of tokens - they would just be easily copied form one client to another and no more security remains.
Those may be coefficients for some not most trivial RNG. constructed be server and saved by both client and server. Then server "challenges" with RNG seed and client should response with proper random value, prooving he knows coefficients.
Those may be some asymmetric crypto, where token is some random "message", then server sends client encruyption keys and expects the correct message encrypted by them, or the token is the password and server generates random text and expects it's correct crypto digital signature to be passed back. You may find encyption libraries at Torry.net for examples. Lockbox3 and Spring4Delphi are among most tested and noted crypto libraries for Delphi implementing some encrypting standards.
Consider you priorities and make your choice.
Would you be able to switch all the authentication layer in one key turn later, having absolutely no care for backward compatibility with non-updated clients, then you might choose the most simple one and only enhance it later if needed. If your users are lazy at upgrades then you'd better choose most secure approach from starters, since you would have no practical way to disable insecure implementation later.
I'm not familiar with Delphi (looooooong time ago...), but as far as the php and security is concerned:
I would use post instead of get (and https if possible)
If you can read php sessions with Delphi, you could add a session variable with a random number and add that as a hidden form field, send it in and check it against the session variable.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I would like to encrypt data that travels back and forth between the server and client in my Web application. I would use SSL but that requires a certificate along with a dedicated IP address. I have no problem getting a certificate but the dedicated IP requires me to upgrade to a business hosting plan which is $20 a month on my Web host. I have no plans on doing that as I'm sticking with my $20/year shared hosting plan.
So, I would like to implement an alternative to SSL. It does more than SSL does, though. Along with encrypting the data sent back and forth, it also encrypts the rows in the database. I was thinking of doing something like this:
JavaScript Code:
var transfer_key = 'whatever';
function encrypt(data, key) {...}
function decrypt(data, key) {...}
function send_data_to_server(url, data)
{
$.post(url, {'data' : encrypt(data, transfer_key) }, function(response) {
var decrypted_response = JSON.parse(decrypt(response));
});
}
PHP Code:
$data = $_POST['data'];
$transfer_key = 'whatever';
$storage_key = 'whatever2';
function encrypt($data, $key) {...}
function decrypt($data, $key) {...}
databaseQuery('INSERT INTO table VALUES (?)', encrypt($data, $storage_key));
$decrypted_data = decrypt($data, $transfer_key);
$response = processData($decrypted_data);
echo encrypt($transfer_key, $response);
As you can see, the data the client sends to the server is encrypted, and vice versa. And the data in the database is encrypted as well. Now of course, I would never implement the keys like that. I would probably have a second or third key that's randomly generated for each user. So transfer_key could be equal to a constant_key concatenated with a random key, and same goes for storage_key.
Would this be a good alternative to SSL?
How can I implement this type of encryption in such a way that it is harder to defeat? Are there any particular weaknesses to this approach?
I'm probably going to find a JavaScript library that takes care of the encryption and use PHP's mcrypt extension for the server-side. I was thinking of Blowfish, maybe AES256, but I'm not sure which one gives me the best ratio of encryption strength to memory consumption.
Advice?
Uh, oh. Good luck with that. Have you had a look at the TLS specification? Do you think you can come up with something adequate that will be tested by millions of people?
No, really, TLS has been tested and improved over the years by so many people, cryptographers who do nothing else than breaking such protocols, it would be a hard task coming up with something adequate.
SSL has been developed by experts in the field and they most certainly thought at first, too, that their protocol was absolutely unbreakable. But then there was version 2, then 3, then TLS v.1, v1.1 and now 1.2.
If you don't have any prior experience in designing secure protocols you should stick with the mainstream and use TLS/SSL.
Security is one of the rare fields where it makes sense and is actually cool to go with the mainstream, so I'd say the added money would be well spent.
Edit:
Maybe I was a bit harsh, and I lacked some explanation as to why your approach cannot compete with a somewhat complex protocol such as TLS, so let's analyze it:
How would you do the key exchange? For AES to work on both ends, you need to do a Key Exchange, for symmetric encryption, both parties need to possess the same key. As you said, you would like to generate it randomly on the client - so far so good. First problem - you need to generate a secure random number - otherwise, e.g. by using the built-in Javascript random number generator - attackers would be able to predict your random numbers after some time.
Let's say you got that mastered. Then the next problem arises, how would you send this key to the server in a secure manner, i.e. perform the key exchange? There you will need some form of authentication on the server side, otherwise just about anyone could impose as your server and do this:
trick people into sending their keys to their rogue server first
then forward the key to your server
your server would dutifully send the data encrypted with the established key
the attackers would intercept that data and happily read your secrets by decrypting with the key they just stole
So you need server authentication, at least, if not client authentication, too. This will imply that you need some form of asymmetric/public key cryptography to encrypt/wrap the key with the server's public key so that just the server is able to decrypt it.
Once you mastered that, you are still susceptible to more involved forms of attacks such as replay attacks, man-in-the-middle-attacks, reflection attacks, ...
Maybe you also want Perfect Forward Secrecy so that once a key does get compromised the attacker would not be capable of decrypting any past data. You will need Diffie-Hellman (preferably in its Elliptic Curve Cryptography form) to achieve this.
Last but not least, a session mechanism would probably also be nice so that you can pick up previous sessions with already established symmetric keys, so that you can reduce the load on the server by not having to re-establish it again using the somewhat resource-intensive public key algorithms.
-> Add a couple more features, such as securely negotiating an algorithm suite that both client and server acknowledge to support and you will have reimplemented the TLS protocol.
Sorry if this sounds a bit sarcastic, but I know it seems tempting to roll your own crypto schemes (it's fun, too), but in the end you should stick with TLS: it's (relatively) easy to use, it runs on the transport layer (so you can code your applications as if there were no encryption at all) and best of all, it's secure.
EDIT: Well, there have been some attacks recently, but almost all attacks exploited the "human factor" in these protocols by attacking the public key certificates that back the protocol (Comodo, DigiNotar etc. are prominent examples) or more arcane features of the protocol like algorithm negotiation etc., but the BEAST has been the first time that TLS has been successfully attacked on the cryptography level, which is interesting and scary at the same time, because the basics of that attack have been known for some years now.
Still, with recent fixes for BEAST in place by now, I would bet that TLS is still the best option you have for secure communication on the web, especially when compared to hand-crafted solutions.
Ryan: I'm saying this in what I hope is the best possible way: memory consumption is the absolute least of your problems.
There is nothing secure about this. Nothing. N.o.t.h.i.n.g.
It's dead from the very first sending of that javascript... I don't care how long your keys are or how random the salt is.
What you have won't stop someone sitting in a coffee shop with their laptop open grabbing packets from intercepting the keys and being able to easily decrypt everything else you pass back and forth. Heck, just seeing the words "encrypt", "decrypt", and "key" in the stream would be enough to pique someones interest to dive further for fun (or profit..). Never mind watching an open connection suddenly start transferring parts of the packets encrypted and other parts in the clear.
If what you have is worth encrypting then it's worth the additional $240/year to do it right. Please, step back from the ledge and just do it right.
Everyone is being so negative, and while I share the sentiment that you personally should probably not be doing this, let me make some general remarks:
For a secure channel you need three things:
line encryption
key exchange
authentication
For encryption, you need to implement a cipher. That's doable.
Key exchange is the crucial point: Both peers need to know that they know a common key without anyone else being able to know the common key. There exist protocols for that, and it should be possible to implement that. SSL is doing that, for example. The fact that you can sniff an SSL connection and not learn anything shows that it can be done.
Authentication is necessary to stop man-in-the-middle attacks, and this requires some sort of out-of-band information exchange (like a phone call or PKI infrastructure). Whether any of this really works practically is highly debatable, even for SSL.
So basically if you can implement all those components over HTTP, then in principle it should be possible to run secure communication over HTTP. After all, SSL is doing the same thing, it's running a secure channel over an insecure medium. Basically what you want is to implement SSL in JavaScript. Check out aSSL, they've tried something like that.
My advice is to stick with SSL/TLS. I think this will make your life easier and also give your solution industry recognized credibility.
Instead of the static IP address, could you use DynDNS (or similar service) with a self-signed certificate?
I am not sure if this is the right place but lets see.
I am developing an system to send private messages from one user to an other use. Under the hood runs PHP 5.2.x .
Now I am looking for any way to encrypt private messages in a way that i cant access them. At the moment I have no idea how to realize such a system, where I don't know the encryption key.
My first idea was to combine it with something like OAuth.
Some more requirements to clarify the problem:
Public Webpage
good usability
it will never work if you're doing the decryption on your server. You need to do the decryption completely on client side with javascript.
Ideas for looking for information on javascript crypto engines:
http://www.ohdave.com/rsa/
http://www.movable-type.co.uk/scripts/aes.html
If your users all use modern browsers with support for client side database storegae, you can use this to store the keys: an example
you should know, that it would be not very secure if you want the de-/en-cryption to be fast, or it will be really slow, because javascript is not the best language to do crypto stuff.
what about RSA and other public-key cryptography? http://en.wikipedia.org/wiki/Public-key_cryptography
You could use the Diffie-Hellman protocol to generate encryption keys that are only known to the users.
But as a user, you have to have access to those keys in order to read your messages. So you'd have to find a way to store the key at the client instead of your server, otherwise you'd still be able to decrypt the messages. This would be quite a challenge for a PHP site, so I doubt it can be accomplished.
How about you just don't store the key?