Reputation: 318
I'm trying to display different pieces of information from my BitStamp account onto a Google Spreadsheet. In order to do that Google Apps Script (GAS) is employed, with Javascript of course.
The error I get is a API0005 which, as you can see from BitStamp API reference page, stands for invalid signature:
API0005 Invalid signature Posted signature doesn't match with ours
Now, I've been gathering info from several sources, especially here on Stack, but can't quite figure out where the problem is.
There's something I noticed though, which I would like to highlight, as I guess the problem could have to do with that:
For ease of construction I use to append the main steps of the signature synthesis process onto the spreadsheet itself, so to have a better understanding of its development.
You will notice small changes in the nonce output even between a line of code and the next, each time the funcion is somehow called or invoked; and this doesnt surprise me because I guess that everytime nonce
is called some milliseconds have passed and the output must be different (after all it was purposely designed for that reason I guess).
But my first concern is: is it ok that it changes even when the toUpperCase()
conversion is called?
(And by the way this shouldn't be the cause of the problem anyway I guess)
var nonce = new (function() {
this.generate = function() {
var now = Date.now();
this.counter = (now === this.last? this.counter + 1 : 0);
this.last = now;
// add padding to nonce
var padding =
this.counter < 10 ? '000' :
this.counter < 100 ? '00' :
this.counter < 1000 ? '0' : '';
return now+padding+this.counter;
};
})();
//funzione write
function write() {
var cred = {
id:'digit2118',
key:'2RhZfUKIYJbT8CBYk6T27uRSF8Gufre',
secret:'T8CBYk6T274yyR8Z2RhZfUxbRbmZZHJ'
};
//adding some cells output to monitor each step of the "conversion"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("B14");
cell.setValue(cred.id);
// .. and so on, see screen cap..
var message = nonce.generate() + cred.id + cred.key;
var res = Utilities.computeHmacSha256Signature(cred.secret, message).map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
var signature = res.toUpperCase();
// qui mettiamo i dati per fare la comunicazione vera e propria
var data = {
key: cred.key,
signature: res,
nonce: nonce.generate()
};
var options = {
'method' : 'post',
//'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
//'payload' : JSON.stringify(data)
'muteHttpExceptions' : true,
'payload' : data
};
var risposta = UrlFetchApp.fetch('https://www.bitstamp.net/api/v2/balance/', options);
var risposta2 = JSON.parse(risposta.getContentText());
Logger.log(risposta2);
//Logger.log(risposta.getContentText());
return signature;
}//end of write();
Logger.log(write());
So in the end I can't see where, but that must be something I am missing.
(ps:this is where I got the Nonce code from: Generate Nonce,)
EDIT: Question Solved.
Updated code with problem & solution below.
Thanks to @Tanaike
Upvotes: 1
Views: 705
Reputation: 318
After incorporating the wise suggestion provided by @Tanaike, i.e. to correctly switch value
and key
in the Utilities.computeHmacSha256Signature(value, key)
command, things didn't work yet and I still used to get an Invalid Signature API0005 error.
Long story short, the problem was another oversight in the code:
I correctly switched the signature into toUpperCase()
but when it came to send the array to BitStamp, I used to send the lowercase version, which was res
instead of signature
:
var signature = res.toUpperCase();
// qui mettiamo i dati per fare la comunicazione vera e propria
var data = {
key: cred.key,
signature: res,
nonce: nonce.generate()
};
The detail has been fixed and now it's working fine! This is the complete and updated working code, for your consideration:
//funzione write
function write() {
/* nuova funzione nonce */
_generateNonce = function() {
var now = new Date().getTime();
if(now !== this.last)
this.nonceIncr = -1;
this.last = now;
this.nonceIncr++;
// add padding to nonce incr
// @link https://stackoverflow.com/questions/6823592/numbers-in-the-form-of-001
var padding =
this.nonceIncr < 10 ? '000' :
this.nonceIncr < 100 ? '00' :
this.nonceIncr < 1000 ? '0' : '';
return now + padding + this.nonceIncr;
}
var nonce = this._generateNonce(); //fine funzione
var cred = {
id:'digit2118',
key:'2RhZfUKIYJbT8CBYk6T27uRSF8Gufrer',
secret:'T8CBYk6T274yyR8Z2RhZfUxbRbmZZHJr'
};
var message = nonce + cred.id + cred.key;
var res = Utilities.computeHmacSha256Signature(message, cred.secret).map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
var signature = res.toUpperCase();
var data = {
key: cred.key,
signature: signature,
nonce: nonce
};
var options = {
'method' : 'post',
//'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
//'payload' : JSON.stringify(data)
'muteHttpExceptions' : true,
'payload' : data
};
var risposta = UrlFetchApp.fetch('https://www.bitstamp.net/api/v2/balance/', options);
var risposta2 = JSON.parse(risposta.getContentText());
var risposta3 = risposta2['usd_balance'];
Logger.log(risposta3);
return signature;
}//end of write();
Upvotes: 0
Reputation: 201378
How about this modification?
Utilities.computeHmacSha256Signature(value, key)
, it's value
and key
in order.
Utilities.computeHmacSha256Signature(cred.secret, message)
to Utilities.computeHmacSha256Signature(message, cred.secret)
.var res = Utilities.computeHmacSha256Signature(cred.secret, message).map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
To:
var res = Utilities.computeHmacSha256Signature(message, cred.secret).map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
nonce
as a constant value in a request and try again.
nonce
might be required to be fixed in a request. About this, please test at your environment.nonce
was fixed as a constant value in a request.I cannot test this modification in my environment. So if this was not the directly solution for your issue, I apologize. If an error message was changed by this modification, also please provide it.
Upvotes: 1