Nibbler: Multi-Base Encoder

Posted at 9:58 pm on April 5th, 2010

Filed in:

Recently, I was as surprised as you will no doubt be, to discover that there didn’t seem to be a Base32 encoder for JavaScript! There are lots of Base64 encoders out there (and just as many for Hexadecimal), but Base32 seems to be a pretty small niche.

So I decided to write my own, and about half-way through, it evolved from a Base32 encoder to a multi-base encoder: Nibbler.js.

An important note: Base32, Base64, etc. are not encryption. They are content-encoding schemes that simply re-group the binary digits of your data into smaller bundles, so that any data can be transmitted as plain ASCII. See the Wikipedia article about Base64 for more info.

Usage

Nibbler itself isn’t the encoder object, but rather a constructor for easily creating encoders. Base32 carries five bits per byte, so to create a Base32 encoder object, set the codeBits option to 5.

base32 = new Nibbler({
    dataBits: 8,
    codeBits: 5,
    keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
    pad: '='
});

The object has encode and decode methods:

base32.encode("Hello, World");  // "JBSWY3DPFQQFO33SNRSCC====="
base32.decode("IFWG62DB");      // "Aloha"

Base64 carries 6 bits per byte:

base64 = new Nibbler({
    dataBits: 8,
    codeBits: 6,
    keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    pad: '='
});

If the data you’re encoding only uses seven bits, you can create an object that excludes those unused bits from its encoded output, by setting the dataBits option to 7:

base64_7bit = new Nibbler({
    dataBits: 7,
    codeBits: 6,
    keyString: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    pad: '='
});

In the next few days or years I plan to create an encode/decode tool to provide a user interface to this library.

12 Responses

  1. Great code, was looking for something like this, thanks.

    I did add a UTF8_encode so it match the PHP base64 decode, else there where no way it would take ñ or ó ...

    chears!
    Jacob

    October 26th, 2010 at 5:27 am
  2. Matt Robenolt said:

    Hey, I adapted this to work nicely with Nodejs. :)

    https://github.com/mattrobenolt/node_nibbler

    March 31st, 2011 at 9:46 am
  3. Thanks for sharing!

    March 31st, 2011 at 10:02 pm
  4. Thanks for the code, but I can't decode it with c#;
    error message says "Invalid character in a Base-64 string." your script coded "3226,3222,3217" to "MzIyNiwzMjIyLDMyMTc===" but c# can't decode it, whats the problem?

    August 5th, 2011 at 7:14 am
  5. Hi, Farhad, sorry it took me this long to answer, but I didn't see that I had a comment until last night.

    I've never used c# before, but my best guess is that it doesn't know what to do with the padding character, "=". Have you tried removing those to see what it does?

    September 16th, 2011 at 1:21 am
  6. Ej52 said:

    Great code, have converted this to C# :)

    @Farhad
    The reason C#'s Base64 methods don't decode Base64
    strings encoded with Nibbler, is due to Nibbler
    adding to much padding on certain input strings.

    In your case Nibbler added 2 extra padding chars.
    "3226,3222,3217" should be "MzIyNiwzMjIyLDMyMTc="

    November 6th, 2011 at 11:01 am
  7. @Ej52, thanks for spotting this. I probably won't have time to look for the bug soon, but if no one (it could be you!) submits a fix before I get to it, it's on my list!

    November 6th, 2011 at 11:25 am
  8. Ej52 said:

    @Thomas, temp fix based on the size of the "keyString"
    not great but produces the right amount of padding
    for Base64 encoding ;)

    len = output.length % group;

    if (keyString.length == 64)
    len = 3 - (input.length % 3);

    for (i = 0; i < len; i += 1) {
    output.push(pad);
    }

    November 6th, 2011 at 12:46 pm
  9. Ej52 said:

    @Thomas, after trying multiple math equations to get the
    padding correct based on the "dataBits" and "codeBits" it
    seems there is no way to do it.

    The only way to get the padding correct is to work out the
    quantum's seprately based on the encoding (64/32).

    Padding issue aside, Nibbler seems to work perfectly for
    base 64, 32, 16(HEX).

    November 7th, 2011 at 12:12 pm
  10. A year and a half later... fixed! It was really simple once I managed to remember that this needed fixing, at a time when I had the time to do it.

    I fixed it by replacing wrong math...

    len = output.length % group;
    for (i = 0; i < len; i += 1) {
       output.push(pad);
    }

    ...with right math:

    while (output.length % group > 0) {
       output.push(pad);
    }
    April 24th, 2013 at 4:27 am
  11. Gene said:

    I followed the example here and I can't comment there so maybe you can help
    http://blog.thomassmart.com/2012/08/security-tips-1/

    Some times it works and some times it doesn't. I made a fiddle so you can try it.
    http://jsfiddle.net/En7m5/3/

    Nibbler only works all the time if I use the key you used in your example ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 which is less secure because it isn't randomized. I tried adding padding but that didn't work and I tried other random keys besides the one in the example and those don't work all the time either.

    July 18th, 2013 at 12:13 pm
  12. Gene, the reason the example in your Fiddle doesn't work is that the key "JNUBDWRZALTX10FMM9EO3628CKKP5IVY7S" has duplicate characters. At a glance I notice two M's and two K's. Simply put, when Nibbler (or any base32 library) decodes "06M8DKK9ZDPOF" and finds an M, it has no way of knowing which M in the keyString it's supposed to be, and so it uses the first one it finds. Same for the K's. Any 32 unique ASCII characters, in any order, will be a suitable keyString for Base32. For Base64, any 64. Any duplicate characters in the keyString, even if they're not consecutive the way they are in the example, will wreck the whole thing.

    However, unrelated to this problem, the thomassmart.com usage is completely wrong. Base32, Base64, etc. should *never* be used as encryption. These encodings are nothing more than a way of representing data in a format that can be transmitted as plain ASCII text. It's no good for keeping secrets.

    July 18th, 2013 at 1:20 pm

Leave a Comment

  • Formatting
    • No HTML. Any code you enter will display as that code.
    • If you are putting code in your reply in order to present the code itself, you can use these special HTML comments for formatting:
      Inline: <!--code-->...<!--/code-->
      Block: <!--pre-->...<!--/pre-->

© Thomas Peri