La notación de sintaxis abstracta uno ( ASN.1 ) es un lenguaje de descripción de interfaz (IDL) estándar para definir estructuras de datos que se pueden serializar y deserializar de forma multiplataforma. Se utiliza ampliamente en telecomunicaciones y redes informáticas , y especialmente en criptografía . [1]
Los desarrolladores de protocolos definen estructuras de datos en módulos ASN.1, que generalmente son una sección de un documento de estándares más amplio escrito en el lenguaje ASN.1. La ventaja es que la descripción ASN.1 de la codificación de datos es independiente de un lenguaje de programación o de computadora en particular. Debido a que ASN.1 es legible tanto para humanos como para máquinas , un compilador ASN.1 puede compilar módulos en bibliotecas de código, codecs , que decodifican o codifican las estructuras de datos. Algunos compiladores ASN.1 pueden producir código para codificar o decodificar varias codificaciones, por ejemplo, empaquetadas, BER o XML .
ASN.1 es una norma conjunta del Sector de Normalización de las Telecomunicaciones de la Unión Internacional de Telecomunicaciones (UIT-T) en el Grupo de Estudio 17 de la UIT-T y la Organización Internacional de Normalización / Comisión Electrotécnica Internacional (ISO/IEC), definida originalmente en 1984 como parte de CCITT X.409:1984. [2] En 1988, ASN.1 pasó a tener su propia norma, X.208 , debido a su amplia aplicabilidad. La versión de 1995, sustancialmente revisada, está cubierta por la serie X.680 . [3] La última revisión de la serie de recomendaciones X.680 es la Edición 6.0, publicada en 2021. [4]
ASN.1 es una notación de declaración de tipo de datos. No define cómo manipular una variable de ese tipo. La manipulación de variables se define en otros lenguajes, como SDL (lenguaje de especificación y descripción) para el modelado ejecutable o TTCN-3 (notación de prueba y control de prueba) para pruebas de conformidad. Ambos lenguajes admiten de forma nativa las declaraciones ASN.1. Es posible importar un módulo ASN.1 y declarar una variable de cualquiera de los tipos ASN.1 declarados en el módulo.
ASN.1 se utiliza para definir una gran cantidad de protocolos. Sus usos más extendidos siguen siendo las telecomunicaciones, la criptografía y la biometría.
ASN.1 está estrechamente asociado con un conjunto de reglas de codificación que especifican cómo representar una estructura de datos como una serie de bytes. Las reglas de codificación estándar de ASN.1 incluyen:
Las recomendaciones de ASN.1 proporcionan una serie de reglas de codificación predefinidas. Si ninguna de las reglas de codificación existentes es adecuada, la Notación de control de codificación (ECN) ofrece una manera para que el usuario defina sus propias reglas de codificación personalizadas.
La codificación de correo con privacidad mejorada (PEM) no tiene ninguna relación con ASN.1 y sus códecs, pero los datos ASN.1 codificados, que a menudo son binarios, suelen estar codificados con PEM para que puedan transmitirse como datos de texto, por ejemplo, a través de relés SMTP o mediante búferes de copiar y pegar.
Este es un módulo ASN.1 de ejemplo que define los mensajes (estructuras de datos) de un protocolo Foo ficticio :
DEFINICIONES DE PROTOCOLO FOOO ::= BEGIN FooQuestion ::= SECUENCIA { númeroDeSeguimiento ENTERO , pregunta IA5String } FooAnswer ::= SECUENCIA { preguntaNumber ENTERO , respuesta BOOLEAN } FIN
Esta podría ser una especificación publicada por los creadores del protocolo Foo. Los flujos de conversación, los intercambios de transacciones y los estados no están definidos en ASN.1, sino que se dejan para otras notaciones y descripciones textuales del protocolo.
Suponiendo un mensaje que cumple con el Protocolo Foo y que se enviará a la parte receptora, este mensaje en particular ( unidad de datos de protocolo (PDU)) es:
myQuestion FooQuestion ::= { trackingNumber 5 , pregunta "¿Hay alguien ahí?" }
ASN.1 admite restricciones de valores y tamaños, y extensibilidad. La especificación anterior se puede cambiar a
DEFINICIONES DE PROTOCOLO FOOO ::= BEGIN FooQuestion ::= SECUENCIA { númeroDeSeguimiento ENTERO ( 0 . . 199 ), pregunta IA5String } FooAnswer ::= SECUENCIA { preguntaNumber ENTERO ( 10. . 20 ), respuesta BOOLEAN } FooHistory ::= SECUENCIA { preguntas SECUENCIA ( TAMAÑO ( 0. . 10 )) DE FooPregunta , respuestas SECUENCIA ( TAMAÑO ( 1. . 10 )) DE FooRespuesta , unaMatriz SECUENCIA ( TAMAÑO ( 100 )) DE ENTERO ( 0. . 1000 ), ... } FIN
Este cambio restringe que los valores de trackingNumbers estén entre 0 y 199 inclusive, y que los de questionNumbers estén entre 10 y 20 inclusive. El tamaño de la matriz questions puede estar entre 0 y 10 elementos, y el de answers entre 1 y 10 elementos. El campo anArray es una matriz de 100 elementos de longitud fija de números enteros que deben estar en el rango de 0 a 1000. El marcador de extensibilidad '...' significa que la especificación de mensajes FooHistory puede tener campos adicionales en futuras versiones de la especificación; los sistemas compatibles con una versión deberían poder recibir y transmitir transacciones de una versión posterior, aunque solo podrían procesar los campos especificados en la versión anterior. Los buenos compiladores ASN.1 generarán (en C, C++, Java, etc.) código fuente que comprobará automáticamente que las transacciones se encuentren dentro de estas restricciones. Las transacciones que violen las restricciones no deberían aceptarse desde la aplicación ni presentarse a ella. La gestión de restricciones en esta capa simplifica significativamente la especificación del protocolo porque las aplicaciones estarán protegidas contra violaciones de restricciones, lo que reduce el riesgo y los costos.
Para enviar el mensaje myQuestion a través de la red, el mensaje se serializa (codifica) como una serie de bytes utilizando una de las reglas de codificación . La especificación del protocolo Foo debe nombrar explícitamente un conjunto de reglas de codificación para usar, de modo que los usuarios del protocolo Foo sepan cuál deben usar y esperar.
A continuación se muestra la estructura de datos que se muestra arriba como myQuestion codificada en formato DER (todos los números están en hexadecimal):
30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f
DER es una codificación de tipo-longitud-valor , por lo que la secuencia anterior se puede interpretar, con referencia a los tipos estándar SEQUENCE, INTEGER y IA5String, de la siguiente manera:
30 — etiqueta tipo que indica SECUENCIA13 — longitud en octetos del valor que sigue 02 — etiqueta de tipo que indica número ENTERO 01 — longitud en octetos del valor que sigue 05 — valor (5) 16 — etiqueta de tipo que indica IA5String (IA5 significa el conjunto completo ISO 646 de 7 bits, incluidas las variantes, pero generalmente es US-ASCII) 0e — longitud en octetos del valor que sigue 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f — valor ("¿Hay alguien ahí?")
Como alternativa, es posible codificar la misma estructura de datos ASN.1 con reglas de codificación XML (XER) para lograr una mayor legibilidad humana "por cable". Aparecería así: los 108 octetos siguientes (el recuento de espacios incluye los espacios utilizados para la sangría):
<FooQuestion> <trackingNumber> 5 </trackingNumber> <question> ¿Hay alguien ahí? </question> </FooQuestion>
Como alternativa, si se emplean reglas de codificación empaquetadas , se producirán los siguientes 122 bits (16 octetos suman 128 bits, pero aquí solo 122 bits llevan información y los últimos 6 bits son simplemente relleno):
01 05 0e 83 bb ce 2d f9 3c a0 e9 a3 2f 2c af c0
En este formato, las etiquetas de tipo para los elementos requeridos no están codificadas, por lo que no se pueden analizar sin conocer los esquemas esperados utilizados para codificar. Además, los bytes para el valor de IA5String se empaquetan utilizando unidades de 7 bits en lugar de unidades de 8 bits, porque el codificador sabe que codificar un valor de byte de IA5String requiere solo 7 bits. Sin embargo, los bytes de longitud aún se codifican aquí, incluso para la primera etiqueta de entero 01 (pero un empaquetador PER también podría omitirlo si sabe que el rango de valores permitido cabe en 8 bits, e incluso podría compactar el byte de valor único 05 con menos de 8 bits, si sabe que los valores permitidos solo pueden caber en un rango más pequeño).
Los últimos 6 bits del PER codificado se rellenan con bits nulos en los 6 bits menos significativos del último byte c0: estos bits adicionales no pueden transmitirse ni usarse para codificar otra cosa si esta secuencia se inserta como parte de una secuencia PER no alineada más larga.
Esto significa que los datos PER no alineados son esencialmente un flujo ordenado de bits, y no un flujo ordenado de bytes como en el caso de los PER alineados, y que será un poco más complejo de decodificar por software en los procesadores habituales porque requerirá desplazamiento y enmascaramiento de bits contextuales adicionales y no direccionamiento directo de bytes (pero la misma observación sería cierta con los procesadores modernos y las unidades de memoria/almacenamiento cuya unidad mínima direccionable es mayor que 1 octeto). Sin embargo, los procesadores modernos y los procesadores de señales incluyen soporte de hardware para una decodificación interna rápida de flujos de bits con manejo automático de unidades de cómputo que cruzan los límites de las unidades de almacenamiento direccionables (esto es necesario para un procesamiento eficiente en códecs de datos para compresión/descompresión o con algunos algoritmos de cifrado/descifrado).
Si se requiriera alineación en los límites de octetos, un codificador PER alineado produciría:
01 05 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f
(en este caso, cada octeto se rellena individualmente con bits nulos en sus bits más significativos no utilizados).
La mayoría de las herramientas que admiten ASN.1 hacen lo siguiente:
Se puede encontrar una lista de herramientas que admiten ASN.1 en la página web de herramientas del UIT-T.
ASN.1 es similar en propósito y uso a Google Protocol Buffers y Apache Thrift , que también son lenguajes de descripción de interfaz para serialización de datos multiplataforma. Al igual que esos lenguajes, tiene un esquema (en ASN.1, llamado "módulo") y un conjunto de codificaciones, generalmente codificaciones de tipo-longitud-valor. A diferencia de ellos, ASN.1 no proporciona una implementación de código abierto única y fácilmente utilizable, y se publica como una especificación para ser implementada por proveedores externos. Sin embargo, ASN.1, definido en 1984, los precede por muchos años. También incluye una variedad más amplia de tipos de datos básicos, algunos de los cuales están obsoletos, y tiene más opciones de extensibilidad. Un solo mensaje ASN.1 puede incluir datos de múltiples módulos definidos en múltiples estándares, incluso estándares definidos con años de diferencia.
ASN.1 también incluye compatibilidad integrada con restricciones de valores y tamaños. Por ejemplo, un módulo puede especificar un campo entero que debe estar en el rango de 0 a 100. También se puede especificar la longitud de una secuencia de valores (una matriz), ya sea como una longitud fija o como un rango de longitudes permitidas. Las restricciones también se pueden especificar como combinaciones lógicas de conjuntos de restricciones básicas.
Los valores utilizados como restricciones pueden ser literales utilizados en la especificación PDU o valores ASN.1 especificados en otra parte del archivo de esquema. Algunas herramientas ASN.1 pondrán estos valores ASN.1 a disposición de los programadores en el código fuente generado. Si se utilizan como constantes para el protocolo que se está definiendo, los desarrolladores pueden utilizarlos en la implementación lógica del protocolo. De este modo, todas las PDU y las constantes del protocolo se pueden definir en el esquema, y todas las implementaciones del protocolo en cualquier lenguaje compatible se basan en esos valores. Esto evita que los desarrolladores tengan que codificar manualmente las constantes del protocolo en el código fuente de su implementación. Esto ayuda significativamente al desarrollo del protocolo; las constantes del protocolo se pueden alterar en el esquema ASN.1 y todas las implementaciones se actualizan simplemente mediante la recompilación, lo que promueve un ciclo de desarrollo rápido y de bajo riesgo.
Si las herramientas ASN.1 implementan correctamente la comprobación de restricciones en el código fuente generado, esto actúa para validar automáticamente los datos del protocolo durante la operación del programa. Generalmente, las herramientas ASN.1 incluirán la comprobación de restricciones en las rutinas de serialización/deserialización generadas, lo que generará errores o excepciones si se encuentran datos fuera de los límites. Es complejo implementar todos los aspectos de las restricciones ASN.1 en un compilador ASN.1. No todas las herramientas admiten la gama completa de posibles expresiones de restricciones. Tanto el esquema XML como el esquema JSON admiten conceptos de restricciones similares. La compatibilidad de las herramientas con las restricciones varía. El compilador xsd.exe de Microsoft las ignora.
ASN.1 es visualmente similar a la forma aumentada Backus-Naur (ABNF), que se utiliza para definir muchos protocolos de Internet como HTTP y SMTP . Sin embargo, en la práctica son bastante diferentes: ASN.1 define una estructura de datos, que se puede codificar de varias maneras (por ejemplo, JSON, XML, binario). ABNF, por otro lado, define la codificación ("sintaxis") al mismo tiempo que define la estructura de datos ("semántica"). ABNF tiende a usarse con más frecuencia para definir protocolos textuales legibles por humanos y, por lo general, no se usa para definir codificaciones de tipo-longitud-valor.
Muchos lenguajes de programación definen formatos de serialización específicos del lenguaje. Por ejemplo, el módulo "pickle" de Python y el módulo "Marshal" de Ruby. Estos formatos son generalmente específicos del lenguaje. Tampoco requieren un esquema, lo que los hace más fáciles de usar en escenarios de almacenamiento ad hoc, pero inadecuados para protocolos de comunicaciones.
De manera similar, JSON y XML no requieren un esquema, lo que los hace fáciles de usar. Ambos son estándares multiplataforma que gozan de gran popularidad en los protocolos de comunicación, en particular cuando se combinan con un esquema JSON o XML .
Algunas herramientas ASN.1 pueden traducir entre ASN.1 y el esquema XML (XSD). La traducción está estandarizada por la ITU. Esto permite que un protocolo se defina en ASN.1 y también automáticamente en XSD. Por lo tanto, es posible (aunque quizás no sea aconsejable) tener en un proyecto un esquema XSD compilado por herramientas ASN.1 que produzcan código fuente que serialice objetos a/desde un formato de cable JSON. Un uso más práctico es permitir que otros subproyectos consuman un esquema XSD en lugar de un esquema ASN.1, tal vez adecuando la disponibilidad de las herramientas para el lenguaje de elección del subproyecto, con XER utilizado como el formato de cable del protocolo.
Para obtener más detalles, consulte Comparación de formatos de serialización de datos .