public void setCredentials(HttpExchange exchange) throws IOException {
    StringBuilder buffer = new StringBuilder().append("Digest");

    buffer
        .append(" ")
        .append("username")
        .append('=')
        .append('"')
        .append(securityRealm.getPrincipal())
        .append('"');

    buffer
        .append(", ")
        .append("realm")
        .append('=')
        .append('"')
        .append(String.valueOf(details.get("realm")))
        .append('"');

    buffer
        .append(", ")
        .append("nonce")
        .append('=')
        .append('"')
        .append(String.valueOf(details.get("nonce")))
        .append('"');

    buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"');

    buffer
        .append(", ")
        .append("algorithm")
        .append('=')
        .append(String.valueOf(details.get("algorithm")));

    String cnonce = newCnonce(exchange, securityRealm, details);

    buffer
        .append(", ")
        .append("response")
        .append('=')
        .append('"')
        .append(newResponse(cnonce, exchange, securityRealm, details))
        .append('"');

    buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop")));

    buffer.append(", ").append("nc").append('=').append(NC);

    buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"');

    exchange.setRequestHeader(
        HttpHeaders.AUTHORIZATION, new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1)));
  }
  protected String newResponse(
      String cnonce, HttpExchange exchange, Realm securityRealm, Map details) {
    try {
      MessageDigest md = MessageDigest.getInstance("MD5");

      // calc A1 digest
      md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1));
      byte[] ha1 = md.digest();
      // calc A2 digest
      md.reset();
      md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1));
      byte[] ha2 = md.digest();

      md.update(TypeUtil.toString(ha1, 16).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(NC.getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1));
      md.update((byte) ':');
      md.update(TypeUtil.toString(ha2, 16).getBytes(StringUtil.__ISO_8859_1));
      byte[] digest = md.digest();

      // check digest
      return encode(digest);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }