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 Jul 22, 2024
1 parent 5857e29 commit f22ba44
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
38 changes: 31 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,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 @@ -544,8 +545,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 @@ -871,8 +873,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 @@ -930,9 +933,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 @@ -955,12 +960,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 @@ -1945,6 +1952,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
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 f22ba44

Please sign in to comment.