{"_id":"speakeasy","_rev":"56-ab64731a6fc65943b165862eb84a1f66","name":"speakeasy","description":"Two-factor authentication for Node.js. One-time passcode generator (HOTP/TOTP) with support for Google Authenticator.","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.0","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"ezcrypto":"0.0.3","thirty-two":"0.0.1"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{},"_npmUser":{"name":"markbao","email":"mark@markbao.com"},"_id":"speakeasy@1.0.0","_engineSupported":true,"_npmVersion":"1.0.94","_nodeVersion":"v0.4.7","_defaultsLoaded":true,"dist":{"shasum":"e75356423be2b412e541b2c6133e4aeb53f1f895","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.0.tgz","integrity":"sha512-sHahWm43PbpAmljFY1IyhihObW9in4BlC/wBhLKHqqaEkuesEKG34fwW1Wm0kAAUwO5vnq1U7CNZXbc6FBSI1g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYcfk6YPvzTPRNXgFj1gMv1scuQE4nq8a0Wr7PLNRPvwIhAK/ccfNTp8GDa333o7UQOz3OUtRttiwr8F14MsvfbZVy"}]},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"1.0.1":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.1","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"ezcrypto":"0.0.3","thirty-two":"0.0.1"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{},"_id":"speakeasy@1.0.1","dist":{"shasum":"f141cc26f777859b36b04034286398f7e64af23c","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.1.tgz","integrity":"sha512-15Jb1AuEUJzZREmgtms7hsaxnrHG5SH0sBOla8/0wC0VC/EMVQnMdQxwLbw/zVkOijF+osNb1L8wj2I4fJPp/g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHoWe6opFNgApwa+5gqkBqJBIYotjFsiNvLtvunUFtwRAiEAr8E3wfJ8CCM0z58pKOowfrPa1kgy13vAFO6XpJ5ZV60="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"1.0.2":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.2","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"ezcrypto":"0.0.3","thirty-two":"0.0.1"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{},"_id":"speakeasy@1.0.2","dist":{"shasum":"8543fb2af830be13c1ecc442a05da11c30661c76","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.2.tgz","integrity":"sha512-gt8+fe7SdlWBRjR0eCOm8LkhfXAIDn3FKbHcneXBy2vEVSvOavuWiUYSKDR6AEkHNhX8qssHcboG+ZhyzJLwjw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEf0QFHwrQz6fqrTZ/JlpHaSWV4V7ay47o8qULl217JaAiBNSrVOXsFG6/904WHOP6Qt8Y+gtwq/0p8dG6S95MbYMQ=="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"1.0.3":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.3","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"ezcrypto":"0.0.3","thirty-two":"0.0.1"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{"vows":"*"},"scripts":{"test":"vows --spec test/*"},"_id":"speakeasy@1.0.3","dist":{"shasum":"dc3f5bd5a14277bfc30790a22d128342fa21d712","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.3.tgz","integrity":"sha512-GRKmNuB8MUXaNysecME+1xn2+wD1NCBm2uVjCFUyhm5lFZHn80KKCqYPthD2+cuRt5C2R/G0Xf0PSPekyMMFxA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBCsoyL69lX8Us8V/n7Bjzh/wYdJdK8tbRIiJoLCSqbSAiBL3o5Tw1f5lYspNh6VUqPfAvRGAX9ZiVNVQEx+8icn4g=="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"1.0.4":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.4","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"thirty-two":"0.0.2"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{"vows":"*"},"scripts":{"test":"vows --spec test/*"},"gitHead":"d27a8a20f9bd874f5d4ecc07dcadb50ce574a5a0","bugs":{"url":"https://github.com/markbao/speakeasy/issues"},"_id":"speakeasy@1.0.4","_shasum":"05994f23c337ad9a86b1868aab290ba0e7e9f89e","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"dist":{"shasum":"05994f23c337ad9a86b1868aab290ba0e7e9f89e","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.4.tgz","integrity":"sha512-jYsJJ5ZJPenaa4HKILpZksPcjNhHxyt4ffG45CKQqksGUYspugh5KRprDMDU+xjhVTs83HyXcTJWEw3ore9fDA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0Za9ArI96JqUs8YWs030Z98gEXpT4rlmrF2XX7xLwjwIhANkDrzc+J0U2LFlGY1celP3BymvdqKS+b1VpXW3uKG8w"}]},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"1.0.5":{"author":{"name":"Mark Bao","email":"mark@markbao.com","url":"http://markbao.com/"},"name":"speakeasy","description":"Easy two-factor authentication with node.js. Time-based or counter-based (HOTP/TOTP), and supports the Google Authenticator mobile app. Also includes a key generator. Uses the HMAC One-Time Password algorithms.","version":"1.0.5","homepage":"http://github.com/markbao/speakeasy","repository":{"type":"git","url":"git://github.com/markbao/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.3.0"},"dependencies":{"thirty-two":"0.0.2"},"keywords":["two-factor","authentication","hotp","totp","multi-factor","hmac","one-time password","passwords"],"devDependencies":{"vows":"*"},"scripts":{"test":"vows --spec test/*"},"gitHead":"f6cd5a143e428d5643873bdde7c742e90c912055","bugs":{"url":"https://github.com/markbao/speakeasy/issues"},"_id":"speakeasy@1.0.5","_shasum":"bad81fdc721e6c5439e2e00d016e7ab7dd08d50d","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"dist":{"shasum":"bad81fdc721e6c5439e2e00d016e7ab7dd08d50d","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-1.0.5.tgz","integrity":"sha512-k+QPYq5xaWJbAaEwW2EjLYd8l+Ps//j7I6AiSov1J3BLJTMKLhixlV1HdbDeQASpC3S+Pymr4UJAeoWGyNnerg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDmw/O5ruz1esP5QA8+MU6yIfe6Ai9ZX342KWgag3mYEgIhAJKRDgHMtxtLEi+/L8dgy1rw45MHGNAoXrB5/TE+JJT2"}]},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}},"2.0.0":{"name":"speakeasy","description":"Two-factor authentication for Node.js. One-time passcode generator (HOTP/TOTP) with support for Google Authenticator.","version":"2.0.0","author":{"name":"Mark Bao & Speakeasy Contributors","email":"mark@markbao.com"},"contributors":[{"name":"Michael Phan-Ba","email":"michael@mikepb.com"},{"name":"Guy Halford-Thompson","email":"guy@cach.me"}],"homepage":"http://github.com/speakeasyjs/speakeasy","bugs":{"url":"https://github.com/speakeasyjs/speakeasy/issues"},"keywords":["authentication","google authenticator","hmac","hotp","multi-factor","one-time password","passwords","totp","two factor","two-factor","two-factor authentication"],"license":"MIT","repository":{"type":"git","url":"git://github.com/speakeasyjs/speakeasy.git"},"main":"index.js","engines":{"node":">= 0.10.0"},"dependencies":{"base32.js":"0.0.1"},"devDependencies":{"chai":"^3.4.1","coveralls":"^2.11.6","istanbul":"^0.4.2","jsdoc":"^3.3.1","mocha":"^2.2.5","semistandard":"^7.0.5","snazzy":"^2.0.1"},"scripts":{"test":"mocha","doc":"jsdoc -c jsdoc.json && sed -i '' -e 's/․/./g' docs/speakeasy/*/*.html","cover":"istanbul cover _mocha -- test/* -R spec","lint":"semistandard --verbose | snazzy"},"gitHead":"4e0aa91dee166306e07ea11e371d5a5df95f4391","_id":"speakeasy@2.0.0","_shasum":"85c91a071b09a5cb8642590d983566165f57613a","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"markbao","email":"mark@markbao.com"},"dist":{"shasum":"85c91a071b09a5cb8642590d983566165f57613a","tarball":"https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz","integrity":"sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCvMbi3Vl6hg86srRirpSbF57iHaOiwtbPecTqDpReAgAIhAOFgvX+zliMPZjRMuEuIybLv5HYhMVfot/8Ru9qGotpA"}]},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"directories":{}}},"maintainers":[{"name":"markbao","email":"mark@markbao.com"}],"time":{"modified":"2022-06-26T22:41:15.138Z","created":"2011-11-03T20:00:03.148Z","1.0.0":"2011-11-03T20:00:03.289Z","1.0.1":"2012-09-10T20:30:21.513Z","1.0.2":"2012-10-21T19:36:52.507Z","1.0.3":"2013-02-05T16:36:56.231Z","1.0.4":"2016-01-08T20:21:32.994Z","1.0.5":"2016-01-23T18:16:26.530Z","2.0.0":"2016-01-27T06:42:51.677Z"},"author":{"name":"Mark Bao & Speakeasy Contributors","email":"mark@markbao.com"},"repository":{"type":"git","url":"git://github.com/speakeasyjs/speakeasy.git"},"users":{"jden":true,"oliversalzburg":true,"djk":true,"cdokolas":true,"jebu":true,"shanewholloway":true,"detj":true,"qqqppp9998":true,"alphatr":true,"leizongmin":true,"rocket0191":true,"jsdnxx":true,"natarajanmca11":true,"parkerproject":true,"egantz":true,"chirag8642":true,"tanmaypatel":true,"nec":true,"ferrari":true,"igorissen":true,"kamalnrf":true,"heartnett":true,"simon129":true,"netroy":true,"tunderdomb":true,"jakubknejzlik":true,"itcorp":true,"chrisx":true,"supra126":true,"miloc":true,"goulash1971":true,"vandeurenglenn":true,"vivek.vikhere":true,"mjurczyk":true,"cfleschhut":true,"leejefon":true,"mmork":true,"ashish.npm":true},"readme":"<img src=\"http://i.imgur.com/qRyNMx4.png\" width=\"550\">\n\n[![Build Status](https://travis-ci.org/speakeasyjs/speakeasy.svg?branch=v2)](https://travis-ci.org/speakeasyjs/speakeasy)\n[![NPM downloads](https://img.shields.io/npm/dt/speakeasy.svg)](https://www.npmjs.com/package/speakeasy)\n[![Coverage Status](https://coveralls.io/repos/github/speakeasyjs/speakeasy/badge.svg?branch=v2)](https://coveralls.io/github/speakeasyjs/speakeasy?branch=v2)\n[![NPM version](https://img.shields.io/npm/v/speakeasy.svg)](https://www.npmjs.com/package/speakeasy)\n\n---\n\n**Jump to** — [Install](#install) · [Demo](#demo) · [Two-Factor Usage](#two-factor) · [General Usage](#general-usage) · [Documentation](#documentation) · [Contributing](#contributing) · [License](#license)\n\n---\n\nSpeakeasy is a one-time passcode generator, ideal for use in two-factor\nauthentication, that supports Google Authenticator and other two-factor devices.\n\nIt is well-tested and includes robust support for custom token lengths,\nauthentication windows, hash algorithms like SHA256 and SHA512, and other\nfeatures, and includes helpers like a secret key generator.\n\nSpeakeasy implements one-time passcode generators as standardized by the\n[Initiative for Open Authentication (OATH)][oath]. The HMAC-Based One-Time\nPassword (HOTP) algorithm defined by [RFC 4226][rfc4226] and the Time-Based\nOne-time Password (TOTP) algorithm defined in [RFC 6238][rfc6238] are\nsupported. This project incorporates code from [passcode][], originally a\nfork of Speakeasy, and [notp][].\n\n\n<a name=\"install\"></a>\n## Install\n\n```sh\nnpm install --save speakeasy\n```\n\n<a name=\"demo\"></a>\n## Demo\n\nThis demo uses the `generateSecret` method of Speakeasy to generate a secret key,\ndisplays a Google Authenticator–compatible QR code which you can scan into your\nphone's two-factor app, and shows the token, which you can verify with your\nphone. Includes sample code. https://sedemo-mktb.rhcloud.com/\n\n<a href=\"https://sedemo-mktb.rhcloud.com/\"><img src=\"http://i.imgur.com/gPwPP4u.png\" height=\"43\"></a>\n\n<a name=\"two-factor\"></a>\n## Two-Factor Usage\n\nLet's say you have a user that wants to enable two-factor authentication, and you intend to do two-factor authentication using an app like Google Authenticator, Duo Security, Authy, etc. This is a three-step process:\n\n1. Generate a secret\n2. Show a QR code for the user to scan in\n3. Authenticate the token for the first time\n\n### Generating a key\n\nUse Speakeasy's key generator to get a key.\n\n```js\nvar secret = speakeasy.generateSecret();\n// Returns an object with secret.ascii, secret.hex, and secret.base32.\n// Also returns secret.otpauth_url, which we'll use later.\n```\n\nThis will generate a secret key of length 32, which will be the secret key for the user.\n\nNow, we want to make sure that this secret works by validating the token that the user gets from it for the first time. In other words, we don't want to set this as the user's secret key just yet – we first want to verify their token for the first time. We need to persist the secret so that we can use it for token validation later.\n\nSo, store one of the encodings for the secret, preferably `secret.base32`, somewhere temporary, since we'll use that in the future to authenticate the user's first token.\n\n```js\n// Example for storing the secret key somewhere (varies by implementation):\nuser.two_factor_temp_secret = secret.base32;\n```\n\n### Displaying a QR code\n\nNext, we'll want to display a QR code to the user so they can scan in the secret into their app. Google Authenticator and similar apps take in a QR code that holds a URL with the protocol `otpauth://`, which you get automatically from `secret.otpauth_url`.\n\nUse a QR code module to generate a QR code that stores the data in `secret.otpauth_url`, and then display the QR code to the user. This is one simple way to do it, which generates a PNG data URL which you can put into an `<img>` tag on a webpage:\n\n```js\n// Use the node-qrcode package\n// npm install --save node-qrcode\nvar QRCode = require('qrcode');\n\n// Get the data URL of the authenticator URL\nQRCode.toDataURL(secret.otpauth_url, function(err, data_url) {\n  console.log(data_url);\n\n  // Display this data URL to the user in an <img> tag\n  // Example:\n  write('<img src=\"' + data_url + '\">');\n});\n```\n\nAsk the user to scan this QR code into their authenticator app.\n\n### Verifying the token\n\nFinally, we want to make sure that the token on the server side and the token on the client side match. The best practice is to do a token check before fully enabling two-factor authenticaton for the user. This code applies to the first and subsequent token checks.\n\nAfter the user scans the QR code, ask the user to enter in the token that they see in their app. Then, verify it against the secret.\n\n```js\n// Let's say the user says that the token they have is 132890\nvar userToken = '132890';\n\n// Let's say we stored the user's temporary secret in a user object like above:\n// (This is specific to your implementation)\nvar base32secret = user.two_factor_temp_secret;\n```\n```js\n// Use verify() to check the token against the secret\nvar verified = speakeasy.totp.verify({ secret: base32secret,\n                                       encoding: 'base32',\n                                       token: userToken });\n```\n\n`verified` will be true if the token is successfully verified, false if not.\n\nIf successfully verified, you can now save the secret to the user's account and use the same process above whenever you need to use two-factor to authenticate the user, like during login.\n\n```js\n// Example for saving user's token (varies by implementation):\nuser.two_factor_secret = user.two_factor_temp_secret;\nuser.two_factor_enabled = true\n```\n\nNow you're done implementing two-factor authentication!\n\n<a name=\"general-usage\"></a>\n## General Usage\n\n```js\nvar speakeasy = require(\"speakeasy\");\n```\n\n#### Generating a key\n\n```js\n// Generate a secret key.\nvar secret = speakeasy.generateSecret({length: 20});\n// Access using secret.ascii, secret.hex, or secret.base32.\n```\n\n#### Getting a time-based token for the current time\n\n```js\n// Generate a time-based token based on the base-32 key.\n// HOTP (counter-based tokens) can also be used if `totp` is replaced by\n// `hotp` (i.e. speakeasy.hotp()) and a `counter` is given in the options.\nvar token = speakeasy.totp({\n  secret: secret.base32,\n  encoding: 'base32'\n});\n\n// Returns token for the secret at the current time\n// Compare this to user input\n```\n\n#### Verifying a token\n\n```js\n// Verify a given token\nvar tokenValidates = speakeasy.totp.verify({\n  secret: secret.base32,\n  encoding: 'base32',\n  token: '123456',\n  window: 6\n});\n// Returns true if the token matches\n```\n\n#### Verifying a token and calculating a delta\n\nA TOTP is incremented every `step` time-step seconds. By default, the time-step\nis 30 seconds. You may change the time-step using the `step` option, with units\nin seconds.\n\n```js\n// Verify a given token is within 3 time-steps (+/- 2 minutes) from the server\n// time-step.\nvar tokenDelta = speakeasy.totp.verifyDelta({\n  secret: secret.base32,\n  encoding: 'base32',\n  token: '123456',\n  window: 2,\n  step: 60\n});\n// Returns {delta: 0} where the delta is the time step difference\n// between the given token and the current time\n```\n\n#### Getting a time-based token for a custom time\n\n```js\nvar token = speakeasy.totp({\n  secret: secret.base32,\n  encoding: 'base32',\n  time: 1453667708 // specified in seconds\n});\n```\n\n#### Calculating a counter-based token\n\n```js\n// Get a counter-based token\nvar token = speakeasy.hotp({\n  secret: secret.base32,\n  encoding: 'base32',\n  counter: 123\n});\n\n// Verify a counter-based token\nvar tokenValidates = speakeasy.hotp.verify({\n  secret: secret.base32,\n  encoding: 'base32',\n  token: '123456',\n  counter: 123\n});\n```\n\n#### Using other encodings\n\nThe default encoding (when `encoding` is not specified) is `ascii`.\n\n```js\n// Specifying an ASCII token for TOTP\n// (encoding is 'ascii' by default)\nvar token = speakeasy.totp({\n  secret: secret.ascii\n});\n```\n\n```js\n// Specifying a hex token for TOTP\nvar token = speakeasy.totp({\n  secret: secret.hex,\n  encoding: 'hex'\n});\n```\n\n\n#### Using other hash algorithms\n\nThe default hash algorithm is SHA1.\n\n```js\n// Specifying SHA256\nvar token = speakeasy.totp({\n  secret: secret.ascii,\n  algorithm: 'sha256'\n});\n```\n\n```js\n// Specifying SHA512\nvar token = speakeasy.totp({\n  secret: secret.ascii,\n  algorithm: 'sha512'\n});\n```\n\n#### Getting an otpauth:// URL and QR code for non-SHA1 hash algorithms\n\n```js\n// Generate a secret, if needed\nvar secret = speakeasy.generateSecret();\n// By default, generateSecret() returns an otpauth_url for SHA1\n\n// Use otpauthURL() to get a custom authentication URL for SHA512\nvar url = speakeasy.otpauthURL({ secret: secret.ascii, label: 'Name of Secret', algorithm: 'sha512' });\n\n// Pass URL into a QR code generator\n```\n\n#### Specifying a window for verifying HOTP and TOTP\n\nVerify a HOTP token with counter value 42 and a window of 10. HOTP has a one-sided window, so this will check counter values from 42 to 52, inclusive, and return a `{ delta: n }` where `n` is the difference between the given counter value and the counter position at which the token was found, or `undefined` if it was not found within the window. See the <a href=\"#totp․verifyDelta\">`hotp․verifyDelta(options)`</a> documentation for more info.\n\n```js\nvar token = speakeasy.hotp.verifyDelta({\n  secret: secret.ascii,\n  counter: 42,\n  token: '123456',\n  window: 10\n});\n```\n\nHow this works:\n\n```js\n// Set ASCII secret\nvar secret = 'rNONHRni6BAk7y2TiKrv';\n\n// Get HOTP counter token at counter = 42 \nvar counter42 = speakeasy.hotp({ secret: secret, counter: 42 });\n// => '566646'\n\n// Get HOTP counter token at counter = 45\nvar counter45 = speakeasy.hotp({ secret: secret, counter: 45 });\n// => '323238'\n\n// Verify the secret at counter 42 with the actual value and a window of 10\n// This will check all counter values from 42 to 52, inclusive\nspeakeasy.hotp.verifyDelta({ secret: secret, counter: 42, token: counter42, window: 10 });\n// => { delta: 0 } because the given token at counter 42 is 0 steps away from the given counter 42\n\n// Verify the secret at counter 45, but give a counter of 42 and a window of 10\n// This will check all counter values from 42 to 52, inclusive\nspeakeasy.hotp.verifyDelta({ secret: secret, counter: 42, token: counter45, window: 10 });\n// => { delta: 3 } because the given token at counter 45 is 0 steps away from given counter 42\n\n// Not in window: specify a window of 1, which only tests counters 42 and 43, not 45\nspeakeasy.hotp.verifyDelta({ secret: secret, counter: 42, token: counter45, window: 1 });\n// => undefined\n\n// Shortcut to use verify() to simply return whether it is verified as within the window\nspeakeasy.hotp.verify({ secret: secret, counter: 42, token: counter45, window: 10 });\n// => true\n\n// Not in window: specify a window of 1, which only tests counters 42 and 43, not 45\nspeakeasy.hotp.verify({ secret: secret, counter: 42, token: counter45, window: 1 });\n// => false\n```\n\nVerify a TOTP token at the current time with a window of 2. Since the default time step is 30 seconds, and TOTP has a two-sided window, this will check tokens between [current time minus two tokens before] and [current time plus two tokens after]. In other words, with a time step of 30 seconds, it will check the token at the current time, plus the tokens at the current time minus 30 seconds, minus 60 seconds, plus 30 seconds, and plus 60 seconds – basically, it will check tokens between a minute ago and a minute from now. It will return a `{ delta: n }` where `n` is the difference between the current time step and the counter position at which the token was found, or `undefined` if it was not found within the window. See the <a href=\"#totp․verifyDelta\">`totp․verifyDelta(options)`</a> documentation for more info.\n\n```js\nvar verified = speakeasy.totp.verifyDelta({\n  secret: secret.ascii,\n  token: '123456',\n  window: 2\n});\n```\n\nThe mechanics of TOTP windows are the same as for HOTP, as shown above, just with two-sided windows, meaning that the `delta` value can be negative if the token is found before the given time or counter.\n\n```js\nvar secret = 'rNONHRni6BAk7y2TiKrv';\n\n// By way of example, we will force TOTP to return tokens at time 1453853945 and\n// at time 1453854005 (60 seconds ahead, or 2 steps ahead)\nvar token1 = speakeasy.totp({ secret: secret, time: 1453853945 }); // 625175\nvar token3 = speakeasy.totp({ secret: secret, time: 1453854005 }); // 222636\n\n// We can check the time at token 3, 1453853975, with token 1, but use a window of 2\n// With a time step of 30 seconds, this will check all tokens from 60 seconds \n// before the time to 60 seconds after the time\nspeakeasy.totp.verifyDelta({ secret: secret, token: token1, window: 2, time: 1453854005 });\n// => { delta: -2 }\n\n// This signifies that the given token, token1, is -2 steps away from\n// the given time, which means that it is the token for the value at\n// (-2 * time step) = (-2 * 30 seconds) = 60 seconds ago.\n```\n\nAs shown previously, you can also change `verifyDelta()` to `verify()` to simply return a boolean if the given token is within the given window.\n\n<a name=\"documentation\"></a>\n## Documentation\n\nFull API documentation (in JSDoc format) is available below and at http://speakeasyjs.github.io/speakeasy/\n\n<a href=\"http://speakeasyjs.github.io/speakeasy/\"><img src=\"http://i.imgur.com/hD9w41T.png\" height=\"43\"></a>\n\n### Functions\n\n<dl>\n<dt><a href=\"#digest\">digest(options)</a> ⇒ <code>Buffer</code></dt>\n<dd><p>Digest the one-time passcode options.</p>\n</dd>\n<dt><a href=\"#hotp\">hotp(options)</a> ⇒ <code>String</code></dt>\n<dd><p>Generate a counter-based one-time token.</p>\n</dd>\n<dt><a href=\"#hotp․verifyDelta\">hotp․verifyDelta(options)</a> ⇒ <code>Object</code></dt>\n<dd><p>Verify a counter-based one-time token against the secret and return the delta.</p>\n</dd>\n<dt><a href=\"#hotp․verify\">hotp․verify(options)</a> ⇒ <code>Boolean</code></dt>\n<dd><p>Verify a counter-based one-time token against the secret and return true if it\nverifies.</p>\n</dd>\n<dt><a href=\"#totp\">totp(options)</a> ⇒ <code>String</code></dt>\n<dd><p>Generate a time-based one-time token.</p>\n</dd>\n<dt><a href=\"#totp․verifyDelta\">totp․verifyDelta(options)</a> ⇒ <code>Object</code></dt>\n<dd><p>Verify a time-based one-time token against the secret and return the delta.</p>\n</dd>\n<dt><a href=\"#totp․verify\">totp․verify(options)</a> ⇒ <code>Boolean</code></dt>\n<dd><p>Verify a time-based one-time token against the secret and return true if it\nverifies.\n</dd>\n<dt><a href=\"#generateSecret\">generateSecret(options)</a> ⇒ <code>Object</code> | <code><a href=\"#GeneratedSecret\">GeneratedSecret</a></code></dt>\n<dd><p>Generates a random secret with the set A-Z a-z 0-9 and symbols, of any length\n(default 32).</p>\n</dd>\n<dt><a href=\"#generateSecretASCII\">generateSecretASCII([length], [symbols])</a> ⇒ <code>String</code></dt>\n<dd><p>Generates a key of a certain length (default 32) from A-Z, a-z, 0-9, and\nsymbols (if requested).</p>\n</dd>\n<dt><a href=\"#otpauthURL\">otpauthURL(options)</a> ⇒ <code>String</code></dt>\n<dd><p>Generate an URL for use with the Google Authenticator app.</p>\n</dd>\n</dl>\n\n### Typedefs\n\n<dl>\n<dt><a href=\"#GeneratedSecret\">GeneratedSecret</a> : <code>Object</code></dt>\n<dd></dd>\n</dl>\n\n<a name=\"digest\"></a>\n### digest(options) ⇒ <code>Buffer</code>\nDigest the one-time passcode options.\n\n**Kind**: function  \n\n**Returns**: <code>Buffer</code> - The one-time passcode as a buffer.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.counter | <code>Integer</code> |  | Counter value |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n| [options.key] | <code>String</code> |  | (DEPRECATED. Use `secret` instead.)   Shared secret key |\n\n<a name=\"hotp\"></a>\n### hotp(options) ⇒ <code>String</code>\n\nGenerate a counter-based one-time token. Specify the key and counter, and\nreceive the one-time password for that counter position as a string. You can\nalso specify a token length, as well as the encoding (ASCII, hexadecimal, or\nbase32) and the hashing algorithm to use (SHA1, SHA256, SHA512).\n\n**Kind**: function  \n\n**Returns**: <code>String</code> - The one-time passcode.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.counter | <code>Integer</code> |  | Counter value |\n| [options.digest] | <code>Buffer</code> |  | Digest, automatically generated by default |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n| [options.key] | <code>String</code> |  | (DEPRECATED. Use `secret` instead.)   Shared secret key |\n| [options.length] | <code>Integer</code> | <code>6</code> | (DEPRECATED. Use `digits` instead.) The   number of digits for the one-time passcode. |\n\n<a name=\"hotp․verifyDelta\"></a>\n### hotp․verifyDelta(options) ⇒ <code>Object</code>\nVerify a counter-based one-time token against the secret and return the delta.\nBy default, it verifies the token at the given counter value, with no leeway\n(no look-ahead or look-behind). A token validated at the current counter value\nwill have a delta of 0.\n\nYou can specify a window to add more leeway to the verification process.\nSetting the window param will check for the token at the given counter value\nas well as `window` tokens ahead (one-sided window). See param for more info.\n\n`verifyDelta()` will return the delta between the counter value of the token\nand the given counter value. For example, if given a counter 5 and a window\n10, `verifyDelta()` will look at tokens from 5 to 15, inclusive. If it finds\nit at counter position 7, it will return `{ delta: 2 }`.\n\n**Kind**: function  \n\n**Returns**: <code>Object</code> - On success, returns an object with the counter\n  difference between the client and the server as the `delta` property (i.e.\n  `{ delta: 0 }`).  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.token | <code>String</code> |  | Passcode to validate |\n| options.counter | <code>Integer</code> |  | Counter value. This should be stored by   the application and must be incremented for each request. |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.window] | <code>Integer</code> | <code>0</code> | The allowable margin for the counter.   The function will check \"W\" codes in the future against the provided   passcode, e.g. if W = 10, and C = 5, this function will check the   passcode against all One Time Passcodes between 5 and 15, inclusive. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n\n<a name=\"hotp․verify\"></a>\n### hotp․verify(options) ⇒ <code>Boolean</code>\nVerify a counter-based one-time token against the secret and return true if it\nverifies. Helper function for `hotp.verifyDelta()`` that returns a boolean\ninstead of an object. For more on how to use a window with this, see\nhotp.verifyDelta.\n\n**Kind**: function  \n\n**Returns**: <code>Boolean</code> - Returns true if the token matches within the given\n  window, false otherwise.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.token | <code>String</code> |  | Passcode to validate |\n| options.counter | <code>Integer</code> |  | Counter value. This should be stored by   the application and must be incremented for each request. |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.window] | <code>Integer</code> | <code>0</code> | The allowable margin for the counter.   The function will check \"W\" codes in the future against the provided   passcode, e.g. if W = 10, and C = 5, this function will check the   passcode against all One Time Passcodes between 5 and 15, inclusive. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n\n<a name=\"totp\"></a>\n### totp(options) ⇒ <code>String</code>\n\nGenerate a time-based one-time token. Specify the key, and receive the\none-time password for that time as a string. By default, it uses the current\ntime and a time step of 30 seconds, so there is a new token every 30 seconds.\nYou may override the time step and epoch for custom timing. You can also\nspecify a token length, as well as the encoding (ASCII, hexadecimal, or\nbase32) and the hashing algorithm to use (SHA1, SHA256, SHA512).\n\nUnder the hood, TOTP calculates the counter value by finding how many time\nsteps have passed since the epoch, and calls HOTP with that counter value.\n\n**Kind**: function  \n\n**Returns**: <code>String</code> - The one-time passcode.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| [options.time] | <code>Integer</code> |  | Time in seconds with which to calculate counter value.   Defaults to `Date.now()`. |\n| [options.step] | <code>Integer</code> | <code>30</code> | Time step in seconds |\n| [options.epoch] | <code>Integer</code> | <code>0</code> | Initial time since the UNIX epoch from   which to calculate the counter value. Defaults to 0 (no offset). |\n| [options.counter] | <code>Integer</code> |  | Counter value, calculated by default. |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n| [options.key] | <code>String</code> |  | (DEPRECATED. Use `secret` instead.)   Shared secret key |\n| [options.initial_time] | <code>Integer</code> | <code>0</code> | (DEPRECATED. Use `epoch` instead.)   Initial time since the UNIX epoch from which to calculate the counter   value. Defaults to 0 (no offset). |\n| [options.length] | <code>Integer</code> | <code>6</code> | (DEPRECATED. Use `digits` instead.) The   number of digits for the one-time passcode. |\n\n<a name=\"totp․verifyDelta\"></a>\n### totp․verifyDelta(options) ⇒ <code>Object</code>\nVerify a time-based one-time token against the secret and return the delta.\nBy default, it verifies the token at the current time window, with no leeway\n(no look-ahead or look-behind). A token validated at the current time window\nwill have a delta of 0.\n\nYou can specify a window to add more leeway to the verification process.\nSetting the window param will check for the token at the given counter value\nas well as `window` tokens ahead and `window` tokens behind (two-sided\nwindow). See param for more info.\n\n`verifyDelta()` will return the delta between the counter value of the token\nand the given counter value. For example, if given a time at counter 1000 and\na window of 5, `verifyDelta()` will look at tokens from 995 to 1005,\ninclusive. In other words, if the time-step is 30 seconds, it will look at\ntokens from 2.5 minutes ago to 2.5 minutes in the future, inclusive.\nIf it finds it at counter position 1002, it will return `{ delta: 2 }`.\nIf it finds it at counter position 997, it will return `{ delta: -3 }`.\n\n**Kind**: function  \n\n**Returns**: <code>Object</code> - On success, returns an object with the time step\n  difference between the client and the server as the `delta` property (e.g.\n  `{ delta: 0 }`).  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.token | <code>String</code> |  | Passcode to validate |\n| [options.time] | <code>Integer</code> |  | Time in seconds with which to calculate counter value.   Defaults to `Date.now()`. |\n| [options.step] | <code>Integer</code> | <code>30</code> | Time step in seconds |\n| [options.epoch] | <code>Integer</code> | <code>0</code> | Initial time since the UNIX epoch from   which to calculate the counter value. Defaults to 0 (no offset). |\n| [options.counter] | <code>Integer</code> |  | Counter value, calculated by default. |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.window] | <code>Integer</code> | <code>0</code> | The allowable margin for the counter.   The function will check \"W\" codes in the future and the past against the   provided passcode, e.g. if W = 5, and C = 1000, this function will check   the passcode against all One Time Passcodes between 995 and 1005,   inclusive. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n\n<a name=\"totp․verify\"></a>\n### totp․verify(options) ⇒ <code>Boolean</code>\nVerify a time-based one-time token against the secret and return true if it\nverifies. Helper function for verifyDelta() that returns a boolean instead of\nan object. For more on how to use a window with this, see totp.verifyDelta.\n\n**Kind**: function\n\n**Returns**: <code>Boolean</code> - Returns true if the token matches within the given\n  window, false otherwise.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.token | <code>String</code> |  | Passcode to validate |\n| [options.time] | <code>Integer</code> |  | Time in seconds with which to calculate counter value.   Defaults to `Date.now()`. |\n| [options.step] | <code>Integer</code> | <code>30</code> | Time step in seconds |\n| [options.epoch] | <code>Integer</code> | <code>0</code> | Initial time since the UNIX epoch from   which to calculate the counter value. Defaults to 0 (no offset). |\n| [options.counter] | <code>Integer</code> |  | Counter value, calculated by default. |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. |\n| [options.window] | <code>Integer</code> | <code>0</code> | The allowable margin for the counter.   The function will check \"W\" codes in the future and the past against the   provided passcode, e.g. if W = 5, and C = 1000, this function will check   the passcode against all One Time Passcodes between 995 and 1005,   inclusive. |\n| [options.encoding] | <code>String</code> | <code>&quot;ascii&quot;</code> | Key encoding (ascii, hex,   base32, base64). |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n\n<a name=\"generateSecret\"></a>\n### generateSecret(options) ⇒ <code>Object</code> &#124; <code>[GeneratedSecret](#GeneratedSecret)</code>\nGenerates a random secret with the set A-Z a-z 0-9 and symbols, of any length\n(default 32). Returns the secret key in ASCII, hexadecimal, and base32 format,\nalong with the URL used for the QR code for Google Authenticator (an otpauth\nURL). Use a QR code library to generate a QR code based on the Google\nAuthenticator URL to obtain a QR code you can scan into the app.\n\n**Kind**: function    \n\n**Returns**: A [`GeneratedSecret`](#GeneratedSecret) object\n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| [options.length] | <code>Integer</code> | <code>32</code> | Length of the secret |\n| [options.symbols] | <code>Boolean</code> | <code>false</code> | Whether to include symbols |\n| [options.otpauth_url] | <code>Boolean</code> | <code>true</code> | Whether to output a Google   Authenticator-compatible otpauth:// URL (only returns otpauth:// URL, no QR code) |\n| [options.name] | <code>String</code> |  | The name to use with Google Authenticator. |\n| [options.qr_codes] | <code>Boolean</code> | <code>false</code> | (DEPRECATED. Do not use to prevent   leaking of secret to a third party. Use your own QR code implementation.)   Output QR code URLs for the token. |\n| [options.google_auth_qr] | <code>Boolean</code> | <code>false</code> | (DEPRECATED. Do not use to   prevent leaking of secret to a third party. Use your own QR code   implementation.) Output a Google Authenticator otpauth:// QR code URL. |\n\n<a name=\"generateSecretASCII\"></a>\n### generateSecretASCII([length], [symbols]) ⇒ <code>String</code>\nGenerates a key of a certain length (default 32) from A-Z, a-z, 0-9, and\nsymbols (if requested).\n\n**Kind**: function  \n\n**Returns**: <code>String</code> - The generated key.  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [length] | <code>Integer</code> | <code>32</code> | The length of the key. |\n| [symbols] | <code>Boolean</code> | <code>false</code> | Whether to include symbols in the key. |\n\n<a name=\"otpauthURL\"></a>\n### otpauthURL(options) ⇒ <code>String</code>\nGenerate a Google Authenticator-compatible otpauth:// URL for passing the\nsecret to a mobile device to install the secret.\n\nAuthenticator considers TOTP codes valid for 30 seconds. Additionally,\nthe app presents 6 digits codes to the user. According to the\ndocumentation, the period and number of digits are currently ignored by\nthe app.\n\nTo generate a suitable QR Code, pass the generated URL to a QR Code\ngenerator, such as the `qr-image` module.\n\n**Kind**: function  \n\n**Throws**: Error if secret or label is missing, or if hotp is used and a\n  counter is missing, if the type is not one of `hotp` or `totp`, if the\n  number of digits is non-numeric, or an invalid period is used. Warns if\n  the number of digits is not either 6 or 8 (though 6 is the only one\n  supported by Google Authenticator), and if the hashihng algorithm is\n  not one of the supported SHA1, SHA256, or SHA512.\n\n**Returns**: <code>String</code> - A URL suitable for use with the Google Authenticator.  \n\n**See**: https://github.com/google/google-authenticator/wiki/Key-Uri-Format  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| options | <code>Object</code> |  |  |\n| options.secret | <code>String</code> |  | Shared secret key |\n| options.label | <code>String</code> |  | Used to identify the account with which   the secret key is associated, e.g. the user's email address. |\n| [options.type] | <code>String</code> | <code>&quot;totp&quot;</code> | Either \"hotp\" or \"totp\". |\n| [options.counter] | <code>Integer</code> |  | The initial counter value, required   for HOTP. |\n| [options.issuer] | <code>String</code> |  | The provider or service with which the   secret key is associated. |\n| [options.algorithm] | <code>String</code> | <code>&quot;sha1&quot;</code> | Hash algorithm (sha1, sha256,   sha512). |\n| [options.digits] | <code>Integer</code> | <code>6</code> | The number of digits for the one-time   passcode. Currently ignored by Google Authenticator. |\n| [options.period] | <code>Integer</code> | <code>30</code> | The length of time for which a TOTP   code will be valid, in seconds. Currently ignored by Google   Authenticator. |\n| [options.encoding] | <code>String</code> |  | Key encoding (ascii, hex, base32,   base64). If the key is not encoded in Base-32, it will be reencoded. |\n\n<a name=\"GeneratedSecret\"></a>\n### GeneratedSecret : <code>Object</code>\n\n**Kind**: global typedef  \n\n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| ascii | <code>String</code> | ASCII representation of the secret |\n| hex | <code>String</code> | Hex representation of the secret |\n| base32 | <code>String</code> | Base32 representation of the secret |\n| qr_code_ascii | <code>String</code> | URL for the QR code for the ASCII secret. |\n| qr_code_hex | <code>String</code> | URL for the QR code for the hex secret. |\n| qr_code_base32 | <code>String</code> | URL for the QR code for the base32 secret. |\n| google_auth_qr | <code>String</code> | URL for the Google Authenticator otpauth   URL's QR code. |\n| otpauth_url | <code>String</code> | Google Authenticator-compatible otpauth URL. |\n\n<a name=\"contributing\"></a>\n## Contributing\n\nWe're very happy to have your contributions in Speakeasy.\n\n**Contributing code** — First, make sure you've added tests if adding new functionality. Then, run `npm test` to run all the tests to make sure they pass. Next, make a pull request to this repo. Thanks!\n\n**Filing an issue** — Submit issues to the [GitHub Issues][issues] page.\n\n**Maintainers** —\n\n- Mark Bao ([markbao][markbao])\n- Michael Phan-Ba ([mikepb][mikepb])\n\n## License\n\nThis project incorporates code from [passcode][], which was originally a\nfork of speakeasy, and [notp][], both of which are licensed under MIT.\nPlease see the [LICENSE](LICENSE) file for the full combined license.\n\nIcons created by Gregor Črešnar, iconoci, and Danny Sturgess from the Noun\nProject.\n\n[issues]: https://github.com/speakeasyjs/speakeasy\n[passcode]: http://github.com/mikepb/passcode\n[notp]: https://github.com/guyht/notp\n[oath]: http://www.openauthentication.org/\n[rfc4226]: https://tools.ietf.org/html/rfc4226\n[rfc6238]: https://tools.ietf.org/html/rfc6238\n[markbao]: https://github.com/markbao\n[mikepb]: https://github.com/mikepb\n","homepage":"http://github.com/speakeasyjs/speakeasy","keywords":["authentication","google authenticator","hmac","hotp","multi-factor","one-time password","passwords","totp","two factor","two-factor","two-factor authentication"],"bugs":{"url":"https://github.com/speakeasyjs/speakeasy/issues"},"readmeFilename":"README.md","contributors":[{"name":"Michael Phan-Ba","email":"michael@mikepb.com"},{"name":"Guy Halford-Thompson","email":"guy@cach.me"}],"license":"MIT"}