code: public String computeHash(WebContext ctx, String pathPrefix) throws Exception {
          Matcher matcher = AWS_AUTH4_PATTERN.matcher(ctx.getHeaderValue("Authorization").asString(""));
  
          if (!matcher.matches()) {
              // If the header doesn't match, let's try an URL parameter as we might be processing a presigned URL
              matcher = X_AMZ_CREDENTIAL_PATTERN.matcher(ctx.get("X-Amz-Credential").asString(""));
              if (!matcher.matches()) {
                  throw new IllegalArgumentException("Unknown AWS4 auth pattern");
              }
          }
  
          String date = matcher.group(2);
          String region = matcher.group(3);
          String service = matcher.group(4);
          String serviceType = matcher.group(5);
  
          // For header based requests, the signed headers are in the "Credentials" header, for presigned URLs
          // an extra parameter is given...
          String signedHeaders = matcher.groupCount() == 7 ? matcher.group(6) : ctx.get("X-Amz-SignedHeaders").asString();
  
          byte[] dateKey = hmacSHA256(("AWS4" + storage.getAwsSecretKey()).getBytes(Charsets.UTF_8), date);
          byte[] dateRegionKey = hmacSHA256(dateKey, region);
          byte[] dateRegionServiceKey = hmacSHA256(dateRegionKey, service);
          byte[] signingKey = hmacSHA256(dateRegionServiceKey, serviceType);
  
          byte[] signedData = hmacSHA256(signingKey, buildStringToSign(ctx, signedHeaders, region, service, serviceType));
          return BaseEncoding.base16().lowerCase().encode(signedData);
      }
docs: Computes the authentication hash as specified by the AWS SDK for verification purposes.
  
  @param ctx        the current request to fetch parameters from
  @param pathPrefix the path prefix to preped to the {@link S3Dispatcher#getEffectiveURI(WebContext) effective URI}
  of the request
  @return the computes hash value
  @throws Exception when hashing fails