Skip to content

Commit

Permalink
add: base64url support
Browse files Browse the repository at this point in the history
Using string replaceAll since base64 is external base64-js.
Dependency does not yet support base64url beatgammit/base64-js#53
  • Loading branch information
jrschumacher committed May 17, 2022
1 parent 795bbb5 commit 82ebe1f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 8 deletions.
38 changes: 31 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ Buffer.isEncoding = function isEncoding (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
case 'base64url':
case 'base64':
case 'ucs2':
case 'ucs-2':
Expand Down Expand Up @@ -533,8 +534,9 @@ function slowToString (encoding, start, end) {
case 'binary':
return latin1Slice(this, start, end)

case 'base64url':
case 'base64':
return base64Slice(this, start, end)
return base64Slice(this, start, end, encoding)

case 'ucs2':
case 'ucs-2':
Expand Down Expand Up @@ -859,8 +861,9 @@ function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}

function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
function base64Write (buf, string, offset, length, encoding) {
const b64 = encoding === 'base64url' ? base64urlToBase64(string) : string
return blitBuffer(base64ToBytes(b64), buf, offset, length)
}

function ucs2Write (buf, string, offset, length) {
Expand Down Expand Up @@ -918,9 +921,11 @@ Buffer.prototype.write = function write (string, offset, length, encoding) {
case 'binary':
return asciiWrite(this, string, offset, length)

case 'base64url':
case 'base64':
// console.log(encoding, '::', string)
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
return base64Write(this, string, offset, length, encoding)

case 'ucs2':
case 'ucs-2':
Expand All @@ -943,12 +948,14 @@ Buffer.prototype.toJSON = function toJSON () {
}
}

function base64Slice (buf, start, end) {
function base64Slice (buf, start, end, encoding) {
let b64
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
b64 = base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
b64 = base64.fromByteArray(buf.slice(start, end))
}
return encoding === 'base64url' ? base64urlFromBase64(b64) : b64
}

function utf8Slice (buf, start, end) {
Expand Down Expand Up @@ -1939,6 +1946,23 @@ function boundsError (value, length, type) {

const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g

const BASE64_CHAR_62 = '+'
const BASE64_CHAR_63 = '/'
const BASE64URL_CHAR_62 = '-'
const BASE64URL_CHAR_63 = '_'

function base64urlToBase64 (str) {
return str
.replaceAll(BASE64URL_CHAR_62, BASE64_CHAR_62)
.replaceAll(BASE64URL_CHAR_63, BASE64_CHAR_63)
}

function base64urlFromBase64 (str) {
return str
.replaceAll(BASE64_CHAR_62, BASE64URL_CHAR_62)
.replaceAll(BASE64_CHAR_63, BASE64URL_CHAR_63)
}

function base64clean (str) {
// Node takes equal signs as end of the Base64 encoding
str = str.split('=')[0]
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@
"test-browser-new": "airtap -- test/*.js test/node/*.js",
"test-browser-new-local": "airtap --local -- test/*.js test/node/*.js",
"test-node": "tape test/*.js test/node/*.js",
"update-authors": "./bin/update-authors.sh"
"update-authors": "./bin/update-authors.sh",
"lint": "standard",
"lint:fix": "standard --fix"
},
"standard": {
"ignore": [
Expand Down
18 changes: 18 additions & 0 deletions test/base64.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,21 @@ test('base64: high byte', function (t) {
)
t.end()
})

test('base64url: convert to/from base64', function (t) {
const base64url = '8J-Ps--4j_Cfj7PvuI8='
const base64 = '8J+Ps++4j/Cfj7PvuI8='
const text = '🏳️🏳️'

const base64urlBuf = new B(base64url, 'base64url')
t.equal(base64urlBuf.toString('base64'), base64)
t.equal(base64urlBuf.toString(), text)

const base64Buf = new B(base64, 'base64')
t.equal(base64Buf.toString('base64url'), base64url)
t.equal(base64Buf.toString(), text)

const buf = new B(text)
t.equal(buf.toString('base64url'), base64url)
t.end()
})

0 comments on commit 82ebe1f

Please sign in to comment.