@@ -314,6 +314,8 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4');
314
314
Buffer . from ( expected ) ) ;
315
315
}
316
316
317
+ const base64flavors = [ 'base64' , 'base64url' ] ;
318
+
317
319
{
318
320
// Test that regular and URL-safe base64 both work both ways with padding
319
321
const expected = [ 0xff , 0xff , 0xbe , 0xff , 0xef , 0xbf , 0xfb , 0xef , 0xff , 0xfb ] ;
@@ -341,137 +343,182 @@ assert.strictEqual((Buffer.from('Woman')).toString('base64url'), 'V29tYW4');
341
343
'dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ' +
342
344
'GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm' +
343
345
'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
+ } ) ;
379
387
}
380
388
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
+ } ) ;
449
467
450
468
// Handle padding graciously, multiple-of-4 or not
451
469
assert . strictEqual (
452
470
Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==' , 'base64' ) . length ,
453
471
32
454
472
) ;
473
+ assert . strictEqual (
474
+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==' , 'base64url' )
475
+ . length ,
476
+ 32
477
+ ) ;
455
478
assert . strictEqual (
456
479
Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=' , 'base64' ) . length ,
457
480
32
458
481
) ;
482
+ assert . strictEqual (
483
+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=' , 'base64url' )
484
+ . length ,
485
+ 32
486
+ ) ;
459
487
assert . strictEqual (
460
488
Buffer . from ( '72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw' , 'base64' ) . length ,
461
489
32
462
490
) ;
491
+ assert . strictEqual (
492
+ Buffer . from ( '72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw' , 'base64url' )
493
+ . length ,
494
+ 32
495
+ ) ;
463
496
assert . strictEqual (
464
497
Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==' , 'base64' ) . length ,
465
498
31
466
499
) ;
500
+ assert . strictEqual (
501
+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==' , 'base64url' )
502
+ . length ,
503
+ 31
504
+ ) ;
467
505
assert . strictEqual (
468
506
Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=' , 'base64' ) . length ,
469
507
31
470
508
) ;
509
+ assert . strictEqual (
510
+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=' , 'base64url' )
511
+ . length ,
512
+ 31
513
+ ) ;
471
514
assert . strictEqual (
472
515
Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg' , 'base64' ) . length ,
473
516
31
474
517
) ;
518
+ assert . strictEqual (
519
+ Buffer . from ( 'w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg' , 'base64url' ) . length ,
520
+ 31
521
+ ) ;
475
522
476
523
{
477
524
// This string encodes single '.' character in UTF-16
@@ -483,6 +530,16 @@ assert.strictEqual(
483
530
assert . strictEqual ( dot . toString ( 'base64' ) , '//4uAA==' ) ;
484
531
}
485
532
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
+
486
543
{
487
544
// Writing base64 at a position > 0 should not mangle the result.
488
545
//
@@ -498,6 +555,21 @@ assert.strictEqual(
498
555
'Madness?! This is node.js!' ) ;
499
556
}
500
557
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
+
501
573
// Regression test for https://github.com/nodejs/node/issues/3496.
502
574
assert . strictEqual ( Buffer . from ( '=bad' . repeat ( 1e4 ) , 'base64' ) . length , 0 ) ;
503
575
0 commit comments