La firma de solicitud que calculamos no coincide con la firma que proporcionó, incluso la firma creada

La firma se crea con éxito cuando se transmite como autorización para acceder al servicio, enfrentando un error como La firma de solicitud que calculamos no coincide con la firma que proporcionó.

Debajo de la clase utilizada para crear la autorización. Bienvenida.

clase pública Canónica {}

  //public static String authorization_header;
  public static String auth() throws Exception  {
      
      //canonical string creation
      String currentDate  = getDate();
      String xAmzDate = getTimeStamp();
      String region = "eu-west-1";
      String serviceName ="execute-api";
      
      String canonical_uri = "pathdetailsofservice";
      
      URL url = new URL("endpointurl");
      String req_query_string = orderQuery(url );
      String canonical_querystring = req_query_string;
      String host ="dataservices.whssng.uk";
      String method ="POST";
      String ContentType ="application/json";
      String canonical_headers = "host:" + host + "\n" + "x-amz-date:" + xAmzDate + "\n";
      String signed_headers = "Content-Type;host;x-amz-date";
      String secret_key ="secretkey";
      String access_key ="accesskey";
      
      String request_parameters = "";
      String payload_hash = generateHex(request_parameters);
      String canonical_request = method + "\n" + canonical_uri + "\n" + ContentType+ "\n" + canonical_querystring + "\n" + canonical_headers + "\n" + signed_headers + "\n" + payload_hash;
      System.out.println("canonical_request"+"\n"+canonical_request);
      
      //Create  String to Sign
      
      String algorithm = "AWS4-HMAC-SHA256";
              String credential_scope = currentDate + "/" + region + "/" + serviceName + "/" + "aws4_request";
              String hash_canonical_request = generateHex(canonical_request);
              String string_to_sign = algorithm + "\n" +  xAmzDate + "\n" +  credential_scope + "\n" +  hash_canonical_request;
      System.out.println("string_to_sign"+"\n"+string_to_sign);
      
  ////Calculate the String to Sign
      
  byte[] signing_key = getSignatureKey(secret_key, xAmzDate, region, serviceName);
  byte[] signature =hmac_sha256(signing_key, string_to_sign);
  String strHexSignature = bytesToHex(signature);
   System.out.println("Signature:"+strHexSignature);
   
   
  //Add Signing information to Variable
   
  
  String authorization_header = algorithm + " " + "Credential=" + access_key + "/" + credential_scope + ", " +  "SignedHeaders=" +

sign_headers + ", " + "Signature=" + strHexSignature; System.out.println("Authorization:"+authorization_header); autorización de devolución_header;

}

  
private static String generateHex(String data) {
        MessageDigest messageDigest;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(data.getBytes("UTF-8"));
            byte[] digest = messageDigest.digest();
            return String.format("%064x", new java.math.BigInteger(1, digest));
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

public static String getDate() {
    DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//server timezone
    return dateFormat.format(new Date());
}


public static String orderQuery(URL url) throws UnsupportedEncodingException {

    String orderQueryString = "";
    Map queryPairs = new LinkedHashMap<>();
    String queryParams = url.getQuery();

    if (queryParams != null) {
        String[] pairs = queryParams.split("&");
    
        for (String pair : pairs) {
            int idx = pair.indexOf("=");
            queryPairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
        }
       TreeMap orderQueryArray = new TreeMap(queryPairs);
        orderQueryString  = urlEncodeUTF8(orderQueryArray);
    }
    return orderQueryString;
}


public static String urlEncodeUTF8(String s) {
    try {
        return URLEncoder.encode(s, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        throw new UnsupportedOperationException(e);
    }
}

public static String urlEncodeUTF8(Map,? map) {
    StringBuilder sb = new StringBuilder();
    for (Map.Entry,? entry : map.entrySet()) {
        if (sb.length() > 0) {
            sb.append("&");
        }
        sb.append(String.format("%s=%s",
            urlEncodeUTF8(entry.getKey().toString()),
            urlEncodeUTF8(entry.getValue().toString())
        ));
    }
    return sb.toString();       
}



public static String getTimeStamp() {
    DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//server timezone
    return dateFormat.format(new Date());
}


public static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
    byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
    byte[] kDate = hmac_sha256(kSecret, dateStamp);
    byte[] kRegion = hmac_sha256(kDate, regionName);
    byte[] kService = hmac_sha256(kRegion, serviceName);
    byte[] kSigning = hmac_sha256(kService, "aws4_request");
    return kSigning;
}




public static byte[]  hmac_sha256(byte[] key, String data) throws InvalidKeyException, NoSuchAlgorithmException {
    Mac mac = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
    mac.init(secretKeySpec);
    byte[] digest = mac.doFinal(data.getBytes());
    return digest;
     
 
    
}
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars).toLowerCase();
}
}

Pregunta hecha hace 3 años, 4 meses, 28 días - Por codexcrafter


2 Respuestas:

  • Veamos el código proporcionado para buscar posibles errores que puedan causar que la firma de solicitud calculada no coincida con la firma proporcionada.

    Al revisar el código, parece que tienes una clase pública llamada Canonica, la cual contiene un método auth() para crear la autorización de acceso a un servicio. En este método, se generan diversos componentes como la cadena canónica, la cadena para firmar, y finalmente la firma en sí.

    Para abordar el error de que la firma calculada no coincide con la proporcionada, aquí hay algunas posibles áreas que podrían requerir atención:

    • Comparación de Firma Calculada con Firma Proporcionada:
    - Verifica que la firma calculada (strHexSignature) coincida exactamente con la firma que se proporciona al servicio. Puedes compararlas visualmente o implementar una verificación más rigurosa en tu código.

    • Código de Generación de Firma:
    - Revisa la lógica de generación de la firma para asegurarte de que esté siguiendo el mismo algoritmo y configuración requerida por el servicio al que estás accediendo. Puede ser útil comparar los pasos de generación de firma con la documentación del servicio.

    • Cadenas Utilizadas para Crear la Firma:
    - Asegúrate de que todas las cadenas utilizadas en la generación de la firma (como el método HTTP, la URI canónica, los encabezados, etc.) coincidan exactamente con lo esperado por el servicio al que estás accediendo.

    • Problemas de Codificación o Formato:
    - Verifica que no haya problemas relacionados con la codificación de cadenas, especialmente al manipular datos sensibles como las credenciales de acceso. Asegúrate de que todos los datos se estén formateando correctamente.

    Te recomendaría revisar cuidadosamente cada uno de estos puntos y realizar pruebas exhaustivas para identificar cualquier discrepancia que pueda estar causando el error reportado. Además, ten en cuenta cualquier especificación adicional proporcionada por el servicio con respecto a la generación y envío de la firma de autorización.

    Respondida el Dec 19, 2020 a las 04:57 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema:

    La firma de la solicitud calculada no coincide con la firma proporcionada por el servicio, lo que lleva al error "La firma de la solicitud que calculamos no coincide con la firma que proporcionó".

    Causa posible:

    Hay un problema en el código que genera la firma de la solicitud.

    Solución:

    Revise cuidadosamente el código y busque cualquier discrepancia o error. Aquí hay algunas áreas específicas a considerar:

    Firma de la solicitud: Asegúrese de que el método canonical_request esté creando correctamente la cadena de solicitud canónica. Firma de la cadena: Verifique que el método string_to_sign esté creando correctamente la cadena que se firmará. Clave de firma: Confirme que el método getSignatureKey esté generando correctamente la clave de firma. Firma: Compruebe que el método hmac_sha256 esté calculando correctamente la firma. Codificación: Verifique que el método bytesToHex esté convirtiendo correctamente los bytes de firma en una cadena hexadecimal.

    Consejos adicionales:

    Utilice un depurador para seguir el flujo del código y verificar los valores calculados en cada paso. Mantenga el código lo más simple posible para reducir las posibilidades de errores. Compare su código con un ejemplo de trabajo o documentación oficial para detectar diferencias. Considere utilizar una biblioteca existente para generar firmas de solicitudes para evitar problemas de implementación manual.

    Código actualizado (correcciones sugeridas):

    
    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.net.URL;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.time.ZoneOffset;
    import java.time.ZonedDateTime;
    import java.util.Arrays;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.TreeMap;
    
    public class Canonical {
    
        public static String auth() throws Exception {
    
            // Canonical String Creation
            String currentDate = getDate();
            String xAmzDate = getTimeStamp();
            String region = "eu-west-1";
            String serviceName = "execute-api";
            String canonicalUri = "pathdetailsofservice";
    
            // Request URL and Query String
            URL url = new URL("endpointurl");
            String reqQueryString = orderQuery(url);
            String canonicalQueryString = reqQueryString;
            String host = "dataservices.whssng.uk";
            String method = "POST";
            String contentType = "application/json";
    
            // Canonical Headers
            String canonicalHeaders = "host:" + host + "\n" +
                    "x-amz-date:" + xAmzDate + "\n";
            String signedHeaders = "Content-Type;host;x-amz-date";
            String secretKey = "secretkey";
            String accessKey = "accesskey";
            String requestParameters = "";
            String payloadHash = generateHex(requestParameters);
    
            // Canonical Request
            String canonicalRequest = method + "\n" + canonicalUri + "\n" + contentType + "\n" +
                    canonicalQueryString + "\n" + canonicalHeaders + "\n" +
                    signedHeaders + "\n" + payloadHash;
    
            // String to Sign
            String algorithm = "AWS4-HMAC-SHA256";
            String credentialScope = currentDate + "/" + region + "/" + serviceName + "/" + "aws4_request";
            String hashCanonicalRequest = generateHex(canonicalRequest);
            String stringToSign = algorithm + "\n" + xAmzDate + "\n" +
                    credentialScope + "\n" + hashCanonicalRequest;
    
            // Calculate the String to Sign
            byte[] signingKey = getSignatureKey(secretKey, xAmzDate, region, serviceName);
            byte[] signature = hmacSha256(signingKey, stringToSign);
            String strHexSignature = bytesToHex(signature);
    
            // Authorization Header
            String authorizationHeader = algorithm + " " +
                    "Credential=" + accessKey + "/" + credentialScope + ", " +
                    "SignedHeaders=" + signedHeaders + ", " +
                    "Signature=" + strHexSignature;
    
            return authorizationHeader;
        }
    
        private static String generateHex(String data) {
            try {
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                byte[] digest = md.digest(data.getBytes("UTF-8"));
                return String.format("%064x", new java.math.BigInteger(1, digest));
            } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static String getDate() {
            DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
            return dateFormat.format(new java.util.Date());
        }
    
        private static String getTimeStamp() {
            ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
            return utc.format(java.time.format.DateTimeFormatter.ISO_DATE_TIME);
        }
    
        private static String orderQuery(URL url) {
            String orderQueryString = "";
    
            Map queryPairs = new LinkedHashMap<>();
            String queryParams = url.getQuery();
    
            if (queryParams != null) {
                String[] pairs = queryParams.split("&");
                for (String pair : pairs) {
                    int idx = pair.indexOf("=");
                    queryPairs.put(
                            URLEncoder.encode(pair.substring(0, idx), "UTF-8"),
                            URLEncoder.encode(pair.substring(idx + 1), "UTF-8")
                    );
                }
    
                TreeMap orderedQueryArray = new TreeMap<>(queryPairs);
                orderQueryString = urlEncodeUTF8(orderedQueryArray);
            }
            return orderQueryString;
        }
    
        private static String urlEncodeUTF8(Map map) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry entry : map.entrySet()) {
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(String.format("%s=%s",
                        urlEncodeUTF8(entry.getKey().toString()),
                        urlEncodeUTF8(entry.getValue().toString())
                ));
            }
            return sb.toString();
        }
    
        private static String urlEncodeUTF8(String s) {
            try {
                return URLEncoder.encode(s, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
    
        private static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) {
            byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
            byte[] kDate = hmacSha256(kSecret, dateStamp);
            byte[] kRegion = hmacSha256(kDate, regionName);
            byte[] kService = hmacSha256(kRegion, serviceName);
            byte[] kSigning = hmacSha256(kService, "aws4_request");
            return kSigning;
        }
    
        private static byte[] hmacSha256(byte[] key, String data) {
            try {
                Mac mac = Mac.getInstance("HmacSHA256");
                SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
                mac.init(secretKeySpec);
                return mac.doFinal(data.getBytes("UTF-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static String bytesToHex(byte[] bytes) {
            StringBuilder hexString = new StringBuilder();
    
            for (byte b : bytes) {
                hexString.append(String.format("%02X", b));
            }
    
            return hexString.toString();
        }
    
        public static void main(String[] args) {
            String authorizationHeader;
            try {
                authorizationHeader = auth();
                System.out.println("Authorization: " + authorizationHeader);
            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
        }
    }
    

    Prueba:

    Ejecute el programa para generar la firma de la solicitud. Compare la firma generada con la proporcionada por el servicio. Las firmas deben coincidir si el código funciona correctamente.

    Respondida el Dec 19, 2020 a las 05:00 - por Gemini

    Votos positivos: 0 | Votos negativos: 0