OAuth nonce value - javascript

I am working with the FatSecret REST API
Im using the OAuthSimple javascript library to generate the signed url.
Here's the code I have -
params['oauth_timestamp'] = Math.floor(new Date().getTime()/1000);
params['oauth_nonce'] = '1234';
params['oauth_version'] = '1.0';
var paramStr = '';
for(var key in params){
paramStr += key+"="+params[key]+"&";
}
paramStr = paramStr.substring(0,paramStr.length-1);
var oauth = OAuthSimple();
oauth.setAction('GET');
var o = oauth.sign(
{
path:this.requestURL,
parameters: paramStr,
signatures:{
api_key:this.apiKey,
shared_secret:this.sharedSecret,
access_token: this.accessToken,
access_secret: this.accessSecret
}
});
console.log(o.signed_url);
return o.signed_url;
params is an associative array containing all the non oauth related parameters for this call.
When I use this signed url I get an "invalid/used nonce"
The OAuth Testing Tool uses the same OAuthSimple library and if I put in all the same parameters (including the timestamp) it generates exactly the same url.
The only difference is that the url generated by the testing tool works and gives me the full response from the server. The url generated by my code does't.
I tried various nonce values including sending a MD5 of the timestamp but I get the same error. The reason I'm using 1234 right now is that the testing tool uses 1234 by default and that seems to work.
Any help is appreciated. Thanks in advance.

Updating #Saravanan's answer with something that works on current browsers:
function genNonce() {
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~'
const result = [];
window.crypto.getRandomValues(new Uint8Array(32)).forEach(c =>
result.push(charset[c % charset.length]));
return result.join('');
}
console.info(genNonce());

The nonce value as per twitter documentation:
The value for this request was generated by base64 encoding 32 bytes of random data, and stripping out all non-word characters, but any
approach which produces a relatively random alphanumeric string should
be OK here.
Based on the above notes, I use the following javascript code to generate nonce value each time I send a request:
var nonceLen = 32;
return crypto.randomBytes(Math.ceil(nonceLen * 3 / 4))
.toString('base64') // convert to base64 format
.slice(0, nonceLen) // return required number of characters
.replace(/\+/g, '0') // replace '+' with '0'
.replace(/\//g, '0'); // replace '/' with '0'
Try this if it works!

Try this
This works every time
var nonce = Math.random().toString(36).replace(/[^a-z]/, '').substr(2);

Related

Newbie needs with cryptojs and md5

I am a total newbie in JavaScript. I want to play with a Rest API. This requires the creation of an X-Auth key for authentication.
The documentation said:
The X-Auth-Key header should be constructed using the following
algorithm: md5(api_key + md5(url + X-Auth-User + api_key +
X-Auth-Expires)).
For example, consider a GET request to
https://<server_ip>/api/live_events/1?clean=true by the user 'admin'
with the api_key '1acpJN7oEDn3BDDYhQ' that expires on June 1, 2011
UTC. In this case the url parameter is '/live_events/1' and the
X-Auth-Expires value is '1306886400'. Thus the value of X-Auth-Key
should be computed as follows:
md5('1acpJN7oEDn3BDDYhQ' +
md5('/live_events/1'+'admin'+'1acpJN7oEDn3BDDYhQ'+'1306886400'))
=> md5('1acpJN7oEDn3BDDYhQ' + md5('/live_events/1admin1acpJN7oEDn3BDDYhQ1306886400'))
=> '180c88df8d0d4182385f6eb7e7045a42'
I have tried to implement this with CryptoJs so far, but unfortunately I can't get the values of the example:
<script>
var md5xx = CryptoJS.MD5('/live_events/1admin1acpJN7oEDn3BDDYhQ1306886400')
var md5yy = CryptoJS.MD5(('1acpJN7oEDn3BDDYhQ') + String(md5xx));
console.log(md5yy.toString());
// => 17222238c238b7ac9f76ea8d0fe1e330
</script>
I would really appreciate some help! Thanks in advance!
The md5 hash you obtained 17222238c238b7ac9f76ea8d0fe1e330 is correct.
The given 180c88df8d0d4182385f6eb7e7045a42 example with reverse lookup gives a different link /jobs/1admin1acpJN7oEDn3BDDYhQ1306886400 instead of /live_events/1admin1acpJN7oEDn3BDDYhQ1306886400.
You can cross check with
https://md5.gromweb.com/?md5=180c88df8d0d4182385f6eb7e7045a42
and
https://md5.gromweb.com/?md5=a39ee4e3aa79939249cb6b5e7faead28
//the hash you actually expected
var md5xx = CryptoJS.MD5('/jobs/1admin1acpJN7oEDn3BDDYhQ1306886400')
var md5yy = CryptoJS.MD5(('1acpJN7oEDn3BDDYhQ') + String(md5xx));
console.log(md5yy.toString());
//correct hash according to the given link
var md5xx = CryptoJS.MD5('/live_events/1admin1acpJN7oEDn3BDDYhQ1306886400')
var md5yy = CryptoJS.MD5(('1acpJN7oEDn3BDDYhQ') + String(md5xx));
console.log(md5yy.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

Hmac-SHA256 not returning expected hash

I realize there are a ton of questions on here about this, but after looking through a good portion of them I haven't really seen anything addressing my issue.
Using SHA256 on the following input I get the correct output:
var canonString = 'GET\n'+
'/\n'+
'Action=ListUsers&Version=2010-05-08\n'+
'content-type:application/x-www-form-urlencoded; charset=utf-8\n'+
'host:iam.amazonaws.com\n'+
'x-amz-date:20150830T123600Z\n'+
'\n'+
'content-type;host;x-amz-date\n'+
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
console.log(CryptoJS.SHA256(canonString).toString()); //returns the expected value of f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59
So SHA256 is working properly on that. Similarly, using the Hmac-SHA256 on the following input I get the correct response:
var kDate = CryptoJS.HmacSHA256("20150830", "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY");
var kRegion = CryptoJS.HmacSHA256('us-east-1', kDate);
var kService = CryptoJS.HmacSHA256('iam', kRegion);
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
console.log(kSigning.toString()); //returns the expected value of c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9
So this Hmac-SHA256 function works correctly on this input. However, on the following input, Hmac-SHA256 DOES NOT return the expected output.
var stringToSign = 'AWS4-HMAC-SHA256\n'+
'20150830T123600Z\n'+
'20150830/us-east-1/iam/aws4_request\n'+
CryptoJS.SHA256(canonString).toString();
CryptoJS.HmacSHA256(kSigning.toString(), stringToSign); //Returns 8a96b6691875490d30d05731cc9aa26be1fd64cf611ed929753b6498075aa886
//Expected value is 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
//Trying in opposite order just in case
CryptoJS.HmacSHA256(stringToSign, kSigning.toString()); //Returns fe52b221b5173b501c9863cec59554224072ca34c1c827ec5fb8a257f97637b1
//Still not expected value which is 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
So, something is clearly going wrong with my stringToSign, and I don't know what it is. I was thinking that the newline character is being interpreted as two different characters and not just a single character. However, escaping it like '\\n' did not fix it either! I am at a loss here. Here are the two docs I've been following (doc1 doc2). Does anyone know why I can't get the expected output?
Remember that the sha256 digest is a byte sequence: it is not a "normal string". It looks like CryptoJS is converting the true sha256 digest to something else for convenience, so make it not do that and you're good to go.
Using Node's crypto library (which is a built-in API) rather than CryptoJS (which has absolutely terrible documentation, so using it is kind of questionable):
const crypto = require("crypto");
function HMAC(key, text) {
return crypto.createHmac("sha256", key).update(text).digest();
}
And then we form the canonical hash:
const canonString = [
'GET',
'/',
'Action=ListUsers&Version=2010-05-08',
'content-type:application/x-www-form-urlencoded; charset=utf-8',
'host:iam.amazonaws.com',
'x-amz-date:20150830T123600Z',
'',
'content-type;host;x-amz-date',
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
].join('\n');
// note: plain hash, not a secret-key-seeded hash
const canonHash = crypto.createHash("sha256").update(canonString).digest();
console.log("Canonical hash is :", canonHash.toString('hex'));
This yields f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59, but only because we logged it as hexadecimal string using .toString('hex'): the real value is still a byte sequence.
We then continue:
const kSecret = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
const kDate = HMAC("AWS4" + kSecret,"20150830");
const kRegion = HMAC(kDate,"us-east-1");
const kService = HMAC(kRegion,"iam");
const kSigning = HMAC(kService,"aws4_request");
console.log("kSigning hash is :", kSigning.toString('hex'));
Which yields c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9: note that again this is only after toString('hex') for console logging purposes. The sha256 byte digest kSigning itself is not a hex string.
Then finally:
const stringToSign = [
'AWS4-HMAC-SHA256',
'20150830T123600Z',
'20150830/us-east-1/iam/aws4_request',
canonHash.toString('hex')
].join('\n');
const signed = HMAC(kSigning, stringToSign);
console.log("Final signed hash is:", signed.toString('hex'));
Which yields 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7, and note that we had to turn the canonical hash into a hexadecimal string for signing purposes, not just logging, as per the instructions in the pages you link to. But, we still do not touch the kSigning digest, that stays a real sha256 byte sequence.

Trying to make hmac-sha256 work with Powershell for Canvas API

I was appointed the task of making a process in which a PowerShell script needs to make a call to Canvas servers in order to get data out of it for other uses that are outside the scope of this question.
The first thing I did was research how the Canvas API actually works. I eventually found this post holds everything I think I should know about the API. The API requires an HMAC SHA 256 hash.
I have decided to reverse engineer his the writer's code that makes the hash in order to make the same script in PowerShell.
Here is my slightly edited code (node.js)
var crypto = require('crypto')
var url = require('url')
var HMAC_ALG = 'sha256'
var apiAuth = module.exports = {
buildMessage: function(secret, timestamp, uri) {
var urlInfo = url.parse(uri, false);
var query = urlInfo.query ? urlInfo.query.split('&').sort().join('&') : '';
var parts = [ 'GET', urlInfo.host, '', '', urlInfo.pathname, query, timestamp, secret ]
console.log(parts);
return parts.join('\n');
},
buildHmacSig: function(secret, timestamp, reqOpts,message) {
//var message = apiAuth.buildMessage(secret, timestamp, reqOpts);
var hmac = crypto.createHmac(HMAC_ALG, new Buffer(secret))
hmac.update(message)
Console.log(message);
return hmac.digest('base64')
}
}
Here are the parameters that I put in the node js application
var canvas = require('[filepath]/new_canvas');
var secret = 'mycrazysecret';
var today = new Date();
var timestamp= today.toUTCString();
var regOpts = 'mycrazymessage';
var message = canvas.buildMessage(secret, timestamp, regOpts)
var hmac = canvas.buildHmacSig(secret, timestamp, regOpts,message);
the final code it this
'Oexq8/ulAGxSIQXGDVqoXyqk5x+n9cMrc3avcTW9aZk='
Here is my PowerShell file:
function buffer
{
param ($string)
$c=#()
Foreach ($element in $string.toCharArray()) {$c+= [System.Convert]::ToSByte($element)}
return $c
}
$message = 'GET\n\n\n\nmycrazymessage\n\nFri, 18 Nov 2016 15:29:52 GMT\nmycrazysecret'
$secret = 'mycrazysecret'
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = buffer -string $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
echo $signature
The final result is 'pF92zam81wclnnb8csDsscsSYNQ7it9qLrcJkRTi5rM='
I do not know getting the to produce the same results is even possible, but the question I am asking why aren't they producing to different results? (the keys are the same as well)
In PowerShell, the default escape sequence uses backticks ` rather than backslash \.
In order for the parser to recognize the escape sequence as not just a backtick character literal and the letter n, use an expandable string (" instead of '):
$message = "GET`n`n`n`nmycrazymessage`n`nFri, 18 Nov 2016 15:29:52 GMT`nmycrazysecret"
Other than that, your HMAC signature procedure is correct (it correctly outputs Oexq8/ulAGxSIQXGDVqoXyqk5x+n9cMrc3avcTW9aZk= after changing the $message value)

Is there Any Way to Convert Mongo ObjectId into string by javascript/jquery

Is it possible to convert mongo objectId into string.
The above pictures shows data i received and shown in console.I need id value in string form .but ObjectId is returning as object
In Database id is look like this- 565d3bf4cefddf1748d1fc5e -objectId and i need id exactly like this –
According to the Mongo documentation:
a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
You can check it out here: https://docs.mongodb.org/manual/reference/object-id/
So in javascript you could do something like this.
var mId = {
Timestamp:1448950573,
Machine:13565407,
Pid:1756,
Increment:8888962
};
function getId(mongoId) {
var result =
pad0(mongoId.Timestamp.toString(16), 8) +
pad0(mongoId.Machine.toString(16), 6) +
pad0(mongoId.Pid.toString(16), 4) +
pad0(mongoId.Increment.toString(16), 6);
return result;
}
function pad0(str, len) {
var zeros = "00000000000000000000000000";
if (str.length < len) {
return zeros.substr(0, len-str.length) + str;
}
return str;
}
console.log(getId(mId))
It produces "565d3b2dcefddf06dc87a282" which was not exactly the id you had, but that might just be a tweak or i was working with different data :D.
EDIT
Added a padding function so that zeros are not truncated.
Hope that helps
EDIT:
I assume you are using c# to connect to and serve documents from the mongo DB. In that case, there is a driver that also supports toString().
Here is an example using the mongo csharp driver:
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
// ...
string outputFileName; // initialize to the output file
IMongoCollection<BsonDocument> collection; // initialize to the collection to read from
using (var streamWriter = new StreamWriter(outputFileName))
{
await collection.Find(new BsonDocument())
.ForEachAsync(async (document) =>
{
using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonWriter(stringWriter))
{
var context = BsonSerializationContext.CreateRoot(jsonWriter);
collection.DocumentSerializer.Serialize(context, document);
var line = stringWriter.ToString();
await streamWriter.WriteLineAsync(line);
}
});
}
ORIGINAL:
These are Mongo ObjectId's and if you haven't already deserialised the document they should support a toString method that will return a hexadecimal string.
but if you want this applied to the whole document, using JSON.stringify(MogoDocument) should deserialize this for you into a plain object.

how to get Hmac code with javascript

I can get a hmac sing using Python as following:
import hmac, base64, hashlib
def make_sign():
hash_data = "data"
secret = "this is secret"
sha512 = hashlib.sha512
hmac_obj = hmac.new(secret, hash_data, sha512)
str_hash = hmac_obj.digest()
sign = base64.b64encode(str_hash)
hex_hash = hmac_obj.hexdigest()
hex_sign = base64.b64encode(hex_hash)
print "correct_sign:",sign
print "hex_digest_sign:",hex_sign
make_sign()
output:
correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
hex_digest_sign: MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY=
but with js, I can get hex_digest_sign, but I need to get correct_sign for web request.
function make_request() {
hash_data = "data"
secret = "this is secret"
hmac = hmac_512(hash_data, secret)
var sign = $.base64.encode(hmac),
console.log("js_sign="+sign);
}
function hmac_512(message, secret) {
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA512, secret);
hmac.update(message);
var hash = hmac.finalize();
return hash;
}
js output:
js_sign="MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY="
the correct sign is correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
how to get it in js?
I suspect that you are running into trouble with types and encoding. According to the CryptoJS source, the iterative hashing style that you are using returns a WordArray once you call finalize().
With that, once you go to print the results, you are printing the contents of the WordArray.
The purpose for itterative hashing is typically if you have a large input, you can break it into chunks to work on one piece at a time. Try the below edit I made that removes this as it does not look like you need to iterate.
function hmac_512(message, secret) {
var newHMAC = CryptoJS.HmacSHA256(message, secret);
return newHMAC;
}
The above will simply return the HMAC in string form which, once Base64 encoded, should match the result you see in Python.
Hope this helps!

Categories