Flattening JS Arrays

Just posting this random off-topic bit of code here because when I went Googling for this, the only thing I found was an NPM package, which is way overkill here.

JavaScript just recently got a couple new Array methods in ES9 (or around thereabouts). Array.flat(depth) to flatten multidimensional arrays and Array.flatMap(callback), which does Array.map(callback) followed by Array.flat(1) (potentially more efficiently done than manually chaining the functions). These methods are currently available in Mozilla Firefox 62+ and Google Chrome 69+, however I wanted to be able to use it in current Firefox 60 or 61 (ESR and main releases, respectively). So, polyfill time, but the alternatives currently on MDN are not quite as good/simple as I want, so I wrote my own. I also feel like using reduce as they suggest could be worse for performance in many cases, whereas my version only has a single concat call per flatten level (I’ve not done any significant perf testing here, though). Near as I can tell, the below polyfill should match the specification’s behavior, save for extra error handling details.

// Polyfill for new ES9 Array method (Firefox 62+)
if (!this.Array.prototype.flat)
this.Array.prototype.flat = function(depth=1) {
if (depth < 1)
return Array.from(this);
const flattened = [].concat(...this);
return (depth > 1 && flattened.some(Array.isArray)) ? flattened.flat(depth-1) : flattened;
};

// Polyfill for new ES9 Array method (Firefox 62+)
if (!this.Array.prototype.flatMap)
this.Array.prototype.flatMap = function(mapFn) {
return this.map(mapFn).flat(1);
};

(apologies for WordPress not wanting to show indentation correctly here…)

There’s too little code for me to consider anything here being deserving of any legitimate copyright, but I’ll officially declare the above public domain, nonetheless. (code comments indicating the source of reused code are generally good practice, but not required, of course) If you find this useful somehow, noting so in a comment below would be appreciated.

Advertisements

Converting an old overlay-based Firefox extension into a restartless addon

Converting an old overlay-based Mozilla Firefox extension of non-trivial complexity into a restartless addon used to be impractical. When restartless addon support was added in Firefox, quite frankly, it was a partially implemented mess. Bugs have been filed and fixed over the years, sometimes taking forever to see any progress, some not at all. I took a stab at converting Flagfox into a restartless addon around Firefox 10.0 and found it to still be impractical at the time. My second attempt was last month, and I’ve got a Flagfox beta up and running that is restartless (and extractionless). There aren’t really that many good sources of information on how to make this transition online, and it’s easy to think it’s still not practical. What follows is an attempt to remedy this a little bit.

Update:
An updated version of this guide is available on MDN, and will be updated as needed.
Continue reading

An entropy based password strength checker in a data URI

Sometime last month, around the time that some major breaches of user databases from some popular sites were making the news, I got to thinking about password strength. Fred Wenzel’s post about storing user passwords is a great read on the topic, and one little part struck me: for unsalted quick hashing algorithms, if the hash is leaked then even completely random alphanumeric passwords up to 10 characters long are readily crackable. I realized it was time to change my passwords as most of them, while not something a person could guess, were easily crackable if a hash were to be leaked in a user database breach. So next step was to come up with some good strong passwords. There are some sites out there that will test one for you, but if you’re paranoid like me then you’re obviously not going to type your actual password in there. I wanted something I could test locally and I was already aware of the basic theory of entropy with regard to passwords so I did a little more research and wrote my own little password checker. Sure, I could’ve probably hunted for an addon to do this, but I wanted something simple and it was a neat little project that sounded like fun to write. Gerv posted on the this exact topic today, so I thought I might as well post my little checker for those who want it.

Note that my checker has a few nice properties:

  • Its strength assessment is based on calculated entropy, not purely whether or not you include upper and lower case characters, numbers, and/or symbols. Adding one of these cases adds to the possible characters available and increases the entropy, but the final number is based on this math and not whether or not you follow any particular practice. The end result is that it will correctly tell you that adding two characters to an alphanumeric password is better than adding case-sensitivity.
  • It has a high standard; it will likely label passwords that might be considered good elsewhere as not good enough.
  • It’s simple, local, and entirely contained in a data URI. This means you can read the code yourself very easily and verify it’s not going to send it anywhere.

But it has a few disadvantages too:

  • It doesn’t check for common and easily guessable passwords or patterns. It’ll only give you a rating against a brute-force attack from a computer with no hints. Passwords are rarely truly random and people writing programs to crack them know this. The lessons of what stupid stuff to not put in your passwords are not addressed here.
  • It doesn’t handle Unicode well. It could add new character categories for other languages’ alphabets and syllabaries, but for now if you have anything other then alpha-numeric-symbolic it will give you an overly optimistic strength rating. Also, it goes by each byte not each character, so a multi-byte character is counted as multiple characters.
  • I’ve only tested it in Firefox thus far.

It’s not perfect, but as long as your password is alpha-numeric-symbolic and not easily guessable by someone it will give you a good analysis of password strength.

Load my entropy based password checker (data URI)

Note that you can bookmark the checker page directly, at which point the whole thing is stored in the bookmark itself. This is sometimes called a bookmarklet. I’ve re-encoded it with base64 and put it behind a TinyURL because WordPress can’t link to it as-is.

I decided I might as well put a license on my code so I went with MPL2 if anyone wants to use it.

For anyone who was wondering how to easily make data URIs, I recommend the The data: URI Kitchen. I used the nicely meta Self-contained data: URI Kitchen, which is itself contained in a data URI (but is text only).

Apparently, JavaScript can’t do 64-bit math

Sometimes fuzzy variable types can bite you in the ass.

I tested my initial implementation of IPv6 support in Flagfox on quite a few sites and all seemed well when I released the first test version with it, Flagfox 4.1b2. Today I decided to test a wider variety of IPv6 addresses and compare them to expected results in the raw list. It turns out that a few of them were being looked up wrong. The problem in adding IPv6 support is that IPv6 addresses are big. Not just a few times bigger; way bigger. IPv4 addresses are 32-bit and IPv6 addresses are 128-bit. Four times the bits does not mean four times the number of possible address. Each bit you go up doubles the maximum number that can be represented, thus the number range isn’t 4 times larger, it’s 79228162514264337593543950336 times larger. To borrow a metaphor from The TCP/IP Guide: If you imagine the IPv4 address space is the size of a 1.6 in (4.1 cm) square, then the IPv6 address space would be represented by a square the size of the solar system. These IPv6 addresses when represented in full are quite big numbers, too big for me to deal with in Flagfox in fact. Fortunately, the way IPv6 is set up I don’t need to know about the whole 128 bits, I only really care about the first 64 bits. The first half is for the network and the second half is for the host on that network. The data Maxmind has for IPv6 is a list of those network prefixes and what country they’re in. Most are 32 bits and none are larger than 64 bits. So, I basically did the same thing I did for 32-bit IPv4 addresses except now with the 64-bit network prefix of the IPv6 addresses. Now, anyone guess where I went wrong? Logically, I didn’t; it’s the technical aspect that got me. Flagfox, like most extensions, is written in JavaScript. JavaScript, it turns out, can’t think in 64-bit numbers and its fuzzy variable typing was just silently dropping the less significant parts it couldn’t handle and just plugged along its way without any warning. (I was led astray by some Mozilla docs, but I’ll get to that later) I didn’t catch the problem until I tested artificially made up addresses that were too much for a JS engine to handle, at which point my search algorithm gave incorrect results.

So, what’s my fix then if JavaScript simply cannot handle the math needed to deal with the full IPv6 network prefix? I could theoretically switch out of JavaScript into C for the needed math using JS-ctypes, as C can do 64-bit math just fine, but that would be messy and JS-ctypes is new so I’d have to drop support for everything but Firefox 4.0+ which I don’t want to do. Instead, I’ve decided to just work within the limits. Those 64-bits for the network prefix can be broken down into two parts: the 48-bit global routing prefix and the 16-bit subnet ID. (The TCP/IP Guide reference on that is here; that site has been really helpful) Fortunately, JavaScript can deal with 48-bit numbers, which may be a weird size to do math with in programs, but it works. So for Flagfox 4.1b3 I’ve changed everything to search by the 48-bit main network prefix instead of the full 64-bit prefix including the sub-network ID. Out of the 6352 IPv6 address ranges in Maxmind’s current database, only 3 go down to the subnet level, so over 99.95% of the ranges are just fine with this. Unfortunately, this means any networks with subnet ranges in the database that span multiple countries aren’t able to be supported, but this is a very rare occurrence so it shouldn’t be a problem (for now). Hopefully in the future JavaScript just gets 64-bit integer support and I can upgrade to the full route I initially tried.

Now, how did I make this mistake in the first place? I’m using the nsIBinaryInputStream interface to read my IP database files and it has a perfectly normally listed read64() method just like the read32() method I was already using. There’s actually not anything wrong with this if you’re using that interface from C, but if you’re using it from JS, then you’re going to hit this problem. In order to hopefully avoid someone else making this same mistake, I have edited the online documentation to add a little warning next to the read64() method about the fact that JS does not currently support 64-bit integers.