-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ccfe9ab
Showing
13 changed files
with
4,453 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"presets": [ | ||
[ | ||
"@babel/preset-env", | ||
{ | ||
"targets": "> 0.25%, not dead, not op_mini >=0" | ||
} | ||
], | ||
"@babel/preset-typescript" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module.exports = { | ||
env: { | ||
browser: true, | ||
es6: true, | ||
node: true, | ||
}, | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/eslint-recommended', | ||
'plugin:prettier/recommended', | ||
], | ||
globals: { | ||
Atomics: 'readonly', | ||
SharedArrayBuffer: 'readonly', | ||
}, | ||
parser: '@typescript-eslint/parser', | ||
parserOptions: { | ||
ecmaVersion: 11, | ||
sourceType: 'module', | ||
}, | ||
plugins: ['@typescript-eslint', 'prettier'], | ||
rules: { | ||
indent: ['error', 2], | ||
'linebreak-style': ['error', 'unix'], | ||
quotes: ['error', 'single'], | ||
semi: ['error', 'always'], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
dist | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"bracketSpacing": false, | ||
"singleQuote": true, | ||
"printWidth": 80, | ||
"trailingComma": "all" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
const SIMILAR_CHAR = { | ||
O: '0', | ||
I: '1', | ||
L: '1', | ||
B: '8', | ||
}; | ||
|
||
const CASTABLE_CHAR = { | ||
O: 'W', | ||
I: 'X', | ||
L: 'Y', | ||
B: 'Z', | ||
}; | ||
|
||
class Base32OTP { | ||
readonly digits: number; | ||
readonly outputDigits: number; | ||
|
||
constructor(digits = 6) { | ||
this.digits = digits; | ||
this.outputDigits = Number(Math.pow(10, digits) - 1).toString(32).length; | ||
} | ||
|
||
encode(rawCode: number | string) { | ||
if ( | ||
typeof rawCode === 'string' && | ||
(!/^\d+$/.test(rawCode) || rawCode.length > this.digits) | ||
) | ||
throw new Error('Invalid code passed'); | ||
|
||
let code = Number(rawCode).toString(32).toUpperCase(); | ||
|
||
Object.keys(CASTABLE_CHAR).forEach(function (badLetter) { | ||
code = code.replace( | ||
new RegExp(badLetter, 'g'), | ||
|
||
CASTABLE_CHAR[<keyof typeof CASTABLE_CHAR>badLetter], | ||
); | ||
}); | ||
|
||
const template = Array.from({length: this.outputDigits}, function () { | ||
return '0'; | ||
}); | ||
|
||
return Object.assign(template, code.split('').reverse()).reverse().join(''); | ||
} | ||
|
||
decode(rawCode: string) { | ||
if ( | ||
/^\d+$/.test(rawCode) && | ||
rawCode.length === this.digits && | ||
rawCode.length !== this.outputDigits | ||
) | ||
return rawCode; | ||
|
||
if (!/^[\dA-Za-z]+$/.test(rawCode) || rawCode.length !== this.outputDigits) | ||
throw new Error( | ||
'Code should be ' + this.outputDigits + ' alphanumeric characters', | ||
); | ||
|
||
let code = rawCode.toUpperCase(); | ||
|
||
Object.keys(SIMILAR_CHAR).forEach(function (badLetter) { | ||
code = code.replace( | ||
new RegExp(badLetter, 'g'), | ||
|
||
SIMILAR_CHAR[<keyof typeof SIMILAR_CHAR>badLetter], | ||
); | ||
}); | ||
|
||
Object.keys(CASTABLE_CHAR).forEach(function (badLetter) { | ||
code = code.replace( | ||
new RegExp(CASTABLE_CHAR[<keyof typeof CASTABLE_CHAR>badLetter], 'g'), | ||
|
||
badLetter, | ||
); | ||
}); | ||
|
||
const template = Array.from({length: this.digits}, () => '0'); | ||
|
||
code = parseInt(code, 32).toString(10); | ||
|
||
return Object.assign(template, code.split('').reverse()).reverse().join(''); | ||
} | ||
} | ||
|
||
export default Base32OTP; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2020 Russell Steadman | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Basic32 | ||
|
||
Basic32 encodes and decodes OTP (One-time passcode) tokens to and from a standard length Base32 string, effectively making them shorter. | ||
|
||
## Why? | ||
|
||
Basic32 decreases the number of characters needed for a OTP code, making the code easier for users to remember. | ||
|
||
| Regular TOTP | Encoded TOTP | | ||
| ------------ | ------------ | | ||
| 6 digits | 4 chars | | ||
| 7 digits | 5 chars | | ||
| 8 digits | 6 chars | | ||
| 9 digits | 6 chars | | ||
|
||
## Installation | ||
|
||
```sh | ||
npm i basic32 | ||
``` | ||
|
||
```javascript | ||
import Basic32 from 'basic32'; | ||
``` | ||
|
||
## Usage | ||
|
||
```javascript | ||
import Basic32 from 'basic32'; | ||
|
||
/* Initialize the encoder */ | ||
const basic = new Basic32(/* Number of digits in OTP code, default: 6 */); | ||
|
||
/* Encode a number or string */ | ||
basic.encode(123456); // -> "3WX0" | ||
basic.encode('123456'); // -> "3WX0" | ||
|
||
/* Decode a string */ | ||
basic.decode('3WX0'); // -> "123456" | ||
|
||
/* Decode a string, but zero is switched with letter o */ | ||
basic.decode('3WXO'); // -> "123456" | ||
|
||
/* Decode the wrong number of characters */ | ||
basic.decode('3WX0A'); // -> new Error("Code should be 4 alphanumeric characters") | ||
|
||
/* Decode an already decoded string */ | ||
basic.decode('123456'); // -> "123456" | ||
``` | ||
|
||
## Character Corrections | ||
|
||
The following character transposition errors are automatically fixed. | ||
|
||
| User Writes | Interpreted | | ||
| ----------- | ----------- | | ||
| (Letter) O | (Number) 0 | | ||
| (Letter) I | (Number) 1 | | ||
| (Letter) L | (Number) 1 | | ||
| (Letter) B | (Number) 8 | | ||
|
||
## License | ||
|
||
MIT © 2020 [Russell Steadman](https://github.com/teamtofu). See LICENSE. |
Oops, something went wrong.