Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

How/where to get value of x-identity and x-signature using bitcore? #708

Open
Lalitpatadiya12 opened this issue Oct 5, 2017 · 17 comments
Open

Comments

@Lalitpatadiya12
Copy link

I can not find the value of Authentication header from the docs

x-identity : Identity is the Peer-ID
x-signature : Signature is the current request signature

can any one have idea please let me know

@dabura667
Copy link
Contributor

dabura667 commented Oct 5, 2017

From bitcore-wallet-client:

/**
 * Sign an HTTP request
 * @private
 * @static
 * @memberof Client.API
 * @param {String} method - The HTTP method
 * @param {String} url - The URL for the request
 * @param {Object} args - The arguments in case this is a POST/PUT request
 * @param {String} privKey - Private key to sign the request
 */
API._signRequest = function(method, url, args, privKey) {
  var message = [method.toLowerCase(), url, JSON.stringify(args)].join('|');
  return Utils.signMessage(message, privKey);
};

Utils.signMessage

Utils.signMessage = function(text, privKey) {
  $.checkArgument(text);
  var priv = new PrivateKey(privKey);
  var hash = Utils.hashMessage(text);
  return crypto.ECDSA.sign(hash, priv, 'little').toString();
};
Utils.hashMessage = function(text) {
  $.checkArgument(text);
  var buf = new Buffer(text);
  var ret = crypto.Hash.sha256sha256(buf);
  ret = new Bitcore.encoding.BufferReader(ret).readReverse();
  return ret;
};

So basically, x-signature should be:

  1. method (get or post) | url | JSON.stringify(args) is the message, if GET request, JSON is just "{}"
    • example: get|https://bws.bitpay.com/bws/v1/getfee?someArg=23&r=2763|{} or post|https://bws.bitpay.com/bws/v1/postsomething|{"someArg":23,"r":2763}
  2. double sha256 hash the message. (Note: the library reverses the bytes, and then passes 'little' to the ECDSA library from bitcore-lib which reverses the bytes again... kinda weird.)
  3. sign the message using ECDSA. Getting the r and s values (using low S)
  4. the x-signature is a stringify of sig

Edit: ECDSA was using the .sig attribute for sign.

@Lalitpatadiya12
Copy link
Author

@dabura667 Thank for immediate reply, I am beginner so i need some more clear detail, if you have please give me step by step process what should i do, and more thing what about peer- ID..?

@dabura667
Copy link
Contributor

If you are a beginner, just use bitcore-wallet to interact with BWS.

@Lalitpatadiya12
Copy link
Author

@dabura667 does bitcore-wallet give all feature of bitcore wallet service ..?

@dabura667
Copy link
Contributor

yes. bitcore-wallet-service is server-side, bitcore-wallet is the client software that talks to the BWS server.

@Lalitpatadiya12
Copy link
Author

@dabura667 means using bitcore-wallet-service i can not generate multiple address right..?

@robertclarkson
Copy link

Hi @dabura667 I'm trying to create the signature for the message from a PHP based system, and I don't seem to be able to recreate the signature correctly
The error I am getting:

info Client Err: 401 /v1/addresses/ {"code":"NOT_AUTHORIZED","message":"Invalid signature"} 
<> ::ffff:127.0.0.1 2018-03-16T00:51:50.913Z "GET /bws/api/v1/addresses/" 401 55 2.451 "GuzzleHttp/6.2.1 curl/7.47.0 PHP/7.1.15-1+ubuntu16.04.1+deb.sury.org+2

I am using this PHP library https://github.com/simplito/elliptic-php

My code:

$message = implode('|',[strtolower($method), $url, json_encode($args)]);
$ec = new EC('secp256k1');
$key = KeyPair::fromPrivate($ec, $this->requestSigningKey, 'hex');
$signature = $key->sign($message);
$derSign = $signature->toDER('hex');

Any help much appreciated.

@dabura667
Copy link
Contributor

Two things:

  1. Is json_encode the exact same as JS JSON.stringify?
  2. What hash algorithm does sign() use? It must be sha256(sha256(message))

@dabura667
Copy link
Contributor

Also the signature must be low-S.

I suck at reading PHP, sorry.

@robertclarkson
Copy link

@dabura667 Thanks for the help so far. No worries at all, don't expect you to be fluent in all languages.

  1. json_encode appears to be the same, in any case there are no args with the get request.
  2. sign doesnt use sha256(sha256()) so I have modified the code to do this, unfortunately with no further change
$ec = new EC('secp256k1');
$key = KeyPair::fromPrivate($ec, $this->requestSigningKey, 'hex');
$data = hash('sha256', hash('sha256', $message));
$signature = $key->sign($data);
$derSign = $signature->toDER('hex');

as far as Low-s goes, $signature holds a Signature object that has an $r and a $s and a $recovery param

the toDer('hex') function seems to combine the $r and $s with padding in some way and return the result encoded in hex

I've tried using the string value of $s from the signature, this was encoded in base10 and didnt work either.

@robertclarkson
Copy link

@dabura667 I should add I'm dumping the message in the bitcore backend and I can see it's formulated correctly / the same as the requests from the copay client.
I'm sure the issue is with the signature somehow. I'm not reversing the message or setting 'little' for the endian anywhere, so maybe this could be the issue?

@dabura667
Copy link
Contributor

If you are unsure about little endian, flip the byte order before passing to sign.

Also, just to clarify, sign doesn’t do any hashing at all? Most libraries default to SHA1, so you could be SHA1-ing the double SHA256.

Also, to calculate low-s, check if s > n/2 (where n is the order of the secp256k1 curve) and if it is, you should replace s with n - s

Let me know if that helps.

@dabura667
Copy link
Contributor

Also, remember to use the right private key for signing key.

@robertclarkson
Copy link

Thanks @dabura667 I'm signing with the key in the .wallet.dat referenced as "requestPrivKey"

I've looked in the sign function and I can't see any hashing, although I have to say its getting a bit over my head, I'm not an encryption guru unfortunately.

It seems to be getting truncated, then something next, but no idea, almost unreadable. :)

$msg = $this->_truncateToN(new BN($msg, 16));

...

$s = $k->invm($this->n)->mul($r->mul($key->getPrivate())->iadd($msg));
            

https://github.com/simplito/elliptic-php/blob/f18586ff8c26830a9f5476e7dc8d2ab5623f80f9/lib/EC.php#L91

Is low-s the result i need to send? or am i supposed to calculate the signature with a parameter low-s set? (sorry im totally lacking knowledge in this area)

@robertclarkson
Copy link

robertclarkson commented Mar 20, 2018

Holy shit i just tried another library and got it working. So for anyone else trying to do this, try this other library "BitcoinECDSA" :

$message = implode('|',[strtolower($method), $url, json_encode($args,JSON_FORCE_OBJECT)]);
$data = hash('sha256', hex2bin(hash('sha256', $message)));
$bitcoinECDSA = new BitcoinECDSA();
$bitcoinECDSA->setPrivateKey($this->requestSigningKey);
$signedMessage = $bitcoinECDSA->signHash($data);

Thank you @dabura667 for all your help!

@robertclarkson
Copy link

robertclarkson commented Mar 20, 2018

There seems to be a problem with this library in that when it signs it can produce R values that are negative which goes against BIP-0066.
https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki

@robertclarkson
Copy link

Hey @dabura667 One more thing, how is the proposalsSignature generated for a transaction proposal? Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants