{"_rev":"4-fdad91b1ab83c1aa0cb677d56c40079d","time":{"created":"2024-07-16T10:43:38.645Z","modified":"2024-07-16T10:43:39.191Z","1.0.0":"2024-07-16T09:23:42.596Z","1.0.1":"2024-07-16T10:29:23.402Z","1.0.2":"2024-07-16T10:38:18.385Z","1.0.3":"2024-07-16T10:43:38.896Z"},"_id":"@ahextechnology/otp-generator","name":"@ahextechnology/otp-generator","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.3":{"name":"@ahextechnology/otp-generator","version":"1.0.3","description":"Repository containing Node.js code for TOTP and HOTP implementations for secure two-factor authentication.","main":"index.js","scripts":{"start":"node index.js"},"repository":{"type":"git","url":"git+https://github.com/Maneesha7390/ahex-OTP-generator.git"},"keywords":["TOTP","HOTP"],"author":{"name":"Maneesha Padavala"},"license":"ISC","bugs":{"url":"https://github.com/Maneesha7390/ahex-OTP-generator/issues"},"homepage":"https://github.com/Maneesha7390/ahex-OTP-generator#readme","dependencies":{"crypto":"^1.0.1"},"devDependencies":{},"_id":"@ahextechnology/otp-generator@1.0.3","gitHead":"311a4374b41823c4262d2430f35a5d31da5fca5c","_nodeVersion":"20.15.0","_npmVersion":"10.7.0","dist":{"integrity":"sha512-I8QK64AzArp13n4Z8TvKjgPxeENegMNxaNn59MBKoNtjVlCAFajNk9bYlXj1gz0kirU1ODL9JdSfL/WDTioeDw==","shasum":"5d90dce4046c5cf5ed458829424842e146e8b71d","tarball":"https://registry.npmjs.org/@ahextechnology/otp-generator/-/otp-generator-1.0.3.tgz","fileCount":3,"unpackedSize":8313,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBWmXKmlZrRobQePniwo+8Zx+5Cv58grGIICws5n5TovAiAVvt4xhee2+/izbD5vMC0FRJ76H8qXB8dBmzT5q76Fig=="}]},"_npmUser":{"name":"maneeshapadavala","email":"maneesha.p@ahex.co.in"},"directories":{},"maintainers":[{"name":"shivam30","email":"shivam@ahex.co.in"},{"name":"maneeshapadavala","email":"maneesha.p@ahex.co.in"},{"name":"saurabh.ahex","email":"saurabh@ahex.co.in"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/otp-generator_1.0.3_1721126618746_0.0792622338854938"},"_hasShrinkwrap":false}},"maintainers":[{"name":"shivam30","email":"shivam@ahex.co.in"},{"name":"maneeshapadavala","email":"maneesha.p@ahex.co.in"},{"name":"saurabh.ahex","email":"saurabh@ahex.co.in"}],"description":"Repository containing Node.js code for TOTP and HOTP implementations for secure two-factor authentication.","homepage":"https://github.com/Maneesha7390/ahex-OTP-generator#readme","keywords":["TOTP","HOTP"],"repository":{"type":"git","url":"git+https://github.com/Maneesha7390/ahex-OTP-generator.git"},"author":{"name":"Maneesha Padavala"},"bugs":{"url":"https://github.com/Maneesha7390/ahex-OTP-generator/issues"},"license":"ISC","readme":"\r\n# TOTP and HOTP Implementation\r\n\r\nThis package provides functionality to generate and verify Time-based One-Time Passwords (TOTP) and HMAC-based One-Time Passwords (HOTP) using the `crypto` module in Node.js. The implementation follows the RFC 4226 (HOTP) and RFC 6238 (TOTP) standards.\r\n\r\n## Installation\r\n\r\nTo use this package, you need to have Node.js installed. You can include this code in your project by copying the provided functions into a file, or by creating a module.\r\n\r\n## Usage\r\n\r\n### Configuration\r\n\r\nYou can configure the number of bytes, encoding, algorithm, number of digits, and step as needed:\r\n\r\n``` javascript\r\nconst crypto = require('crypto');\r\nlet bytes = 10;\r\nlet encoding = 'base64';\r\nlet algorithm = 'sha1';\r\nlet digits = 6;\r\nlet step = 30;\r\n```\r\n\r\n### Functions\r\n\r\n#### `generateSecret()`\r\n\r\nGenerates a secret key for TOTP/HOTP.\r\n\r\n``` javascript\r\nfunction generateSecret() {\r\n  const secret = crypto.randomBytes(bytes).toString(encoding);\r\n  return secret;\r\n}\r\n```\r\n\r\n#### `generateTOTP(secret, time = null, digits, step)`\r\n\r\nGenerates a TOTP based on the provided secret, time, number of digits, and step.\r\n\r\n``` javascript\r\nfunction generateTOTP(secret, time = null, digits, step) {\r\n  const currentTime = time || Date.now();\r\n  const timeInSeconds = Math.floor(currentTime / 1000);\r\n  const counter = Buffer.alloc(8);\r\n  let timeCounter = Math.floor(timeInSeconds / step);\r\n\r\n  for (let i = counter.length - 1; i >= 0; i--) {\r\n    counter[i] = timeCounter & 0xff;\r\n    timeCounter = Math.floor(timeCounter / 256);\r\n  }\r\n\r\n  const hmac = crypto.createHmac(algorithm, Buffer.from(secret, encoding));\r\n  hmac.update(counter);\r\n  const hash = hmac.digest();\r\n\r\n  const offset = hash[hash.length - 1] & 0xf;\r\n  const binary =\r\n    ((hash[offset] & 0x7f) << 24) |\r\n    ((hash[offset + 1] & 0xff) << 16) |\r\n    ((hash[offset + 2] & 0xff) << 8) |\r\n    (hash[offset + 3] & 0xff);\r\n\r\n  const mod = Math.pow(10, digits);\r\n  const otp = binary % mod;\r\n  return otp.toString().padStart(digits, '0');\r\n}\r\n```\r\n\r\n#### `verifyTOTP(secret, token, window = 0, digits, step)`\r\n\r\nVerifies a TOTP based on the provided secret, token, window, number of digits, and step.\r\n\r\n``` javascript\r\nfunction verifyTOTP(secret, token, window = 0, digits, step) {\r\n  const currentTime = Math.floor(Date.now() / 1000);\r\n  for (let i = -window; i <= window; i++) {\r\n    const adjustedTime = currentTime + i * step;\r\n    const totp = generateTOTP(secret, adjustedTime * 1000, digits, step);\r\n    if (token === totp) {\r\n      return true;\r\n    }\r\n  }\r\n  return false;\r\n}\r\n```\r\n\r\n#### `generateHOTP(secret, counter, digits)`\r\n\r\nGenerates an HOTP based on the provided secret, counter, and number of digits.\r\n\r\n``` javascript\r\nfunction generateHOTP(secret, counter, digits) {\r\n  const hmac = crypto.createHmac(algorithm, Buffer.from(secret, encoding));\r\n  const counterBuffer = Buffer.alloc(8);\r\n  counterBuffer.writeUIntBE(counter, 0, 8);\r\n  hmac.update(counterBuffer);\r\n  const hash = hmac.digest();\r\n\r\n  const offset = hash[hash.length - 1] & 0xf;\r\n  const binary =\r\n    ((hash[offset] & 0x7f) << 24) |\r\n    ((hash[offset + 1] & 0xff) << 16) |\r\n    ((hash[offset + 2] & 0xff) << 8) |\r\n    (hash[offset + 3] & 0xff);\r\n\r\n  const mod = Math.pow(10, digits);\r\n  const otp = binary % mod;\r\n  return otp.toString().padStart(digits, '0');\r\n}\r\n```\r\n\r\n#### `verifyHOTP(secret, token, counter, digits)`\r\n\r\nVerifies an HOTP based on the provided secret, token, counter, and number of digits.\r\n\r\n``` javascript\r\nfunction verifyHOTP(secret, token, counter, digits) {\r\n  const hotp = generateHOTP(secret, counter, digits);\r\n  return token === hotp;\r\n}\r\n```\r\n\r\n### Example Usage\r\n\r\n``` javascript\r\nconst {\r\n  generateSecret,\r\n  generateTOTP,\r\n  verifyTOTP,\r\n  generateHOTP,\r\n  verifyHOTP,\r\n} = require('./path/to/this/module');\r\n\r\nconst secret = generateSecret();\r\nconsole.log('Secret:', secret);\r\n\r\nconst totp = generateTOTP(secret, null, digits, step);\r\nconsole.log('TOTP:', totp);\r\n\r\nconst isValidTOTP = verifyTOTP(secret, totp, 1, digits, step);\r\nconsole.log('Is valid TOTP:', isValidTOTP);\r\n\r\nconst hotp = generateHOTP(secret, 1, digits);\r\nconsole.log('HOTP:', hotp);\r\n\r\nconst isValidHOTP = verifyHOTP(secret, hotp, 1, digits);\r\nconsole.log('Is valid HOTP:', isValidHOTP);\r\n```\r\n\r\n### Explanation\r\n\r\n1. **Why 8 Bytes for the Counter?**\r\n   - The HOTP and TOTP algorithms specify that the counter value used in the HMAC computation should be an 8-byte (64-bit) integer. This allows a very high number of possible one-time passwords and ensures that the counter can support a large range of values.\r\n\r\n2. **Why `Math.pow(10, digits)`?**\r\n   - The base `10` is used because we are generating numeric OTPs. Raising `10` to the power of `digits` (e.g., 6) gives the range within which the OTP should fall (e.g., 0 to 999999 for a 6-digit OTP).\r\n\r\n## License\r\n\r\nThis module is available under the [MIT License](LICENSE).\r\n","readmeFilename":"README.md"}