Showing posts with label OpenSSL. Show all posts
Showing posts with label OpenSSL. Show all posts

Wednesday, January 25, 2012

Encrypting Transmissions between JavaScript and PHP Part 3: Decrypting with PHP

Welcome to Part3 of Encrypting Transmissions between JavaScript and PHP.  You can see the previous parts at: Part 1 Part 2

There are just four easy steps to go through in order to decrypt the string from Part 2.
As with JavaScript, let's start off by getting the private key loaded into PHP.  Oddly enough, you can do it exactly the same way:


$key = "-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA3sZto3ZI4vmtMv0Vx+OaliJ/EeVnQ7R+rX8bya+zzoI/S2f7
gD+K/xNK/AD6RZ0Q1dgJ8+Nl1N+DLyDzWvLoFTNbmNJeo+j3VM5I0xXpWeETMtRG
cYysogZILprICezZM5CfC7awAh36xJD35v6mXkwWkAq2QShQDApMJyoFJI2x9DeD
oRIwgMh5pWSaNsfFRJqGaNhWHPZNILkc/PfEeI3JZEjYO7+Bpdgo7VD5jbbPv7R1
xtwko1IClhgPA3jizuQJQnaJL9G6T+MjStXG5mdfnz2oTKBOIFMzblHSlqOYDnhP
7Jbh0x0xE5dPaQQ0fsMxJqWEkDNIcfhWv8BkfQIDAQABAoIBAQCf1AcXDqcOSQlN
GqyEw7PF4Sv/f/GNbrKv8RDTq346O9IDXK/g/DXR+VqD4IOubBiHA79oPg5yIoXw
yxgteTau9zDRPKTvvhWsv28aGo9Xj5aBkjCUCNRWTmF9Jkk8bbQLPcgN1F0Et9OR
MVzaWnqsDrTlVPobVzvO15h5RLl51eOZDHZ1enrIR6gqVksloyVfoWY15Vhdx89k
jbcJ7EMvhQRLZZwIWoP1YIeP/JkREiMju8dMFGazhagZ/ejScCXy+M0LdHMe0Ow2
g5Sx9XYTxCBDj2ReONzVxiih7ZfB0QBT3+ITZIHkEbmXx93azZ98C5v5txTfxBLO
gIN0k1QBAoGBAP8t27t5qMwpEo8dZADo0NC7+qCusENMo4v2YWkyqdYTH2tLNwFK
PpbDuYuqqBClpbKKgUvQOsVaIWRM8Y58r9LiOQTHRfOmYI5W7b9uAj4t2DXP35wj
SdoSV8cBusf/bHd1w8nSAf16e2d5LmFnvIg5zmad8m5vyiWYjE64/8d9AoGBAN99
4pDXrmJ1yMNQVCeT9X2UxG56T18JnxCywE5rSJK5/uPnAGi6d20FV/JDpPe07hOv
lvJzcbYYWvPB0bVw1TkteJsVRmGWo7rwqBpNkofcBNOaEQivOYwv5Yiz97OB5URR
umYauFGI4PUrDH+jn+rlIW/TNtIpkwHqzKgzZ6EBAoGAR4bRKrGlUOTKYPc6Cs83
iOrIC7YrjhGzXg4Hq/cZh/oAOpDwsBnhhV0Da1TAmznzQiJ0r42Ei8EBzx2KMAhf
OFtU5DP/NZaTRhKzvY7WbhtnmV3VLezuTIQLuqqPcnP0MV//K1kEWcq1QIHFMGRl
gkHByx3G0JHhNbyWx5Ivj/kCgYBh5F/zFaXalsDjXDIgS9zBrwIDaiuN80brJ4C4
WKGnMzUEWlCBjvt0k1ycTyjZHzURBl5VwF9UZYKhNopGsS+UJein9T+oyzTYU0Uu
kD/YpnSuwtMnPKk2UFx37mxXAlSMAkhlJNsLS6tNeBe3aNJJLyfgNWHT2EX+Fvyh
yDJiAQKBgFnLzyAWgIECvCmBGmwAl/QK6/6w0P4CEBBt2lBTFB0dFrlkuVC2/DSY
ZLhUMtynmYZEaEreIOJqMXQfHbTUODRVrTfyKVdjvExS5SiwWENYLY/5n+lacZ/b
7iUXpuQdQPttce9IKxqo0DVg7dy7WzmFYGwCfTBTAxvaWvwFc6Pu
-----END RSA PRIVATE KEY-----";
I probably should have used a shorter key length for the demo.  Oh well.  Oh, a word on security.  Embedding your private key actually is a problem if you aren't being extra careful.  It might be wiser to read your key in from a file.  You can find documentation on how to do this in the PHP OpenSSL Documentation.

Next we utilize the PHP OpenSSL library to convert the key string into a resource.
$res=openssl_pkey_get_private($key); 
If you chose to password protect your key, the syntax would instead be:
$res=openssl_pkey_get_private($key,'password'); 
The final two steps are to Base64 decode and decrypt the encrypted text.

$text=base64_decode($_POST['encryptMe']);
openssl_private_decrypt($text,$decryptedText,$res);
That is it folks.  Your decrypted text is now in $decryptedText. Unless something went wrong.  In which case, good luck.

Encrypting Transmissions between JavaScript and PHP Part 2: Making JavaScript encrypt the right thing using the right thing

So now that we have the keys from Part 1 we can start setting up the JavaScript portion of our party.  If you have done a search for "Javascript RSA" you have probably found several different libraries that will implement it for you.  Of particular note are:
https://ziyan.info/2008/10/javascript-rsa/ and http://www-cs-students.stanford.edu/~tjw/jsbn/
The former is a modified implementation of the latter.  For the sake of this post we are going to use the former. For my own personal use I modified the code a little bit to make it more readable and so I could understand it better, but it doesn't change the way anything works so I'm not going to include it unless anyone wants it.

You will want to download the files rsa.js and jsbn.js and include them on your web page the way you normally do such things (i.e. <script language="JavaScript" type="text/javascript" src="jsbn.js"> and <script language="JavaScript" type="text/javascript" src="rsa.js">).

First and foremost we need to set things up to use the key.  How do we read that into JavaScript? Nice and simple, we cut and paste.


var pem="-----BEGIN PUBLIC KEY-----\
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3sZto3ZI4vmtMv0Vx+Oa\
liJ/EeVnQ7R+rX8bya+zzoI/S2f7gD+K/xNK/AD6RZ0Q1dgJ8+Nl1N+DLyDzWvLo\
FTNbmNJeo+j3VM5I0xXpWeETMtRGcYysogZILprICezZM5CfC7awAh36xJD35v6m\
XkwWkAq2QShQDApMJyoFJI2x9DeDoRIwgMh5pWSaNsfFRJqGaNhWHPZNILkc/PfE\
eI3JZEjYO7+Bpdgo7VD5jbbPv7R1xtwko1IClhgPA3jizuQJQnaJL9G6T+MjStXG\
5mdfnz2oTKBOIFMzblHSlqOYDnhP7Jbh0x0xE5dPaQQ0fsMxJqWEkDNIcfhWv8Bk\
fQIDAQAB\
-----END PUBLIC KEY-----";
You will note the \ at the end of each line.  Since the key is so long you will most likely want to use a line break so you can have it on multiple lines.  I recommend not having any white space before or after the \.
Lest anyone worry about having the public key in the actual code, remember that it is the public key.  People are supposed to know it. You could theoretically have the server generate a new public key with each request and embed it in the JavaScript for you, but in my opinion there is very little reason to do so unless you are super hyper paranoid or are protecting something more exciting than a user's blog.  You can check out the PHP OpenSSL documentation if you would like to pursue something more in depth.

Next, we load the key into the library with:
var key = RSA.getPublicKey(pem);
Now things are ready to go.  The actual code to encrypt something is :
encryptedText=RSA.encrypt(stringToBeEncrypted, key);
 How you choose to go about implementing that is up to you since there are quite a few usable ways, but here is a simple example:


<SCRIPT>
function encryptData(){
element=document.getElementById('encryptMe');
element.value=RSA.encrypt(element.value, key);
}
</SCRIPT>
<FORM ACTION='decrypt.php' METHOD='POST' id='txtAuth' onsubmit='encryptData()'>";
<INPUT type='text' name='encryptMe' id='encryptMe'></INPUT>
<input name='txtSubmit' type='submit' id='txtSubmit' value='Submit'>"; </FORM>";

I hope that this will save someone some trouble! Here is Part 3!




Encrypting Transmissions between JavaScript and PHP Part 1: Creating a useful OpenSSL RSA private/public key pair

I am working on configuring my web pages to encrypt a user's password when they log in to a web page.  At the moment I do not have the luxury of using HTTPS so I am focusing on using JavaScript to encrypt just the password using a RSA public key and decrypting it on the server side in PHP using the private key.

I had a hard time finding instructions for creating OpenSSL private/public key pairs that covered everything all in one place so I figured I would document what I have learned so I don't have to search for it again in 4 years the next time I need to do it.

Assuming you already have the latest version of OpenSSL installed, run the following commands from the command line.  I am using 2048 bit keys, if you wish you may substitute a different number in the instructions below. Also, I am not encrypting the keys.  For my purposes it is pointless as the password would be stored with the key.

1.  openssl genrsa -out privateKey.pem -f4 2048

  • This creates the initial private key.  the -f4 option signifies that the public exponent should be 10001
2. openssl rsa -in privateKey.pem -out publicKey.pem -pubout

  • This derives a public key from our private key
3. openssl rsa -in privateKey.pem -out publicKey.modulus -modulus -noout

  • This derives the modulus from the private key

4. openssl req -new -x509 -key privateKey.pem -out privateKey.x509 -days 1095

  • x509 self signed certificate
5. openssl req -new -key privateKey.pem -out privateKey.csr

  • normal certificate request for if you need to get an official certificate


As a quick refresher, you use the private key for the following:

  • decrypt content encrypted with your public key
  • sign (encrypt) content to be verified with your public key
You use the public key for the following:

  • encrypt content to be decrypted by the private key
  • verify content signed by the private key
For my purposes, I will be using the public key to encrypt content sent from a user's web browser via javascript, and using the public key to decrypt it on the server side via PHP. Check out Part 2 Next!