// Path: httpsig/callout/src/main/java/com/google/apigee/util/TimeResolver.java
// public class TimeResolver {
//     private static final Pattern expiryPattern =
//         Pattern.compile("^([1-9][0-9]*)(s|m|h|d|w|)$", Pattern.CASE_INSENSITIVE);
//     private static final Map<String, Long> timeMultipliers;
//     private static String defaultUnit = "s";
// 
//     static {
//       Map<String, Long> m1 = new HashMap<String, Long>();
//       m1.put("s", 1L );
//       m1.put("m", 60L);
//       m1.put("h", 60L * 60 );
//       m1.put("d", 60L * 60 * 24 );
//       m1.put("w", 60L * 60 * 24 * 7 );
//       timeMultipliers = Collections.unmodifiableMap(m1);
//     }
// 
//     public static ZonedDateTime getExpiryDate(String expiresInString) {
//       Long milliseconds = resolveExpression(expiresInString);
//       Long seconds = milliseconds / 1000;
//       int secondsToAdd = seconds.intValue();
//       if (secondsToAdd <= 0) return null; /* no expiry */
//       ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
//       zdt = zdt.plusSeconds(secondsToAdd);
//       return zdt;
//     }
// 
//     /*
//      * Convert a simple time duration string, expressed in days, hours, minutes,
//      * or seconds, in a form like 30d, 12d, 8h, 24h, 45m, 30s, into a numeric
//      * quantity in seconds.  Eg, "10s" is converted to 10. "10m" is converted to 600.
//      *
//      * Default TimeUnit is s. Eg. the string "30" is treated as 30s.
//      */
//     public static Long resolveExpression(String subject) {
//       Matcher m = expiryPattern.matcher(subject);
//       if (m.find()) {
//         String key = m.group(2);
//         if (key.equals("")) key = defaultUnit;
//         return Long.parseLong(m.group(1), 10) * timeMultipliers.get(key);
//       }
//       return -1L;
//     }
//   }


import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.apigee.util.TimeResolver;
import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

        List<String> list = new ArrayList<String>();
        list.add("keyId");
        list.add("algorithm");
        list.add("headers");
        list.add("signature");
        list.add("created");
        list.add("expires");
        knownSignatureItems = Collections.unmodifiableList(list);
    }

    public static boolean isSupportedAlgorithm(String alg){
        return alg.equals("hs2019") || supportedAlgorithms.containsKey(alg);
    }

    public static HttpSignature forVerification(String s) throws IllegalStateException {
        HttpSignature sig = new HttpSignature();
        sig.parseHttpSignatureString(s);
        sig._mode = Mode.VERIFYING;
        return sig;
    }

    public static HttpSignature forGeneration(boolean wantCreated, String expiresIn)
    {
        HttpSignature sig = new HttpSignature();
        if (wantCreated) {
            long now = ZonedDateTime.now().toEpochSecond();
            sig.params.put("created", (Integer) Math.toIntExact(now));

            if (expiresIn != null) {
// Path: httpsig/callout/src/main/java/com/google/apigee/util/TimeResolver.java
// public class TimeResolver {
//     private static final Pattern expiryPattern =
//         Pattern.compile("^([1-9][0-9]*)(s|m|h|d|w|)$", Pattern.CASE_INSENSITIVE);
//     private static final Map<String, Long> timeMultipliers;
//     private static String defaultUnit = "s";
// 
//     static {
//       Map<String, Long> m1 = new HashMap<String, Long>();
//       m1.put("s", 1L );
//       m1.put("m", 60L);
//       m1.put("h", 60L * 60 );
//       m1.put("d", 60L * 60 * 24 );
//       m1.put("w", 60L * 60 * 24 * 7 );
//       timeMultipliers = Collections.unmodifiableMap(m1);
//     }
// 
//     public static ZonedDateTime getExpiryDate(String expiresInString) {
//       Long milliseconds = resolveExpression(expiresInString);
//       Long seconds = milliseconds / 1000;
//       int secondsToAdd = seconds.intValue();
//       if (secondsToAdd <= 0) return null; /* no expiry */
//       ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
//       zdt = zdt.plusSeconds(secondsToAdd);
//       return zdt;
//     }
// 
//     /*
//      * Convert a simple time duration string, expressed in days, hours, minutes,
//      * or seconds, in a form like 30d, 12d, 8h, 24h, 45m, 30s, into a numeric
//      * quantity in seconds.  Eg, "10s" is converted to 10. "10m" is converted to 600.
//      *
//      * Default TimeUnit is s. Eg. the string "30" is treated as 30s.
//      */
//     public static Long resolveExpression(String subject) {
//       Matcher m = expiryPattern.matcher(subject);
//       if (m.find()) {
//         String key = m.group(2);
//         if (key.equals("")) key = defaultUnit;
//         return Long.parseLong(m.group(1), 10) * timeMultipliers.get(key);
//       }
//       return -1L;
//     }
//   }


// Path: httpsig/callout/src/main/java/com/google/apigee/callout/httpsignature/HttpSignature.java
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.apigee.util.TimeResolver;
import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


        List<String> list = new ArrayList<String>();
        list.add("keyId");
        list.add("algorithm");
        list.add("headers");
        list.add("signature");
        list.add("created");
        list.add("expires");
        knownSignatureItems = Collections.unmodifiableList(list);
    }

    public static boolean isSupportedAlgorithm(String alg){
        return alg.equals("hs2019") || supportedAlgorithms.containsKey(alg);
    }

    public static HttpSignature forVerification(String s) throws IllegalStateException {
        HttpSignature sig = new HttpSignature();
        sig.parseHttpSignatureString(s);
        sig._mode = Mode.VERIFYING;
        return sig;
    }

    public static HttpSignature forGeneration(boolean wantCreated, String expiresIn)
    {
        HttpSignature sig = new HttpSignature();
        if (wantCreated) {
            long now = ZonedDateTime.now().toEpochSecond();
            sig.params.put("created", (Integer) Math.toIntExact(now));

            if (expiresIn != null) {
                Long lifetimeInSeconds = TimeResolver.resolveExpression(expiresIn);