String createCanonicalRequest(HttpUriRequest request) { StringBuilder result = new StringBuilder(); result.append(request.getMethod()).append('\n'); String path = request.getURI().getPath(); if (path.isEmpty()) { path = "/"; } result.append(path).append('\n'); String queryString = request.getURI().getQuery(); queryString = queryString != null ? queryString : ""; addCanonicalQueryString(queryString, result).append('\n'); addCanonicalHeaders(request, result).append('\n'); HttpEntity entity = null; try { if (request instanceof HttpEntityEnclosingRequestBase) { entity = ((HttpEntityEnclosingRequestBase) request).getEntity(); } else { entity = new StringEntity(""); } InputStream content = entity.getContent(); addHashedPayload(content, result); } catch (IOException e) { throw new RuntimeException("Could not create hash for entity " + entity, e); } return result.toString(); }
StringBuilder addSignedHeaders( SortedMap<String, String> sortedFormattedHeaders, StringBuilder builder) { int startingLength = builder.length(); for (String headerName : sortedFormattedHeaders.keySet()) { if (builder.length() > startingLength) { builder.append(';'); } builder.append(headerName); } return builder; }
StringBuilder addCanonicalHeaders( SortedMap<String, String> sortedFormattedHeaders, StringBuilder builder) { for (Map.Entry<String, String> entry : sortedFormattedHeaders.entrySet()) { builder.append(entry.getKey()).append(':').append(entry.getValue()).append('\n'); } return builder; }
StringBuilder addCanonicalQueryString(String queryString, StringBuilder builder) { int startingLength = builder.length(); SortedMap<String, String> encodedParams = new TreeMap<>(); for (String queryParam : queryString.split("&")) { if (!queryParam.isEmpty()) { String[] parts = queryParam.split("=", 2); encodedParams.put(encodeQueryStringValue(parts[0]), encodeQueryStringValue(parts[1])); } } for (Map.Entry<String, String> entry : encodedParams.entrySet()) { if (builder.length() > startingLength) { builder.append('&'); } builder.append(entry.getKey()).append('=').append(entry.getValue()); } return builder; }
StringBuilder addHashedPayload(InputStream payload, StringBuilder builder) throws IOException { return builder.append(toHexString(sha256(payload))); }