How to pass password with special characters to RPC API via curl?

1

When I set a simple password in my .conf file

rpcuser=user
rpcpassword=password

I can contact my wallet using curl from the command line like so:

$ curl --verbose --user 'user:password' --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getbalance", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 18332 (#0)
* Server auth using Basic with user 'user'
> POST / HTTP/1.1
> Host: 127.0.0.1:18332
> Authorization: Basic dXNlcjpwYXNzd29yZA==
> User-Agent: curl/7.50.1
> Accept: */*
> content-type: text/plain;
> Content-Length: 74
> 
* upload completely sent off: 74 out of 74 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Τετ, 21 Ιούν 2017 08:59:30 GMT
< Content-Length: 52
< 
{"result":14.13139559,"error":null,"id":"curltest"}
* Connection #0 to host 127.0.0.1 left intact

But if I set a more complex password with special characters, such as

rpcuser=user
rpcpassword=!@#$%^&*()

then the call fails with 401 - Unauthorized

$ curl --verbose --user 'user:!@#$%^&*()' --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getbalance", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 18332 (#0)
* Server auth using Basic with user 'user'
> POST / HTTP/1.1
> Host: 127.0.0.1:18332
> Authorization: Basic dXNlcjohQCMkJV4mKigp
> User-Agent: curl/7.50.1
> Accept: */*
> content-type: text/plain;
> Content-Length: 74
> 
* upload completely sent off: 74 out of 74 bytes
< HTTP/1.1 401 Unauthorized
* Authentication problem. Ignoring this.
< WWW-Authenticate: Basic realm="jsonrpc"
< Date: Τετ, 21 Ιούν 2017 09:03:05 GMT
< Content-Length: 0
< Content-Type: text/html; charset=ISO-8859-1
< 
* Connection #0 to host 127.0.0.1 left intact

It doesn't seem like the password was mangled at the shell level. It was passed verbatim.

$ echo dXNlcjohQCMkJV4mKigp | base64 -d
user:!@#$%^&*()

There must be a way to do this, because bitcoin-cli works with the complex password just fine.

$ bitcoin-cli getbalance
14.13139559

Looking into bitcoin-cli.cpp it seems the client is using basic HTTP auth, which is consistent with what the wiki says.

strRPCUserColonPass = GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", "");

...and later on...

evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());

Can someone please figure this out for me?

I want to know because I'm trying to pass complex passwords into EasyBitcoin-PHP and failing.

Thanks.

alexg

Posted 2017-06-21T09:13:16.977

Reputation: 180

Answers

2

It seems that this is a bug in Bitcoin Core. I will take a look at it.

Edit: I see the problem now. You have # in your password. The config file parse will interpret # as the beginning of a comment. So this means that it thinks the rest of your password is considered a comment by the config file. You cannot use # anywhere in the config file or everything after it will be interpreted as a comment.

In your example, the rpcpassword that Core is using is !@. To have # in your rpcpassword, I think you will actually need to use the rpcauth option which uses hashes instead of putting the password string in the config file.

Andrew Chow

Posted 2017-06-21T09:13:16.977

Reputation: 40 910

Doh! This is so obvious in retrospect!alexg 2017-06-21T21:35:33.043