Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Monday, October 12, 2009

A Star (A*) path/route finding Javascript code

For a little side project I was working on, I needed a Javascript implementation of the A Star (A*) path finding algorithm. I couldn't find a good/simple one online, so I coded my own. I'm posting it here in case anyone else is interested in using it. Example map:  
Example path:  
The usage is simple. Make a single function call, passing in the start and destination x/y locations as arrays (e.g. [1, 2]), the board as a two-dimensional array (where 0 means a spot is open), and the number of rows and columns in your board. A final parameter indicates whether diagonal movement should be allowed.
  
<script>
path = a_star(start, destination, board, rows, columns, allow_diagonals);
</script>
 

The function will return an array of nodes from start to destination with the shortest path. The x/y values of each node can be accessed like so: path[0].x or path[0].y.  

<script>
for (var i = 0; i < path.length; i++)
    alert("X/Y of path node: "+path[i].x+"/"+path[i].y);
</script>
 

Download the A Star Javascript code.

Example implementation:
<html>
    <body>
        <script src="a_star.js"></script>
        <script>
        //Set the number of rows and columns for the board
        var rows = 10;
        var columns = 10;

        //Create the board, setting random squares to be obstacles
        var board = [];
        for (var x = 0; x < columns; x++)
        {
            board[x] = [];

            for (var y = 0; y < rows; y++)
            {
                //Give each square a 25% chance of being an obstacle
                var square = Math.floor(Math.random()*4);

                //0 = open, 1 = obstacle
                if (square == 0)
                    board[x][y] = 1;
                else
                    board[x][y] = 0;
            }
        }
    
        //Set the start and destination squares (and guarantee they're not an obstacle)
        var start = [1, 1];
        board[1][1] = 0;

        var destination = [8, 8];
        board[8][8] = 0;


          //Indicate whether we should do cardinal directions only (N, E, S, W) or diagonal directions as well
         var allow_diagonals = true;
 

        //Use A* to see if there's a path between them
        var path = a_star(start, destination, board, rows, columns, allow_diagonals);

        //Draw the board
        for (var y = 0; y < rows; y++)
        {
            document.write("<div>");

            for (var x = 0; x < columns; x++)        
            {
                document.write("<div id='board_"+x+"_"+y+"' style='"
                    + "float: left;"
                    + " width: 20; height: 20;"
                    + " border: thin solid black;"
                    + " background-color: "+(board[x][y] == 0 ? "white" : "black")
                    + "'></div>");
            }

            document.write("<div style='clear: both;'></div>");
            document.write("</div>");
        }


         //Mark the start and end nodes a special border color
        document.getElementById("board_" + start[0] + "_" + start[1]).style.borderColor = "yellow";
        document.getElementById("board_" + destination[0] + "_" + destination[1]).style.borderColor = "yellow";


         //Highlight the path
        for (var i = 0; i < path.length; i++)
            document.getElementById("board_" + path[i].x + "_" + path[i].y).style.backgroundColor = "red";
        </script>
    </body>
</html>

Saturday, November 03, 2007

Encrypting to PGP / GnuPG / GPG using Javascript

In a previous post I wrote about receiving PGP-encrypted data and using GnuPG (GPG) from a PHP script to decrypt it. In this post I'm going to show the client-side, a webpage (or in my case, a Google Gadget) that uses Javascript to PGP-encrypt sensitive information and send it to a server. Yes, you could use SSL, but the destination I was sending it to didn't have an SSL certificate.

To do the Javascript encryption, I modified some code from Herbert Hanewinkel, and I'll post the necessary Javascript include files, which he makes available.
<!--Create a holding variable that will be used later -->
<input type="hidden" name="keyid" id="keyid" value="">

<!-- Drop your public key into an invisible textarea. It's called public for a reason; there's no danger in letting people see it. -->

<textarea id="public_key" name="public_key" style="display:none;">
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.2 (GNU/Linux)

mQGiBEcrXY0RBACao9CBQL/BggPP5HcnWXLV/O5MEYhAAg3kl6l6Xu3CVKtGlw5d
P8CJSZuPZSrcQs+GI4PAkS1AH4f7Ex7phwUIMak6ufv5wX5iWU4JwxDCuvYOmlyz
l4iMsH5uJSI7QvQ7zl9QR3KC/qONZ5EWYiW7Gu/1yJ6JuykM2vumhi9CMwCg9KZy
vh5HDynAEf+8PbeD9z7aRcED/1x2muLD1gt5fSBSyyCjcvYtQ8od+UT/GwVpCMRu
Eq+t0uBrrecKmQ9GzkXhnP7KXLe7NDgTZwxAqTjMAkf+v/v5HOnBClOdzoS6EAFO
JotlB+SJiqXoClvhfHRJKhJwyMfKlmGUAWr9itaWQbdLXo5BGqDyaoXjw5jyQ4ch
yf5PA/wMjqDcUux8eOGivU63CGLHriHRMT2QtPSU73zDf3X8+X9EPZxLPZ7SCFTO
YCeyNBe5PvMsk0n8ZO/Gnezxh345NtJ9LXxk+65svGaxnTPQksdzOJAzE8KjlHDF
ZNGl52J6R/TPOxwBSt42ackTfn50IJJC/0kSvHRKck+Ll4MR4bQ7QmVuamFtaW4g
SGFyZGluIChHb29nbGUgQW5hbHl0aWNzKSA8ZXZpbG92ZXJsb3JkQGdtYWlsLmNv
bT6IYAQTEQIAIAUCRytdjQIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJ3f
PyIusymjPNcAnAqILzNRYnpk2xD0ruE0OJyGZ4OoAJoDSV9G/rVmNVVjTb2PMwMm
v49UgbkBDQRHK12NEAQAsZW2iev4FbLAaYZJ073DP1F+RuzNaa+KplQ4pHnoci2l
7JqTD+iVlODdpWbzEYQursq5L2v7xdKRN56aga0AV4j0JCXouc5atYsGCY6OY7PT
OGWMB21y8K8I9LM/9h/YZblc+7pChqeC9dJ1pL8G9dhNh02cMyEwp8BuTsx39IMA
AwUD/3+Ei+zt/rWFFtHMMByvqyRnqk8U3QWiTgN8DhY+9lol7w2OCgKjFaVZUqzt
pQnAXO665er49suqrx8riZ6Lan0YO6swxjQ8C7BUj9/fMDAlDBfpOspWDMzYu/9e
fOAqk3z8PJlPIUlMxIwy6a1wuoSt2ko3wmP2VH6Mv+0dltrriEkEGBECAAkFAkcr
XY0CGwwACgkQnd8/Ii6zKaNB5ACg33r2gxWkiZidQLZRXg5sidz7KAoAn3ajmkuL
vO273vANfSgRe9MrGJAI
=aiWr
-----END PGP PUBLIC KEY BLOCK-----

</textarea>

<!-- Include some required files. They are hyperlinked! Download them now! -->
<script language="Javascript" src="rsa.js" type="text/javascript"> </script>
<script language="Javascript" src="aes-enc.js" type="text/javascript"> </script>
<script language="Javascript" src="sha1.js" type="text/javascript"> </script>
<script language="Javascript" src="base64.js" type="text/javascript"> </script>
<script language="Javascript" src="mouse.js" type="text/javascript"> </script>
<script language="Javascript" src="PGencode.js" type="text/javascript"> </script>
<script language="Javascript" src="PGpubkey.js" type="text/javascript"> </script>

<script language="Javascript">

var keytyp = -1;
var keyid = '';
var pubkey = '';

function getkey()
{
    var pu = new getPublicKey( document.getElementById( "public_key" ).value );
    if(pu.vers == -1) return;

    document.getElementById("keyid").value = pu.keyid;

    /* I didn't end up needing this variable in the encrypt function, since I already knew the key type was Elgamal */
    /* document.getElementById( "pktype" ).value = pu.type; */

    pubkey = pu.pkey.replace(/\n/g,'');
}

/* Pass in the data to encrypt */
function encrypt(text)
{
    keyid='0000000000000000';
    if( document.getElementById( "keyid" ).value.length )
        keyid=document.getElementById( "keyid" ).value;

    if(keyid.length != 16)
    {
        alert('Invalid Key Id');
        return;
    }

    /* Since I already knew my key type was Elgamal, I didn't need this block of code. I just set "keytype=1" below. */
    /*
    keytyp = -1;
    if( document.getElementById( "pktype" ).value == 'ELGAMAL')
        keytyp = 1;
    else if( document.getElementById( "pktype" ).value == 'RSA')
        keytyp = 0;

    if(keytyp == -1)
    {
        alert('Unsupported Key Type');
        return;
    }
    */
    keytyp = 1;

    return doEncrypt(keyid, keytyp, pubkey, text);
}

var encrypted_data = encrypt("sensitive data here!");
alert(encrypted_data);

/*
Special Note: I was forced to send the data through a URL (i.e. a GET rather than a POST). This forced me to encode the data prior to attaching to URL. Contains "+", so we must use "encodeURIComponent()" instead of "escape()". (See below for how the server-side PHP script will handle the received data.) */
encrypted_data = encodeURIComponent(encrypted_data);

/* Do something with the data. */
window.location = "http://www.test.com/index.php?encrypted_data="+encrypted_data;
</script>

Here's what happens on the server side, in the PHP script that receives it. (In the previous blog post about the PHP side I just pulled the encrypted data from a file, but here's what I was really doing.)
<?php
/* Reverse the effects of the Javascript "encodeURIComponent" */
$encrypted_data = rawurldecode( $_GET['encrypted_data'] );

/* From here, jump right into the PHP script outlined in the previous post, commenting out the line where you're pulling the encrypted data from a file, since you just got it from the GET request. */
?>

Friday, November 02, 2007

Setting up GnuPG (GPG) for use with PHP

Step 1 (failed):
$ pecl install gnupg

downloading gnupg-1.3.1.tar ...
Starting to download gnupg-1.3.1.tar (-1 bytes)
.............done: 124,416 bytes
5 source files, building
running: phpize
Configuring for:
PHP Api Version: 20020918
Zend Module Api No: 20020429
Zend Extension Api No: 20050606
`phpize' failed

Step 2 (success). Some information drawn from http://www.php.net/manual/en/install.pecl.php, a basic tutorial on how to install PECL extensions.
$ cd /usr/lib64/php/extensions

(This is where my PHP extensions [files with .so extension] are stored)
$ pecl download gnupg
$ tar -zxvf gnupg-1.3.1.tgz
$ cd gnupg-1.3.1/
$ phpize
$ ./configure
$ make
$ make install

"gnupg.so" now appears in /usr/lib64/php/extensions
Now I need to install the extension in the php.ini file
$ whereis php.ini

/etc/php.ini
$ vi /etc/php.ini

Find the list of extensions in php.ini, in my case headed by "[extension section]". Add "extension=gnupg.so" to the end of the list, save and exit.
Now I need to restart apache so the extension takes effect.
$ apache2ctl graceful

Now do some PHP coding. Assumes you have GnuPG (gpg) installed, and have set up your key pair ("gpg --gen-key"). Some of these steps might be unnecessary, but after hours of fiddling around, I'm not about to walk through it again and find the essential ones.
/* Change this to your own path */
putenv("GNUPGHOME=/home/bch36/.gnupg/");

$encrypted_data = file_get_contents("encrypted.gpg");

$res = gnupg_init();

gnupg_seterrormode($res,GNUPG_ERROR_WARNING);

/* Change this to your own fingerprint. Find your fingerprint by running "gpg --fingerprint" from the commandline. Comment this out when everything works. */
print_r(gnupg_keyinfo($res,"ASDF1234QWER5678ZXCV9012ASDF3456QWER7890"));

/* Put your own fingerprint and passphrase here. Also, this function will fail unless you see Important Note #1 below */
gnupg_adddecryptkey($res, "ASDF1234QWER5678ZXCV9012ASDF3456QWER7890", "put your secret passphrase here");

/* You'll want to comment this out when everything is working */
echo gnupg_geterror($res);

/* This function will fail unless you see Important Note #2 below */
$plain = gnupg_decrypt($res, $encrypted_data);

Important Notes:
1. To get gnupg_keyinfo() to work, you'll need to let your webserver have some access to your keyring. Do the following (replace "www" with the group that your own webserver runs under):
> cd /home/bch36/.gnupg
> chown :www pubring.gpg trustdb.gpg
> chmod 660 pubring.gpg trustdb.gpg

2. To get gnupg_decrypt() to work, you'll need to grant more access. Note that the webserver will now have access to your secret key! However, if you don't do the following, the gnupg_decrypt() function will fail and you'll get the following warning when printing out gnupg_geterror(): "Warning: gnupg_adddecryptkey() [function.gnupg-adddecryptkey]: get_key failed in ..."
> chown :www secring.gpg
> chmod 660 secring.gpg

As a possible point of interest, I'm only doing decryption because I want a remote webpage to use Javascript to PGP encrypt data and send it to my PHP file, which can then decrypt it. I guess it's a workaround for not having SSL. I'll try to post an entry about the client-side next (Javascript PGP).