1# node-jose # 2 3[![Greenkeeper badge](https://badges.greenkeeper.io/cisco/node-jose.svg)](https://greenkeeper.io/) 4[![Build Status](https://travis-ci.org/cisco/node-jose.svg?branch=master)](https://travis-ci.org/cisco/node-jose) 5 6A JavaScript implementation of the JSON Object Signing and Encryption (JOSE) for current web browsers and node.js-based servers. This library implements (wherever possible) all algorithms, formats, and options in [JWS](https://tools.ietf.org/html/rfc7515 "Jones, M., J. Bradley and N. Sakimura, 'JSON Web Signature (JWS)' RFC 7515, May 2015"), [JWE](https://tools.ietf.org/html/rfc7516 "Jones, M. and J. Hildebrand 'JSON Web Encryption (JWE)', RFC 7516, May 2015"), [JWK](https://tools.ietf.org/html/rfc7517 "Jones, M., 'JSON Web Key (JWK)', RFC 7517, May 2015"), and [JWA](https://tools.ietf.org/html/rfc7518 "Jones, M., 'JSON Web Algorithms (JWA)', RFC 7518, May 2015") and uses native cryptographic support ([WebCrypto API](http://www.w3.org/TR/WebCryptoAPI/) or node.js' "[crypto](https://nodejs.org/api/crypto.html)" module) where feasible. 7 8<!-- START doctoc generated TOC please keep comment here to allow auto update --> 9<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> 10 11 12- [Installing](#installing) 13- [Basics](#basics) 14- [Keys and Key Stores](#keys-and-key-stores) 15 - [Obtaining a KeyStore](#obtaining-a-keystore) 16 - [Exporting a KeyStore](#exporting-a-keystore) 17 - [Retrieving Keys](#retrieving-keys) 18 - [Searching for Keys](#searching-for-keys) 19 - [Managing Keys](#managing-keys) 20 - [Importing and Exporting a Single Key](#importing-and-exporting-a-single-key) 21 - [Obtaining a Key's Thumbprint](#obtaining-a-keys-thumbprint) 22- [Signatures](#signatures) 23 - [Keys Used for Signing and Verifying](#keys-used-for-signing-and-verifying) 24 - [Signing Content](#signing-content) 25 - [Verifying a JWS](#verifying-a-jws) 26 - [Allowing (or Disallowing) Signature Algorithms](#allowing-or-disallowing-signature-algorithms) 27 - [Handling `crit` Header Members](#handling-crit-header-members) 28- [Encryption](#encryption) 29 - [Keys Used for Encrypting and Decrypting](#keys-used-for-encrypting-and-decrypting) 30 - [Encrypting Content](#encrypting-content) 31 - [Decrypting a JWE](#decrypting-a-jwe) 32 - [Allowing (or Disallowing) Encryption Algorithms](#allowing-or-disallowing-encryption-algorithms) 33 - [Handling `crit` Header Members](#handling-crit-header-members-1) 34- [Useful Utilities](#useful-utilities) 35 - [Converting to Buffer](#converting-to-buffer) 36 - [URI-Safe Base64](#uri-safe-base64) 37 - [Random Bytes](#random-bytes) 38 39<!-- END doctoc generated TOC please keep comment here to allow auto update --> 40 41## Installing ## 42 43To install the latest from [NPM](https://npmjs.com/): 44 45```shell 46 npm install node-jose 47``` 48 49Or to install a specific release: 50 51```shell 52 npm install node-jose@0.3.0 53``` 54 55Alternatively, the latest unpublished code can be installed directly from the repository: 56 57```shell 58 npm install git+https://github.com/cisco/node-jose.git 59``` 60 61## Basics ## 62 63Require the library as normal: 64 65```javascript 66var jose = require('node-jose'); 67``` 68 69This library uses [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) for nearly every operation. 70 71This library supports [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). To use in a web browser, `require('node-jose')` and bundle with the rest of your app. 72 73The content to be signed/encrypted -- or returned from being verified/decrypted -- are [Buffer](https://nodejs.org/api/buffer.html) objects. 74 75## Keys and Key Stores ## 76 77The `jose.JWK` namespace deals with JWK and JWK-sets. 78 79* `jose.JWK.Key` is a logical representation of a JWK, and is the "raw" entry point for various cryptographic operations (e.g., sign, verify, encrypt, decrypt). 80* `jose.JWK.KeyStore` represents a collection of Keys. 81 82Creating a JWE or JWS ultimately require one or more explicit Key objects. 83 84Processing a JWE or JWS relies on a KeyStore. 85 86### Obtaining a KeyStore ### 87To create an empty keystore: 88 89```javascript 90keystore = jose.JWK.createKeyStore(); 91``` 92 93To import a JWK-set as a keystore: 94 95```javascript 96// {input} is a String or JSON object representing the JWK-set 97jose.JWK.asKeyStore(input). 98 then(function(result) { 99 // {result} is a jose.JWK.KeyStore 100 keystore = result; 101 }); 102``` 103 104### Exporting a KeyStore ### 105 106To export the public keys of a keystore as a JWK-set: 107 108```javascript 109output = keystore.toJSON(); 110``` 111 112To export **all** the keys of a keystore: 113 114```javascript 115output = keystore.toJSON(true); 116``` 117 118### Retrieving Keys ### 119 120To retrieve a key from a keystore: 121 122```javascript 123// by 'kid' 124key = keystore.get(kid); 125``` 126 127This retrieves the first key that matches the given {kid}. If multiple keys have the same {kid}, you can further narrow what to retrieve: 128 129```javascript 130// ... and by 'kty' 131key = keystore.get(kid, { kty: 'RSA' }); 132 133// ... and by 'use' 134key = keystore.get(kid, { use: 'enc' }); 135 136// ... and by 'alg' 137key = keystore.get(kid, { use: 'RSA-OAEP' }); 138 139// ... and by 'kty' and 'use' 140key = keystore.get(kid, { kty: 'RSA', use: 'enc' }); 141 142// same as above, but with a single {props} argument 143key = keystore.get({ kid: kid, kty: 'RSA', use: 'enc' }); 144``` 145 146### Searching for Keys ### 147 148To retrieve all the keys from a keystore: 149 150```javascript 151everything = keystore.all(); 152``` 153 154`all()` can be filtered much like `get()`: 155 156```javascript 157// filter by 'kid' 158everything = keystore.all({ kid: kid }); 159 160// filter by 'kty' 161everything = keystore.all({ kty: 'RSA' }); 162 163// filter by 'use' 164everything = keystore.all({ use: 'enc' }); 165 166// filter by 'alg' 167everything = keystore.all({ alg: 'RSA-OAEP' }); 168 169// filter by 'kid' + 'kty' + 'alg' 170everything = keystore.all({ kid: kid, kty: 'RSA', alg: 'RSA-OAEP' }); 171``` 172 173### Managing Keys ### 174 175To import an existing Key (as a JSON object or Key instance): 176 177```javascript 178// input is either a: 179// * jose.JWK.Key to copy from; or 180// * JSON object representing a JWK; or 181keystore.add(input). 182 then(function(result) { 183 // {result} is a jose.JWK.Key 184 key = result; 185 }); 186``` 187 188To import and existing Key from a PEM or DER: 189 190```javascript 191// input is either a: 192// * String serialization of a JSON JWK/(base64-encoded) PEM/(binary-encoded) DER 193// * Buffer of a JSON JWK/(base64-encoded) PEM/(binary-encoded) DER 194// form is either a: 195// * "json" for a JSON stringified JWK 196// * "private" for a DER encoded 'raw' private key 197// * "pkcs8" for a DER encoded (unencrypted!) PKCS8 private key 198// * "public" for a DER encoded SPKI public key (alternate to 'spki') 199// * "spki" for a DER encoded SPKI public key 200// * "pkix" for a DER encoded PKIX X.509 certificate 201// * "x509" for a DER encoded PKIX X.509 certificate 202// * "pem" for a PEM encoded of PKCS8 / SPKI / PKIX 203keystore.add(input, form). 204 then(function(result) { 205 // {result} is a jose.JWK.Key 206 }); 207``` 208 209To generate a new Key: 210 211```javascript 212// first argument is the key type (kty) 213// second is the key size (in bits) or named curve ('crv') for "EC" 214keystore.generate("oct", 256). 215 then(function(result) { 216 // {result} is a jose.JWK.Key 217 key = result; 218 }); 219 220// ... with properties 221var props = { 222 kid: 'gBdaS-G8RLax2qgObTD94w', 223 alg: 'A256GCM', 224 use: 'enc' 225}; 226keystore.generate("oct", 256, props). 227 then(function(result) { 228 // {result} is a jose.JWK.Key 229 key = result; 230 }); 231``` 232 233To remove a Key from its Keystore: 234```javascript 235keystore.remove(key); 236// NOTE: key.keystore does not change!! 237``` 238 239### Importing and Exporting a Single Key ### 240 241To create a single "stand alone" key: 242 243```javascript 244jose.JWK.createKey("oct", 256, { alg: "A256GCM" }). 245 then(function(result) { 246 // {result} is a jose.JWK.Key 247 // {result.keystore} is a unique jose.JWK.KeyStore 248 }); 249``` 250 251 252To import a single Key: 253 254```javascript 255// where input is either a: 256// * jose.JWK.Key instance 257// * JSON Object representation of a JWK 258jose.JWK.asKey(input). 259 then(function(result) { 260 // {result} is a jose.JWK.Key 261 // {result.keystore} is a unique jose.JWK.KeyStore 262 }); 263 264// where input is either a: 265// * String serialization of a JSON JWK/(base64-encoded) PEM/(binary-encoded) DER 266// * Buffer of a JSON JWK/(base64-encoded) PEM/(binary-encoded) DER 267// form is either a: 268// * "json" for a JSON stringified JWK 269// * "pkcs8" for a DER encoded (unencrypted!) PKCS8 private key 270// * "spki" for a DER encoded SPKI public key 271// * "pkix" for a DER encoded PKIX X.509 certificate 272// * "x509" for a DER encoded PKIX X.509 certificate 273// * "pem" for a PEM encoded of PKCS8 / SPKI / PKIX 274jose.JWK.asKey(input, form). 275 then(function(result) { 276 // {result} is a jose.JWK.Key 277 // {result.keystore} is a unique jose.JWK.KeyStore 278 }); 279``` 280 281To export the public portion of a Key as a JWK: 282 283```javascript 284var output = key.toJSON(); 285``` 286 287To export the public **and** private portions of a Key: 288 289```javascript 290var output = key.toJSON(true); 291``` 292 293### Obtaining a Key's Thumbprint ### 294 295To get or calculate a [RFC 7638](https://tools.ietf.org/html/rfc7638) thumbprint for a key: 296 297```javascript 298// where hash is a supported algorithm, currently one of: 299// * SHA-1 300// * SHA-256 301// * SHA-384 302// * SHA-512 303key.thumbprint(hash). 304 then(function(print) { 305 // {print} is a Buffer containing the thumbprint binary value 306 }); 307``` 308 309When importing or generating a key that does not have a "kid" defined, a 310"SHA-256" thumbprint is calculated and used as the "kid". 311 312## Signatures ## 313 314### Keys Used for Signing and Verifying ### 315 316When signing content, the key is expected to meet one of the following: 317 3181. A secret key (e.g, `"kty":"oct"`) 3192. The **private** key from a PKI (`"kty":"EC"` or `"kty":"RSA"`) key pair 320 321When verifying content, the key is expected to meet one of the following: 322 3231. A secret key (e.g, `"kty":"oct"`) 3242. The **public** key from a PKI (`"kty":"EC"` or `"kty":"RSA"`) key pair 325 326 327### Signing Content ### 328 329At its simplest, to create a JWS: 330 331```javascript 332// {input} is a Buffer 333jose.JWS.createSign(key). 334 update(input). 335 final(). 336 then(function(result) { 337 // {result} is a JSON object -- JWS using the JSON General Serialization 338 }); 339``` 340 341The JWS is signed using the preferred algorithm appropriate for the given Key. The preferred algorithm is the first item returned by `key.algorithms("sign")`. 342 343To create a JWS using another serialization format: 344 345```javascript 346jose.JWS.createSign({ format: 'flattened' }, key). 347 update(input). 348 final(). 349 then(function(result) { 350 // {result} is a JSON object -- JWS using the JSON Flattened Serialization 351 }); 352 353jose.JWS.createSign({ format: 'compact' }, key). 354 update(input). 355 final(). 356 then(function(result) { 357 // {result} is a String -- JWS using the Compact Serialization 358 }); 359``` 360 361To create a JWS using a specific algorithm: 362```javascript 363jose.JWS.createSign({ alg: 'PS256' }, key). 364 update(input). 365 final(). 366 then(function(result) { 367 // .... 368 }); 369``` 370 371To create a JWS for a specified content type: 372 373```javascript 374jose.JWS.createSign({ fields: { cty: 'jwk+json' } }, key). 375 update(input). 376 final(). 377 then(function(result) { 378 // .... 379 }); 380``` 381 382To create a JWS from String content: 383 384```javascript 385jose.JWS.createSign(key). 386 update(input, "utf8"). 387 final(). 388 then(function(result) { 389 // .... 390 }); 391``` 392 393To create a JWS with multiple signatures: 394 395```javascript 396// {keys} is an Array of jose.JWK.Key instances 397jose.JWS.createSign(keys). 398 update(input). 399 final(). 400 then(function(result) { 401 // .... 402 }); 403``` 404 405### Verifying a JWS ### 406 407To verify a JWS, and retrieve the payload: 408 409```javascript 410jose.JWS.createVerify(keystore). 411 verify(input). 412 then(function(result) { 413 // {result} is a Object with: 414 // * header: the combined 'protected' and 'unprotected' header members 415 // * payload: Buffer of the signed content 416 // * signature: Buffer of the verified signature 417 // * key: The key used to verify the signature 418 }); 419``` 420 421To verify using an implied Key: 422 423```javascript 424// {key} can be: 425// * jose.JWK.Key 426// * JSON object representing a JWK 427jose.JWS.createVerify(key). 428 verify(input). 429 then(function(result) { 430 // ... 431 }); 432``` 433 434To verify using a key embedded in the JWS: 435 436```javascript 437jose.JWS.createVerify(). 438 verify(input, { allowEmbeddedKey: true }). 439 then(function(result) { 440 // ... 441 }); 442``` 443 444Alternatively, a cached `createVerify()` can be configured to allow an embedded key: 445 446```javascript 447var verifier = jose.JWS.createVerify({ allowEmbeddedKey: true }); 448 449verifier.verify(input). 450 then(function(result) { 451 // ... 452 }); 453``` 454 455The key can be embedded using either 'jwk' or 'x5c', and can be located in either the JWS Unprotected Header or JWS Protected Header. 456 457**NOTE:** `verify()` will use the embedded key (if found and permitted) instead of any other key. 458 459#### Allowing (or Disallowing) Signature Algorithms ### 460 461To restrict what signature algorithms are allowed when verifying, add the `allowAlgs` member to the `options` Object. The `allowAlgs` member is either a string or an array of strings, where the string value(s) can be one of the following: 462 463* `"*"`: accept all supported algorithms 464* **`<alg name>`** (e.g., `"PS256"`): accept the specific algorithm (can have a single '*' to match a range of algorithms) 465* **`!<alg name>`** (e.g., `"!RS256"`): *do not* accept the specific algorithm (can have a single '*' to match a range of algorithms) 466 467The negation is intended to be used with the wildcard accept string, and disallow takes precedence over allowed. 468 469To only accept RSA-PSS sigatures: 470 471```javascript 472var opts = { 473 algorithms: ["PS*"] 474}; 475jose.JWS.createVerify(key, opts). 476 verify(input). 477 then(function(result) { 478 // ... 479 }); 480``` 481 482To accept any algorithm, but disallow HMAC-based signatures: 483 484```javascript 485var opts = { 486 algorithms: ["*", "!HS*"] 487}; 488jose.JWS.createVerify(key, opts). 489 verify(input). 490 then(input). 491 then(function(result) { 492 // ... 493 }); 494``` 495 496#### Handling `crit` Header Members #### 497 498To accept 'crit' field members, add the `handlers` member to the options Object. The `handlers` member is itself an Object, where its member names are the `crit` header member, and the value is one of: 499 500* `Boolean`: accepts (if `true`) -- or rejects (if `false`) -- the JWS if the member is present. 501* `Function`: takes the JWE decrypt output (just prior to decrypting) and returns a Promise for the processing of the member. 502* `Object`: An object with the following `Function` members: 503 * "prepare" -- takes the JWE decrypt output (just prior to decrypting) and returns a Promise for the processing of the member. 504 * "complete" -- takes the JWE decrypt output (immediately after decrypting) and returns a Promise for the processing of the member. 505 506**NOTE** If the handler function returns a promise, the fulfilled value is ignored. It is expected these handler functions will modify the provided value directly. 507 508To simply accept a `crit` header member: 509 510```javascript 511var opts = { 512 handlers: { 513 "exp": true 514 } 515}; 516jose.JWS.createVerify(key, opts). 517 verify(input). 518 then(function(result) { 519 // ... 520 }); 521``` 522 523To perform additional (pre-verify) processing on a `crit` header member: 524 525```javascript 526var opts = { 527 handlers: { 528 "exp": function(jws) { 529 // {jws} is the JWS verify output, pre-verification 530 jws.header.exp = new Date(jws.header.exp); 531 } 532 } 533}; 534jose.JWS.createVerify(key, opts). 535 verify(input). 536 then(function(result) { 537 // ... 538 }); 539``` 540 541To perform additional (post-verify) processing on a `crit` header member: 542 543```javascript 544var opts = { 545 handlers: { 546 "exp": { 547 complete: function(jws) { 548 // {jws} is the JWS verify output, post-verification 549 jws.header.exp = new Date(jws.header.exp); 550 } 551 } 552 } 553}; 554jose.JWS.createVerify(key, opts). 555 verify(input). 556 then(function(result) { 557 // ... 558 }); 559``` 560 561 562## Encryption ## 563 564 565### Keys Used for Encrypting and Decrypting ### 566 567When encrypting content, the key is expected to meet one of the following: 568 5691. A secret key (e.g, `"kty":"oct"`) 5702. The **public** key from a PKI (`"kty":"EC"` or `"kty":"RSA"`) key pair 571 572When decrypting content, the key is expected to meet one of the following: 573 5741. A secret key (e.g, `"kty":"oct"`) 5752. The **private** key from a PKI (`"kty":"EC"` or `"kty":"RSA"`) key pair 576 577 578### Encrypting Content ### 579 580At its simplest, to create a JWE: 581 582```javascript 583// {input} is a Buffer 584jose.JWE.createEncrypt(key). 585 update(input). 586 final(). 587 then(function(result) { 588 // {result} is a JSON Object -- JWE using the JSON General Serialization 589 }); 590``` 591 592How the JWE content is encrypted depends on the provided Key. 593 594* If the Key only supports content encryption algorithms, then the preferred algorithm is used to encrypt the content and the key encryption algorithm (i.e., the "alg" member) is set to "dir". The preferred algorithm is the first item returned by `key.algorithms("encrypt")`. 595* If the Key supports key management algorithms, then the JWE content is encrypted using "A128CBC-HS256" by default, and the Content Encryption Key is encrypted using the preferred algorithms for the given Key. The preferred algorithm is the first item returned by `key.algorithms("wrap")`. 596 597 598To create a JWE using a different serialization format: 599 600```javascript 601jose.JWE.createEncrypt({ format: 'compact' }, key). 602 update(input). 603 final(). 604 then(function(result) { 605 // {result} is a String -- JWE using the Compact Serialization 606 }); 607 608jose.JWE.createEncrypt({ format: 'flattened' }, key). 609 update(input). 610 final(). 611 then(function(result) { 612 // {result} is a JSON Object -- JWE using the JSON Flattened Serialization 613 }); 614``` 615 616To create a JWE and compressing the content before encrypting: 617 618```javascript 619jose.JWE.createEncrypt({ zip: true }, key). 620 update(input). 621 final(). 622 then(function(result) { 623 // .... 624 }); 625``` 626 627To create a JWE for a specific content type: 628 629```javascript 630jose.JWE.createEncrypt({ fields: { cty : 'jwk+json' } }, key). 631 update(input). 632 final(). 633 then(function(result) { 634 // .... 635 }); 636``` 637 638To create a JWE with multiple recipients: 639 640```javascript 641// {keys} is an Array of jose.JWK.Key instances 642jose.JWE.createEncrypt(keys). 643 update(input). 644 final(). 645 then(function(result) { 646 // .... 647 }); 648``` 649 650### Decrypting a JWE ### 651 652To decrypt a JWE, and retrieve the plaintext: 653 654```javascript 655jose.JWE.createDecrypt(keystore). 656 decrypt(input). 657 then(function(result) { 658 // {result} is a Object with: 659 // * header: the combined 'protected' and 'unprotected' header members 660 // * protected: an array of the member names from the "protected" member 661 // * key: Key used to decrypt 662 // * payload: Buffer of the decrypted content 663 // * plaintext: Buffer of the decrypted content (alternate) 664 }); 665``` 666 667To decrypt a JWE using an implied key: 668 669```javascript 670jose.JWE.createDecrypt(key). 671 decrypt(input). 672 then(function(result) { 673 // .... 674 }); 675``` 676 677#### Allowing (or Disallowing) Encryption Algorithms ### 678 679To restrict what encryption algorithms are allowed when verifying, add the `allowAlgs` member to the `options` Object. The `allowAlgs` member is either a string or an array of strings, where the string value(s) can be one of the following: 680 681* `"*"`: accept all supported algorithms 682* **`<alg name>`** (e.g., `"A128KW"`): accept the specific algorithm (can have a single '*' to match a range of similar algorithms) 683* **`!<alg name>`** (e.g., `"!RSA1_5"`): *do not* accept the specific algorithm (can have a single '*' to match a range of similar algorithms) 684 685The negation is intended to be used with the wildcard accept string, and disallow takes precedence over allowed. 686 687To only accept "dir" and AES-GCM encryption: 688 689```javascript 690var opts = { 691 algorithms: ["dir", "A*GCM"] 692}; 693jose.JWE.createDecrypt(key, opts). 694 decrypt(input). 695 then(function(result) { 696 // ... 697 }); 698``` 699 700To accept any algorithm, but disallow RSA-based encryption: 701 702```javascript 703var opts = { 704 algorithms: ["*", "!RSA*"] 705}; 706jose.JWS.createVerify(key, opts). 707 verify(input). 708 then(input). 709 then(function(result) { 710 // ... 711 }); 712``` 713 714#### Handling `crit` Header Members #### 715 716To accept 'crit' field members, add the `handlers` member to the options Object. The `handlers` member is itself an Object, where its member names are the `crit` header member, and the value is one of: 717 718* `Boolean`: accepts (if `true`) -- or rejects (if `false`) -- the JWE if the member is present. 719* `Function`: takes the JWE decrypt output (just prior to decrypting) and returns a Promise for the processing of the member. 720* `Object`: An object with the following `Function` members: 721 * "prepare" -- takes the JWE decrypt output (just prior to decrypting) and returns a Promise for the processing of the member. 722 * "complete" -- takes the JWE decrypt output (immediately after decrypting) and returns a Promise for the processing of the member. 723 724**NOTE** If the handler function returns a promise, the fulfilled value is ignored. It is expected these handler functions will modify the provided value directly. 725 726To simply accept a `crit` header member: 727 728```javascript 729var opts = { 730 handlers: { 731 "exp": true 732 } 733}; 734jose.JWE.createDecrypt(key, opts). 735 decrypt(input). 736 then(function(result) { 737 // ... 738 }); 739``` 740 741To perform additional (pre-decrypt) processing on a `crit` header member: 742 743```javascript 744var opts = { 745 handlers: { 746 "exp": function(jwe) { 747 // {jwe} is the JWE decrypt output, pre-decryption 748 jwe.header.exp = new Date(jwe.header.exp); 749 } 750 } 751}; 752jose.JWE.createDecrypt(key, opts). 753 decrypt(input). 754 then(function(result) { 755 // ... 756 }); 757``` 758 759To perform additional (post-decrypt) processing on a `crit` header member: 760 761```javascript 762var opts = { 763 handlers: { 764 "exp": { 765 complete: function(jwe) { 766 // {jwe} is the JWE decrypt output, post-decryption 767 jwe.header.exp = new Date(jwe.header.exp); 768 } 769 } 770 } 771}; 772jose.JWE.createDecrypt(key, opts). 773 decrypt(input). 774 then(function(result) { 775 // ... 776 }); 777``` 778 779## Useful Utilities ## 780 781### Converting to Buffer ### 782 783To convert a [Typed Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays), [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), or Array of Numbers to a Buffer: 784 785```javascript 786buff = jose.util.asBuffer(input); 787``` 788 789### URI-Safe Base64 ### 790 791This exposes [urlsafe-base64](https://github.com/RGBboy/urlsafe-base64)'s `encode` and `decode` methods as `encode` and `decode` (respectively). 792 793To convert from a Buffer to a base64uri-encoded String: 794 795```javascript 796var output = jose.util.base64url.encode(input); 797``` 798 799To convert a String to a base64uri-encoded String: 800 801```javascript 802// explicit encoding 803output = jose.util.base64url.encode(input, "utf8"); 804 805// implied "utf8" encoding 806output = jose.util.base64url.encode(input); 807``` 808 809To convert a base64uri-encoded String to a Buffer: 810 811```javascript 812var output = jose.util.base64url.decode(input); 813``` 814 815### Random Bytes ### 816 817To generate a Buffer of octets, regardless of platform: 818 819```javascript 820// argument is size (in bytes) 821var rnd = jose.util.randomBytes(32); 822``` 823 824This function uses: 825 826* `crypto.randomBytes()` on node.js 827* `crypto.getRandomValues()` on modern browsers 828* A PRNG based on AES and SHA-1 for older platforms 829