JavaScrypt Development Log

2003 September 24

Modified formatPlaintext in aes.js to fill plaintext buffers that aren't an even number of 32 byte AES blocks with pseudorandom bytes from getRandomBytes rather than zeroes.

Extracted the JavaScript code embedded in index.html into a new jscrypt.js module. This will make it easier to programmatically assemble the “lean” version from the main file.

Updated the Makefile to explicitly list the JavaScript modules included in the archive as opposed to including them with a wildcard specification. This permits keeping the compressed JavaScript files for the lean version in the same directory without having them included in the archive.

Added mark-up to index.html to denote those parts to be dropped when assembling the lean version.

2003 September 25

For some reason, on Mozilla 1.3/Linux, the “Key” edit line displayed in a larger Courier font in the lean version (but not the full version, which has no changes whatsoever which should affect the style of this box). I removed “Courier” from the font-family and left it as “monospace”, which appears to work everywhere. No other browser had any problem with Courier as an alternative to monospace.

2003 September 27

Added the three ECB test cases from the NIST standard test set to the test.html testbed. Each button plugs the key, plaintext, and ciphertext for the test in the corresponding boxes; you may then encrypt and decrypt to verify nothing changes. Key size and block size are now sensed automatically based on the length of the hexadecimal value in the field.

2003 September 28

Integrated the pass_phrase.html and stego.html pages along with their supporting wordtab.js and stegodict.js files. Added these files to the appropriate places in the Makefile.

Added the ability to suppress the generation of headers and trailers in Base64 armour by setting base64addsent to false before calling armour_base64 in armour.js. This permits Stego to optionally suppress headers when it's being used to steganify a Base64 file belonging to another application.

2003 September 29

Added user-defined seed specification to pass_phrase.html. If a pseudorandom seed is requested, its value is displayed in the user-defined seed field so it may be saved for subsequent use.

2003 November 15

Extracted the entropy collection logic from javascrypt.html and pass_phrase.html into a new entropy.js module. Added a new mouseMotionEntropy function which captures mouse motion events and collects a specified number of subsequent triples of screen X and Y co-ordinates (we use the absolute screen position as it is more entropic than position within the client window), and the time of the mouse movement. This primes the entropy array with reasonably high quality data before most operations which require it.

Modified jscrypt.js to use AESprng in aesprng.js to generate the initial vector for CBC encryption and pad to an even number of blocks (if required). The AES-based pseudorandom generator is primed with a seed computed from the entropy vector.

Updated aesprng_test.html to conform with the changes to initial vector generation.

2003 November 17

Increased the maximum length of the key in javascrypt.html and the seed in pass_phrase.html to 1024 characters.

2003 November 18

Replaced "./" link targets in references to the JavaScrypt home page with "index.html" so these links work correctly when referencing the pages from a file: URL on a machine to which the user has downloaded the pages.

2003 November 19

Modified aesprng_test.html to generate hexadecimal pseudorandom streams suitable for testing with ENT, and rewrote the code which assembles the strings and stuffs them into the results dialogue box to run about a thousand times faster, avoiding JavaScript's (at least on Mozilla) exponential slowdown when appending large results to textarea value fields.

2003 November 20

Further cleaned up aesprng_test.html so it's comprehensible without reading the source code. It now lets you specify the number of bytes to be generated and whether they're generated with the next or nextInt methods with HTML controls, shows the number of bytes when generated if the script is paused by an “unresponsive” warning, and lets you generate seeds just like pass_phrase.html does. I also cleaned up the format of the output it generates so it look just like an “XD” output and no longer requires the “-s” option when converting to binary with XD. The aesprng_test.html being sufficiently civilised now, I included it in the source distribution.

Added comments to the methods in aesprng.js.

Added missing example.html description to distribution.html.

2003 November 21

Fixed truncation of warning message in index.html if JavaScript is not enabled. I also added a gimmick so that the background of the JavaScript enabled field is pink if JavaScript isn't present and green if it is.

Modified all Fourmilab links outside the JavaScrypt document tree to include an explicit “”. This permits them to function even when the pages are accessed from a local copy via a file: URL.

The welcome page, index.html, was needlessly including several JavaScript modules it never actually used. I removed the script includes for them.

2003 November 27

Modified the nextInt methods in aesprng.js and lecuyer.js to avoid the bias which results from using a modulus to obtain a pseudorandom value with a range which isn't a power of two. As explained in section 10.8 of Ferguson and Schneier's Practical Cryptography, to avoid a bias toward smaller values, one must generate pseudorandom values between 0 and the next higher power of two minus one, then discard results which are out of range in order to preserve a uniform distribution within the requested range. In aesprng.js, this fix has two additional salutary effects. First of all, it reduces the number of raw bytes generated to the minimum required to produce the desired result range and, if the requested range is 0–255, produces identical results to those obtained by calling the next() method directly.

2003 November 29

As reported by Steven Wittens, jscrypt.js failed to handle plaintexts which contained Unicode characters greater than 0xFF. The conversion of the plaintext string to the AES plaintext byte array simply truncated characters to 8 bits. I added a new utf-8.js module which handles transformation between Unicode strings and UTF-8 encoded byte streams. Canonical transformation is implemented in the functions unicode_to_utf8 and utf8_to_unicode, which take a string argument and return the encoded or decoded string.

For use with JavaScrypt, the wrapper functions encode_utf8 and decode_utf8 are used to provide more efficient representation of the very common case of text which consists only of ASCII and Latin-1 characters. If its argument contains neither any characters with code points greater than or equal to 0xFF nor the character 0x9D (Unicode OPERATING SYSTEM COMMAND), encode_utf8 is an identity transformation—the encoded string is identical to the input. Otherwise, encode_utf8 returns a string which begins with the character 0x9D acting as a sentinel, followed by the UTF-8 encoding of the argument string. The decode_utf8 function checks for the presence of the 0x9D sentinel and decodes the balance of the argument string as UTF-8 or returns the argument unchanged accordingly. Now, it might have been more logical to use one of the two Unicode PRIVATE USE control characters as the sentinels, but both of them are overloaded by characters in the regrettable “Windows-1252” character set. Characters from that set have no business appearing in JavaScript strings, but you never know what somebody is going to paste into an HTML text box, so this choice keeps such text from being unnecessarily expanded to UTF-8.

Both jscrypt.js and pass_phrase.html now apply encode_utf8 to text keys and seeds. This avoids the loss of information in upper bytes of characters greater than 0x7F. Since encode_utf8 is an identity for strings without such characters, this change is upward compatible with any key or seed consisting entirely of ASCII and Latin-1 graphic characters.

Added this development log to the Web directory, and provided a link from the main page.

2004 March 19

The “lean” version, jscrypt.html failed to embed the JavaScript code for utf-8.js because the program which does the embedding assumed file names consisted only of alphanumeric characters and failed to recognise the external script reference to that file. I modified the embedding program accordingly and rebuilt jscrypt.html with it. Earlier testing failed to reveal this problem which only manifested itself when the lean version was copied to a directory which did not contain utf-8.js.

2005 December 16

The formatPlaintext function in aes.js uses a heuristic instead of instanceof to decide whether its argument is a string (primitive or reference) or an array of bytes (numbers) in order to remain compatible with versions of Internet Explorer prior to 5.0 which did not implement instanceof. Unfortunately, this trick ran afoul of changes to the JavaScript implementation in Mozilla Firefox 1.5. After a bit of experimentation, I made the test even more tricky and complicated and it now seems to work on Firefox 1.5 as well as Firefox 1.0, Mozilla, Opera, Internet Explorer (although I have nothing older than 6.0) and Netscape 4.7 on SGI.

The link for verifying the distribution signing key on KeyServer was broken due to a change in their domain name; fixed.

Added content-type declarations of charset=iso-8859-1 to all HTML documents and fixed most validation errors reported by the W3C HTML validator for 4.01 Transitional. A few remain, however, so we're not claiming full compliance. The problem is that without the wrap="off" attribute in a number of textarea fields, undesired line wrapping will occur. You're supposed to be able to control this with the CSS white-space: pre statement, but it doesn't seem to do anything inside a textarea, even in Firefox 1.5. So, there's no option but to leave the wrap in place, even though the validator complains about it.

The HTML 4.01 compatibility fixes broke the Perl program which creates the “lean” version of the encryption/decryption page; fixed.

2005 December 24

Upgraded the following files for XHTML 1.0 syntax and validated them for compliance: aesprng_test.html, distribution.html, example.html, index.html, and log.html.

2005 December 25

Upgraded the following files for XHTML 1.0 syntax and validated them for compliance: javascrypt.html, pass_phrase.html, and stego.html.

Removed wrap="off" attributes in <textarea> fields, as this is not an XHTML 1.0 (or HTML 4.01) supported mode. The CSS mode which is supposed to provide an equivalent doesn't work in current browsers, but in any case this is purely an aesthetic and presentation issue: wrapping of text within a textarea does not affect its processing.

Modified the Perl program used to build the jscrypt.html “lean” version of the encryption/decryption utility use XHTML “CDATA” quoting of embedded JavaScript code to avoid validation errors. The XHTML quoting is commented out with JavaScript comments to avoid problems with older browsers.

2018 March 12

Deleted the distribution signature file and references to it in the documents. These signatures and the PGP/GPG keys used to sign and verify them are a perpetual source of fragility due to changing fashions in cryptography. It's better to do without than have to constantly fix them.

Converted all HTML and JavaScript files in the distribution to Fourmilab's source code standard of all spaces for white space (no tabs), Unix end of line (LF) convention, and all white space at the ends of lines trimmed. In the Age of Extravagant Computing the space savings from using tabs is incommensurate with the trouble they create with text editors that can't agree on where the tab stops are.

Updated all HTML files to use Unicode typography for quotes, dashes, ellipses, etc.

Verified all links to books on Amazon, updated those for which there are new editions, and converted all to the current associate link format.

Created new CSS style sheet, javascrypt.css, and used it in all the main HTML documents, in most cases completely replacing their embedded CSS. This is a much-simplified version of the standard Fourmilab style sheet, stripped to contain only what we need and to maintain our goal of operating without references to any external Web resources.

Added “use strict” to all JavaScript files and fixed the resulting quibbles. These were mostly attempts to delete variables pointing to objects (you should assign null to them instead) and failing to declare iteration variables in loops in third-party code incorporated in the program.

Added <label> containers around check and radio boxes so that their labels, and not just the box controls, can be clicked.

Deleted a bunch of commented-out debug code which has been present for more than a decade. It is unlikely in the extreme that at this remove we'll need it.

2018 March 13

Copied over the build tools from the original development directory including the Makefile, JavaScript compression utility, and the TOOLS directory.

Re-crunched all of the production JavaScript files into .jsC files with jcrunch.html.

Did a test re-build of jscrypt.html: the “lean” version of the encryption/decryption utility with everything embedded. At first glance, it looks OK, but we need to check out external CSS, etc. references. Indeed, we need to embed the stylesheet, which is presently included.

Used the CSS compressor at to compress javascrypt.css into javascrypt.cssC, using the “High” setting, which squashes white space but preserves line breaks.

Added code to TOOLS/ to interpolate CSS in the HTML it is compressing. It replaces CSS included with a link tag with the corresponding .cssC compressed file.

Updated the TOOLS/ program to “use strict” and “use warnings” modes and fixed problems those settings detected.

Moved the jcrunch.html utility to the TOOLS directory and updated the Makefile to reference it there.

Installed the externalLinks.js utility to permit opening external links in a specified tab/window in XHTML 1.0 Strict documents. Made the corresponding .jsC file to embed in the lean version. Added to the Makefile.

Converted all of the HTML files to XHTML 1.0 Strict. This involved a number of changes which affected the JavaScript, both embedded and in separate files. In particular, you can't use a “name=” in a form to access its content via DOM—instead it's necessary to explicitly getElementById() from its id=.

2018 March 14

Fixed unbalanced FULL comments in javascrypt.html used to create the “lean” version.

Updated javascrypt.cssC to incorporate additions to its parent uncompressed file.

Added a new webdist target to the Makefile to create a distribution to install on the Web site. Note that the distribution now includes aesprng_test.html, which we previously only included in the Zipped archive.

Cleaned up and added documentation to the Makefile, in particular explaining the distinction between JavaScript programs which are embedded in jscrypt.html and must be maintained in compressed versions and those which are used elsewhere.

Added the option of generating signatures for pass phrases generated by pass_phrase.html using any of the MD5, SHA-224, or SHA-256 algorithms, selected from a drop-down list. The SHA-2 hashes are generated using a new sha256.js file developed by Chen, Yi-Cyuan, and released under the MIT License, which is included in the file. The master distribution for this package is at

Added real-time updating of the word count in pass_phrase.html when the requested bit count is changed (before, it only updated when you pressed “Generate”), and to display the bit count rounded-up based on the number of words which provide at least the requested bit count.

Validated all HTML files.

2018 March 25

There was a typo in the declaration of variables at the top of utf8_to_unicode() in utf-8.js. The variable “b2” was declared twice, where the intent was to declare “b2” and “b3”. This has been broken for more than a decade, but didn't cause any problems until I set “use strict” mode in the 2018-03-14 release. In strict mode, an undeclared variable is an error, and so decoding any encrypted text containing a three byte UTF-8 code would fail. As it happens, I never tried such text while testing the program. The fix is simple, although users may have to flush their browser cache to cause utf-8.js to be reloaded.

The utf-8.js file is included in compressed form in the jscrypt.html “lean” version of the encryption page. I remade utf-8.jsC and then rebuilt the lean version incorporating the fix.

Thanks to Loic Prot for reporting this problem and identifiying the error in the code which caused it.

When jscrypt.html was produced from javascrypt.html, the expansion of the inclusion of our CSS file caused the specification of the character type to move out of the first 1024 bytes of the file, which could cause some browsers to not know how to interpret the file. I moved the <meta> declaration of the character type to right after the <head> tag, in keeping with Fourmilab standards. Although it's not strictly necessary, I also similarly fixed all of the other HTML files.

Changed absolute references to the “Valid XHTML 1.0” icon to https: to avoid mixed content natters when securely viewing from the main site.

2018 May 25

The pass phrase generator (pass_phrase.html) would refuse to generate pass phrases of one or two words because a test in bitsWord() required the bit equivalent of the number of words to be at least 32 and a second test in GeneratePassPhrases() enforced a minimum of two words per phrase. I relaxed these tests to 14 bits and one word; the code works fine with these values, and if that's what the user wants, there's no reason to deny their preference.

This document is in the public domain.

Back to JavaScrypt