Installing a Self Signed Cert on your Local Machine

As browser security increases in 2021 it’s gotten a lot harder to install a self-signed cert on your local dev server and get a nice pretty dark gray lock (I kinda miss the green). It’s very important, especially if you are working with web workers and javascript. Web browsers are continually tightening down the security and you no longer even accept TLS 1.0 and 1.1 anymore, so keep those certs and virtual host configuration and web server SSL settings up to date! This is something you have to do every time you work on a new domain and you won’t have a cool tool like Letsencrypt and Certbot to use because they do a round trip on the server which it means it has to be publically exposed and available online which is something you should never do with your local development server. Since it took all day to figure it out I thought I’d write an article on it.

Privacy Error, Not Secure local Dev website
Local Error for Self Signed Cert

The process is pretty straightforward.

  1. Generate a key and certificate with Openssl.
  2. Specify the key and certificate in your Web Servers configuration file
  3. Restart web server
  4. Export certificate from browser
  5. Import that certificate into the browser
  6. Restart the browser

I set this up on my Windows machine with Git Bash and Openssl running Apache Web Server and using Chrome as my browser, but the steps are the same if you are using a Linux machine, and the web configuration will change if you are using a different web server or depending on where you put your website or generated your cert/key. The web server will always have a way to specify a key and certificate for https.

One of the major changes I had to do that I didn’t have to do before was use a configuration file for openssl. You can find it here at minimal.cnf and it looks like this:

prompt = no
distinguished_name = req_dn
x509_extensions = x509_ext

[ req_dn ]

commonName = www.websitedomain.local

[ x509_ext ]

subjectAltName = @alt_names

[alt_names]
DNS.1 = www.websitedomain.local
DNS.2 = websitedomain.local

minimal.cnf file (change commonName and DNS.1 and DNS.2 to your local domain names…I believe you can also specify an ip as IP.1 if you want under alt_names)

The openssl command is as follows….once again, change the names to something appropriate for your website…these are the files that are referenced in your virtual host file. I set it to be good for less then 3 years because I believe there is some sort of max for security reasons, at least in Chrome.

openssl req -newkey rsa:4096 -x509 -sha256 -days 1000 -nodes -out www.websitedomain.local.crt -keyout www.websitedomain.local.key -config minimal.cnf

My Apache configuration file for this virtual host in httpd-vhosts.conf looks like this:

<VirtualHost *:443>
    ServerAdmin [email protected]
    DocumentRoot "C:/websites/www.websitedomain.local/public_html"
    ServerName www.websitedomain.local
    ServerAlias websitedomain.local
    ErrorLog "logs/www.websitedomain.local-error.log"
    CustomLog "logs/www.websitedomain.local-access.log" common
    DirectoryIndex index.php index.html index.htm
    SSLEngine on
    SSLCertificateFile "C:/websites/www.websitedomain.local/ssl/www.websitedomain.local.crt"
    SSLCertificateKeyFile "C:/websites/www.websitedomain.local/ssl/www.websitedomain.local.key"
    <Directory "C:/websites/www.websitedomain.local/public_html">
        AllowOverride All
        Options  Indexes FollowSymLinks Includes ExecCGI
        Require all granted
    </Directory>
</VirtualHost>

Don’t forget to make sure your hosts file has an entry for your local website domain.

127.0.0.1 www.webmastedomain.local

[Of course change “websitedomain” to the domain you want to setup and access the website through…it’s arbitrary, but needs to be consistent…make sure it’s the same in the configuration file minimal.cnf, hosts file, virtual hosts file and in the url you are trying to access the website through.]

Now comes the tedious part where you export the certificate through the browser and then import the slightly modified certificate as a Trusted root certificate.

And finally, don’t forget to close and reopen your browser before checking the url and it should be good for 1000 days! You can try longer, but I don’t recommend it since security requirements change all the time with browsers and web servers.

Successful Installation of Self Signed Cert for Local Dev Server
Successful Installation of Self Signed Cert for Local Dev Server

Easy Amazon Wishlist 2.0 WordPress plugin goes live!

Easy Amazon Wishlist 2.0!

Ever since Amazon retired their wishlist API it’s been difficult for customer to find a convenient way to display their Wishlists (and now Idea Lists as well!) Wishlists are great for non-profits, social media stars with loyal customers, birthday, or for whatever reason you might want to provide a mechanism for someone to buy you something. We also added the capability to add an Amazon Idea list to your blog. These are ideal for recommending products on Amazon. We are going to work on a Facebook app to do something similar now, and we have great plans for the future of the plugin, but we have to prioritize, so please let us know what new feature for the Easy Amazon Wishlist pugin you would like to see worked on first! https://wordpress.org/plugins/easy-amazon-wishlist/

Coming Soon
What new feature do you want worked on first?
What new feature do you want worked on first?
What new feature do you want worked on first?

Dual Pivot Quicksort Kicks Butt!

So while I was checking out different flavors of quicksort after taking the Coursera Algorithms class I found out about a new version of quicksort that was much faster then I had anticipated.  Java 7 had recently modified their sort function to use a new algorithm called Dual Pivot Quicksort, so I thought I’d check it out.  I found a java version and recoded it to be javascript.  It works well, but currently only sorts integers and in ascending order.  Ideally I should modify it to work the same way the normal array sort algorithm works, that way I’d be comparing apples to apples.  I believe under the hood that the V8 javascript engine has upgraded to the new dual pivot algorithm, but it does have some additional checks and improved functionality where you can pass in the sorting algorithm, which may be why it’s consistently slower then my javascript version of dual pivot quicksort that I coded up.  It’s consistently 10%-50% faster then the default array.sort() algorithm.  The default sort is going to work well enough for 90% of your sorting cases, but if you are following the 10/90 rule and have narrowed down the bottleneck in your code and want to optimize sort, then I would advise taking this code and modifying it for your needs since it will always be faster then the default array.sort().  Check it out on JSPerf http://jsperf.com/javascript-quicksort-comparisons

Technically JS Perf says it’s ±10.25% faster then the default sort the last time I ran it, but it does vary quite a bit. My guess is that it probably varies based on how random the shuffle is.  I suppose it could be because we are comparing a lion to a cheetah….the default sort sorts any object, and lets you pass in the sorting function, while the dual pivot quicksort I coded up only works on integers and in ascending order, but I’d still say it’s worth looking into, ESPECIALLY if whatever language you are coding in hasn’t rewritten their quicksort to use the new algorithm.  I made it a single variable module, and you call it with DualPivotQuicksort.sort(arr). Here’s the code.


/******** Dual Pivot QuickSort ***************/

var DualPivotQuicksort = (function() {

    var dualPivotQS = {};

    dualPivotQS.sort = function(arr, fromIndex, toIndex) {
        if(fromIndex === undefined && toIndex === undefined){
            this.sort(arr, 0, arr.length);
        } else{
            rangeCheck(arr.length, fromIndex, toIndex);
            dualPivotQuicksort(arr, fromIndex, toIndex - 1, 3);
        }
        return arr;
    }

    function rangeCheck(length, fromIndex, toIndex) {
        if (fromIndex > toIndex) {
            console.error("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            console.error(fromIndex);
        }
        if (toIndex > length) {
            console.error(toIndex);
        }
    }

    function swap(arr, i, j) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    function dualPivotQuicksort( arr, left, right, div) {
        var len = right - left;

        if (len < 27) { // insertion sort for tiny array
            for (var i = left + 1; i <= right; i++) {
                for (var j = i; j > left && arr[j] < arr[j - 1]; j--) {
                    swap(arr, j, j - 1);
                }
            }
            return;
        }
        var third = Math.floor(len / div); //TODO: check if we need to round up or down or just nearest

        // "medians"
        var m1 = left  + third;
        var m2 = right - third;

        if (m1 <= left) {
            m1 = left + 1;
        }
        if (m2 >= right) {
            m2 = right - 1;
        }
        if (arr[m1] < arr[m2]) {
            swap(arr, m1, left);
            swap(arr, m2, right);
        }
        else {
            swap(arr, m1, right);
            swap(arr, m2, left);
        }
        // pivots
        var pivot1 = arr[left];
        var pivot2 = arr[right];

        // pointers
        var less  = left  + 1;
        var great = right - 1;

        // sorting
        for (var k = less; k <= great; k++) {
            if (arr[k] < pivot1) {
                swap(arr, k, less++);
            }
            else if (arr[k] > pivot2) {
                while (k < great && arr[great] > pivot2) {
                    great--;
                }
                swap(arr, k, great--);

                if (arr[k] < pivot1) {
                    swap(arr, k, less++);
                }
            }
        }
        // swaps
        var dist = great - less;

        if (dist < 13) {
            div++;
        }
        swap(arr, less  - 1, left);
        swap(arr, great + 1, right);

        // subarrays
        dualPivotQuicksort(arr, left,   less - 2, div);
        dualPivotQuicksort(arr, great + 2, right, div);

        // equal elements
        if (dist > len - 13 && pivot1 != pivot2) {
            for (var k = less; k <= great; k++) {
                if (arr[k] == pivot1) {
                    swap(arr, k, less++);
                }
                else if (arr[k] == pivot2) {
                    swap(arr, k, great--);

                    if (arr[k] == pivot1) {
                        swap(arr, k, less++);
                    }
                }
            }
        }
        // subarray
        if (pivot1 < pivot2) {
            dualPivotQuicksort(arr, less, great, div);
        }
    }
    return dualPivotQS;
}());

/************************************************/

Javascript Modular Design

So I just completed my update of my Facebook app My Amazon Wishlist  I converted all of my messy initialization and jquery UI event handling code into a nice neat single variable javascript module.  It is sooooo much prettier….cleaner, more modular (it’s right there in the name!), less likely to interfere with any other javascript includes.  I briefly contemplated creating javascript objects for the lists….if I were to recode it from the start that’s how I would do it, but for now I’ll leave it as is because cloning the objects is faster and it can stay as is until I decide to implement more features.  The back-end is all php objects, and has made it incredibly easy to update and add features, as well as re-use in my wordpress plugin.  I also updated from jQuery 1.8.1 to 1.10 and had to update a few deprecated function calls that were removed in 1.9 ….GO $(document).on(‘click’, ‘id’, function(){});!…I also had to replace window.parent.document calls inside an iframe with  with jQuery postmessage calls….they actually turned out quite nicely….you have to setup a listener in the parent frame, then in the iframe (or another website even..it solves the cross-domain problem). post the message to the parent.  In my case I was sending multiple pieces of data, so I put it into an array, stringified it and passed it to the parent.  One thing I would note….in the listener you should make it so that it only accepts messages from the website you expect to be sending messages.  Here’s the code from the iframe:

var msgArray = new Object();
msgArray[‘newHeight’] = $(‘#aws-item’).height().toString();
msgArray[‘listNo’] = listNo;
msgArray[‘itemNo’] = itemNo;
msgArray[‘iframeID’] = iframeID;
var message = JSON.stringify(msgArray);
parent.window.postMessage(message, ‘*’);

And so ends my first article for my new website!  I think I’ll write the next one on how I localized (L10N) my WordPress plugin http://wordpress.org/plugins/easy-amazon-wishlist/