Política de HMAC

Esta página se aplica a Apigee y Apigee Hybrid.

Consulta la documentación de Apigee Edge.

Esta política calcula y, opcionalmente, verifica un código de autenticación de mensajes basado en hash (HMAC). A veces se conoce como código de autenticación de mensajes con clave o hash con clave. HMAC usa una función de hash criptográfica, como SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 o MD-5, que se aplica a un mensaje junto con una clave secreta para generar una firma o un código de autenticación de mensajes en ese mensaje. El término "mensaje" hace referencia a cualquier flujo de bytes. En el uso habitual de HMAC, el remitente de un mensaje envía un mensaje y su HMAC a un receptor, y este puede usar el HMAC junto con la clave secreta compartida para autenticar el mensaje.

Esta política es una política estándar y se puede implementar en cualquier tipo de entorno. Para obtener información sobre los tipos de políticas y la disponibilidad de cada tipo de entorno, consulta Tipos de políticas.

Para obtener más información sobre HMAC, consulta HMAC: Keyed-Hashing for Message Authentication (rfc2104).

Ejemplos

Generar HMAC

<HMAC name='HMAC-1'>

  <Algorithm>SHA256</Algorithm>

  <!-- the default encoding of the SecretKey is UTF-8 -->
  <SecretKey encoding='base64' ref='private.secretkey'/>

  <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional -->

  <!--
    The Message element accepts a template, which means the "message" the policy operates
    on can include fixed and multiple variable parts, including newlines and static functions.
    Whitespace, such as newlines and space characters, is significant.
   -->
  <Message>Fixed Part
{a_variable}
{timeFormatUTCMs(timeFormatString1,system.timestamp)}
{nonce}</Message>

  <!-- default encoding is base64 -->
  <Output encoding='base16'>name_of_variable</Output>

</HMAC>

Verificar HMAC

<HMAC name='HMAC-1'>

  <Algorithm>SHA256</Algorithm>

  <!-- the default encoding of the SecretKey is UTF-8 -->
  <SecretKey encoding='base16' ref='private.secretkey'/>

  <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional -->

  <!--
     The Message element accepts a template. This policy verifies an HMAC on the request content.
   -->
  <Message>{request.content}</Message>

  <!--
    VerificationValue is optional.
    Include it to perform an HMAC check.
  -->
  <VerificationValue encoding='base16' ref='expected_hmac_value'/>

  <!-- default encoding of the output is base64 -->
  <Output encoding='base16'>name_of_variable</Output>

</HMAC>

El cálculo de una firma y la verificación de esa firma siguen exactamente el mismo proceso. La política HMAC calcula un HMAC y, opcionalmente, puede verificar la firma calculada con un valor esperado. El elemento VerificationValue opcional (si está presente) indica a la política que compruebe el valor calculado con un valor conocido o proporcionado.


Referencia de elementos para HMAC

En la referencia de la política se describen los elementos y atributos de la política HMAC.

Atributos que se aplican al elemento de nivel superior

<HMAC name="HMAC" continueOnError="false" enabled="true" async="false">

Los siguientes atributos son comunes a todos los elementos principales de la política.

Atributo Descripción Predeterminado Presencia
name El nombre interno de la política. Solo puedes usar los siguientes caracteres en el nombre: A-Z0-9._\-$ %. Sin embargo, la interfaz de usuario de Apigee aplica restricciones adicionales, como la eliminación automática de caracteres que no son alfanuméricos.

También puede usar el elemento <DisplayName> para etiquetar la política en el editor de proxy de la interfaz de usuario de Apigee con un nombre diferente en lenguaje natural.

N/A Obligatorio
continueOnError Asigna el valor false para devolver un error cuando falle una política. Este es el comportamiento esperado de la mayoría de las políticas.

Asigna el valor true para que la ejecución del flujo continúe incluso después de que falle una política. Consulta también:

falso Opcional
habilitada Asigna el valor true para aplicar la política.

Selecciona false para desactivar la política. La política no se aplicará, aunque siga adjunta a un flujo.

true Opcional
asíncrono Este atributo está obsoleto. falso Obsoleto

<Algorithm>

<Algorithm>algorithm-name</Algorithm>

Especifica el algoritmo hash que se va a usar al calcular el HMAC.

Predeterminado N/A
Presencia Obligatorio
Tipo Cadena
Valores válidos SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 y MD-5

La configuración de la política acepta nombres de algoritmos sin distinguir entre mayúsculas y minúsculas, y con o sin guion entre las letras y los números. Por ejemplo, SHA256, SHA-256 y sha256 son equivalentes.

<DisplayName>

<DisplayName>Policy Display Name</DisplayName>

Se usa junto con el atributo name para etiquetar la política en el editor de proxies de la interfaz de usuario de Apigee con un nombre diferente en lenguaje natural.

Predeterminado Si omite este elemento, se usará el valor del atributo name de la política.
Presencia Opcional
Tipo Cadena

<Message>

<Message>message_template_here</Message>
or
<Message ref='variable_here'/>

Especifica la carga útil del mensaje que se va a firmar. La entrada de este elemento admite plantillas de mensajes (sustitución de variables) para incluir elementos adicionales en el tiempo de ejecución, como marcas de tiempo, nonces, listas de encabezados u otra información. Por ejemplo:

<Message>Fixed Part
    {a_variable}
    {timeFormatUTCMs(timeFormatString1,system.timestamp)}
    {nonce}
</Message>

La plantilla de mensaje puede incluir partes fijas y variables, como saltos de línea y funciones estáticas. Los espacios en blanco, como los saltos de línea y los espacios, son significativos.

Predeterminado N/A
Presencia Obligatorio
Tipo Cadena
Valores válidos Se puede usar cualquier cadena como valor de texto. Si proporciona un atributo ref, tendrá prioridad sobre el valor de texto. La política evalúa el valor de texto o la variable a la que se hace referencia como una plantilla de mensaje.

<Output>

<Output encoding='encoding_name'>variable_name</Output>

Especifica el nombre de la variable que la política debe definir con el valor HMAC calculado. También especifica la codificación que se va a usar en la salida.

Predeterminado

La variable de salida predeterminada es hmac.POLICYNAME.output.

El valor predeterminado del atributo encoding es base64.

Presencia Opcional. Si este elemento no está presente, la política asigna a la variable de flujo hmac.POLICYNAME.output un valor codificado en base64.
Tipo Cadena
Valores válidos

Para la codificación, hex, base16, base64 y base64url.

El sistema no distingue entre mayúsculas y minúsculas. Por ejemplo, hex y base16 son sinónimos.

El valor de texto del elemento Output puede ser cualquier nombre de variable de flujo válido.

<SecretKey>

<SecretKey encoding='encoding_name' ref='private.secretkey'/>

Especifica la clave secreta que se usa para calcular el HMAC. La clave se obtiene de la variable a la que se hace referencia y se decodifica según la codificación específica.

Predeterminado

No hay ningún valor predeterminado para la variable de referencia; el atributo ref es obligatorio.

Si no se incluye el atributo encoding, la política decodifica de forma predeterminada la cadena de clave secreta con UTF-8 para obtener los bytes de la clave.

Presencia Obligatorio
Tipo Cadena
Valores válidos

En el caso de encoding, los valores válidos son hex, base16, base64 y utf8. El valor predeterminado es UTF8. En estos valores, el sistema no distingue entre mayúsculas y minúsculas, y los guiones no tienen importancia. Base16 es lo mismo que base-16 y bAse16. Base16 y Hex son sinónimos.

El uso de un atributo de codificación le permite especificar una clave que incluya bytes fuera del intervalo de caracteres imprimibles UTF-8. Por ejemplo, supongamos que la configuración de la política incluye lo siguiente:

 <SecretKey encoding='hex' ref='private.encodedsecretkey'/>

Supongamos que private.encodedsecretkey contiene la cadena 536563726574313233.

En este caso, los bytes de la clave se decodificarán como [53 65 63 72 65 74 31 32 33] (cada byte representado en hexadecimal). Por ejemplo, si usa encoding='base64', y private.encodedsecretkey contiene la cadena U2VjcmV0MTIz, se obtendrá el mismo conjunto de bytes para la clave. Si no se incluye el atributo de codificación o se incluye con el valor UTF8, la cadena Secret123 dará como resultado el mismo conjunto de bytes. En este ejemplo se muestran tres formas diferentes de representar la misma clave.

<VerificationValue>

<VerificationValue encoding='encoding_name' ref='variable_name'/>
or
<VerificationValue encoding='encoding_name'>string_value</VerificationValue>

(Opcional) Especifica el valor de verificación, así como la codificación que se ha usado para codificar el valor de verificación. La política usará esta codificación para decodificar el valor.

Predeterminado No hay ningún valor de verificación predeterminado. Si el elemento está presente, pero el atributo encoding no, la política usa una codificación predeterminada de base64.
Presencia Opcional
Tipo Cadena
Valores válidos

Los valores válidos del atributo de codificación son: hex, base16, base64 y base64url. Los valores no distinguen entre mayúsculas y minúsculas; hex y base16 son sinónimos.

La codificación de VerificationValue no tiene por qué ser la misma que la que se usa para el elemento Output.

<IgnoreUnresolvedVariables>

<IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables>

Asigna el valor false si quieres que la política genere un error cuando no se pueda resolver ninguna variable de referencia especificada en la política. Asigna el valor true para tratar cualquier variable que no se pueda resolver como una cadena vacía (nula).

El booleano IgnoreUnresolvedVariables solo afecta a las variables a las que hace referencia la plantilla de mensaje. Aunque SecretKey y VerificationValue pueden hacer referencia a una variable, ambas deben poder resolverse, por lo que el ajuste ignore no se aplica a ellas.

Predeterminado Falso
Presencia Opcional
Tipo Booleano
Valores válidos verdadero o falso

Variables de flujo

La política puede definir estas variables durante la ejecución.

Variable Descripción Ejemplo
hmac.policy_name.message La política asigna a esta variable el mensaje efectivo, que es el resultado de evaluar la plantilla de mensaje especificada en el elemento Message. hmac.HMAC-Policy.message = "Hello, World"
hmac.policy_name.output Obtiene el resultado del cálculo de HMAC cuando el elemento Output no especifica un nombre de variable. hmac.HMAC-Policy.output = /yyRjydfP+fBHTwXFgc5AZhLAg2kwCri+e35girrGw4=
hmac.policy_name.outputencoding Obtiene el nombre de la codificación de salida. hmac.HMAC-Policy.outputencoding = base64

Incidencias frecuentes

En un nivel, la política de HMAC parece sencilla: proporciona una clave y un mensaje, y obtén un HMAC calculado como respuesta. Puede ser frustrante usar la política si obtienes un valor HMAC inesperado para una combinación de mensaje y clave conocida. En esta sección se explican algunas notas de uso para solucionar estos problemas.

Hay dos errores habituales que provocan que los HMACs no coincidan durante la verificación: diferencias en los espacios en blanco del mensaje y diferencias en la codificación y descodificación. Esto se aplica tanto al elemento SecretKey como al elemento Output.

Diferencias de espacios en blanco

Las diferencias que pueden parecer poco importantes para una persona afectan al valor HMAC de salida. Por ejemplo, supongamos que una clave secreta se puede representar como "Secret123". Con la decodificación UTF-8, los bytes de la clave serán: [53 65 63 72 65 74 31 32 33]. Si se usa esa clave para calcular un HMAC-SHA256 en el mensaje abc, se obtiene a7938720fe5749d31076e6961360364c0cd271443f1b580779932c244293bc94. Si se añade un espacio al mensaje, de modo que sea abc<SPACE>, donde <SPACE> implica un ASCII 32, se obtiene un HMAC-SHA256 de 274669b2a85d2532da48e2ce3d8e52ee17346d1bcd1a606d87db1934b5ab294b.

Del mismo modo, si el mensaje es abc<NEWLINE>, donde <NEWLINE> implica un ASCII 10, el HMAC es 0780370844ca07f896066837e8230d3b6a775f678a4ae03e6b5e864c674831f5. Si se hacen pequeños cambios en el mensaje, los valores de HMAC serán muy diferentes. Es un comportamiento programado. Este es el comportamiento previsto y deseado de HMAC.

Conclusión: Es importante asegurarse de que el cuerpo del mensaje que se usa para calcular el HMAC original y el cuerpo del mensaje que se usa para verificar el HMAC sean exactamente iguales. Si el verificador de un HMAC cambia la carga útil del mensaje de alguna forma, ya sea añadiendo espacios en blanco o reformateando el texto, el HMAC calculado cambiará.

Presta especial atención al usar una plantilla de mensaje en la configuración de la política. Por ejemplo, este fragmento de configuración de la política muestra un posible problema:

<HMAC name='HMAC-1'>
    ...
    <!-- the result of this message template will include surrounding whitespace -->
    <Message>
        {request.content}
    </Message>
    ...
       
</HMAC>

El resultado de evaluar la plantilla de mensaje en el elemento <Message> incluirá saltos de línea y espacios alrededor del contenido del mensaje. Probablemente no es lo que se pretende. Una configuración mejor tendría este aspecto:

<HMAC name='HMAC-1'>
    ...
    <Message>{request.content}</Message>
    ...
         
</HMAC>

Diferencias en la codificación

Las diferentes decodificaciones del mismo material de claves dan lugar a claves diferentes. Supongamos que una clave secreta que se puede representar como "U2VjcmV0S2V5MTIz". Con la decodificación UTF-8, los bytes de la clave, representados en base16, serán [55 32 56 6a 63 6d 56 30 53 32 56 35 4d 54 49 7a]. Con la decodificación en base64, los bytes de la clave serán [53 65 63 72 65 74 4b 65 79 31 32 33]. Si el material de origen se decodifica de forma diferente, se obtendrán claves distintas, lo que dará lugar a valores HMAC diferentes.

Conclusión: Es importante asegurarse de que el material de claves utilizado para calcular el HMAC original y la clave utilizada para verificar el HMAC sean exactamente iguales. Probablemente significa que se debe usar la misma codificación de la clave en ambos extremos. En la política de HMAC, puedes usar el atributo encoding en el SecretKeyelemento para especificar la codificación de la clave.

También debes tener en cuenta las codificaciones de la salida. Un HMAC-SHA256 expresado en codificación hexadecimal o base16, como 27f17e11c8ece93844c5eb5e55161d993368628a214f9a51c25d0185e8ea06e2, es lo mismo que un HMAC-SHA256 expresado en formato codificado en base64, como J/F+Ecjs6ThExeteVRYdmTNoYoohT5pRwl0BhejqBuI=. Aunque tienen un aspecto diferente, estas dos cadenas representan el mismo valor. Asegúrate de que se usa la misma codificación para codificar el HMAC calculado originalmente y el HMAC de verificación. En la política de HMAC, puede usar el atributo encoding en el Outputelemento para especificar la codificación de salida que quiera, y el mismo atributo en el VerificationValueelemento para especificar cómo decodificar el verificador.

Error reference

This section describes the fault codes and error messages that are returned and fault variables that are set by Apigee when this policy triggers an error. This information is important to know if you are developing fault rules to handle faults. To learn more, see What you need to know about policy errors and Handling faults.

Runtime errors

These errors can occur when the policy executes.

Fault code HTTP status Occurs when
steps.hmac.UnresolvedVariable 401

This error occurs if a variable specified in the HMAC policy is either:

  • Out of scope (not available in the specific flow where the policy is being executed)

    or

  • Can't be resolved (is not defined)
steps.hmac.HmacVerificationFailed 401 The HMAC verification failed; the verification value provided does not match the calculated value.
steps.hmac.HmacCalculationFailed 401 The policy was unable to calculate the HMAC.
steps.hmac.EmptySecretKey 401 The value of the secret key variable is empty.
steps.hmac.EmptyVerificationValue 401 The variable holding the verification value is emtpy.

Deployment errors

These errors can occur when you deploy a proxy containing this policy.

Error name HTTP status Occurs when
steps.hmac.MissingConfigurationElement 401 This error occurs when a required element or attribute is missing.
steps.hmac.InvalidValueForElement 401 This error occurs if the value specified in the Algorithm element is not one of the following values: SHA-1, SHA-224, SHA-256, SHA-512, or MD-5.
steps.hmac.InvalidSecretInConfig 401 This error occurs if there is a text value explicitly provided for SecretKey.
steps.hmac.InvalidVariableName 401 This error occurs if the SecretKey variable does not contain the private prefix (private.).

Fault variables

These variables are set when a runtime error occurs. For more information, see What you need to know about policy errors.

Variables Where Example
fault.name="fault_name" fault_name is the name of the fault, as listed in the Runtime errors table above. The fault name is the last part of the fault code. fault.name Matches "UnresolvedVariable"
hmac.policy_name.failed The policy sets this variable in the case of a failure. hmac.HMAC-Policy.failed = true

Example error response

For error handling, the best practice is to trap the errorcode part of the error response. Do not rely on the text in the faultstring, because it could change.

Example fault rule

<FaultRules>
    <FaultRule name="HMAC Policy Errors">
        <Step>
            <Name>AM-Unauthorized</Name>
            <Condition>(fault.name Matches "HmacVerificationFailed")</Condition>
        </Step>
        <Condition>hmac.HMAC-1.failed = true</Condition>
    </FaultRule>
</FaultRules>