From 80f46d32b48a1b9fd6b81ae523d9e255c7190671 Mon Sep 17 00:00:00 2001
From: Andreas Brekken
Date: Sat, 1 Mar 2014 17:04:38 +0100
Subject: [PATCH 1/2] Remove String.lpad and cleanup
---
src/convert.js | 132 ++++++++++++++++++++++++++++++-------------------
1 file changed, 80 insertions(+), 52 deletions(-)
diff --git a/src/convert.js b/src/convert.js
index 0079145..5db63ab 100644
--- a/src/convert.js
+++ b/src/convert.js
@@ -1,74 +1,102 @@
-// convert to/from various values
+var base64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-String.prototype.lpad = function(padString, length) {
- var str = this;
+exports.lpad = function lpad(str, padString, length) {
while (str.length < length) str = padString + str;
return str;
}
-// Convert a byte array to a hex string
-module.exports.bytesToHex = function(bytes) {
- return bytes.map(function(x) { return x.toString(16).lpad('0',2) }).join('');
+/**
+ * Convert a byte array to a hex string
+ */
+exports.bytesToHex = function(bytes) {
+ return bytes.map(function(x) {
+ return exports.lpad(x.toString(16), '0', 2)
+ }).join('');
};
-// Convert a hex string to a byte array
-module.exports.hexToBytes = function(hex) {
- return hex.match(/../g).map(function(x) { return parseInt(x,16) });
+/**
+ * Convert a hex string to a byte array
+ */
+exports.hexToBytes = function(hex) {
+ return hex.match(/../g).map(function(x) {
+ return parseInt(x,16)
+ });
}
- // Convert a byte array to a base-64 string
-module.exports.bytesToBase64 = function(bytes) {
-
- for(var base64 = [], i = 0; i < bytes.length; i += 3) {
- var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
- for (var j = 0; j < 4; j++) {
- if (i * 8 + j * 6 <= bytes.length * 8)
- base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
- else base64.push("=");
- }
- }
-
- return base64.join("");
+/**
+ * Convert a byte array to a base-64 string
+ */
+exports.bytesToBase64 = function(bytes) {
+ var base64 = []
+
+ for (var i = 0; i < bytes.length; i += 3) {
+ var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+
+ for (var j = 0; j < 4; j++) {
+ if (i * 8 + j * 6 <= bytes.length * 8) {
+ base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
+ } else {
+ base64.push('=');
+ }
+ }
+ }
+
+ return base64.join('');
}
-
- // Convert a base-64 string to a byte array
-module.exports.base64ToBytes = function(base64) {
-
- // Remove non-base-64 characters
- base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
-
- for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
- if (imod4 == 0) continue;
- bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
- (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
- }
-
- return bytes;
+/**
+ * Convert a base-64 string to a byte array
+ */
+exports.base64ToBytes = function(base64) {
+ // Remove non-base-64 characters
+ base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
+
+ var bytes = []
+ , imod4 = 0
+
+ for (var i = 0; i < base64.length; imod4 = ++i % 4) {
+ if (!imod4) continue
+
+ bytes.push(
+ (
+ (base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) <<
+ (imod4 * 2)
+ ) |
+ (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))
+ );
+ }
+
+ return bytes;
}
-// Hex only (allowing bin would be potentially risky, as 01010101 = \x01 * 4 or 85)
-module.exports.coerceToBytes = function(input) {
- if (typeof input == "string") return module.exports.hexToBytes(input);
- return input;
+/**
+ * Hex only (allowing bin would be potentially risky, as 01010101 = \x01 * 4 or 85)
+ */
+exports.coerceToBytes = function(input) {
+ if (typeof input != 'string') return input
+ return exports.hexToBytes(input);
}
-module.exports.binToBytes = function(bin) {
- return bin.match(/......../g).map(function(x) { return parseInt(x,2) });
+exports.binToBytes = function(bin) {
+ return bin.match(/......../g).map(function(x) {
+ return parseInt(x,2)
+ });
}
-module.exports.bytesToBin = function(bytes) {
- return bytes.map(function(x) { return x.toString(2).lpad('0',8) }).join('');
+exports.bytesToBin = function(bytes) {
+ return bytes.map(function(x) {
+ return exports.lpad(x.toString(2), '0', 8)
+ }).join('');
}
-module.exports.bytesToString = function(bytes) {
- return bytes.map(function(x){ return String.fromCharCode(x) }).join('');
+exports.bytesToString = function(bytes) {
+ return bytes.map(function(x){
+ return String.fromCharCode(x)
+ }).join('');
}
-module.exports.stringToBytes = function(string) {
- return string.split('').map(function(x) { return x.charCodeAt(0) });
+exports.stringToBytes = function(string) {
+ return string.split('').map(function(x) {
+ return x.charCodeAt(0)
+ });
}
-
-// utf8
From 81b44ef269e6fd661ab9cde14ca75584166dc128 Mon Sep 17 00:00:00 2001
From: Andreas Brekken
Date: Sat, 1 Mar 2014 17:05:49 +0100
Subject: [PATCH 2/2] Add RFC test vectors for convert.bytesToBase64
---
test/convert.js | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/test/convert.js b/test/convert.js
index 643cde8..2e8b510 100644
--- a/test/convert.js
+++ b/test/convert.js
@@ -25,4 +25,23 @@ describe('convert', function() {
assert.equal(hex.length, 512);
assert.deepEqual(convert.hexToBytes(hex), bytes);
})
+
+ describe('bytesToBase64', function() {
+ it('passes RFC4648 test vectors', function() {
+ // Test vectors from:
+ // http://tools.ietf.org/html/rfc4648#page-12
+
+ var b64 = function(s) {
+ return convert.bytesToBase64(convert.stringToBytes(s))
+ }
+
+ assert.equal(b64(''), '')
+ assert.equal(b64('f'), 'Zg==')
+ assert.equal(b64('fo'), 'Zm8=')
+ assert.equal(b64('foo'), 'Zm9v')
+ assert.equal(b64('foob'), 'Zm9vYg==')
+ assert.equal(b64('fooba'), 'Zm9vYmE=')
+ assert.equal(b64('foobar'), 'Zm9vYmFy')
+ })
+ })
})