From 3c56d28f1630498ce709fc6d44312155fc42e30a Mon Sep 17 00:00:00 2001 From: Havard Wall Date: Sat, 25 Jul 2015 11:59:38 +0200 Subject: [PATCH] Fix hotp zero-padding bug Numbers with fewer digits than the required length would be truncated. This fix ensures proper padding. --- lib/speakeasy.js | 32 ++++++++++++++++++++++++++------ test/test_hotp.js | 11 +++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/speakeasy.js b/lib/speakeasy.js index 3e9693b..2ad9102 100644 --- a/lib/speakeasy.js +++ b/lib/speakeasy.js @@ -92,13 +92,8 @@ speakeasy.hotp = function(options) { |(digest_bytes[offset+2] & 0xff) << 8 |(digest_bytes[offset+3] & 0xff); - bin_code = bin_code.toString(); + var code = speakeasy.bin_to_string(bin_code, length); - // get the chars at position bin_code - length through length chars - var sub_start = bin_code.length - length; - var code = bin_code.substr(sub_start, length); - - // we now have a code with `length` number of digits, so return it return(code); } @@ -141,6 +136,31 @@ speakeasy.totp = function(options) { return(code); } +// speakeasy.bin_to_string(bin, length) +// +// helper function to convert a number to a string of given length. +// +speakeasy.bin_to_string = function(bin, length) { + var bin_str = bin.toString(); + + if (bin_str.length < length) { + // pad with 0's + var pad = ''; + var padLength = length - bin_str.length; + for (var j = 0; j < padLength; ++j) { + pad += '0'; + } + + return pad + bin_str; + } else { + // get the chars at position bin_code - length through length chars + var sub_start = bin_str.length - length; + var code = bin_str.substr(sub_start, length); + + return code; + } +} + // speakeasy.hex_to_ascii(key) // // helper function to convert a hex key to ascii. diff --git a/test/test_hotp.js b/test/test_hotp.js index 7f2e39e..1f3a379 100644 --- a/test/test_hotp.js +++ b/test/test_hotp.js @@ -56,4 +56,15 @@ vows.describe('HOTP Counter-Based Algorithm Test').addBatch({ assert.equal(topic, '338314'); } }, + + 'Test 0-padding encoding with key = \'h/,Iv]ET34!].kfNUU^Nf!I#gp1bNT1C\' at counter 3 and length = 8': { + topic: function() { + return speakeasy.hotp({key: 'h/,Iv]ET34!].kfNUU^Nf!I#gp1bNT1C', length: 8, counter: 3}); + }, + + 'correct one-time password returned': function(topic) { + assert.equal(topic, '05314231'); + } + }, + }).exportTo(module);