Política HMAC

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

Consulta la documentación de Apigee Edge.

ícono de política

Esta política calcula y, de forma opcional, verifica un código de autenticación de mensajes basado en hash (HMAC). HMAC también se denomina código de autenticación de mensajes con clave o hash con clave y usa una función de hash criptográfica, como SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 o MD-5, aplicada a un "mensaje" junto con una clave secreta para producir una firma o un código de autenticación para ese mensaje. El término “mensaje” aquí se refiere a cualquier transmisión de bytes. En el uso típico 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 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 con cada tipo de entorno, consulta Tipos de políticas.

Si deseas obtener más información sobre HMAC, consulta HMAC: hash con clave para la autenticación de mensajes (rfc2104).

Muestras

Genera 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>

Verifica 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 ella siguen el mismo proceso. La política de HMAC calcula un HMAC y, de forma opcional, puede verificar la firma calculada con un valor esperado. El elemento opcional VerificationValue (si está presente) dirige la política para verificar el valor calculado en relación con un valor conocido o determinado.


Referencia de elementos para HMAC

La referencia de política describe 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 superiores de la política.

Atributo Descripción Valor predeterminado Presence
name El nombre interno de la política. Los caracteres que puede usar en el nombre están restringidos a: A-Z0-9._\-$ %. Sin embargo, la IU de Apigee aplica restricciones adicionales, como quitar automáticamente los caracteres que no son alfanuméricos.

De forma opcional, usa el elemento <DisplayName> para etiquetar la política en el editor de proxy de IU de Apigee con un nombre de lenguaje natural diferente.

N/A Obligatorio
continueOnError Configúralo como false para devolver un error cuando una política falla. Este es el comportamiento previsto para la mayoría de las políticas.

Configúralo como true para continuar con la ejecución del flujo incluso después de que una política falle. También consulta lo siguiente:

false Opcional
habilitado Configúralo como true para aplicar la política.

Configúralo como false para “desactivar” la política. La política no se aplicará, incluso si permanece conectada a un flujo.

true Opcional
async Este atributo dejó de estar disponible. false Obsoleto

<Algorithm>

<Algorithm>algorithm-name</Algorithm>

Especifica el algoritmo hash que se usará para calcular el HMAC.

Valor predeterminado N/A
Presence Obligatorio
Tipo String
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 distinción entre mayúsculas y minúsculas, y con o sin el guion entre las letras y los números. Por ejemplo, SHA256, SHA-256 y sha256 son equivalentes.

<DisplayName>

<DisplayName>Policy Display Name</DisplayName>

Además de usar el atributo de nombre para etiquetar la política en el editor de proxy de IU de Apigee con un nombre diferente y con lenguaje natural.

Valor predeterminado Si omites este elemento, se usa el valor del atributo de nombre de la política.
Presence Opcional
Tipo String

<Message>

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

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

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

La plantilla de mensajes puede incluir partes fijas y variables, incluidas las líneas nuevas y las funciones estáticas. El espacio en blanco, como los saltos de línea y los caracteres de espacio, es importante.

Valor predeterminado N/A
Presence Obligatorio
Tipo String
Valores válidos Cualquier string es válida para el valor de texto. Si proporcionas 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 establecer con el valor HMAC calculado. También especifica la codificación que se usará para la salida.

Valor predeterminado

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

El valor predeterminado para el atributo encoding es base64.

Presence Opcional. Si este elemento no está presente, la política establece la variable de flujo hmac.POLICYNAME.output, con un valor codificado en base64.
Tipo String
Valores válidos

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

Los valores no distinguen mayúsculas de minúsculas, hex y base16 son sinónimos.

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

<SecretKey>

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

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

Valor predeterminado

No hay un valor predeterminado para la variable a la que se hace referencia; el atributo ref es obligatorio.

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

Presence Obligatorio
Tipo String
Valores válidos

Para encoding, los valores válidos son hex, base16, base64, utf8. El valor predeterminado es UTF8. Los valores no distinguen entre mayúsculas y minúsculas, y los guiones son insignificantes. Base16 es lo mismo que base-16 y bAse16. Base16 y Hex son sinónimos.

El uso de un atributo de codificación te permite especificar una clave que incluye bytes fuera del rango de caracteres UTF-8 imprimibles. 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 string 536563726574313233.

En este caso, los bytes clave se decodificarán como: [53 65 63 72 65 74 31 32 33] (cada byte representado en formato hexadecimal). Otro ejemplo: si usas encoding='base64' y si private.encodedsecretkey contiene la cadena U2VjcmV0MTIz, dará como resultado el mismo conjunto de bytes para la clave. Si no hay un atributo de codificación o un atributo de codificación de UTF8, el valor de string Secret123 generaría el mismo conjunto de bytes. Aquí 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>

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

Valor predeterminado No hay un valor de verificación predeterminado. Si el elemento está presente, pero el atributo encoding está ausente, la política usa una codificación predeterminada de base64.
Presence Opcional
Tipo String
Valores válidos

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

No es necesario que la codificación de VerificationValue sea la misma que la que se usa para el elemento Output.

<IgnoreUnresolvedVariables>

<IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables>

Configúralo como false si deseas que la política muestre un error cuando no se pueda resolver cualquier variable a la que se especifica en la política. Se establece como true para tratar cualquier variable no recuperable como una string vacía (null).

El valor booleano IgnoreUnresolvedVariables afecta solo a las variables a las que se hace referencia en la plantilla de mensaje. Si bien SecretKey y VerificationValue pueden hacer referencia a una variable, ambas se deben poder resolver, por lo que la configuración ignore no se aplica a ellas.

Valor predeterminado Falso
Presence Opcional
Tipo Booleano
Valores válidos True o False

Variables de flujo

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

Variable Descripción Ejemplo
hmac.policy_name.message La política establece esta variable con el mensaje real, que es el resultado de la evaluación de la plantilla de mensajes especificada en el elemento Message. hmac.HMAC-Policy.message = "Hello, World"
hmac.policy_name.output Obtiene el resultado del cálculo 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

Problemas comunes

En un nivel, la política HMAC parece ser directa: proporcionar una clave y un mensaje, y obtener un HMAC calculado en respuesta. Puede ser frustrante cuando usas la política si obtienes un valor inesperado de HMAC para una combinación conocida de mensaje y clave. En esta sección, se explicarán algunas notas de uso para solucionar estos problemas.

Hay dos dificultades comunes que dan como resultado HMAC que no coinciden durante la verificación: las diferencias de espacios en blanco en el mensaje y las diferencias en codificación y decodificación. Esta última se aplica al elemento SecretKey y al elemento Output.

Diferencias en espacios en blanco

Las diferencias que pueden parecer no importantes para una persona afectan el valor de HMAC de salida. Por ejemplo, supongamos que hay una clave secreta que se puede representar como “Secret123”. Con la decodificación de UTF-8, los bytes clave serán: [53 65 63 72 65 74 31 32 33]. El uso de esa clave para calcular un HMAC-SHA256 en el mensaje abc da como resultado a7938720fe5749d31076e6961360364c0cd271443f1b580779932c244293bc94. Agregar un solo espacio al mensaje, de modo que sea abc<SPACE>, donde <SPACE> implica un ASCII 32, da como resultado una HMAC-SHA256 de 274669b2a85d2532da48e2ce3d8e52ee17346d1bcd1a606d87db1934b5ab294b.

De manera similar, si el mensaje es abc<NEWLINE>, en el que <NEWLINE> implica un ASCII 10, el HMAC es 0780370844ca07f896066837e8230d3b6a775f678a4ae03e6b5e864c674831f5. Los pequeños cambios en el mensaje dan como resultado valores HMAC muy diferentes. Se diseñó de este modo. Este es un comportamiento intencionado y deseado de HMAC.

Conclusión: Es importante garantizar 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 los mismos. Si el verificador de un HMAC cambia la carga útil del mensaje de cualquier manera, ya que agrega cualquier espacio en blanco o vuelve a formatear el texto, el HMAC calculado cambiará.

Ten especial cuidado cuando usas 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 la evaluación de la plantilla de mensaje dentro del elemento <Message> incluirá saltos de líneas y espacios alrededor del contenido del mensaje. Es probable que esto no sea lo que se busca. Una configuración mejor se vería de la siguiente manera:

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

Diferencias en la codificación

Las diferentes decodificaciones del mismo material de clave dan como resultado diferentes claves. Supongamos que una clave secreta se puede representar como “U2VjcmV0S2V5MTIz”. Con la decodificación de UTF-8, los bytes 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 de base64, los bytes clave serán [53 65 63 72 65 74 4b 65 79 31 32 33]. La decodificación de material de origen da como resultado claves diferentes y eso generará diferentes valores de HMAC.

Conclusiones: Es importante asegurarse de que el material de clave usado para calcular el HMAC original y la clave usada para verificar el HMAC sean exactamente los mismos. Esto probablemente significa que debes asegurarte de que se use la misma codificación de la clave en ambos extremos. En la política HMAC, puedes usar el atributo encoding en el elemento SecretKey para especificar la codificación de claves.

También considera las codificaciones en el resultado. Un HMAC-SHA256 expresado en codificación base16 o hexadecimal como 27f17e11c8ece93844c5eb5e55161d993368628a214f9a51c25d0185e8ea06e2 es igual a un HMAC-SHA256 expresado en formato base64 como J/F+Ecjs6ThExeteVRYdmTNoYoohT5pRwl0BhejqBuI=. Se ven diferentes, pero estas dos cadenas representan el mismo valor. Asegúrate de que se use la misma codificación para codificar el HMAC calculado originalmente y el HMAC verificado. En la política HMAC, puedes usar el atributo encoding en el elemento Output para especificar la codificación de salida deseada y el mismo atributo en el elemento VerificationValue para especificar cómo decodificar el verificador.

Referencia de errores

En esta sección, se describen los códigos de falla y los mensajes de error que se muestran, y las variables de falla que establece Apigee cuando esta política activa un error. Esta información es importante para saber si estás desarrollando reglas de fallas con el propósito de manejar fallas. Para obtener más información, consulta Qué debes saber sobre los errores de políticas y Cómo solucionar fallas.

Errores de entorno de ejecución

Estos errores pueden producirse cuando se ejecuta la política.

Código de falla Estado de HTTP Ocurre cuando
steps.hmac.UnresolvedVariable 401

Este error se produce si una variable especificada en la política HMAC es una de las siguientes:

  • Está fuera del alcance (no está disponible en el flujo específico en el que se ejecuta la política) o

    o

  • No se puede resolver (no está definida)
steps.hmac.HmacVerificationFailed 401 Falló la verificación de HMAC. El valor de verificación proporcionado no coincide con el valor calculado.
steps.hmac.HmacCalculationFailed 401 La política no pudo calcular el HMAC.
steps.hmac.EmptySecretKey 401 El valor de la variable de clave secreta está vacío.
steps.hmac.EmptyVerificationValue 401 La variable que contiene el valor de verificación está vacía.

Errores en la implementación

Estos errores pueden generarse cuando implementas un proxy que contiene esta política.

Nombre del error Estado de HTTP Ocurre cuando
steps.hmac.MissingConfigurationElement 401 Este error ocurre cuando falta un elemento o un atributo obligatorio.
steps.hmac.InvalidValueForElement 401 Este error se produce si el valor especificado en el elemento Algoritmo no es uno de los siguientes valores: SHA-1, SHA-224, SHA-256, SHA-512 o MD-5.
steps.hmac.InvalidSecretInConfig 401 Este error se produce si hay un valor de texto proporcionado de forma explícita para SecretKey.
steps.hmac.InvalidVariableName 401 Este error se produce si la variable SecretKey no contiene el prefijo private (private.).

Variables con fallas

Estas variables se configuran cuando se genera un error de entorno de ejecución. Para obtener más información, consulta Qué debes saber sobre los errores de la política.

Variables Donde Ejemplo
fault.name="fault_name" fault_name es el nombre de la falla, como se indica en la tabla de Errores del entorno de ejecución anterior. El nombre de la falla es la última parte del código de la falla. fault.name Matches "UnresolvedVariable"
hmac.policy_name.failed La política establece esta variable en caso de falla. hmac.HMAC-Policy.failed = true

Ejemplo de respuesta de error

Para controlar errores, se recomienda capturar la parte errorcode de la respuesta de error. No dependas del texto en la faultstring, ya que podría cambiar.

Ejemplo de regla de falla

<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>