@@ -314,6 +314,8 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4');
314314 Buffer . from ( expected ) ) ;
315315}
316316
317+ const base64flavors = [ 'base64' , 'base64url' ] ;
318+
317319{
318320 // Test that regular and URL-safe base64 both work both ways with padding
319321 const expected = [ 0xff , 0xff , 0xbe , 0xff , 0xef , 0xbf , 0xfb , 0xef , 0xff , 0xfb ] ;
@@ -341,137 +343,182 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4');
341343 'dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ' +
342344 'GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm' +
343345 '5hbCBwbGVhc3VyZS4=' ;
344- assert . strictEqual ( ( Buffer . from ( quote ) ) . toString ( 'base64' ) , expected ) ;
345-
346- let b = Buffer . allocUnsafe ( 1024 ) ;
347- let bytesWritten = b . write ( expected , 0 , 'base64' ) ;
348- assert . strictEqual ( quote . length , bytesWritten ) ;
349- assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
350-
351- // Check that the base64 decoder ignores whitespace
352- const expectedWhite = `${ expected . slice ( 0 , 60 ) } \n` +
353- `${ expected . slice ( 60 , 120 ) } \n` +
354- `${ expected . slice ( 120 , 180 ) } \n` +
355- `${ expected . slice ( 180 , 240 ) } \n` +
356- `${ expected . slice ( 240 , 300 ) } \n` +
357- `${ expected . slice ( 300 , 360 ) } \n` ;
358- b = Buffer . allocUnsafe ( 1024 ) ;
359- bytesWritten = b . write ( expectedWhite , 0 , 'base64' ) ;
360- assert . strictEqual ( quote . length , bytesWritten ) ;
361- assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
362-
363- // Check that the base64 decoder on the constructor works
364- // even in the presence of whitespace.
365- b = Buffer . from ( expectedWhite , 'base64' ) ;
366- assert . strictEqual ( quote . length , b . length ) ;
367- assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
368-
369- // Check that the base64 decoder ignores illegal chars
370- const expectedIllegal = expected . slice ( 0 , 60 ) + ' \x80' +
371- expected . slice ( 60 , 120 ) + ' \xff' +
372- expected . slice ( 120 , 180 ) + ' \x00' +
373- expected . slice ( 180 , 240 ) + ' \x98' +
374- expected . slice ( 240 , 300 ) + '\x03' +
375- expected . slice ( 300 , 360 ) ;
376- b = Buffer . from ( expectedIllegal , 'base64' ) ;
377- assert . strictEqual ( quote . length , b . length ) ;
378- assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
346+ assert . strictEqual ( Buffer . from ( quote ) . toString ( 'base64' ) , expected ) ;
347+ assert . strictEqual (
348+ Buffer . from ( quote ) . toString ( 'base64url' ) ,
349+ expected . replaceAll ( '+' , '-' ) . replaceAll ( '/' , '_' ) . replaceAll ( '=' , '' )
350+ ) ;
351+
352+ base64flavors . forEach ( ( encoding ) => {
353+ let b = Buffer . allocUnsafe ( 1024 ) ;
354+ let bytesWritten = b . write ( expected , 0 , encoding ) ;
355+ assert . strictEqual ( quote . length , bytesWritten ) ;
356+ assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
357+
358+ // Check that the base64 decoder ignores whitespace
359+ const expectedWhite = `${ expected . slice ( 0 , 60 ) } \n` +
360+ `${ expected . slice ( 60 , 120 ) } \n` +
361+ `${ expected . slice ( 120 , 180 ) } \n` +
362+ `${ expected . slice ( 180 , 240 ) } \n` +
363+ `${ expected . slice ( 240 , 300 ) } \n` +
364+ `${ expected . slice ( 300 , 360 ) } \n` ;
365+ b = Buffer . allocUnsafe ( 1024 ) ;
366+ bytesWritten = b . write ( expectedWhite , 0 , encoding ) ;
367+ assert . strictEqual ( quote . length , bytesWritten ) ;
368+ assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
369+
370+ // Check that the base64 decoder on the constructor works
371+ // even in the presence of whitespace.
372+ b = Buffer . from ( expectedWhite , encoding ) ;
373+ assert . strictEqual ( quote . length , b . length ) ;
374+ assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
375+
376+ // Check that the base64 decoder ignores illegal chars
377+ const expectedIllegal = expected . slice ( 0 , 60 ) + ' \x80' +
378+ expected . slice ( 60 , 120 ) + ' \xff' +
379+ expected . slice ( 120 , 180 ) + ' \x00' +
380+ expected . slice ( 180 , 240 ) + ' \x98' +
381+ expected . slice ( 240 , 300 ) + '\x03' +
382+ expected . slice ( 300 , 360 ) ;
383+ b = Buffer . from ( expectedIllegal , encoding ) ;
384+ assert . strictEqual ( quote . length , b . length ) ;
385+ assert . strictEqual ( quote , b . toString ( 'ascii' , 0 , quote . length ) ) ;
386+ } ) ;
379387}
380388
381- assert . strictEqual ( Buffer . from ( '' , 'base64' ) . toString ( ) , '' ) ;
382- assert . strictEqual ( Buffer . from ( 'K' , 'base64' ) . toString ( ) , '' ) ;
383-
384- // multiple-of-4 with padding
385- assert . strictEqual ( Buffer . from ( 'Kg==' , 'base64' ) . toString ( ) , '*' ) ;
386- assert . strictEqual ( Buffer . from ( 'Kio=' , 'base64' ) . toString ( ) , '*' . repeat ( 2 ) ) ;
387- assert . strictEqual ( Buffer . from ( 'Kioq' , 'base64' ) . toString ( ) , '*' . repeat ( 3 ) ) ;
388- assert . strictEqual ( Buffer . from ( 'KioqKg==' , 'base64' ) . toString ( ) , '*' . repeat ( 4 ) ) ;
389- assert . strictEqual ( Buffer . from ( 'KioqKio=' , 'base64' ) . toString ( ) , '*' . repeat ( 5 ) ) ;
390- assert . strictEqual ( Buffer . from ( 'KioqKioq' , 'base64' ) . toString ( ) , '*' . repeat ( 6 ) ) ;
391- assert . strictEqual ( Buffer . from ( 'KioqKioqKg==' , 'base64' ) . toString ( ) ,
392- '*' . repeat ( 7 ) ) ;
393- assert . strictEqual ( Buffer . from ( 'KioqKioqKio=' , 'base64' ) . toString ( ) ,
394- '*' . repeat ( 8 ) ) ;
395- assert . strictEqual ( Buffer . from ( 'KioqKioqKioq' , 'base64' ) . toString ( ) ,
396- '*' . repeat ( 9 ) ) ;
397- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKg==' , 'base64' ) . toString ( ) ,
398- '*' . repeat ( 10 ) ) ;
399- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKio=' , 'base64' ) . toString ( ) ,
400- '*' . repeat ( 11 ) ) ;
401- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioq' , 'base64' ) . toString ( ) ,
402- '*' . repeat ( 12 ) ) ;
403- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKg==' , 'base64' ) . toString ( ) ,
404- '*' . repeat ( 13 ) ) ;
405- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKio=' , 'base64' ) . toString ( ) ,
406- '*' . repeat ( 14 ) ) ;
407- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioq' , 'base64' ) . toString ( ) ,
408- '*' . repeat ( 15 ) ) ;
409- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKg==' , 'base64' ) . toString ( ) ,
410- '*' . repeat ( 16 ) ) ;
411- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKio=' , 'base64' ) . toString ( ) ,
412- '*' . repeat ( 17 ) ) ;
413- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioq' , 'base64' ) . toString ( ) ,
414- '*' . repeat ( 18 ) ) ;
415- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKg==' ,
416- 'base64' ) . toString ( ) ,
417- '*' . repeat ( 19 ) ) ;
418- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKio=' ,
419- 'base64' ) . toString ( ) ,
420- '*' . repeat ( 20 ) ) ;
421-
422- // No padding, not a multiple of 4
423- assert . strictEqual ( Buffer . from ( 'Kg' , 'base64' ) . toString ( ) , '*' ) ;
424- assert . strictEqual ( Buffer . from ( 'Kio' , 'base64' ) . toString ( ) , '*' . repeat ( 2 ) ) ;
425- assert . strictEqual ( Buffer . from ( 'KioqKg' , 'base64' ) . toString ( ) , '*' . repeat ( 4 ) ) ;
426- assert . strictEqual ( Buffer . from ( 'KioqKio' , 'base64' ) . toString ( ) , '*' . repeat ( 5 ) ) ;
427- assert . strictEqual ( Buffer . from ( 'KioqKioqKg' , 'base64' ) . toString ( ) ,
428- '*' . repeat ( 7 ) ) ;
429- assert . strictEqual ( Buffer . from ( 'KioqKioqKio' , 'base64' ) . toString ( ) ,
430- '*' . repeat ( 8 ) ) ;
431- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKg' , 'base64' ) . toString ( ) ,
432- '*' . repeat ( 10 ) ) ;
433- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKio' , 'base64' ) . toString ( ) ,
434- '*' . repeat ( 11 ) ) ;
435- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKg' , 'base64' ) . toString ( ) ,
436- '*' . repeat ( 13 ) ) ;
437- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKio' , 'base64' ) . toString ( ) ,
438- '*' . repeat ( 14 ) ) ;
439- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKg' , 'base64' ) . toString ( ) ,
440- '*' . repeat ( 16 ) ) ;
441- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKio' , 'base64' ) . toString ( ) ,
442- '*' . repeat ( 17 ) ) ;
443- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKg' ,
444- 'base64' ) . toString ( ) ,
445- '*' . repeat ( 19 ) ) ;
446- assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKio' ,
447- 'base64' ) . toString ( ) ,
448- '*' . repeat ( 20 ) ) ;
389+ base64flavors . forEach ( ( encoding ) => {
390+ assert . strictEqual ( Buffer . from ( '' , encoding ) . toString ( ) , '' ) ;
391+ assert . strictEqual ( Buffer . from ( 'K' , encoding ) . toString ( ) , '' ) ;
392+
393+ // multiple-of-4 with padding
394+ assert . strictEqual ( Buffer . from ( 'Kg==' , encoding ) . toString ( ) , '*' ) ;
395+ assert . strictEqual ( Buffer . from ( 'Kio=' , encoding ) . toString ( ) , '*' . repeat ( 2 ) ) ;
396+ assert . strictEqual ( Buffer . from ( 'Kioq' , encoding ) . toString ( ) , '*' . repeat ( 3 ) ) ;
397+ assert . strictEqual (
398+ Buffer . from ( 'KioqKg==' , encoding ) . toString ( ) , '*' . repeat ( 4 ) ) ;
399+ assert . strictEqual (
400+ Buffer . from ( 'KioqKio=' , encoding ) . toString ( ) , '*' . repeat ( 5 ) ) ;
401+ assert . strictEqual (
402+ Buffer . from ( 'KioqKioq' , encoding ) . toString ( ) , '*' . repeat ( 6 ) ) ;
403+ assert . strictEqual ( Buffer . from ( 'KioqKioqKg==' , encoding ) . toString ( ) ,
404+ '*' . repeat ( 7 ) ) ;
405+ assert . strictEqual ( Buffer . from ( 'KioqKioqKio=' , encoding ) . toString ( ) ,
406+ '*' . repeat ( 8 ) ) ;
407+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioq' , encoding ) . toString ( ) ,
408+ '*' . repeat ( 9 ) ) ;
409+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKg==' , encoding ) . toString ( ) ,
410+ '*' . repeat ( 10 ) ) ;
411+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKio=' , encoding ) . toString ( ) ,
412+ '*' . repeat ( 11 ) ) ;
413+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioq' , encoding ) . toString ( ) ,
414+ '*' . repeat ( 12 ) ) ;
415+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKg==' , encoding ) . toString ( ) ,
416+ '*' . repeat ( 13 ) ) ;
417+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKio=' , encoding ) . toString ( ) ,
418+ '*' . repeat ( 14 ) ) ;
419+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioq' , encoding ) . toString ( ) ,
420+ '*' . repeat ( 15 ) ) ;
421+ assert . strictEqual (
422+ Buffer . from ( 'KioqKioqKioqKioqKioqKg==' , encoding ) . toString ( ) ,
423+ '*' . repeat ( 16 ) ) ;
424+ assert . strictEqual (
425+ Buffer . from ( 'KioqKioqKioqKioqKioqKio=' , encoding ) . toString ( ) ,
426+ '*' . repeat ( 17 ) ) ;
427+ assert . strictEqual (
428+ Buffer . from ( 'KioqKioqKioqKioqKioqKioq' , encoding ) . toString ( ) ,
429+ '*' . repeat ( 18 ) ) ;
430+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKg==' ,
431+ encoding ) . toString ( ) ,
432+ '*' . repeat ( 19 ) ) ;
433+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKioqKio=' ,
434+ encoding ) . toString ( ) ,
435+ '*' . repeat ( 20 ) ) ;
436+
437+ // No padding, not a multiple of 4
438+ assert . strictEqual ( Buffer . from ( 'Kg' , encoding ) . toString ( ) , '*' ) ;
439+ assert . strictEqual ( Buffer . from ( 'Kio' , encoding ) . toString ( ) , '*' . repeat ( 2 ) ) ;
440+ assert . strictEqual ( Buffer . from ( 'KioqKg' , encoding ) . toString ( ) , '*' . repeat ( 4 ) ) ;
441+ assert . strictEqual (
442+ Buffer . from ( 'KioqKio' , encoding ) . toString ( ) , '*' . repeat ( 5 ) ) ;
443+ assert . strictEqual ( Buffer . from ( 'KioqKioqKg' , encoding ) . toString ( ) ,
444+ '*' . repeat ( 7 ) ) ;
445+ assert . strictEqual ( Buffer . from ( 'KioqKioqKio' , encoding ) . toString ( ) ,
446+ '*' . repeat ( 8 ) ) ;
447+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKg' , encoding ) . toString ( ) ,
448+ '*' . repeat ( 10 ) ) ;
449+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKio' , encoding ) . toString ( ) ,
450+ '*' . repeat ( 11 ) ) ;
451+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKg' , encoding ) . toString ( ) ,
452+ '*' . repeat ( 13 ) ) ;
453+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKio' , encoding ) . toString ( ) ,
454+ '*' . repeat ( 14 ) ) ;
455+ assert . strictEqual ( Buffer . from ( 'KioqKioqKioqKioqKioqKg' , encoding ) . toString ( ) ,
456+ '*' . repeat ( 16 ) ) ;
457+ assert . strictEqual (
458+ Buffer . from ( 'KioqKioqKioqKioqKioqKio' , encoding ) . toString ( ) ,
459+ '*' . repeat ( 17 ) ) ;
460+ assert . strictEqual (
461+ Buffer . from ( 'KioqKioqKioqKioqKioqKioqKg' , encoding ) . toString ( ) ,
462+ '*' . repeat ( 19 ) ) ;
463+ assert . strictEqual (
464+ Buffer . from ( 'KioqKioqKioqKioqKioqKioqKio' , encoding ) . toString ( ) ,
465+ '*' . repeat ( 20 ) ) ;
466+ } ) ;
449467
450468// Handle padding graciously, multiple-of-4 or not
451469assert . strictEqual (
452470 Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==' , 'base64' ) . length ,
453471 32
454472) ;
473+ assert . strictEqual (
474+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==' , 'base64url' )
475+ . length ,
476+ 32
477+ ) ;
455478assert . strictEqual (
456479 Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=' , 'base64' ) . length ,
457480 32
458481) ;
482+ assert . strictEqual (
483+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=' , 'base64url' )
484+ . length ,
485+ 32
486+ ) ;
459487assert . strictEqual (
460488 Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw' , 'base64' ) . length ,
461489 32
462490) ;
491+ assert . strictEqual (
492+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw' , 'base64url' )
493+ . length ,
494+ 32
495+ ) ;
463496assert . strictEqual (
464497 Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==' , 'base64' ) . length ,
465498 31
466499) ;
500+ assert . strictEqual (
501+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==' , 'base64url' )
502+ . length ,
503+ 31
504+ ) ;
467505assert . strictEqual (
468506 Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=' , 'base64' ) . length ,
469507 31
470508) ;
509+ assert . strictEqual (
510+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=' , 'base64url' )
511+ . length ,
512+ 31
513+ ) ;
471514assert . strictEqual (
472515 Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg' , 'base64' ) . length ,
473516 31
474517) ;
518+ assert . strictEqual (
519+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg' , 'base64url' ) . length ,
520+ 31
521+ ) ;
475522
476523{
477524// This string encodes single '.' character in UTF-16
@@ -483,6 +530,16 @@ assert.strictEqual(
483530 assert . strictEqual ( dot . toString ( 'base64' ) , '//4uAA==' ) ;
484531}
485532
533+ {
534+ // This string encodes single '.' character in UTF-16
535+ const dot = Buffer . from ( '//4uAA' , 'base64url' ) ;
536+ assert . strictEqual ( dot [ 0 ] , 0xff ) ;
537+ assert . strictEqual ( dot [ 1 ] , 0xfe ) ;
538+ assert . strictEqual ( dot [ 2 ] , 0x2e ) ;
539+ assert . strictEqual ( dot [ 3 ] , 0x00 ) ;
540+ assert . strictEqual ( dot . toString ( 'base64url' ) , '__4uAA' ) ;
541+ }
542+
486543{
487544 // Writing base64 at a position > 0 should not mangle the result.
488545 //
@@ -498,6 +555,21 @@ assert.strictEqual(
498555 'Madness?! This is node.js!' ) ;
499556}
500557
558+ {
559+ // Writing base64url at a position > 0 should not mangle the result.
560+ //
561+ // https://github.com/joyent/node/issues/402
562+ const segments = [ 'TWFkbmVzcz8h' , 'IFRoaXM' , 'IGlz' , 'IG5vZGUuanMh' ] ;
563+ const b = Buffer . allocUnsafe ( 64 ) ;
564+ let pos = 0 ;
565+
566+ for ( let i = 0 ; i < segments . length ; ++ i ) {
567+ pos += b . write ( segments [ i ] , pos , 'base64url' ) ;
568+ }
569+ assert . strictEqual ( b . toString ( 'latin1' , 0 , pos ) ,
570+ 'Madness?! This is node.js!' ) ;
571+ }
572+
501573// Regression test for https://github.com/nodejs/node/issues/3496.
502574assert . strictEqual ( Buffer . from ( '=bad' . repeat ( 1e4 ) , 'base64' ) . length , 0 ) ;
503575
0 commit comments