Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
The 'otplib' (One Time Password Library) npm package is a comprehensive library for generating and validating one-time passwords (OTPs) using various algorithms such as TOTP (Time-based One-Time Password) and HOTP (HMAC-based One-Time Password). It is commonly used for implementing two-factor authentication (2FA) in applications.
Generate TOTP
This feature allows you to generate a Time-based One-Time Password (TOTP). The code sets the step interval to 30 seconds, generates a secret, and then generates a TOTP based on that secret.
const otplib = require('otplib');
otplib.authenticator.options = { step: 30 }; // 30 seconds step
const secret = otplib.authenticator.generateSecret();
const token = otplib.authenticator.generate(secret);
console.log(`Generated TOTP: ${token}`);
Validate TOTP
This feature allows you to validate a given TOTP against a secret. The code sets the step interval to 30 seconds, defines a secret and a token, and then checks if the token is valid for the given secret.
const otplib = require('otplib');
otplib.authenticator.options = { step: 30 };
const secret = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD';
const token = '123456';
const isValid = otplib.authenticator.check(token, secret);
console.log(`Is the TOTP valid? ${isValid}`);
Generate HOTP
This feature allows you to generate an HMAC-based One-Time Password (HOTP). The code generates a secret, sets a counter, and then generates an HOTP based on the secret and counter.
const otplib = require('otplib');
const secret = otplib.hotp.generateSecret();
const counter = 1;
const token = otplib.hotp.generate(secret, counter);
console.log(`Generated HOTP: ${token}`);
Validate HOTP
This feature allows you to validate a given HOTP against a secret and counter. The code defines a secret, a counter, and a token, and then checks if the token is valid for the given secret and counter.
const otplib = require('otplib');
const secret = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD';
const counter = 1;
const token = '123456';
const isValid = otplib.hotp.check(token, secret, counter);
console.log(`Is the HOTP valid? ${isValid}`);
Speakeasy is another popular library for generating and validating one-time passwords (OTPs) using TOTP and HOTP algorithms. It offers similar functionalities to otplib but with a slightly different API. Speakeasy is known for its simplicity and ease of use.
Notp is a minimalistic library for generating and validating TOTP and HOTP tokens. It provides basic functionalities similar to otplib but lacks some of the advanced configuration options and features available in otplib.
Time-based (TOTP) and HMAC-based (HOTP) One-Time Password library
otplib
is a JavaScript One Time Password (OTP) library for OTP generation and verification.
It implements both HOTP - RFC 4226
and TOTP - RFC 6238,
and are tested against the test vectors provided in their respective RFC specifications.
These datasets can be found in the tests/data
folder.
This library is also compatible with Google Authenticator, and includes additional methods to allow you to work with Google Authenticator.
crypto (node)
crypto-js
@ronomon/crypto-async
thirty-two
base32-encode
+ base32-decode
browser
default (node)
default-async (same as default, but with async methods)
v11 (adapter for previous version)
If you need to customise your base32 or crypto libraries, check out the In-Depth Guide and Available Packages
npm install otplib --save
import { authenticator } from 'otplib';
const secret = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD';
// Alternative:
// const secret = authenticator.generateSecret();
// Note: .generateSecret() is only available for authenticator and not totp/hotp
const token = authenticator.generate(secret);
try {
const isValid = authenticator.check(token, secret);
// or
const isValid = authenticator.verify({ token, secret });
} catch (err) {
// Possible errors
// - options validation
// - "Invalid input - it is not base32 encoded string" (if thiry-two is used)
console.error(err);
}
Please replace "authenticator" with "totp" or "hotp" depending on your requirements.
// For TOTP
import { totp } from 'otplib';
const token = totp.generate(secret);
const isValid = totp.check(token, secret);
const isValid = totp.verify({ token, secret });
// For HOTP
import { hotp } from 'otplib';
const token = hotp.generate(secret, counter);
const isValid = hotp.check(token, secret, counter);
const isValid = hotp.verify({ token, secret, counter });
For all available APIs, please refer to API Documentation.
The browser preset is a self-contained umd
module, and it is provided in a separate bundle.
npm install @otplib/preset-browser --save
The following is an example, where we are using the scripts hosted by unpkg.com
.
<script src="https://unpkg.com/@otplib/preset-browser@^12.0.0/buffer.js"></script>
<script src="https://unpkg.com/@otplib/preset-browser@^12.0.0/index.js"></script>
<script type="text/javascript">
// window.otplib.authenticator
// window.otplib.hotp
// window.otplib.totp
</script>
For more details, please refer to the @otplib/preset-browser documentation.
Version | Links |
---|---|
v12.x | Website / API / Readme |
v11.x | API / Readme |
v10.x and below | Available via git history |
This library follows semver
. As such, major version bumps usually mean API changes or behavior changes.
Please check upgrade notes for more information,
especially before making any major upgrades.
To simplify releases, all packages within this repository have their versions synced. Therefore, if there are any releases or updates to a package, we will bump all packages.
Check out the release notes associated with each tagged versions in the releases page.
Release Type | Version Pattern | Command | |
---|---|---|---|
Current / Stable | 0.0.0 | npm install otplib | |
Release Candidate | 0.0.0-0 | npm install otplib@next |
v12.x is a huge architectural and language rewrite. Please check out the docs if you are migrating. A preset adapter is available to provide methods that behave like
v11.x
ofotplib
.
// Update
import { authenticator } from 'otplib'; // v11.x
// to
import { authenticator } from '@otplib/preset-v11';
// There should be no changes to your current code.
// However, deprecated or modified class methods will have console.warn.
All instantiated classes will have their options inherited from their respective options
generator. i.e. HOTP from hotpOptions
, TOTP from totpOptions
and Authenticator from authenticatorOptions
.
All OTP classes have an object setter and getter method to override these default options.
For example,
import { authenticator, totp, hotp } from 'otplib';
// setting
authenticator.options = { digits: 6 };
totp.options = { digits: 6 };
hotp.options = { digits: 6 };
// getting
const opts = authenticator.options;
const opts = totp.options;
const opts = hotp.options;
// reset to default
authenticator.resetOptions();
totp.resetOptions();
hotp.resetOptions();
// getting all options, with validation
// and backfilled with library defaults
const opts = authenticator.allOptions();
const opts = totp.allOptions();
const opts = hotp.allOptions();
Option | Type | Description |
---|---|---|
algorithm | string | The algorithm used for calculating the HMAC. |
createDigest | function | Creates the digest which token is derived from. |
createHmacKey | function | Formats the secret into a HMAC key, applying transformations (like padding) where needed. |
digest | string | USE WITH CAUTION. Same digest = same token. Used in cases where digest is generated externally. (eg: async use cases) |
digits | integer | The length of the token. |
encoding | string | The encoding that was used on the secret. |
// HOTP defaults
{
algorithm: 'sha1'
createDigest: undefined, // to be provided via a @otplib/plugin-*
createHmacKey: hotpCreateHmacKey,
digits: 6,
encoding: 'ascii',
}
Note: Includes all HOTP Options
Option | Type | Description |
---|---|---|
epoch | integer | USE WITH CAUTION. Same epoch = same token. Starting time since the UNIX epoch (seconds). Epoch is JavaScript formatted. i.e. Date.now() or UNIX time * 1000 |
step | integer | Time step (seconds) |
window | integer, [number, number] | Tokens in the previous and future x-windows that should be considered valid. If integer, same value will be used for both. Alternatively, define array: [past, future] |
// TOTP defaults
{
// ...includes all HOTP defaults
createHmacKey: totpCreateHmacKey,
epoch: Date.now(),
step: 30,
window: 0,
}
Note: Includes all HOTP + TOTP Options
Option | Type | Description |
---|---|---|
createRandomBytes | function | Creates a random string containing the defined number of bytes to be used in generating a secret key. |
keyEncoder | function | Encodes a secret key into a Base32 string before it is sent to the user (in QR Code etc). |
keyDecoder | function | Decodes the Base32 string given by the user into a secret. |
// Authenticator defaults
{
// ...includes all HOTP + TOTP defaults
encoding: 'hex',
createRandomBytes: undefined, // to be provided via a @otplib/plugin-*
keyEncoder: undefined, // to be provided via a @otplib/plugin-*
keyDecoder: undefined, // to be provided via a @otplib/plugin-*
}
TypeScript
support was introduced in v10.0.0
, which added type definitions over .js
files.
As of v12.0.0
, the library has been re-written in Typescript from the ground up.
async
support was introduced in v12.0.0
as an additional core library.
This was added as some libraries like expo.io or even the browser API (window.Crypto.subtle) started providing only async methods.
You to find more details in the core-async folder.
@otplib/preset-browser
is a umd
bundle with some node modules replaced to reduce the browser size.
The approximate size for the optimised, minified + gzipped bundle is 9.53KB.
Paired with the gzipped browser buffer.js
module, it would be about 7.65KB + 9.53KB = 17.18KB
.
For more details, please refer to the @otplib/preset-browser documentation.
In RFC 6238, the secret / seed length for different algorithms are predefined:
HMAC-SHA1 - 20 bytes
HMAC-SHA256 - 32 bytes
HMAC-SHA512 - 64 bytes
As such, the length of the secret provided (after any decoding) will be padded and sliced according to the expected length for respective algorithms.
The default encoding option has been set to hex
(Authenticator) instead of ascii
(TOTP).
Note: RFC4648 obseletes RFC 3548. Any encoders following the newer specifications will work.
Google Authenticator requires keys to be base32 encoded. It also requires the base32 encoder to be RFC 3548 compliant.
OTP calculation will still work should you want to use other base32 encoding methods (like Crockford's Base32) but it will NOT be compatible with Google Authenticator.
const secret = authenticator.generateSecret(); // base32 encoded hex secret key
const token = authenticator.generate(secret);
You may want to generate and display a QR Code so that users can scan
instead of manually entering the secret. Google Authenticator and similar apps
take in a QR code that holds a URL with the protocol otpauth://
,
which you get from authenticator.keyuri
.
Google Authenticator will ignore the algorithm
, digits
, and step
options.
See the keyuri documentation
for more information.
If you are using a different authenticator app, check the documentation for that app to see if any options are ignored, which will result in invalid tokens.
While this library provides the "otpauth" uri, you'll need a library to generate the QR Code image.
An example is shown below:
// npm install qrcode
import qrcode from 'qrcode';
import { authenticator } from '@otplib/preset-default';
const user = 'A user name, possibly an email';
const service = 'A service name';
// v11.x and above
const otpauth = authenticator.keyuri(user, service, secret);
// v10.x and below
const otpauth = authenticator.keyuri(
encodeURIComponent(user),
encodeURIComponent(service),
secret
);
qrcode.toDataURL(otpauth, (err, imageUrl) => {
if (err) {
console.log('Error with QR');
return;
}
console.log(imageUrl);
});
Note: For versions
v10.x
and below,keyuri
does not URI encodeuser
andservice
. You'll need to do so before passing in the parameteres.
Helper methods for getting the remaining time and used time within a validity period
of a totp
or authenticator
token were introduced in v10.0.0
.
authenticator.timeUsed(); // or totp.timeUsed();
authenticator.timeRemaining(); // or totp.timeRemaining();
// The start of a new token would be when:
// - timeUsed() === 0
// - timeRemaining() === step
Expo contains modified crypto implmentations targeted at the platform.
While otplib
does not provide an expo
specified package, with the re-architecture
of otplib
, you can now provide an expo native createDigest
to the library.
Alternatively, you can make use of crypto provided by @otplib/plugin-crypto-js
or
the bundled browser umd module @otplib/preset-browser
.
Pull Requests are much welcomed for a native expo implementation as well.
If you'll like to explore the library with local-repl
you can do so as well.
# after cloning the repo:
npm run setup
npm run build
npx local-repl
# You should see something like:
# Node v8.9.4, local-repl 4.0.0
# otplib 10.0.0
# Context: otplib
# [otplib] >
[otplib] > secret = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD'
[otplib] > otplib.authenticator.generate(secret)
It is common for services to also provide a set of backup codes to authenticate and bypass the OTP step in the event that you are not able to access your 2FA device or have misplaced the device.
As this process is separate from the specifications for OTP, this library does not provide any backup code related verification logic, and thus would have to be implemented separately.
Thanks goes to these wonderful people (emoji key):
Gerald Yeo 💻 📖 🚧 ⚠️ | Oliver Schneider 📖 | Marc-Aurèle DARCHE 📖 | Ahmed Hamdy (@shakram02) 📖 | Tony Brix 💻 📖 | Plai 📖 |
This project follows the all-contributors specification. Contributions of any kind welcome!
otplib
is MIT licensed
FAQs
HMAC-based (HOTP) and Time-based (TOTP) One-Time Password library
The npm package otplib receives a total of 396,803 weekly downloads. As such, otplib popularity was classified as popular.
We found that otplib demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.