|
|
@@ -10,6 +10,7 @@ export interface ToTpGeneratorOptions {
|
|
|
algorithm?: TotpAlgorithm;
|
|
|
label?: string;
|
|
|
secretLength?: number;
|
|
|
+ secret?: string;
|
|
|
issuer: string;
|
|
|
}
|
|
|
|
|
|
@@ -71,15 +72,18 @@ export class TotpChecker {
|
|
|
return TotpChecker.DoGenerateCode(totpSecret, this.getCurrentPeriod(period), digits || 6, algorithm || "SHA-1").shift()!;
|
|
|
}
|
|
|
|
|
|
+ public static GenerateSecret(secretLength?:number) {
|
|
|
+ secretLength = secretLength || 13;
|
|
|
+ return Array.from(crypto.randomBytes(secretLength)).map(x => RFC_4648[x % RFC_4648.length]).join("");
|
|
|
+ }
|
|
|
public static GenerateUrl(optionsOrIssuer: ToTpGeneratorOptions | string): ToTpSecretAndUrl {
|
|
|
let options: ToTpGeneratorOptions = typeof optionsOrIssuer === "string" ? { issuer: optionsOrIssuer } : optionsOrIssuer;
|
|
|
options.digits = options.digits || 6;
|
|
|
options.period = options.period || 30;
|
|
|
options.algorithm = options.algorithm || "SHA-1";
|
|
|
options.label = encodeURIComponent(options.label || options.issuer);
|
|
|
- options.secretLength = options.secretLength || 13;
|
|
|
|
|
|
- const secretStr = Array.from(crypto.randomBytes(options.secretLength)).map(x => RFC_4648[x % RFC_4648.length]).join("");
|
|
|
+ const secretStr = options.secret || TotpChecker.GenerateSecret(options.secretLength || 13)
|
|
|
return {
|
|
|
url: `otpauth://totp/${options.issuer}?issuer=${options.issuer}&secret=${secretStr}&digits=${options.digits}&period=${options.period}&algorithm=${options.algorithm}`,
|
|
|
secret: secretStr
|