speakeasy
speakeasy copied to clipboard
"list" argument must be an Array of Buffers
The following code is throwing an error "list" argument must be an Array of Buffers
speakeasy.hotp({ secret: 'ir6jqgomwnldmrhn', encoding: 'base32', counter: speakeasy._counter({}) })
I am doing this in an angular 5 app.
Having the same exact error in a React app on the verify.
I got the same issue when I used 'base32' as encoding. Use 'ascii' or any other encoding. This is issue is caused because of this code:
if (!Buffer.isBuffer(secret)) {
secret = encoding === 'base32' ? base32.decode(secret)
: new Buffer(secret, encoding);
}
which makes the key string to buffer for further processing(creating hmac which needs 'secret'/'key' to be buffer ). As of now, I would suggest trying other encoding options.
Hi @blackhawkbigpunch , The point is that the key is generated at the server side and it is base32. The client must generate the correct topt and send it to the server for validation. I have to use base32 encoding.
I had the same issue but resolved it by using master. The last released version is over 2 years old.
Is speakeasy not supported anymore. Last update was a while ago
The point is that the key is generated at the server side and it is base32. The client must generate the correct topt and send it to the server for validation. I have to use base32 encoding.
@amreladawy you don't. It's just an encoding. You can let the server create a hex version of the same secret and use that on the client. I just had to do that to use the same secret in cypress testing code that runs in the browser.
On the server:
require('base32.js').decode('ir6jqgomwnldmrhn').toString('hex')
'447c9819ccb3563644ed'
Now you can do that on the client
speakeasy.hotp({
secret: '447c9819ccb3563644ed',
encoding: 'hex',
counter: speakeasy._counter({})
})
Thanks @Prinzhorn
Due to the long time it took to get a reply on this, I switched to jssha https://github.com/Caligatio/jsSHA which I had to use specific version 1.6.0
to get it working.
const generateGoogleCode = secret => {
const secretAscii = base32.decode(secret);
const secretHex = toHex(secretAscii);
const code = speakeasy.totp({
secret: secretHex,
algorithm: 'sha1',
encoding: 'hex'
});
return code;
};
convert the base32 secret to ascii, then convert to hex, it will work
Solved, In "node_modules/speakeasy/index.js" replace from line 39 to 41 with this code
if (!Buffer.isBuffer(secret)) {
secret = encoding === 'base32' ? new Buffer(base32.decode(secret)) : new Buffer(secret, encoding);
}
In case anyone had an issues with this. I used @ygweric code more or less but here I added full code (with dependencies and toHex implementation). For base32 decoding, I used `hi-base32: "^0.5.0" in my package.json
const secret = "...."; // retrieved from server as string in base32
const base32 = require('hi-base32');
const secretAscii = base32.decode(secret);
const secretHex = toHex(secretAscii);
const totp = speakeasy.totp({secret: secretHex, encoding: 'hex'});
function toHex(str) {
let result = '';
for (let i = 0; i < str.length; i++) {
result += str.charCodeAt(i).toString(16);
}
return result;
}
@mustapha1509 thanks it worked for me