I am attempting the same thing currently. At first I used the same approach for converting to hex: 

ClassMethod Hex(pRaw As %String) As %String [ Internal ]
{
set out="", l=$l(pRaw)
for = 1:1:{
set out=out_$zhex($ascii(pRaw,i))
}
quit $$$LOWER(out)
}

But have discovered that the Hex function above is not correct. Instead use the system function,  ##class(%xsd.hexBinary).LogicalToXSD.

##class(%xsd.hexBinary).LogicalToXSD

The conversion to hex using the custom method was removing zeroes in the string. That had a cascading effect, the canonical request hash will be wrong, and consequently so will the string to sign and then ultimately the signature. Hope this helps anyone else that might be struggling. 

Here is some documentation specifically for S3:

https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html

The code posted by Jon was close, we actually need to step into the first row before getting data. The snippet of code below will allow a developer to connect to IRIS and pass a query string then obtain the result, all using Node.js. I hope this helps someone else attempting the same thing. 

var irisobj = require('iris');
var myData = new irisobj.IRIS();
var result = myData.open({ path:"C:/InterSystems/IRIS/Mgr",
                       username: "USERNAME",
                       password: "PASSWORD",
                       namespace: "YOURNAMESPACE"
            }
        );

var result = myData.invoke_classmethod({class: "%SYSTEM.SQL", method: "Execute", arguments: ["SELECT TOP 1 ID FROM SOMETABLE"]});
var o = {oref: result.result};

myData.invoke_method(o, '%Next');
var value = myData.invoke_method(o, '%GetData', 1);

console.log(value.result);

myData.close();