So i am trying to authenticate myself to the monero-rpc-wallet, the server requires me to use digest authentication.

If my username is: Alladin and password: open sesame

The www-authenticate header looks like this:

    WWW-Authenticate: Digest qop="auth",algorithm=MD5,realm="monero-wallet-rpc",nonce="hHQVNuEdyZszjmEPwS/jkQ==",stale=false
Digest qop="auth",algorithm=MD5-sess,realm="monero-wallet-rpc",nonce="hHQVNuEdyZszjmEPwS/jkQ==",stale=false

And my java code to implement it looks like this:

connection.addRequestProperty("Authorization", "Digest [don't know what goes here]");

The place where i put "don't know what goes here", can someone go through the steps in showing me what i need to put in there?

If i figure this out i can build a nice java library that communicates with the wallet-rpc that has authentication built it. Right now i am able to build the library without this authentication because i don't know how to do it, but would much prefer to have the added security of authentication.

  • For future reference, this problem doesn't seem to have much to do with Monero, per se, and you'll probably get more, and more complete answers on stackoverflow.com, in this case using the java tag. – Nate Jan 8 at 11:45

I took a look over here: https://en.wikipedia.org/wiki/Digest_access_authentication and from how I understand it you must do the following

Get the nonce and realm from that first message:


Then use the following flow:

HA1=MD5(MD5(username:realm:password):nonce:cnonce) //cnonce is a client nonce

Your response would look something like:

import java.security.*;


java.security.SecureRandom random = java.security.SecureRandom.getInstance("SHA1PRNG");
byte[] nonceBytes = new byte[16]; 

String clientNonce = new String(org.apache.commons.codec.binary.Base64.encodeBase64(nonceBytes), "UTF-8");
String serverNonce = "hHQVNuEdyZszjmEPwS/jkQ==";

String HA1String = "aladdin:monero-wallet-rpc:open sesame";
String HA2String = "GET:<your-uri>";
byte[] ha1Bytes = HA1String.getBytes("UTF-8");
byte[] ha2Bytes = HA2String.getBytes("UTF-8");

MessageDigest md = MessageDigest.getInstance("MD5");
String HA1_1 = new String(md.digest(ha1Bytes)) + ":" + serverNonce + ":" + clientNonce;
byte[] ha1_1 = HA1_1.getBytes("UTF-8");

String HA1 = new String(md.digest(ha1_1);
String HA2 = new String(md.digest(ha2Bytes));

String HA1nonceHA2 = HA1+ "hHQVNuEdyZszjmEPwS/jkQ==" + HA2;
byte[] ha1nonceha2bytes = HA1nonceHA2.getBytes("UTF-8");

String responseVal = new String(md.digest(ha1nonceha2bytes));

String response = "Digest "+
                 "nonce=\"" + serverNonce + "\",\r\n"+
                 "uri=\"" + <your-uri> + "\",\r\n"+
                 "nc=00000001,\r\n"+ //Increment this each time.
                 "cnonce=\"" + clientNonce + "\",\r\n"+
                 "response=\"" + responseVal + "\""

connection.addRequestProperty("Authorization", response);

That should at least get you close. Remember null checks etc.

  • Few comments, 1) extra ; in code (fixed, if my edit is approved), 2) putting \r\n chars in response gives me java.lang.IllegalArgumentException: illegal character(s) in message header value, 3) where you had new String(), I had to convert specifically to lowercase hex strings, which I did using DatatypeConverter.printHexBinary(bytes).toLowerCase(). This is consistent with the wiki entry. – Nate Jan 8 at 12:07
  • <Thread necromancer card award> Ha ha. I haven't written much in java so forgive my generic-like answers. There should be an HttpHeader object within some WebRequest type library that you can build and just add each header and value to when building the request. Thanks for the edits. – sk1tt1sh Jan 10 at 1:39

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.