eBay - Digital Signature in SAP PI UDF - Signature validation failed error - digital-signature

`I'm getting a { "errors": [ { "errorId": 215120, "domain": "ACCESS", "category": "REQUEST", "message": "Signature validation failed", "longMessage": "Signature validation failed to fulfill the request." } ]} error when i try to test within our mapping via Java UDF.
I'm using RSA as the cipher. This is what the code looks like.
//signature base - signature base will be converted to bytes (UTF-8) then to base64. will be used in signature header.
signatureInput.append("\"x-ebay-signature-key\":");
signatureInput.append(" " + jwe);
signatureInput.append("\n");
signatureInput.append(" \"#method\":");
signatureInput.append(" GET");
signatureInput.append("\n");
signatureInput.append(" \"#path\":");
signatureInput.append(" /sell/finances/v1/payout ");
signatureInput.append("\n");
signatureInput.append("\"#authority\":");
signatureInput.append(" apiz.ebay.com");
signatureInput.append("\n");
signatureInput.append("\"#signature-params\": (\"x-ebay-signature-key\" \"#method\" \"#path\" \"#authority\")" );
signatureInput.append(";created=" + unixTime);
//signature-input - will be used in signature-input header
signatureParams.append("\"#signature-params\": (\"x-ebay-signature-key\" \"#method\" \"#path\" \"#authority\")" );
signatureParams.append(";created=" + unixTime);
**private key will be converted to bytes (UTF-8) then to base64. Then extract the private key
**
byte[] privateKeyBytes = Base64.getDecoder().decode(EncodedPrivateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
signBase will be signed using the private key here
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privKey);
signature.update(EncodedSignBase.getBytes());
byte[] signedData = signature.sign();
signed message will be encoded to base64
String signedMessage = Base64.getEncoder().encodeToString(signedData);
these are the request headers
con_payouts.setRequestMethod("GET");
con_payouts.setRequestProperty("Content-Type", "application/json");
con_payouts.setRequestProperty("Authorization", "Bearer " + accessToken);
con_payouts.setRequestProperty("Accept", "application/json");
con_payouts.setRequestProperty("Accept-Charset", "utf-8");
con_payouts.setRequestProperty("Accept-Encoding", "application/gzip");
con_payouts.setRequestProperty("Content-Type", "application/json");
con_payouts.setRequestProperty("X-EBAY-C-MARKETPLACE-ID", "EBAY_XX *- country code*");
con_payouts.setRequestProperty("x-ebay-signature-key", jwe);
con_payouts.setRequestProperty("Signature", "sig1=:" + signedMessage + ":");
con_payouts.setRequestProperty("Signature-Input", "sig1=" + signParams);
con_payouts.setRequestProperty("x-ebay-enforce-signature", "true");
i referenced this code mostly from this example, -code.com/Java/ebay_add_digital_signature_to_http_request.asp. But i'm still getting the same error. At this point i'm not sure where's the issue in the code.
your text
I already tried interchanging some of the variables, i also tried enconding everything to base64 before the request. Also asked help from ebay support, they provided a sample valid signature, then have to check if i will get the same output, but i'm still getting the same error. I also encountered the "invalid timestamp", but as per ebay, timestamp should still be applicable within 15 minutes.`

Related

Authentication errors using Azure blob storage and Azure CDN

I'm having intermittent 403 errors trying to access a blob storage, via Azure CDN, with the symmetric access key. It seems that sometimes there's a header added for "Range", in the format of "bytes=xxx". The full error message is below:
{'Date': 'Mon, 12 Dec 2022 13:07:40 GMT', 'Content-Type': 'application/xml', 'Content-Length': '697', 'Connection': 'keep-alive', 'x-ms-request-id': '3f89c2c1-e01e-0050-132a-0eeb42000000', 'x-ms-error-code': 'AuthenticationFailed', 'x-azure-ref': '20221212T130740Z-6rfkrgx8qt0shbtz3x46rwnhrn0000000630000000002ayd', 'X-Cache': 'TCP_MISS'}
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:3f89c2c1-e01e-0050-132a-0eeb42000000
Time:2022-12-12T13:07:40.7638741Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request 'xxxxxx=' is not the same as any computed signature. Server used following string to sign: 'GET
bytes=0-8388607
x-ms-date:Mon, 12 Dec 2022 13:07:36 GMT
x-ms-version:2020-04-08
/deviceimage2zgjscikl7kny/images/data-prod-1.1.packer'.</AuthenticationErrorDetail></Error>
I was able to reproduce the error by generating the MAC signature in Python, but I saw it originally using the Go SDK and az CLI.
We added a rule at the CDN to Bypass caching, and it seems to have improved the situation (problem happens less frequently), but we are still seeing it on occasion.
Has anyone else experienced this? And is there a workaround?
Trying to access a blob storage with an access key, via Azure CDN
I tried in my environment and got below results:
Initially, I got a same when I tried to access blob storage with CDN using Postman.
Postman:
The above error states that signature and date is incorrect. So, we can't pass directly storage access key. You need to create a signature string that represents the given request, sign the string with the HMAC-SHA256 algorithm (using your storage key to sign), and encode the result in base 64.
For creating signature, I used below .NET code:
using System.Globalization;
using System.Net;
using System.Security.Cryptography;
class Program
{
static void Main(string[] args)
{
ListBlobs();
Console.WriteLine("done");
Console.ReadLine();
}
static void ListBlobs()
{
string Account = "venkat123";
string Key = "<Storage account key>";
string Container = "test";
string apiversion = "2021-06-08";
DateTime dt = DateTime.UtcNow;
string StringToSign = String.Format("GET\n"
+ "\n" // content encoding
+ "\n" // content language
+ "\n" // content length
+ "\n" // content md5
+ "\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-date:" + dt.ToString("R") + "\nx-ms-version:" + apiversion + "\n" // headers
+ "/{0}/{1}\ncomp:list\nrestype:container", Account, Container);
string auth = SignThis(StringToSign, Key, Account);
Console.WriteLine($"the date is: {dt.ToString("R")}");
Console.WriteLine($"the auth token is: {auth}");
Console.WriteLine("*********");
string method = "GET";
string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list", Account, Container);
Uri uri = new Uri(urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.Headers.Add("x-ms-date", dt.ToString("R"));
request.Headers.Add("x-ms-version", apiversion);
request.Headers.Add("Authorization", auth);
Console.WriteLine("***list all the blobs in the specified container, in xml format***");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
Account,
signature);
return authorizationHeader;
}
}
Console:
Above executed code, date and signature which I copied and used in postman, and it worked successfully.
Postman:

Invalid Base64 SAML Assertion from OAuth on-behalf-of flow in Azure AD

I am experiencing a weird issue when exchanging a OAuth access token to a SAML Assertion using Azure AD and On-Behalf-Of Flow. I am trying to exchange a OAuth access token to a SAML Assertion using the On-Behalf-Of flow of Azure AD.
Setup
A Front-End communicating with a Back-End using OAuth access tokens
A datasource which I need to get data from, which is protected with SAML
The request to fetch data from the datasource needs to be performed from the Back-End since there are access restrictions to the datasource in place.
Description
Following the documentation for Azure AD v1 (Github docs), I was able to request a response which initially looks fine. The parameters for the request I used are:
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion: <access token containing the correct scopes for the Back-End>
client_id: <client-id-of-back-end>
client_secret: <assigned-secret>
resource: <resource-of-the-datasource>
requested_token_use: on_behalf_of
requested_token_type: urn:ietf:params:oauth:token-type:saml2
The request is sent as POST request, using x-www-form-urlencoded as content-type (endpoint "https://login.microsoftonline.com/tenant-id/oauth2/token").
Issue
I am almost certain, I am encountering a bug, however I did not figure out how to contact Azure without having a Developer Support Plan. The response I receive looks fine at first:
{
"token_type": "Bearer",
"expires_in": "3579",
"ext_expires_in": "3579",
"expires_on": "1613985579",
"resource": "<datasource>",
"access_token": "PEFzc2Vyd...9uPg",
"issued_token_type": "urn:ietf:params:oauth:token-type:saml2",
"refresh_token": "0.ATEAt...hclkg-7g"
}
The assertion from the access_token field is not a valid base64 string. Trying to decode it using C# Base64Convert, results in this exception:
System.FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
I was however able to partly decode it using bashs base64 -D, which gave me a somehow valid assertion:
$ base64 -D "response.txt"
Invalid character in input stream.
<Assertion ID="_26be6964-2e17-4184-8ac7-d4cdbb9d5700" IssueInstant="2021-02-22T12:35:49.919Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"><Issuer>https://sts.windows.net/[id]/</Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI="#_26be6964-2e17-4184-8ac7-d4cdbb9d5700"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>...<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"><AttributeValue>test#domain.com</
Question
I am almost sure, that the assertion should be a valid base64 string to decode using anything capable of doing so. Am I missing something? Or is this a known issue with V1 OBO Flow? Is there a known workaround for this?
the assertion is the access-token that you receive in the initial call to AAD as mentioned here.
This is a JWT token which is Based64 URL encoded and can be decoded using tools like https://JWT.io or https://JWT.ms or using any programming language too. The main point is that if the access-token issued is a valid access-token, it should get decoded, and that's the same access-token that gets added in the subsequent call to fetch a SAML token.
You can also check the following article that speaks on OBO flow: https://blogs.aaddevsup.xyz/2019/08/understanding-azure-ads-on-behalf-of-flow-aka-obo-flow/
The main point to note here would be how we are requesting the initial Access-token from AAD. If your Front-end is a SPA and if you are using Implicit Flow there, you might want to take a look at this "As of May 2018, some implicit-flow derived id_token can't be used for OBO flow. Single-page apps (SPAs) should pass an access token to a middle-tier confidential client to perform OBO flows instead."
While decoding a JWT, it first needs to be converted to a Base64 encoded string from a Base64URL encoded string. Once the JWT is base64 encoded, then it needs to be decoded and later on parse that into json.
A Powershell Sample for the same:
$token = "<put the jwt here>"
if (!$token.Contains(".") -or !$token.StartsWith("eyJ")) {
Write-Error "Invalid token" -ErrorAction Stop
}
# Token
foreach ($i in 0..1) {
$data = $token.Split('.')[$i].Replace('-', '+').Replace('_', '/')
switch ($data.Length % 4) {
0 { break }
2 { $data += '==' }
3 { $data += '=' }
}
}
$decodedToken = [System.Text.Encoding]::UTF8.GetString([convert]::FromBase64String($data)) | ConvertFrom-Json
Write-Verbose "JWT Token:"
Write-Verbose $decodedToken
C# sample:
static void jwtDecoder()
{
try
{
Console.WriteLine("JWT to Decode: " + jwtEncodedString + "\n");
var jwtHandler = new JwtSecurityTokenHandler();
var readableToken = jwtHandler.CanReadToken(jwtEncodedString);
if (readableToken != true)
{
Console.WriteLine("\n\nThe token doesn't seem to be in a proper JWT format.\n\n");
}
if (readableToken == true)
{
var token = jwtHandler.ReadJwtToken(jwtEncodedString);
var headers = token.Header;
var jwtHeader = "{";
foreach (var h in headers)
{
jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
}
jwtHeader += "}";
Console.Write("\nHeader :\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented));
var claims = token.Claims;
var jwtPayLoad = "{";
foreach (Claim c in claims)
{
jwtPayLoad += '"' + c.Type + "\":\"" + c.Value + "\",";
}
jwtPayLoad += "}";
Console.Write("\r\nPayload :\r\n" + JToken.Parse(jwtPayLoad).ToString(Formatting.Indented));
var jwtSignature = "[RawSignature: ";
jwtSignature += token.RawSignature;
jwtSignature += " ]";
Console.Write("\r\nSignature :\r\n" + jwtSignature);
//Console.ReadLine();
}
}
finally
{
Console.Write("\n\nPress Enter to close window ...");
Console.Read();
}
}

Microsoft Face API 1.0 Error Resource Not Found

I am working on a face recognition project with Microsoft Azure Cognitive services. Not quite sure why I am not able to correct my own JSON Malformed syntax I thought I nail this 6 months ago. I want to create a group name, so I call upon 'Person Group API' and everytime I follow MS example I get errors in my code however in the API testing Console no problems here is my code example borrow from MS site :
{ "error": { "code": "ResourceNotFound", "message": "The requested resource was not found." } }
and the code which is run in Console mode :
static async void CreateGroup()
{
string key1 = "YourKey";
// azure the one should work
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add
("Ocp-Apim-Subscription-Key", key1);
var uri = "https://westus.api.cognitive.microsoft.com/face/v1.0/
persongroups/{personGroupId}?" + queryString;
HttpResponseMessage response;
// Request body
string groupname = "myfriends";
string body = "{\"name\":\"" + groupname + ","+ "\"}";
// Request body
using (var content = new StringContent
(body, Encoding.UTF8, "application/json"))
{
await client.PostAsync(uri, content)
.ContinueWith(async responseTask =>
{
var responseBody = await responseTask.Result
.Content.ReadAsStringAsync();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Response: {0}", responseBody);
Console.WriteLine("");
Console.WriteLine("Group Created.... ");
Console.WriteLine("Hit ENTER to exit...");
Console.ReadKey();
});
response = await client.PutAsync(uri, content);
Console.WriteLine("what is this {0}", response.ToString());
Console.ReadKey();
}// end of using statement
}// end of CreateGroup
#endregion
I am guess here but I think its my JSON is malformed again and I just don't know what I am doing wrong again this time. According to the site the field name that I require to send over to ms is 'name' : 'userData' is optional.
Faced the similar issue, after adding "/detect" in the uri the issue fixed.
See the below
var uri = "https://westus.api.cognitive.microsoft.com/face/v1.0/detect
Also make sure the subscription key is valid.
Your request url must specify a group ID in place of where you have {personGroupId}. Per the spec the group ID must be:
User-provided personGroupId as a string. The valid characters include
numbers, English letters in lower case, '-' and '_'. The maximum
length of the personGroupId is 64.
Furthermore, the http verb needs to PUT, whereas you've made a client.PostAsync request. So you'll need to change that to client.PutAsync.
Microsoft provides a client library for C# for the Face API where you can find working C# code.
In python, simply this worked for me.
ENDPOINT='https://westcentralus.api.cognitive.microsoft.com'

Server side verification of Google Play in-app billing purchase signature failed

i'm currently integrating Google Play in-app billing to my androidgame project, i have a Node.js server set up and plan to send it the "originalJson" and "signature" value of the Google Play purchase response for server side verification.
then i put up a bit of test on my Node.js server, first here are the "originalJson" and "signature" value of one of my purchase(fetched from the client side):
originalJson:{"orderId":"GPA.1312-8694-0319-25069","packageName":"com.shihu.sm.testin","productId":"com.shihu.sm.testin.diamond","purchaseTime":1452598011176,"purchaseState":0,"developerPayload":"{\"iabProductId\":\"com.shihu.sm.testin.diamond\",\"gOrderId\":\"2cb77de1a2a94db18b6df84f8037ea5b\",\"serverId\":\"6\",\"productId\":\"202\"}","purchaseToken":"bjoncdcebeclpklebmadidgb.AO-J1OyEbKLL0rhWQAc1hjdWyJPXHkAoHZTfZasqUuFWKWyAlnj-opiDLYILNRpnWgcblO8vV37fWf0kpeNMRZcgRT-fRxAO4P8VQPmU-TJakB-sCiRx8sUxL4nxnUBMnZdFWdpaIZDW5tP3Ck4aO57n1o66PwnjZw"}
signature:JdfwMxprv7iMbI5YnVIWXLEAqiDhAQQva2IdfxtmhqBvLNU4Msi8sj31mnrVJfShxNmQI3zhlNUrCCaXdraFM0/y8O4PoZWYr+PFjCmlMovhG+ldeImEu7x52GLoQ7DsO8Yh4aLYmxemezFc1RjcSpq+l6Zzu9T6j3fHjLfQ060SEFapZITI/poxlFyvJX3bHhF9wGP54tL6pGjB/7fBEqTM1zHXUYeZyz+4akqV8oODlIWwMKhvN5tX/Zra9kh9hm0bnJT/1YWso3tLlT/WTK9nsP1l/lTnEXvgzq9QVSGbT/cpD7KSbR5N4i/NmPYAlCOvesW9OlRD05L8yytpBw==
then i wrote the following code to do the verification with "RSA-SHA1" algorithm and "base64" signature encoding:
var crypto = require('crypto');
console.log('start verification');
var public_key = "-----BEGIN PUBLIC KEY-----" + "\r\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg+VmzvTvb856ur/J+PWC" + "\r\n" +
"gFRhLYV/chAuWzUuqlIh5gnYz1RFOYymCWAKP3wguol8YSe/72zEqAvPutBU2XVj" + "\r\n" +
"zx3sHT+GUInbKjgZHzxw0viPh//OfaooEvEFMz9C6J8ABwpGNQUpACmyw12ZKshP" + "\r\n" +
"HCJ6PZV+nsWry6PEZgnYCF7w5SDP4GY2tr3Q5D0iQwoALA40KYQfsKZ6pI5L8bDT" + "\r\n" +
"2MLTFoemg/npeARy9HYkbonPatBhWjp2flzBRcyQx7DyQ7csLvPl5AGHRT4h5RBq" + "\r\n" +
"RlLj+DBgNDAdwvHGyfhbTz7fPsT6xn7qifxAN+2gQsemSVmhi15zECF/k5MtTiOF" + "\r\n" +
"owIDAQAB" + "\r\n" +
"-----END PUBLIC KEY-----";
verifier= crypto.createVerify("RSA-SHA1");
originalJson = '{"orderId":"GPA.1312-8694-0319-25069","packageName":"com.shihu.sm.testin","productId":"com.shihu.sm.testin.diamond","purchaseTime":1452598011176,"purchaseState":0,"developerPayload":"{\"iabProductId\":\"com.shihu.sm.testin.diamond\",\"gOrderId\":\"2cb77de1a2a94db18b6df84f8037ea5b\",\"serverId\":\"6\",\"productId\":\"202\"}","purchaseToken":"bjoncdcebeclpklebmadidgb.AO-J1OyEbKLL0rhWQAc1hjdWyJPXHkAoHZTfZasqUuFWKWyAlnj-opiDLYILNRpnWgcblO8vV37fWf0kpeNMRZcgRT-fRxAO4P8VQPmU-TJakB-sCiRx8sUxL4nxnUBMnZdFWdpaIZDW5tP3Ck4aO57n1o66PwnjZw"}';
signature = 'JdfwMxprv7iMbI5YnVIWXLEAqiDhAQQva2IdfxtmhqBvLNU4Msi8sj31mnrVJfShxNmQI3zhlNUrCCaXdraFM0/y8O4PoZWYr+PFjCmlMovhG+ldeImEu7x52GLoQ7DsO8Yh4aLYmxemezFc1RjcSpq+l6Zzu9T6j3fHjLfQ060SEFapZITI/poxlFyvJX3bHhF9wGP54tL6pGjB/7fBEqTM1zHXUYeZyz+4akqV8oODlIWwMKhvN5tX/Zra9kh9hm0bnJT/1YWso3tLlT/WTK9nsP1l/lTnEXvgzq9QVSGbT/cpD7KSbR5N4i/NmPYAlCOvesW9OlRD05L8yytpBw=='
verifier.update(originalJson);
if(verifier.verify(public_key, signature, "base64"))
console.log('verification succeeded');
else
console.log("verification failed");
the key string in the middle is the base64 encoded public key from Google Console split by '\r\n' with every 64 characters. at the beginning i didn't split it into chunks of 64 characters and kept failing with error saying can't generate the pub key object, it was later i followed some examples on the internet and got passed that, but till now, i haven't got a successful verification result yet.
i have referenced some more examples, and i think the 'RSA-SHA1' and 'base64' settings for the verification are the correct ones, so what am i still missing or doing wrong?
thanks
It seems that your originalJson string is missing some necessary escaping.
I've managed to verify the signature with the escaping added back in:
var originalJson = '{"orderId":"GPA.1312-8694-0319-25069","packageName":"com.shihu.sm.testin","productId":"com.shihu.sm.testin.diamond","purchaseTime":1452598011176,"purchaseState":0,"developerPayload":"{\\"iabProductId\\":\\"com.shihu.sm.testin.diamond\\",\\"gOrderId\\":\\"2cb77de1a2a94db18b6df84f8037ea5b\\",\\"serverId\\":\\"6\\",\\"productId\\":\\"202\\"}","purchaseToken":"bjoncdcebeclpklebmadidgb.AO-J1OyEbKLL0rhWQAc1hjdWyJPXHkAoHZTfZasqUuFWKWyAlnj-opiDLYILNRpnWgcblO8vV37fWf0kpeNMRZcgRT-fRxAO4P8VQPmU-TJakB-sCiRx8sUxL4nxnUBMnZdFWdpaIZDW5tP3Ck4aO57n1o66PwnjZw"}';
Pay attention to the \\'s. The string is different otherwise.

Can't get HMAC Authentication working with API

I'm trying to authenticate using HMAC with the LocalBitcoins API.
Here is the authentication written in Python:
message = str(nonce) + hmac_auth_key + relative_path + get_or_post_params_urlencoded
signature = hmac.new(hmac_auth_secret, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
And the parameters to create the HMAC message:
Nonce. A 63 bit positive integer, for example unix timestamp as milliseconds.
HMAC authentication key. This is the first one of a key/secret pair.
Relative path, for example /api/wallet/.
GET or POST parameters in their URL encoded format, for example foo=bar&baz=quux.
Here is how I am building the HMAC:
var milliseconds = (new Date).getTime();
var key = config.key;
var secret = config.secret;
var nonce = milliseconds.toString()
var message = nonce + key + 'api/myself';
var hmac_digest = crypto.createHmac("sha256", secret).update(message).digest('hex').toUpperCase();
The signature is sent via 3 HTTP Headers. The options for the call to the api/myself method looks like such (using request):
{ url: 'https://localbitcoins.com/api/myself',
method: 'GET',
headers:
{ 'Apiauth-Key': 'my api key',
'Apiauth-Nonce': 1439925212276,
'Apiauth-Signature': 'the created signature' },
timeout: 5000 }
And the request:
var req = request.get(options, function(error, response, body) {
console.log(body);
});
But everytime I get the following error message:
{ error:
{ message: 'HMAC authentication key and signature was given, but they are invalid.',
error_code: 41 } }
I've tried lots of different combinations in testing but can't get anything to work. What am I missing?
It turns out that my path was wrong.
/path needed to be /path/, which I found out through working with a working Python implementation.
The package is up and running now here: https://github.com/mrmayfield/localbitcoins-node
I think that (new Date).getTime(); is not creating a 63 bit integer. Per Dr. Axel's post. JavaScript has 53 bit integers plus a sign.

Resources