Showing
5 changed files
with
25 additions
and
20 deletions
| ... | @@ -20,49 +20,52 @@ const Authenticator = function (secret, options) { | ... | @@ -20,49 +20,52 @@ const Authenticator = function (secret, options) { |
| 20 | const TOTP_OPTIONS = this.totp_options = { | 20 | const TOTP_OPTIONS = this.totp_options = { |
| 21 | secret: this.secret, | 21 | secret: this.secret, |
| 22 | encoding: options.encoding || 'base32', | 22 | encoding: options.encoding || 'base32', |
| 23 | - step: options.step || 30 | 23 | + step: options.step || 30, |
| 24 | + algorithm: options.algorithm || 'sha512' | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | /** | 28 | /** |
| 28 | * 验证token有效性 | 29 | * 验证token有效性 |
| 29 | - * @type {Authenticator.verify} | 30 | + * @param token |
| 30 | */ | 31 | */ |
| 31 | - const verify = this.verify = function(token) { | 32 | + this.verify = function(token) { |
| 32 | return speakeasy.totp.verify(_.merge({token: token}, TOTP_OPTIONS)); | 33 | return speakeasy.totp.verify(_.merge({token: token}, TOTP_OPTIONS)); |
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | /** | 36 | /** |
| 36 | * 在options.window的范围内验证token的有效性 | 37 | * 在options.window的范围内验证token的有效性 |
| 37 | - * @type {Authenticator.verifyDelta} | 38 | + * @param token |
| 38 | */ | 39 | */ |
| 39 | - const verifyDelta = this.verifyDelta = function(token) { | 40 | + this.verifyDelta = function(token) { |
| 40 | return speakeasy.totp.verifyDelta(_.merge({token: token}, TOTP_OPTIONS)); | 41 | return speakeasy.totp.verifyDelta(_.merge({token: token}, TOTP_OPTIONS)); |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | /** | 44 | /** |
| 44 | * 获取QR显示值 | 45 | * 获取QR显示值 |
| 45 | - * @type {Authenticator.getOtpAuth} | 46 | + * @param title |
| 47 | + * @param issuer | ||
| 48 | + * @return {string} | ||
| 46 | */ | 49 | */ |
| 47 | - const getOtpAuth = this.getOtpAuth = function (title, issuer) { | 50 | + this.getOtpAuth = function (title, issuer) { |
| 48 | - let _title = title || 'HowAreU'; | 51 | + return speakeasy.otpauthURL(_.merge({ label: title, issuer: issuer }, TOTP_OPTIONS)); |
| 49 | - let _issuer = encodeURIComponent(issuer || 'TOTP-KEY'); | ||
| 50 | - return `otpauth://totp/${_title}?secret=${this.secret}&issuer=${_issuer}`; | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | /** | 54 | /** |
| 54 | * 生成svg的QR图片内容 | 55 | * 生成svg的QR图片内容 |
| 55 | - * @type {Authenticator.getQR} | 56 | + * @param title |
| 57 | + * @param issuer | ||
| 58 | + * @return {*} | ||
| 56 | */ | 59 | */ |
| 57 | - const getQR = this.getQR = function(title, issuer) { | 60 | + this.getQR = function(title, issuer) { |
| 58 | - return qr.imageSync(getOtpAuth(title, issuer), { type: 'svg' }); | 61 | + return qr.imageSync(this.getOtpAuth(title, issuer), { type: 'svg' }); |
| 59 | }; | 62 | }; |
| 60 | 63 | ||
| 61 | /** | 64 | /** |
| 62 | * 生成新的token | 65 | * 生成新的token |
| 63 | - * @type {Authenticator.totp} | 66 | + * @return {String} |
| 64 | */ | 67 | */ |
| 65 | - const totp = this.totp = function () { | 68 | + this.totp = function () { |
| 66 | return speakeasy.totp(_.merge({}, TOTP_OPTIONS)); | 69 | return speakeasy.totp(_.merge({}, TOTP_OPTIONS)); |
| 67 | }; | 70 | }; |
| 68 | 71 | ... | ... |
| ... | @@ -16,7 +16,8 @@ const TOTP = function (options) { | ... | @@ -16,7 +16,8 @@ const TOTP = function (options) { |
| 16 | 16 | ||
| 17 | const TOTP_OPTIONS = { | 17 | const TOTP_OPTIONS = { |
| 18 | encoding: options.encoding || 'base32', | 18 | encoding: options.encoding || 'base32', |
| 19 | - step: options.step || 30 | 19 | + step: options.step || 30, |
| 20 | + algorithm: options.algorithm || 'sha512' | ||
| 20 | }; | 21 | }; |
| 21 | 22 | ||
| 22 | /** | 23 | /** | ... | ... |
| ... | @@ -8,10 +8,9 @@ const fs = require('fs-extra'); | ... | @@ -8,10 +8,9 @@ const fs = require('fs-extra'); |
| 8 | const path = require('path'); | 8 | const path = require('path'); |
| 9 | 9 | ||
| 10 | let secret = 'vH6OdbUEjSukTqlDvW3TYdusjiOIkxRnAHNTjJewfZa5yNueG9wx1N9pJMFOmPAV'; | 10 | let secret = 'vH6OdbUEjSukTqlDvW3TYdusjiOIkxRnAHNTjJewfZa5yNueG9wx1N9pJMFOmPAV'; |
| 11 | -let authenticator = new Authenticator(secret); | 11 | +let authenticator = new Authenticator(secret, {algorithm: 'sha512'}); |
| 12 | - | ||
| 13 | console.log(chalk.cyan('totp的secret')); | 12 | console.log(chalk.cyan('totp的secret')); |
| 14 | -console.log(secret); | 13 | +console.log(secret, authenticator.totp_options); |
| 15 | 14 | ||
| 16 | let token = process.argv[2]; | 15 | let token = process.argv[2]; |
| 17 | if (!token) { | 16 | if (!token) { | ... | ... |
test/img/qr.svg
0 → 100644
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 51"><path d="M1 1h7v7h-7zM10 1h3v1h-1v1h-1v-1h-1zM15 1h1v1h-1zM17 1h1v1h-1zM19 1h1v1h2v-1h1v1h1v1h-2v1h-1v-1h-2v1h1v1h2v-1h3v1h1v-1h1v-1h2v1h-1v6h-1v1h-1v-1h-6v-1h-1v2h2v3h-2v2h-1v3h-1v-1h-2v-1h-1v-2h-1v-1h-1v-1h3v3h1v-3h1v1h1v-1h-1v-1h1v-1h-1v-2h1v-1h1v-2h-1v-4h1zM26 1h4v1h1v1h-2v-1h-3zM31 1h2v1h-2zM34 1h1v1h-1zM36 1h3v1h2v-1h1v3h-1v1h-1v-2h-2v-1h-1v2h-1v-1h-1v-1h1zM43 1h7v7h-7zM2 2v5h5v-5zM16 2h1v2h-1v1h-3v-1h1v-1h2zM25 2h1v2h-1zM44 2v5h5v-5zM3 3h3v3h-3zM9 3h2v2h2v1h-1v3h1v1h-2v-1h-2zM12 3h1v1h-1zM45 3h3v3h-3zM30 4h3v3h-1v-1h-1v1h-1zM34 4h1v1h-1zM37 4h2v2h1v3h-1v-2h-1v1h-1v-1h-1v1h-1v-1h-1v-1h2v-1h1zM10 6v2h1v-2zM14 6h1v1h-1zM16 6h2v2h-1v-1h-1zM20 6v2h1v-2zM22 6v2h1v-2zM24 6v3h3v-3zM13 7h1v1h1v-1h1v1h1v1h-1v3h-1v-1h-1v-1h1v-1h-2zM25 7h1v1h-1zM29 7h1v1h-1zM31 7h1v1h1v2h1v1h-2v2h1v1h1v1h-1v1h1v1h-3v-1h1v-1h-1v-1h-1v-1h1v-2h-1v2h-2v-1h1v-2h3v-1h-2v-1h1zM33 7h1v1h-1zM41 7h1v3h-2v-1h1zM36 8h1v1h-1zM1 9h1v1h1v1h-1v1h1v-1h1v1h1v1h-3v1h-1zM3 9h5v1h-1v1h-1v-1h-3zM37 9h1v1h-1zM43 9h5v1h-3v2h-1v-1h-1zM8 10h2v1h-2zM36 10h1v1h1v1h-1v1h1v-1h1v2h-2v2h-1v-3h-3v-1h1v-1h1v1h1zM38 10h1v1h-1zM7 11h1v1h-1zM11 11h2v1h-1v1h-1zM22 11h3v1h-2v1h2v-1h2v1h-1v1h1v1h-1v1h1v2h-2v1h-1v1h-2v-1h1v-1h1v-1h1v-2h-1v-1h-1v1h-1zM27 11h1v1h-1zM41 11h1v1h-1zM46 11h4v3h-1v1h1v1h-1v3h-1v-1h-1v-1h1v-2h-2v-2h2v-1h-2zM6 12h1v1h-1zM8 12h2v2h-1v-1h-1zM42 12h2v1h1v3h2v1h-3v-2h-2v-1h1v-1h-1zM45 12h1v1h-1zM7 13h1v1h-1zM27 13h1v1h-1zM40 13h1v1h-1zM2 14h3v1h-1v1h-2v1h1v1h1v3h-1v-1h-1v-1h-1v-4h1zM6 14h1v1h1v1h-1v1h1v1h-2v-1h-1v1h-1v-2h1v-1h1zM8 14h1v1h-1zM10 14h2v2h-1v-1h-1zM28 14h2v1h1v1h-2v-1h-1zM20 15h1v1h-1zM34 15h1v1h-1zM38 15h2v2h1v1h-2v1h1v1h-1v1h-1v-2h-1v-1h-1v-1h2zM8 16h2v2h-1v-1h-1zM12 16h1v1h-1zM19 16h1v2h1v6h1v1h1v-2h1v-1h-2v-1h5v1h-1v1h3v2h-1v1h1v1h1v-1h1v-1h1v-1h1v2h-1v3h1v1h-1v1h-1v-1h-1v-1h1v-1h-1v1h-1v1h1v1h-1v2h-2v-1h1v-2h-1v2h-1v2h3v-1h1v1h1v1h-1v1h-1v-1h-3v1h3v1h-2v2h-3v1h-1v-1h-1v-1h3v-1h-1v-1h-1v1h-1v-1h-1v-1h3v-1h1v-2h-1v-1h1v-1h-1v1h-2v3h-1v-1h-1v1h-1v1h-2v1h2v-1h1v1h1v1h-1v1h1v2h-1v-1h-1v2h-1v-2h-2v-1h3v-1h-3v-2h-2v-1h1v-2h-1v1h-1v-1h-2v-1h-1v2h-1v-2h-1v-1h1v-1h-1v-1h-2v3h-1v-2h-1v-1h1v-2h-1v-1h1v-2h-1v-1h1v-2h1v-1h3v2h-1v-1h-1v1h1v1h-1v1h1v-1h1v-1h1v1h1v1h1v2h-1v-1h-1v1h1v1h-1v2h1v-1h1v2h-2v1h2v1h1v-1h2v1h1v-2h2v1h1v-1h1v1h2v-1h-2v-2h1v1h1v-1h1v-1h-3v1h-1v-2h-1v-2h1v1h1v-3h-1v-1h-1v-1h1zM22 16h1v1h-1zM35 16h1v1h-1zM42 16h1v1h1v2h1v1h1v1h-1v2h1v3h1v-1h1v2h-2v1h-1v1h1v1h-4v-1h-1v-1h-1v1h-1v-1h-1v-1h3v-4h1v-1h-1v1h-1v-2h2v-1h1v-1h-1zM28 17h1v1h-1zM10 18h1v1h-1zM13 18h2v1h-1v1h-3v-1h2zM31 18h2v2h-1v3h-3v-1h2v-1h-2v1h-1v-2h-2v-1h3v1h2zM15 19h2v2h1v1h-2v-2h-1zM41 19h1v1h-1zM46 19h1v1h-1zM49 19h1v3h-3v-1h1v-1h1zM1 20h1v2h1v1h1v2h-1v1h1v1h-1v1h-1v-1h-1v-1h1v-3h-1zM10 20h1v1h-1zM14 20h1v1h-1zM33 20h1v1h-1zM35 20h1v2h-1zM11 21h2v1h-2zM37 21h1v1h1v1h-1v1h1v-1h1v2h-1v1h-3v-1h1zM13 22h3v1h-2v1h1v1h-1v1h-2v-1h1zM46 22h1v1h-1zM16 23h1v1h-1zM33 23h1v1h-1zM35 23h1v1h-1zM47 23h1v1h-1zM49 23h1v1h-1zM6 24v3h3v-3zM24 24v3h3v-3zM34 24h1v1h-1zM42 24v3h3v-3zM7 25h1v1h-1zM15 25h3v1h-2v1h-1zM25 25h1v1h-1zM43 25h1v1h-1zM33 26h1v1h1v2h-2zM13 27h1v1h-1zM16 27h1v1h-1zM18 27h1v1h-1zM48 27h2v1h-1v1h-1zM14 28h1v1h-1zM24 28v1h1v-1zM27 28v1h1v-1zM43 28v1h1v-1zM1 29h1v1h-1zM7 29h1v1h-1zM12 29h1v1h-1zM37 29h2v1h-1v2h-1zM40 29h1v1h1v1h-2zM47 29h1v1h-1zM49 29h1v1h-1zM2 30h1v1h1v1h-1v2h-1zM34 30h1v1h1v1h-1v1h-3v-1h2zM46 30h1v1h3v2h-2v-1h-1v1h1v1h-1v2h-4v-2h1v-1h2zM7 31h1v1h-1zM18 31v2h-1v-1h-1v2h2v-1h1v-1h2v-1zM39 31h1v1h-1zM42 31h3v1h-3zM4 32h3v1h1v1h-1v1h1v-1h1v1h2v1h-2v1h1v2h1v2h-2v1h-2v-1h1v-1h1v-1h-1v-1h-1v1h1v1h-2v-1h-1v-2h3v-1h-2v-1h-2zM23 32h1v2h-1zM30 32h1v1h-1zM10 33h3v3h1v1h1v1h-1v1h2v1h-3v-1h-2v-1h1v-1h-1v-1h1v-1h-1v-1h-1zM35 33h3v1h1v1h-1v1h-1v1h-1v-2h1v-1h-2zM39 33h3v3h-1v-1h-1v-1h-1zM32 34h1v1h-1zM45 34v1h1v-1zM1 35h1v1h-1zM31 35h1v1h-1zM34 35h1v1h-1zM39 35h1v2h2v-1h1v1h5v1h-1v1h1v-1h2v2h-4v-2h-1v3h3v1h-1v1h-1v4h-1v2h-2v-1h1v-1h-1v-1h-1v1h-2v-1h1v-1h-1v-1h1v-1h-1v-2h3v-1h-1v-1h2v-1h-3v2h-2v1h-1v1h-3v1h-1v-2h2v-1h2v-1h-1v-2h1v-1h1zM49 35h1v2h-2v-1h1zM3 36h1v1h-1zM30 36h1v1h-1zM32 36h2v1h-2zM1 37h2v1h-1v1h-1zM31 37h1v1h1v2h-1v-1h-2v-1h1zM34 37h1v1h-1zM28 38h1v1h1v1h-2zM39 38v1h1v-1zM2 39h1v1h2v1h-1v1h-3v-1h1zM35 39h1v1h-1zM22 40h1v1h-1zM24 40h2v1h1v-1h1v2h1v1h-1v1h2v-1h1v1h1v1h1v1h-1v1h-1v-1h-1v-1h-2v2h1v1h-1v1h-3v-1h-2v2h-7v-1h1v-1h1v1h4v-3h1v1h3v1h1v-1h-1v-1h-3v-1h-2v1h-2v-1h-1v1h1v1h2v1h-3v-1h-1v-1h-1v-1h1v-1h1v-1h2v-1h1v1h2v-2h1zM31 40h1v1h1v1h-1v1h-1v-1h-1v-1h1zM13 41h3v2h-2v-1h-1zM19 41h1v1h-1zM21 41h1v1h-1zM49 41h1v1h-1zM9 42h1v1h-1zM11 42h2v1h-2zM24 42v3h3v-3zM38 42h1v4h-1v1h2v2h-1v-1h-2v1h2v1h-3v-1h-1v1h-1v-3h1v1h1v-1h1v-1h-1v-2h1v1h1zM42 42v3h3v-3zM48 42h1v1h1v1h-1v2h-2v-1h1v-1h-1v-1h1zM1 43h7v7h-7zM10 43h1v1h1v1h-1v1h-1v2h-1v-4h1zM25 43h1v1h-1zM32 43h1v1h-1zM35 43h1v1h-1zM43 43h1v1h-1zM2 44v5h5v-5zM14 44h2v1h-1v1h-1zM3 45h3v3h-3zM12 45h1v1h-1zM49 46h1v1h-1zM13 47h1v2h1v1h-2v-1h-1v-1h1zM15 47h1v1h-1zM30 47h1v1h-1zM10 48h1v1h1v1h-3v-1h1zM31 48h1v1h1v1h-3v-1h1zM49 48h1v2h-2v-1h1zM24 49h1v1h-1zM28 49h1v1h-1zM40 49h1v1h-1zM42 49h1v1h-1zM46 49h1v1h-1z"/></svg> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -6,7 +6,8 @@ const TOTP = require('../lib/totp'); | ... | @@ -6,7 +6,8 @@ const TOTP = require('../lib/totp'); |
| 6 | const chalk = require('chalk'); | 6 | const chalk = require('chalk'); |
| 7 | const fs = require('fs-extra'); | 7 | const fs = require('fs-extra'); |
| 8 | 8 | ||
| 9 | -let totp = new TOTP(); | 9 | +let algorithm = process.argv[2] || 'sha512'; |
| 10 | +let totp = new TOTP({algorithm: algorithm}); | ||
| 10 | 11 | ||
| 11 | let secret = totp.createSecret(); | 12 | let secret = totp.createSecret(); |
| 12 | console.log(chalk.cyan('创建totp的secret')); | 13 | console.log(chalk.cyan('创建totp的secret')); | ... | ... |
-
Please register or login to post a comment