const totp = require('./totp'); console.log('=== TOTP Implementation Test Suite ===\n'); function runTests() { // 1. Basic Functionality Tests console.log('1. Basic Functionality Tests:'); const testSecret = 'JBSWY3DPEHPK3PXP'; const testTime = 1623456789000; // Fixed timestamp for consistent testing try { const code = totp.generate(testTime, testSecret); console.log('Generate TOTP code:'); console.log(` Secret: ${testSecret}`); console.log(` Time: ${new Date(testTime).toISOString()}`); console.log(` Code: ${code}`); console.log(` Length: ${code.length} digits`); console.log(' Result: ✓ (Generated successfully)\n'); } catch (error) { console.log(` Result: ✗ (${error.message})\n`); } // 2. Verification Tests console.log('2. Verification Tests:'); const currentCode = totp.now(testSecret); const verifyResults = [ totp.verify(currentCode, testSecret), totp.verify('000000', testSecret), totp.verify(currentCode, 'WRONGSECRET') ]; console.log('Verify current code:'); console.log(` Code: ${currentCode}`); console.log(` Valid code: ${verifyResults[0] ? '✓' : '✗'}`); console.log(` Invalid code: ${!verifyResults[1] ? '✓' : '✗'}`); console.log(` Wrong secret: ${!verifyResults[2] ? '✓' : '✗'}\n`); // 3. Configuration Tests console.log('3. Configuration Tests:'); const configs = [ { digits: 8 }, { interval: 60 }, { algorithm: 'SHA-256' } ]; configs.forEach(config => { try { const code = totp.generate(testTime, testSecret, config); console.log(`Custom config (${Object.keys(config)[0]}=${Object.values(config)[0]}):`); console.log(` Code: ${code}`); console.log(' Result: ✓\n'); } catch (error) { console.log(`Custom config (${Object.keys(config)[0]}=${Object.values(config)[0]}):`); console.log(` Result: ✗ (${error.message})\n`); } }); // 4. Error Handling Tests console.log('4. Error Handling Tests:'); const errorTests = [ ['Invalid secret', () => totp.generate(testTime, '')], ['Invalid digits', () => totp.generate(testTime, testSecret, { digits: 4 })], ['Invalid interval', () => totp.generate(testTime, testSecret, { interval: -1 })], ['Invalid algorithm', () => totp.generate(testTime, testSecret, { algorithm: 'INVALID' })] ]; errorTests.forEach(([name, test]) => { try { test(); console.log(`${name}: ✗ (Should have thrown)`); } catch (error) { console.log(`${name}: ✓ (${error.type})`); } }); console.log(''); // 5. URI Generation Test console.log('5. URI Generation Test:'); try { const uri = totp.generateUri( testSecret, 'test@example.com', 'TestApp', { digits: 8, interval: 60 } ); console.log('Generated URI:'); console.log(` ${uri}`); console.log(' Result: ✓\n'); } catch (error) { console.log(` Result: ✗ (${error.message})\n`); } // 6. Time Window Tests console.log('6. Time Window Tests:'); const remaining = totp.timeRemaining(); console.log(`Time until next code: ${remaining} seconds`); // Test window verification const currentTime = Date.now(); const pastCode = totp.generate(currentTime - 30000, testSecret); const futureCode = totp.generate(currentTime + 30000, testSecret); console.log('Time window verification:'); console.log(` Past code valid: ${totp.verify(pastCode, testSecret, { window: 1 }) ? '✓' : '✗'}`); console.log(` Future code valid: ${totp.verify(futureCode, testSecret, { window: 1 }) ? '✓' : '✗'}`); console.log(` Outside window invalid: ${!totp.verify(pastCode, testSecret, { window: 0 }) ? '✓' : '✗'}\n`); // 7. Security Tests console.log('7. Security Tests:'); // Test timing attack resistance const start = Date.now(); for (let i = 0; i < 1000; i++) { totp.verify('000000', testSecret); totp.verify('999999', testSecret); } const end = Date.now(); const timeDiff = Math.abs((end - start) / 2000); console.log('Timing attack resistance:'); console.log(` Average verification time: ${timeDiff.toFixed(3)}ms`); console.log(` Time consistency: ${timeDiff < 1 ? '✓' : '✗'}`); } // Run all tests runTests();