|
|
|
ASN.1 por David Esmerodes Fraguas, Eva Marcos Doldán, Oscar Pérez Piñeiro, Diana María Piñeiro Iglesias e Marina Rodríguez Iglesias / Junio'98 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1.1) PRESENTACIÓN.
Uno de los problemas fundamentales que aparecen en la comunicación entre usuarios es el traslado eficaz de los datos, es decir, que los datos que se reciban son los que se han enviado (Integridad). El problema de cómo comunicar dos sistemas diferentes es similar al problema que se presenta entre dos personas a la hora de comunicarse, siendo por ejemplo una inglesa y la otra de nacionalidad alemana (inglés vs alemán). Ilustremos este comentario con un ejemplo :
Supongamos dos máquinas que usan diferentes sistemas e incluso lenguajes de programación diferentes. La máquina A usa el lenguaje de programación Pascal y la máquina B utiliza C. Si queremos trasladar información desde la máquina A a la B, necesitamos: o bien, que la máquina B entienda código en Pascal o bien que la máquina A genere una traducción de su código en Pascal a código C. Imaginemos ahora que en lugar de 2 máquinas, tenemos 20 con diferentes sistemas y diferentes lenguajes de programación; desde luego, la comunicación entre las máquinas se presenta complicada ya a primera vista y, cualquiera de las dos soluciones aportadas antes no parece arreglarnos demasiado la papeleta. La solución consiste en la utilización de una vía de comunicación, de una sintaxis abstracta que sea independiente de la máquina donde estemos trabajando. Esta sintaxis abstracta y un conjunto de reglas para su realización, va a ser común y va utilizarse para la representación de datos y estructuras de datos. En el ejemplo de los dos ciudadanos de distinta nacionalidad, sería como si introdujésemos una lengua común, un esperanto, que hiciese posible la comunicación entre ambos. Pero así como el ciudadano inglés y el alemán han de saber esperanto, cada máquina ha de conocer esa sintaxis abstracta y sus reglas para que sea posible llevar a cabo esta opción. De esta forma, la máquina A debe traducir sus rutinas en Pascal a la representación abstracta apoyándose en las reglas de sintaxis; y, la máquina B debe trasladar esta información codificada en la sintaxis común a su propio lenguaje, el C. El lenguaje del que hablamos se llama ASN.1 (Abstract Syntax Notation One) y las reglas básicas de codificación se llaman BER(Basic Encoding Rules). Los primeros protocolos de transmisión usaban sólo técnicas de codificación simple. Las capas de control de transmisión, tales como HDLC o IP usaban sólo unos pocos bytes para cabeceras (headers), y eran localizados con precisión en campos de bits. Pero con el desarrollo de las aplicaciones mediante lenguajes de alto nivel surgió la necesidad de una estructuración de la información. ASN.1 es un lenguaje formal desarrollado y eestándarizado por CCIT(X:208) e ISO(8824). ASN.1 es importante porque :
El aprendizaje de ASN.1 es similar al de cualquier lenguaje de programación de alto nivel. ASN.1 nos proporciona una herramienta fundamental para el uso de aplicaciones, para la descripción de la información de una forma común e independiente de cualquier implementación particular.
Los estándares relevantes de ISO son:
Los estándares relevantes de CCITT son:
OSI (Open Systems Interconnection), es una arquitectura internacionalmente eestándarizada que rige las interconexiones entre computadoras desde la capa física a la capa de aplicaciones de usuario. Los objetos en las capas altas reciben un tratamiento abstracto y son implementados en las capas más bajas. Por ejemplo, una capa puede requerir la transferencia de ciertos objetos abstractos entre computadoras; una capa baja puede proporcionar transferencia de servicios por medio de strings de unos y ceros, usando reglas de codificación para transformar los objetos abstractos en tales strings. El método de OSI para la especificación de objetos abstractos es llamado ASN.1, y el conjunto de reglas para representar tales objetos como strings de unos y ceros es llamado BER. ASN.1 es una notación flexible que permite definir varios tipos de datos, desde tipos simples como enteros hasta tipos estructurados como conjuntos y secuencias, además de tipos complejos definidos en función de otros. BER describe como representar o codificar los valores de los tipos de ASN.1 como un string de grupos de ocho bits (eight-bit octects). La conversión entre el formato del mensaje de la representación local usada por una computadora y el formato binario en el cual se transportan los datos por las líneas de comunicación es llevada a cabo en OSI en la capa de Presentación ( Presentation Layer). Una sintaxis abstracta es una descripción de un mensaje desde el punto de vista lógico. En el modelo OSI, la representación de los tipos de datos y estructuras para facilitar la transferencia entre sistemas es una función de la Capa de Aplicación (Application Layer); la codificación de los datos en la citada secuencia de bits se atribuye a la Capa de Presentación (Presentation Layer). Esta separación de funciones de OSI, permite a la Capa de Aplicación tratar sólo con el contenido y estructura de los datos, dejando la elección de la forma de representación para la Capa de Presentación. Debido a esta separación aparece la notación abstracta vía ASN.1 y BER.
La Tabla 1 define algunos de los términos clave para llevar a cabo la discusión sobre ASN.1 y la figura 2 ilustra los conceptos fundamentales. Un sistema con una arquitectura de comunicaciones puede dividirse mayoritariamente en dos componentes: · La de transferencia de datos (data transfer component), que son los mecanismos para la transferencia de datos entre sistemas. En el caso de la suite de protocolos TCP/IP, esta componente consistiría en TCP o UDP. En el caso de la arquitectura OSI, esta componente consistiría en la capa de sesión (Session layer). · La de aplicación (application component) es la usuaria de la "componente de transferencia de datos" y consiste en las aplicaciones de usuario. En el caso de TCP/IP, esta componente consistiría en una aplicación como SNMP, FTP, SNTP o TELNET. En el caso de OSI, esta componente actualmente consta de la capa de aplicación (Application layer), la cual está compuesta por un número de aplicaciones de elementos de servicio, y de la capa de presentación ( Presentation layer).
Cuando nosotros cruzamos el límite de la componente de aplicación a la componente de transferencia de datos, hay un cambio significativo en la forma en que se ven los datos. Para la componente de transferencia de datos, los datos recibidos de una aplicación son especificados como valores binarios de una secuencia de octetos. Este valor binario puede ser directamente ensamblado en unidades de servicio de datos (SDUs) para pasar entre entidades de protocolos en una capa. La componente de aplicación, sin embargo, se preocupa de la visión del usuario de los datos. En general, este punto de vista es un conjunto estructurado de información, tal como un documento de texto, un6 6fichero personal... . El usuario está inicialmente interesado en la semántica de los datos. La componente de aplicación debe proporcionar una representación de estos datos que pueda ser convertida a valores binarios; esto es, debe preocuparse de la sintaxis de los datos.
TABLA 1 TÉRMINOS RELEVANTES PARA ASN.1
Sintaxis abstracta. Describe la estructura genérica de los datos independiente- 2 mente de cualquier codificación técnica para la representa- ción de los datos. La sintaxis permite definir tipos de datos y especificar valores para estos datos.
Tipos de datos Un conjunto de valores con nombre. Un tipo puede ser simple, definido por la especificación de un conjunto de los valores que puede tomar; o estructurado, en función de otros tipos.
Codificación La secuencia completa de octetos usados para representar el valor de los datos.
Reglas de Codificación Una especificación de un mapeo de una sintaxis a otra. Espe- cíficamente, para algún conjunto de valores definidos en una sintaxis abstracta, reglas de codificación determinan algorítmicamente la representación de esos valores en una sintaxis de transferencia.
Sintaxis de Transferencia La forma en la cual los datos son actualmente representados en términos de patrones de bits mientras están en tránsito entre entidades.
Para la componente de aplicación, la información es representada en una sintaxis abstracta que trata con tipos de datos y valores de datos. La sintaxis abstracta especifica formalmente los datos independientemente de cualquier representación particular. De este modo, una sintaxis abstracta tiene muchas similitudes con cualquier definición de datos y de tipos de un lenguaje de programación convencional como Pascal, C... . Los protocolos de Aplicación describen sus PDUs en términos de una sintaxis abstracta. Esta sintaxis abstracta es usada para intercambiar información entre componentes de aplicación de diferentes sistemas. El intercambio consiste en PDUs del nivel de aplicación, los cuales contienen información de protocolos de control y datos de usuario. En un sistema, la información representada usando una sintaxis abstracta debe ser mapeada ("traducida"), de alguna forma para su presentación al usuario humano. Similarmente, esta sintaxis abstracta debe ser mapeada en algún formato local al sistema para su almacenamiento. Es importante destacar que tal "traducción" es usada en el caso de la información base de gestión: la MIB. Sin embargo, los elementos en la MIB son definidos usando la sintaxis abstracta. De este modo, la notación de la sintaxis abstracta es empleada por un usuario para definir la MIB; la aplicación debe entonces convertir esta definición de forma conveniente para su almacenamiento local.
La componente debe también traducir la información de la sintaxis abstracta de la aplicación a la sintaxis de transferencia que describe los valores de los datos en formato binario, conveniente para la iteración con la componente de transferencia de datos. Por ejemplo, una sintaxis abstracta puede incluir un tipo de dato carácter; la sintaxis de transferencia podría especificar código ASCII o EBCDIC. La sintaxis de transferencia de este modo define la representación de los datos para ser intercambiados entre las componentes de transferencia de datos. La traducción de sintaxis abstracta a sintaxis de transferencia es llevada a cabo mediante reglas de codificación significativa que especifica la representación de cada tipo y valor de datos. Este enfoque para el intercambio de datos de aplicación soluciona los dos problemas que se presentan en un entorno distribuido heterogéneo en la representación de los datos
La característica fundamental de una sintaxis de transferencia es que debe apoyar la correspondiente sintaxis abstracta. La elección de qué sintaxis de transferencia utilizar dependerá dos consideraciones fundamentalmente: coste y seguridad.
La unidad fundamental de ASN.1 es el módulo. El único propósito de un módulo es nombrar una colección de definiciones de tipos y/o definiciones de valores, que constituyen una especificación de datos. Una definición de tipos es usada para definir y nombrar un nuevo tipo por medio de una asignación de tipos y una definición de valor es usada para definir y nombrar un valor específico, cuando sea necesario por medio de una asignación de valor. Cada asignación de valor o de tipo debe hacerse en una línea diferente. Los módulos tienen como forma básica:
<modulereference> DEFINITIONS ::= BEGIN EXPORTS IMPORTS AssignmentList End
Modulereference en un nombre de módulo seguido opcionalmente por un identificador de objeto para identificar el módulo. El constructor EXPORTS indica que definiciones de tipos y valores en este módulo puede ser importados por otros módulos. IMPORTS indica que definiciones de tipos y valores de otros módulos son importados por este módulo. EXPORTS e IMPORTS no pueden ser incluidos sino aparece el identificador de objeto. Finalmente, la lista de asignación consiste en asignaciones de tipos, asignaciones de valores, y macro definiciones. En ASN.1, un tipo es un conjunto de valores, posiblemente infinito en tamaño; un valor de un tipo dado en ASN.1, es un elemento del conjunto de valores de ese tipo. La asignación de tipos en ASN.1 consiste en una referencia de tipo, el nombre del tipo, el carácter "::=" (carácter de asignación) y el tipo apropiado. Entre cada una de estas partes ha de haber como mínimo un espacio. La definición de tipos sigue pues el esquema: <nuevoTipo> "::=" <especificación de tipo>
La asignación de valores consiste en una referencia al valor (el nombre), el tipo de valor, el operador "::=" y un valor válido. La definición de valores sigue pues el esquema: <nuevoValor> <tipo> "::=" <especificación del valor>
El lenguaje ASN.1 tiene las siguientes propiedades:
El conjunto de caracteres usado por ASN.1 está limitado a:
A-Z, a-z, 0-9, ":", ";", ",", {, }, <, ".", ( , ) , [, ], "-" , " ' "e "
Los caracteres que no están en este conjunto pueden ser usados como valores de strings y como comentarios, pero todas las palabras clave, identificadores y puntuaciones deben usar ese conjunto
Podemos clasificar los tipos de ASN.1 en cuatros categorías:
Cada tipo ASN.1 a excepción de CHOICE y ANY, tiene una etiqueta (tag), que consiste en un nombre de clase y una etiqueta numérica no negativa. Los tipos en ASN.1 son abstractamente los mismos sí y sólo si sus etiquetas numéricas son las mismas. En otras palabras, el nombre un tipo no afecta a su significado abstracto, sólo lo hace su "tag" . Hay cuatro clases de tag:
TABLA 3
Los tipos con tags universal son definidos en X.208. La tabla 4 lista algunos tipos ASN.1 y sus tags de clase universal.
2.1 TIPOS SIMPLES.
Los tipos simples no tienen componentes; son "atómicos". Son definidos directamente por el conjunto de los valores que pueden tomar. Todos los demás tipos están construidos a partir de los tipos simples. En la tabla 3 vemos todos los tipos que se presentan dentro de la clase universal, agrupados por conveniencia, en categorías. Entre ellos se encuentran los tipos simples repartidos por las diferentes categorías (BOOLEAN, INTEGER, ENUMERATED, REAL, OBJECT IDENTIFIER, NULL...), pero en este trabajo vamos a resaltar los siguientes por ser relevantes para los PKCS estándar: (esta última afirmación según guía Layman):
Los tipos simples se clasifican en 2 categorías. Tipos string y tipos no string. BIT STRING, IA5String, OCTET STRING, PrintableString, y UTCTime son tipos string. Los tipos string pueden ser vistos, para los propósitos de codificación, como consistentes de componentes, donde los componentes son substrings. Esta visión permite codificar un valor cuya longitud no es conocida previamente (ej., un valor de entrada octect string de un fichero), con un constructor apropiado (constructed indefinite-length , del que se hablará más adelante). Ver tabla 3.
2.2 TIPOS ESTRUCTURADOS.
Los tipos estructurados son aquellos formados por componentes. ASN.1 define cuatro para la construcción de tipos de datos complejos a partir de tipos simples; todos ellos son relevantes para los PKCS estándares:
Sequence y Sequence of, son tipos usados para definir una lista ordenada de valores de uno o más tipos.
Set y Set of , son muy similares a Sequence y Sequence of, excepto que en este caso el orden de los elementos no es significativo. Los tipos estructurados pueden tener componentes opcionales, posiblemente con valores por defecto.
2.3 TIPOS ETIQUETADOS IMPLICITA Y EXPLICITAMENTE.
ASN.1 estándar define un tipo tagged como sigue: Un tipo definido por la referenciación de un tipo simple existente y un tag; el nuevo tipo es isomorfo al tipo existente, pero es distinto de él. En todos los esquemas de código, un valor del nuevo tipo se distingue del valor del viejo tipo. Los tagged types (tipo etiquetados) son aquellos derivados de otros tipos por el cambio del tag de tipo subyacente(del tipo del que derivan). El "tagging" se utiliza para distinguir tipos dentro de una aplicación: podemos desear tener varios nombres de tipo diferentes tales como "nombre_empleado" y "nombre_cliente", que esencialmente son el mismo tipo. Hay dos tipos de "tagging": La etiquetación implícita y la explícita. La etiquetación implícita en denotada en ASN.1 [class number] IMPLICIT (ver sección 5.1). Los tipos implícitos se forman directamente de otro tipo reemplazando su tag (nombre y número). Para los propósitos de codificación sólo es usado el nuevo tag , pero el tipo subyacente es el mismo. La etiquetación explícita es denotada por la palabra clave en ASN.1 [class number] EXPLICIT (ver sección 5.2).Los tagged types explícitos son aquellos derivados de otros tipos añadiendo un tag exterior a su tipo subyacente. Un tagged type explícito es considerado como un tipo estructurado con una componente, el tipo subyacente. Para propósitos de codificación, el tag nuevo y el viejo han de ser reflejados. El "tagging" es también comúnmente usado para distinguir tipos componente dentro de un tipo estructurado. Por ejemplo, componentes opcionales de un SET o SEQUENCE reciben distintos tags de context-specific para permitir la ambigüedad. Los tags implícitos resultan en códigos cortos, pero los tags explícitos pueden ser necesarios para permitir ambigüedad si el tag del tipo subyacente es indeterminado (ej., el tipo subyacente es CHOICE o ANY).
2.4 OTROS TIPOS. "Otros tipos" en ASN.1 incluye CHOICE y ANY. El tipo CHOICE denota una unión de una o más alternativas; el ANY denota un valor arbitrario de un tipo arbitrario, donde el tipo arbitrario es posiblemente definido en la inscripción de un identificador de objeto o valor entero.
3. REGLAS BÁSICAS DE CODIFICACION. BER.
Las Reglas Básicas de Codificación, abreviado BER , dan una o más formas para representar cualquier valor ASN.1 como una cadena de octetos.
Hay tres métodos para codificar un valor ASN.1 bajo BER, la elección de cual depende del tipo de valor y de si la longitud de ese valor es conocida. Los tres métodos son:
TABLA 5. En cada método, el BER codificado tiene tres o cuatro partes:
Length octects(longitud de octetos). Para los métodos de longitud definida, estos dan el número de octetos contenidos. Para los constructed, de longitud indefinida, indica que la longitud es indefinida.
Este método se aplica a tipos simples y tipos derivados de tipos simples por tagging implícito. Requiere que la longitud de un valor se conozca previamente. Las partes del código BER son las siguientes:
TABLA 7
Forma de tag alta. Dos o más octetos. El primer octeto es de la forma tag corta, excepto que los bits de 5 a 1 todos tienen valor 1. El segundo y siguientes octetos dan el número de tag, que está contenido en los últimos 7 bits de cada octeto; el primer bit de cada octeto se establece a 1 excepto en el último octeto que está a 0.
Este método se aplica a tipos string simples, a tipos estructurados, tipos derivados de tipos string simples por tagging implícito y cualquier tipo definido por tagging explícito. Requiere conocer previamente la longitud. Partes en código BER:
1.- Para tipos string simple y tipos derivados de ellos por tagging implícito: la concatenación del código BER de los substrings consecutivos del valor (valor subyacente para el tagging implícito) 2.- Para los tipos estructurados y los tipos derivados de ellos por tagging implícito, la concatenación del código BER de las componentes del valor (subyacente para tagging implícito) 3.- Para tipos derivados explícitamente, el código BER del valor subyacente.
Este método se aplica a tipos string simples, tipos estructurados, derivados implícitos de tipos string simples y estructurados, y derivados de algo por tagging explícito. No requiere conocer previamente la longitud. Partes:
Ya que los octetos end-of-contents aparecen donde ordinariamente se esperaría código BER (e.g., en los octetos de contenido de una secuencia de valores), el 00 y 00 aparecen como octetos identificador y longitud , respectivamente. De este modo los octetos end-of-contents son realmente los primitiveds, longitud definida codificada de un valor con clase universal, numero de tag 0, y longitud 0.
4. REGLAS DE CODIFICACION DISTINGUIDAS.
Las DER, son un subconjunto de las BER, y dan exactamente una vía para representar cualquier valor ASN.1 como una cadena de octetos. DER es empleado para aplicaciones donde es necesaria una única cadena de octetos.
DER añade las siguientes restricciones a las reglas dadas en la sección 3:
5. NOTACIÓN PARA CODIFICADIONES DE ALGUNOS TIPOS.
Esta sección da la notación para algunos tipos ASN.1 y describe como codificar valores de estos tipos bajo BER y DER. Los tipos descritos son aquellos presentados en la Sección 2. Cada descripción incluye notación ASN.1, código BER, y código DER. Las descripciones también explican cada tipo usado en PKCS y estándares. La notación ASN.1 es generalmente solo para tipos, aunque para el tipo OBJECT IDENTIFIER, la notació2n del valor es dada como buena.
5.1 TIPOS ETIQUETADOS IMPLÍCITAMENTE (TAGGING IMPLÍCITO).
Un tipo etiquetado implícitamente es un tipo derivado de otro tipo por el cambio del tag del tipo subyacente.
El tagging implícito es usado para componentes opcionales SEQUENCE con otro tipo subyacente que ANY en todos los PKCS, y para la alternativa extendedCertificate de PKCS#7's tipo ExtendedCertificateOrCertificate.
5.1.1 La notación ASN.1.
La notación en ASN.1 para los tipos etiquetados implícitamente es: [[clase] número] IMPLICIT Tipo
clase = UNIVERSAL | APPLICATION | PRIVATE donde Tipo es el tipo , clase es un nombre opcional de clase, y número es el número de tag dentro de la clase, debe ser un entero no negativo. En los módulos de ASN.1 en los cuales el método de tagging por defecto es el tagging implícito, la notación [[clase] número ] Tipo es también válida y la palabra IMPLICIT se da por supuesta. Para definiciones establecidas fuera de un módulo, la inclusión explícita de la palabra IMPLICIT es preferible para prevenir cualquier tipo de ambigüedad. Si el nombre de la clase está ausente, entonces el tag es context-specific. Este tipo de tags solo pueden aparecer en una componente de un tipo estructurado o en un tipo CHOICE.
Por ejemplo, el tipo PrivateKeyInfo del PKCS # [5] tiene una componente opcional attributes con un tag implícito del tipo context-specific: PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey privateKey, attributes [0] IMPLICIT attributes Optional }
Aquí el tipo subyacente es Attributes, la clase esta ausente (context-specific), y el número de tag dentro de la clase es 0.
5.1.2 La codificación BER. Los métodos de codificación BER para un valor con tagged implícito pueden ser primitive o constructed, dependiendo del tipo subyacente. El contenido de los octetos es como el código BER de los valores subyacentes. Por ejemplo, la codificación BER del componente attributes del valor PrivateKeyInfo es la siguiente:
5.1.3 La codificación DER. La codificación DER de un valor etiquetado implícitamente puede ser primitive o constructed. El contenido de los octetos es como el del valor subyacente.
5.2 TIPOS ETIQUETADOS EXPLÍCITAMENTE (TAGGING EXPLÍCITO).
El tagging explícito denota un tipo derivado de otro tipo añadiendo un tag exterior al tipo subyacente. El tagging explícito es usado para componentes opcionales SEQUENCE con tipo subyacente ANY en todos los PKCS, y para el componente version del tipo[4] Certificate de X.509 revisado en el RFC 1114 [6]
5.2.1 Notación ASN.1. La notación en ASN.1 para tipos etiquetados explícitamente es
[[clase]] número] EXPLICIT Tipo clase = UNIVERSAL | APPLICATION | PRIVATE
donde Tipo es el tipo, clase es un nombre de clase opcional, y número es el número de tag incluido en la clase, un entero no negativo. Si el nombre de la clase está ausente, entonces el tag es context-specific. Los tags context-specific sólo pueden aparecer en una componente del tipo SEQUENCE, SET o CHOICE. En ASN.1, los "módulos" que tienen por defecto el tagging explicito, la notación [[clase] número] Tipo es aceptada, y la palabra EXPLICIT está implícita. Para definiciones establecidas fuera de un módulo, la inclusión explícita de la palabra EXPLICIT es preferible para prevenir cualquier tipo de ambigüedad.
Por ejemplo, el tipo ContentInfo[7] de PKCS #7 tiene un componente opcional content con un tag explícito del tipo context-specific.
ContentInfo ::= SEQUENCE { ContentType ContentType, content [0] Explicit ANY DEFINIED BY contentType OPTIONAL }
Aquí el tipo subyacente es ANY DEFINED BY contentType (alguno definido por contentType), la clase esta ausente (context-specific) y el número de tag dentro de la clase es 0. Como otro ejemplo, el tipo de X.509, Certificate [4] (actualizado en el RFC 1114) tiene una componente version con un tag explicito context-specific, donde la palabra EXPLICIT está omitida:
Certificate ::=... version [0] Version DEFAULT v1988, ...
El tag es explícito porque el método por defecto de tagging para el módulo de ASN.1 que define el tipo Certificate es tagging explicito.
5.2.2 La codificación BER La codificación en BER del valor etiquetado explícitamente es siempre constructed. El contenido de los octetos es la codificación BER del valor subyacente. Por ejemplo, la codificación BER del componente content del valor ContentInfo es la siguiente:
5.2.3 La codificación DER. La codificación DER de un valor etiquetado explícitamente es siempre constructed. El contenido de los octetos es la codificación DER del valor subyacente.
5.3 ANY.
El tipo ANY denota un valor arbitrario de un tipo arbitrario, donde el tipo arbitrario está definido posiblemente en la inscripción de un identificador de objeto o asociado con un índice entero. El tipo ANY es usado como contenido de un tipo particular contenido en el tipo ContentInfo de PKCS #7, para parámetros de un algoritmo particular del tipo AlgorithmIdentifier en X.509, y para valores de atributos de los tipos Attribute y AttributeVakueAssertion en X.501. El tipo Atribute es usado por PKCS #6, PKCS #7 y PKCS #8, y el tipo AtributeValueAssertion es usado en los nombres distinguidos de X.501.
5.3.1 NOTACIÓN ASN.1. La notación ASN.1 para el tipo ANY es ANY [DEFINED BY identificador] donde identificador es un identificador opcional. En la forma ANY , el tipo actual es indeterminado. La forma ANY DEFINED BY identificador solo puede aparecer en una componente de tipo SEQUENCE o SET en el cual identificador identifica algún otro componente, y ese componente tiene tipo INTEGER o OBJECT IDENTIFIER(o un tipo derivado de estos por tagging). En esta forma, el tipo actual está determinado por el valor de otros componentes, dentro de la inscripción del valor del identificador del objeto, o en la tabla de los valores enteros. Por ejemplo, el tipo AlgorithmIdentifier de X.509 tiene una componente de tipo ANY:
AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameter ANY DEFINED BY algorithm OPTIONAL }
Aquí el tipo actual del componente parameter depende del valor del componente algorithm. El tipo actual podría ser definido en el registro del valor de identificador en el componente algorithm.
5.3.2 La codificación BER La codificación BER del valor ANY es la codificación BER del valor actual. Por ejemplo, la codificación BER del valor del componente parameter es la codificación BER del valor del tipo actual definido en el registro del valor del identificador del objeto para la componente algorithm.
5.3.3 La codificación DER. La codificación DER del valor ANY es la codificación DER del valor actual.
5.4 BIT STRING
El tipo BIT STRING denota un string arbitrario de bits (unos y ceros). Un valor BIT STRING puede tener cualquier longitud incluida la longitud cero. Este tipo es un tipo string. El tipo BIT STRING es usado para firmas digitales en certificados extensos en el tipo ExtendedCertificate de PKCS #6, para firmas digitales en el tipo Certificate en X.509, y para claves públicas en certificados del tipo SubjectPublicKeyInfo en X.509.
5.4.1 NOTACIÓN ASN.1 La notación en ASN.1 para el tipo BIT STRING es la siguiente:
BIT STRING
Por ejemplo, el tipo SubjectPublicKeyInfo en X.509 tiene un componente BIT STRING: SubjectPublicKeyInfo ::= SEQUENCE { Algorithm AlgorithmIdentifier, PublicKey BIT STRING }
5.4.2 CODIFICACIÓN BER La codificación BER del valor de un BIT STRING puede ser primitive o constructed. En la codificación primitive, el primer octeto de contenido nos da el número de bits por el cual la longitud el bit string es menor que el próximo múltiplo de ocho(esto es llamado el "número de bits no usados"). El segundo y siguientes octetos contenido nos dan el valor del bit string convertido en un octet string. El proceso de conversión es el siguiente:
En una codificación constructed, los octetos de contenido nos dan la codificación BER de consecutivos substrings del bit string, donde cada substring excepto el último tiene una longitud múltiplo de ocho bits.
Por ejemplo, la codificación BER del bit string con valor "011011100101110111" puede ser la siguiente de entre otras dependiendo de la elecció2n de los bits de relleno, la forma de los octetos de longitud, y si la codificación es primitive o constructed.
03 04 06 6e 5d c0 codificación DER 03 04 06 6e 5d e0 relleno con "100000" 03 81 04 06 6e 5d c0 octetos de longitud en forma larga
23 09 codificación constructed : "0110111001011101" +"11" 03 03 00 6e 5d 03 02 06 c0
5.4.3 CODIFICACIÓN DER La codificación DER de un valor BIT STRTING es siempre primitive. Los octetos de contenido son como para el código BER primitive, exceptuando que el bit string está rellenado con bits de valor cero.
Por ejemplo, la codificación DER del valor de un BIT STRING "011011100101110111" es: 03 04 06 6e 5d c0
5.5 CHOICE
El tipo CHOICE denota la unión de una o más alternativas. El tipo CHOICE se usa para representar la unión de un certificado extendido y un certificado (de X.509) en el tipo ExtendedCertificateOrCertificate en PKCS #7.
5.5.1 NOTACIÓN ASN.1 En ASN.1 la notación del tipo CHOICE es:
CHOICE { [identificador_1] Tipo_1, ..., [identificador_n] Tipo_n }
donde identificador_1, ... , identificador_n (son opcionales) distinguen las distintas alternativas, y Tipo_1, ... , Tipo_n son los tipos de las alternativas. Los identificadores son principalmente para documentación; no afectan al valor del tipo ni su codificación de ninguna manera. Los tipos deben tener distintos tags. Este requerimiento se satisface típicamente con el tagging implícito o explícito en algunas de las alternativas.
Por ejemplo, el tipo ExtendedCertificateOrCertificate en PKCS #7 es un tipo CHOICE ExtendedCertificateOrCertificate ::= CHOICE { certificate Certificate, -- X.509 certificate extendedCertificate [0] IMPLICIT ExtendedCertificate }
Aquí los identificadores para las alternativas son certificate y extendedCertificate, y los tipos de las alternativas son Certificate y IMPLICIT ExtendedCertificate.
5.5.2 CODIFICACIÓN BER La codificación BER de un valor CHOICE es la codificación BER de la alternativa elegida. El factor de que las alternativas tienen distintos tags hace posible distinguir entre sus codificaciones BER. Por ejemplo, el octeto identificador para la codificación BER es 30 si la alternativa elegida es certificate, y a0 si la alternativa elegida es extendedCertificate.
5.5.3 CODIFICACIÓN DER La codificación DER de un valor CHOICE es el código DER de la alternativa elegida.
5.6 IA5String.
El tipo IA5String denota un string arbitrario de IA5 caracteres. IA5 (Internacional Alphabet 5) es semejante al ASCII. Un valor IA5String puede tener cualquier longitud, incluido el cero. Este tipo es un tipo string.
El tipo IA5String se usa para direcciones de correo electrónico y nombres desestructurados en PKCS #9[10].
5.6.1.La notación ASN.1. La notación ASN.1 para el tipo IA5String es
IA5String
5.6.2. La codificación BER. La codificación BER de un valor IA5String puede ser primitive o constructed. En una codificación primitive, el contenido del octeto da los caracteres en el IA5 string, codificado en ASCII. En una codificación constructed, el contenido del octeto da el encadenamiento de las codificaciones BER de los sucesivos substrings del IA5 string.
Por ejemplo la codificación BER del valor de tipo IA5String "test1@rsa.com" puede ser cualquiera de las siguientes, entre otras, dependiendo del formato de la longitud de los octetos y si la codificación es primitive o constructed:
12 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d DER codificación 12 81 0d formato largo de la longitud de los octetos 74 65 73 74 31 40 72 73 61 2e 63 6f 6d 32 13 codificación contructed: "test1"+"@"+ "rsa.com" 12 05 74 65 73 74 31 12 01 40 12 07 72 73 61 2e 63 6f 6d
Otro ejemplo:
"Jones" 1A 05 4A 6F 6E 65 73
5.6.3. La codificación DER. La codificación DER de un valor de tipo IA5String siempre es primitive. El contenido de los octetos es como en la codificación BER primitive.
Por ejemplo la codificación DER del valor IA5String "test1@rsa.com" es
12 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d
5.7 INTEGER .
El tipo INTEGER denota un entero arbitrario. Los valores del INTEGER pueden ser positivos, negativo, o ceros, y puede tener cualquier magnitud. Además, a un valor entero individual se le puede asignar nombres para indicar un significado especifico.
En SNMP, todos los usos de este tipo están restringidos a un rango especifico.
El tipo INTEGER se usa como una versión de números PKCS, los valores [cryptographic] tales como, módulos, exponentes, y números primos en tipos PKCS #1's RSAPublicKey y RSAPrivateKey [11] y PKCS que #3's DHParameter tipos [12], un contador de mensges de digest iteraciones en tipo PKCS #5's PBEParameter, y la versión de números y serie de números en tipo X.509's Certificate [4].
5.7.1. Notación ASN.1. La notación para el tipo INTEGER es
INTEGER [{ identificador1 (valor1 ) ... identificadorn (valorn ) }]
donde identificador1,...,identificadorn son distintos identificadores opcionales y valor1..., valorn son valores del entero optativos. El identificador, cuanto esta presente, se asocia con valores del tipo.
Por ejemplo el tipo RFC 1114's Versión [6] es un tipo INTEGER con los valores de identificadores:
Versión::= INTEGER{ v1988 (0)}
Se asocia el identificador v1988 con el valor 0. El tipo RFC 1114's Certificate usa el identificador v1988 para dar por defecto el valor 0 al componente versión:
Certificate ::= ... version Version DEFAULT v1988, ...
Otro ejemplo: ColorType: := INTEGER { rojo (0) blanco (1) azul (2) } "ColorType" es un INTEGER y sus posibles valores 0,1,2 se nombran como "rojo","blanco" y "azul" respectivamente. ColorType también podría tener cualquier otro valor entero valido, como 4 o -62.
5.7.2. La codificación BER.
La codificación BER de un valor INTEGER siempre es primitive. El contenido del octeto da el valor del entero, en formato de complemento a 2, siendo el dígito más significativo el primero, con el número del mínimo de octetos. El valor 0 se codifica como un solo octeto 00.
En la tabla 3 se ven algunos ejemplos de la codificación BER (sirven también para la codificación DER)
Tabla 3. Ejemplo de codificaciones BER de valores INTEGER.
5.7.3. La codificación DER.
La codificación DER de un valor INTEGER siempre es primitive. El contenido del octeto es como para la codificación BER primitive.
NOTA: Formato de complemento a dos. El bit más significativo es el bit de signo. Numero positivo: Bit más significativo a cero y el resto representa la magnitud del numero. Numero negativo: cuya magnitud es X, siendo X menor o igual a 2N-1 se representa calculando 2N-X. El bit más significativo va a 1. Para calcular el valor decimal de una secuencia de N-bits en complemento a dos usamos la siguiente formula: valor = -bn-1 * 2 N-1 + En un octeto se puede representar el rango -128..127
5.8 NULL
El tipo NULL denota un valor nulo. El tipo NULL es simplemente la alternativa de que no este presente un valor en esa posición de la estructura. Se usa para parámetros de algoritmos en varios lugares de PKCS.
5.8.1 Notación ASN.1 La codificacón ASN.1 para el tipo NULL es
NULL
5.8.2 Codificación BER La codificación BER de un valor NULL siempre es primitive. El contenido del octeto es vacío. Por ejemplo, la codificación BER de un valor NULL puede ser una de las siguientes y, como en las otras, depende del formato de la longitud de los octetos.
05 00 05 81 00
5.8.3 Codificación DER La codificación DER de un valor NULL siempre es primitive. El contenido del octeto es vacío. Por ejemplo, la codificación DER de un valor NULL es siempre 05 00. Serian los dos octetos siguientes:
00000101 00000000 tag universal 5 longitud 0
5.9 OBJECT IDENTIFIER
El tipo OBJECT IDENTIFIER denota un identificador de objeto, que es una secuencia de enteros no negativos que identifican a un objeto como un algoritmo o como el atributo nombre de directorio. Un valor de tipo OBJECT IDENTIFIER, puede tener cualquier número de componentes. Este tipo es un tipo no-string. El conjunto de objetos definidos tiene una estructura de árbol, cada objeto es uno de sus nodos y la raíz del árbol es un objeto referenciado por el estándar ASN.1. Cada nivel j del árbol tiene n nodos numerados de 0 a n. El valor de un identificador de objetos es la lista de los números de los nodos empezando en la raíz. Esto nos da una idea de lo que representa el objeto. Los valores OBJECT IDENTIFIER vienen dados por un estándar (registration autorithies). Cada estándar es responsable de todas las secuencias de los componentes que empiezan con una secuencia dada. Un estándar típico delega responsabilidad de los subconjuntos de objetos de su dominio a otros estándares, o para tipos particulares de objetos. Hay siempre por lo menos dos componentes. En SNMP, la longitud de la secuencia esta limitada a un máximo de 128 elementos, y el máximo valor para un elemento es 232-1 (4294967295).
Ejemplo: En el subárbol con raíz "RetailStores" el objeto "payroll" tiene de valor local {0 6 2}, y su valor completo sería {x 0 6 2} donde x es el valor de su raíz en el árbol total.
El tipo de OBJECT IDENTIFIER es usado para identificar el contenido en tipo PKCS #7's ContentInfo [ 7], para identificar algoritmos en tipo X.509's AlgorithmIdentifier, y para identificar atributos en tipo X.501's Atribute y tipo AttributeValueAssertion [8]. El tipo Atributo es usado por PKCS #6 [ 9], PKCS #7[ 7], y PKCS #8[ 5], y el tipo AttributeValueAssertion es usado en X.501 nombres distinguidos. Los valores OBJECT IDENTIFIER están definidos en todo el PKCS.
5.9.1 Notación ASN.1 La notación ASN.1 para el tipo OBJECT IDENTIFIER es
OBJECT IDENTIFIER
La notación ASN.1 para valores del tipo OBJECT IDENTIFIER es
{[identificador] componente1... componenten}
componente_i= identificador_i | identificador_i (valor_i) | valor_i
donde identificador, identificador1,..., identificadorn son identificadores, y valor1...., valorn son valores aleatorios del entero. La forma sin identificador es el valor "completo" con todos sus componentes; la forma con identificador abrevia los componentes del principio con otro valor de tipo OBJECT IDENTIFIER. La intención primordial de los identificadores identificador1,... ,identificadorn es de documentación, pero deben corresponder con su valor entero cuando ambos están presentes. Estos identificadores pueden aparecer sin el valor entero sólo si están entre un conjunto pequeño de identificadores definidos en X.208[ 2]. Por ejemplo los siguientes valores al identificador del objeto asignado a RSA Data Security, Inc.: { iso(1) memberbody(2) 840 113549 } { 1 2 840 113549 }
La Tabla4 da algunos otros valores de identificadores de objetos y sus significados.
Tabla 4. Unos valores del [identifier] del objeto y sus significados.
5.9.2 Codificación BER La codificación BER de un valor de tipo OBJECT IDENTIFIER siempre es primitive. El contenido del octeto es el encadenamiento de n-1 string de octetos, donde n es el número de componentes del identificador de objeto completo. Cada string de octetos es la codificación de un valor entero, en base 128, donde el dígito más significativo es el primero, con los mínimos dígitos posibles, y con 8 bits para cada octeto excepto el ultimo que queda fijo a "1." El bit 8 (el más significativo) de cada octeto indica si es el ultimo octeto de los subidentificadores poniendolo a 0. Los 7 bits restantes representan el valor del octeto. Denotamos valor1,...., valorn los valores enteros de los componentes en el identificador del objeto completo. Los n-1 "subidentificadores" a partir de los cuales se deriva el octet string son como sigue: 1. El primer subidentificador es 40valor1+valor2.2 (Esto es razonable ya que valor1, que corresponde al primer nivel del árbol, está limitado a los valores 0 (ccit),1(iso) y 2(hiubt-iso-ccitt); y el valor2, segundo nivel del árbol, esta limitado por el rango 0..39 cuando valor1 es 0 o 1, y hay siempre al menos dos componentes de acuerdo con X.208 [2].) 2. El i-esimo subidentificador, 2<=i<= n-1, es el valor i+1. La codificación de estos octetos es como sigue: el Bit 8 es 0 cuando es el último octeto del subidentificador. Los bist del 7 al 1 son la codificación del valor del subidentificador. En el caso de que necesitemos varios octetos para un mismo identificador su valor vendrá dado por la concatenación de los bist 1..7 de cada uno de los octetos necesarios. Por ejemplo, el subindentificador para el identificador del objeto RSA Data Security, Inc's es 42=40*1+2,840,113549, y 1. La codificación de 42 es 2A, la de 840 es 86 48. la de 113549 es 86 F7 0D, y la de 1 es 01, lo que nos lleva a la siguiente codificación BER: 06 07 2A 86 48 86 F7 0D 01 5.9.3 Codificación DER La codificación DER de un valor de tipo OBJETO IDENTIFIER siempre es primitived. El contenido del octeto es como la codificación BER primitive.
5.10 OCTET STRING
El tipo OCTET STRING coge valores que son una secuencia ordenada de cero o más grupos de ocho bits. Es un tipo de string bastante simple de codificar. Ejemplo : Tag Universal 4 Longitud = 4 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 Primer octeto Segundo octeto Tercer octeto Cuarto octeto 1 1 1 0 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 0 0 1 1 0 1 1 1 Tag Universal 4 --> Es la etiqueta que indica que lo siguiente es un octet string.
5.10.1 La anotación ASN.1
OCTET STRING [SIZE ({ size| size1..size 2})]
donde podemos elegir dos formas de elegir el tamaño : 1.-Usando size1 y size2 que indican que la cadena de octetos debe tener como mínimo 'size1' octetos y como máximo 'size2' octetos. 2.-Si usamos size el tamaño de la cadena sera exactamente 'size' octetos Por ejemplo el tipo PBEParameter de PKCS #5's [Password-base Encryption Estándard] tiene un componente de tipo OCTET STRING: PBEParameter2 ::= SEQUENCE { salt OCTET STRING SIZE(8), iterationCount INTEGER } Aquí el tamaño del componente 'salt' tiene siempre ocho octetos.
5.10.2 La codificación BERUn octet string puede ser una primitive o un constructed : - En la codificación de una primitive, el contenido de los octetos da el valor de la cadena. - En una codificación de un constructed, el contenido de los octetos da la concatenación de subcadenas de octetos codificadas en BER Por ejemplo la codificación en BER del OCTET STRING con valor 01 23 45 67 89 ab cd ef puede ser cualquiera de las siguientes, dependiendo del campo de longitud y dependiendo de si es primitived o un compuesto: codificación BER 04 08 01 23 45 67 89 ab cd ef la forma larga de octetos 04 81 08 01 23 45 67 89 ab cd ef codificación de forma compleja : 01 23 45 67 89 ab cd ef 24 0c 04 04 01 23 45 67 04 04 89 ab cd ef
5.10.3 La codificación DER La codificación DER de un valor OCTET STRING es la de una primitive. El contenido de los octetos se trata igual que si fuera una primitive codificada en BER. Por ejemplo en la codificación BER del valor del OCTET STRING '01 23 45 67 89 ab cd ef ' es : 04 08 01 23 45 67 89 ab cd ef
5.11 El tipo PRINTABLESTRING
El tipo PrintableString es una cadena de caracteres en ASCII, que puede tomar cualquier valor dentro de los siguiente conjuntos de caracteres : A, B,...,Z a, b,..,z 0, 1,...,9 (espacio) ' () + - , . / : = ?
Es un tipo de string. El tipo PrintableString se usa en varios tipos de atributos y palabras reservadas en X.520[Nodo directorio].
5.11.1 La notación ASN.1
PrintableString
5.11.2 La codificación BER Un PrintableString puede ser una primitive o un constructed : - En la codificación de una primitive, el contenido de los octetos da el valor de la cadena de caracteres en ASCII. - En una codificación de un 'compuesto', el contenido de los octetos da la concatenación de subcadenas de caracteres codificadas en BER.
Por ejemplo la codificación en BER del valor PrintableString "Test User 1" puede ser cualquiera de las siguientes dependiendo del campo de longitud de los objetos y si la codificación es primitive o constructed: La etiqueta '13' indica que es un PrintableString (Universal 19) El campo siguiente nos indica la longitud ('0b'=11)
Codificación BER 13 0b 54 65 73 74 20 55 73 65 72 20 31 Forma Larga de los octetos 13 81 0b 54 65 73 74 20 55 73 65 72 20 31 Forma compuesta, "Test" + "User 1" La etiqueta 33 nos indica que se trata de un PrintableString de forma compuesta. Linea 1 --> '0f' nos indica que la longitud total de las subcadenas es 15 Linea 2 y 3--> '13' Indica que es un PrintableString Simple Linea 2 --> '05' es la longitud de la primera subcadena Linea 3 --> '06' es la longitud de la segunda subcadena 1. 33 0f 2. 13 05 54 65 73 74 20 3. 13 06 55 73 65 72 20 31
5.11.3 La codificación DER.La codificación DER de un valor de un PrintableString es la de una primitived. El contenido de los octetos es tratado como una primitived de la codificación BER. Por ejemplo en la codificación DER del PrintableString -> "Test user 1" es
13 0b 54 65 73 74 20 55 73 65 72 20 31
5.12 EL TIPO SEQUENCE
El tipo SEQUENCE es una lista ordenada de cero o más tipos de datos. El tipo SEQUENCE se usa en PKCS y estándares relacionados
5.12.1 La notación ASN.1
SEQUENCE{ [identifier 1 ] Type 1 [{OPTIONAL | DEFAULT value1}], ..., [identifier n ] Type n [{OPTIONAL | DEFAULT valuen}]}
donde - Identifier1 ,..., identifiern son optativos, y tienen que ser identificadores distintos para los componentes - Type1,...,Typen que son los tipos de los componentes, - Value1,...,valuen son valores 'optativos' o 'cogidos por defecto' para los componentes. Los identificadores son primordiales para la documentación; estos no afectan de ninguna manera a los valores del tipo o a sus codificaciones. Tenemos dos formas de especificar que un tipo de componente es opcional en la lista ordenada: 1.- Usando OPTIONAL después del tipo del componente. Cuando usamos esta opción, el valor indica que puede estar o no presente en la secuencia. 2.- Usando DEFAULT después del tipo del componente Cuando usamos esta opción, el valor especificado es usado, cuando el tipo no aparece en la lista. Los tipos de cualquier serie sucesiva de componentes con valor OPTIONAL o DEFAULT, deben tener etiquetas distintas. Este requisito se satisface con etiquetas implícitas o explicitas de algunos componentes. Por ejemplo el tipo Validity de X.509's [Nodo Directorio] es un tipo SEQUENCE con dos componentes:
Validity ::= SEQUENCE { start UTCTime, end UTCTime }
Aquí los identificadores para los componentes son 'start' y 'end' y los tipos de los componentes están ambos en UTCTime.
Otro ejemplo :
Message ::= SEQUENCE { version INTEGER { version-1(0)}, community OCTET STRING}
sample Message ::= {0,'EB069937'h}
5.12.2 La codificación BER
La codificación BER del valor SEQUENCE es siempre la de un compuesto. El contenido de los octetos es la concatenación de los valores de los componentes de la secuencia codificada en BER, en orden de definición, con las siguientes reglas para los componentes, con los valores OPTIONAL y DEFAULT: a) Si el valor de un componente con el VALOR OPTIONAL o DEFAULT no esta en la secuencia, entonces la codificación de ese componente no esta incluida en la secuencia de octetos. b)Si el valor de un componente con el valor DEFAULT toma un valor por defecto, entonces la codificación de ese componente puede o no incluirse en la secuencia de octetos. La etiqueta 16 indica que es un tipo secuencia.
Tag Universal 16 Longitud = 9 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1
Primer octeto Segundo octeto Tercer octeto Cuarto octeto 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
Quinto octeto Sexto octeto Septimo octeto Octavo octeto 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1
Noveno octeto 0 0 1 1 0 1 1 1
5.12.3 La codificación DER
La codificación DER de un valor SEQUENCE es siempre de forma compuesta. El contenido de los octetos se trata como en BER, excepto porque si el valor de un componente con el Calificador DEFAULT es un valor por defecto, no se incluye la codificación de ese componente en el contenido de los octetos.
5.13 SEQUENCE OF
El tipo SEQUENCE OF es una colección ordenada de cero o más sucesos de un tipo dado. El tipo SEQUENCE OF es usado, en X.501[Nodo Directorio].
5.13.1La notación ASN.1
SEQUENCE OF type
donde type un tipo cualquiera.
Por ejemplo el tipo RDNSequence usado en X.501's [Nodo Directorio] consta de cero o más sucesos del tipo RelativeDistinguishedName :
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
5.13.2 La codificación BER
Es siempre igual a la de un compuesto. El contenido de los octetos es la concatenación de los valores de los sucesos en orden de definición.
5.13.3 La codificación DER . La codificación DER de un valor SEQUENCE OF es siempre compuesta. El contenido de los octetos se trata como en BER, es la concatenación de los valores de los sucesos de la codificación DER en orden de ocurrencia.
5.14 SET El tipo SET es un tipo compuesto que denota una colección desordenada de uno o más tipos, alguno de los cuales puede ser declarado como opcional. Cada valor es una lista desordenada de valores, uno de cada tipo de componentes. En la gramática BNF se representa como:
El tipo SET se usa en PKCS. El tipo de "tag" que lo define es "UNIVERSAL 17".
5.14.1 La notación ASN.1 La notación ASN.1 del tipo de SET es SET{ [identificador 1 ] Tipo 1 [{OPTIONAL | DEFAULT valor 1 }], ..., [identificador n ] Tipo n [{OPTIONAL | DEFAULT valor n }]} donde identificador1 ,..., identificadorn son optativos, y son identificadores distintos para los componentes, Tipo1,...,Tipon son los tipos de los componentes, y valor1,...,valorn son valores "optativos" o "cogidos por defecto" para los componentes. Los identificadores son primordiales para la documentación; éstos no afectan de ninguna manera a los valores del tipo o a sus codificaciones. El valor OPTIONAL indica que el valor de un componente es optativo y indica que no está presente en el conjunto. El valor DEFAULT también indica que el valor de un componente es optativo, y le asigna a un valor por defecto cuando el componente no está. Los tipos de cualquier serie sucesiva de componentes con valor "OPTIONAL" o "DEFAULT", deben tener etiquetas distintas. Este requisito se satisface con etiquetas implícitas o explícitas de algunos componentes. Ejemplo:
{ nombre IA5String, edad INTEGER, hembra BOOLEAN }. Tres representaciones de esta instancia son: {"Maggie", 4, true} {, true, "Maggie", 4} {4, true, "Maggie"} 5.14.2La codificación BER
La codificación BER del valor SET es siempre "constructed". El contenido de los octetos es la concatenación de los valores de los componentes de un conjunto en algún orden, con las siguientes reglas para los componentes, con los valores OPTIONAL y DEFAULT Si el valor de un componente con el "VALOR OPTATIVO" o "DEFAULT" no está en el conjunto, entonces la codificación de ese componente no está incluida en el contenido de los octetos. Si el valor de un componente con el valor "DEFAULT" toma un valor por defecto, entonces la codificación de ese componente puede o no incluirse en el contenido de los octetos. Ejemplo: definition: 31 06 SET (INTEGER, 02 01 03 INTEGER) 02 01 08 value: (3,8) 5.14.3 La codificación DER
La codificación DER de un valor SET es siempre compuesta. El contenido de los octetos se trata como en BER, excepto que :
1.-si el valor de un componente con el Calificador DEFAULT es un valor por defecto, no se incluye la codificación de ese componente en el contenido de los octetos. 2.- Existe un orden para los componentes, en orden ascendente de etiqueta.
5.15 SET OF El tipo SET OF es un tipo compuesto que denota una colección de cero o más ocurrencias de un tipo dado. Cada valor es una lista desordenada de cero o más valores de tipos existentes. En la gramática BNF se representa como:
El tipo SET OF es usado para conjuntos de atributos en PKCS#6[9],PKCS#7[7], PKCS#8[5], para conjuntos de identificadores de algoritmos de "mensajes-digest", información "signer" y información "recipient" en PKCS#7[7] y en X.501[8]. El tipo de "tag" que lo define es "UNIVERSAL 17".
5.15.1 La notación ASN.1
La notación de ASN.1 para el tipo SET OF es SET OF tipo donde "tipo" es un tipo cualquiera. Por ejemplo, X.501's RelativeDistinguishedName type [8] esta formado por cero o más ocurrencias del tipo AttributeValueAssertion, donde el orden no es importante: RelativeDistinguishedName ::= SET OF AttributeValueAssertion 5.15.2 La codificación BER
La codificación del valor SET OF es siempre "constructed". El contenido de los octetos es la concatenación, en algún orden, de los valores de las ocurrencias de la codificación BER en una colección. Ejemplo: definition: 31 06 SET OF 02 01 03 (INTEGER) 02 01 08 value: (3,8) 5.15.3 La codificación DER
La codificación DER de un valor SET OF es siempre compuesta. El contenido de los octetos es el mismo que en BER, excepto en aquí existe un orden, ascendente ordenado por nombre en la codificación BER. 5.16 Useful types (tipos prácticos): 1) GeneralizadTime 2) UTCTime. 3) Tipos externos. Los "useful types", normalmente transfieren fechas y datos sobre el tiempo junto con otros tipos de datos. En lugar, de que el usuario defina los tipos para modelos de fecha y datos del tiempo. ASN.1 proporciona una sintaxis. Esta notación no solo es útil, sino que asegura uniformidad. ASN.1 define dos "useful types" para transferir el tiempo y los datos sobre la fecha, GeneralizedTime y UTCTime. Otros dos "useful types" son ObjectDescriptor y "external", que se agregaron a las normas de ASN.1 en 1988. El tipo "ObjectDescriptor" se usa con el tipo " Object identifier". En la gramática BNF se representa como:
5.16.1GeneralizadTime
Consistente en la fecha, especificada con dos dígitos para el año, dos dígitos para el mes, y dos dígitos para el día. Seguidos de la hora en, horas, minutos y opcionalmente segundos. Seguidos de una especificación opcional de la diferencia entre el tiempo local respecto al universal. Tipo GeneralizedTime toma los valores de año, mes, día, hora, tiempo, minutos, segundos, y décimas de segundo en una de cualquiera de tres formas: Tiempo local sólo. "YYYYMMDDHHMMSS.fff", donde el fff es optativo. Tiempo universal (cronómetro UTC) . "YYYYMMDDHHMMSS.fffZ". Diferencia entre local y tiempos de UTC."YYYYMMDDHHMMSS.fff+-HHMM". El tipo de "tag" es "UNIVERSAL 24". 5.16.1.1 La notación ASN.1 La notación de este tipo es la palabra reservada "GeneralizedTime". Por ejemplo, si CurrentTime: := GeneralizedTime entonces cualquiera de lo siguiente tres valores de CurrentTime son válidos: "19991231235959.999" es 1/1000 segundo antes del fin del siglo XX en el tiempo local; "19991231205959.999Z" es el tiempo universal con tres horas de diferencia respecto al tiempo local anterior; y "19991231235959.999+0302" indica el tiempo local tres horas por delante respecto del tiempo universal.
5.16.2 UTCTime
El tipo UTCTime denota una hora elegida universalmente o el valor del tiempo en el meridiano de Greenwich(GMT).. Un valorUTCTime incluye el tiempo local preciso en minutos o segundos, y un desplaza-miento del GMT en horas y minutos. Toma una de las formas: YYMMDDhhmmZ YYMMDDhhmm+hh'mm' YYMMDDhhmm-hh'mm' YYMMDDhhmmssZ YYMMDDhhmmss+hh'mm' YYMMDDhhmmss-hh'mm' donde: YY son los dígitos menos significativos del año MM es el mes (01 a 12) DD es el día (01 a 31) hh es la hora (00 a 23) mm son los minutos (00 a 59) ss son los segundos (00 a 59) Z indica que tiempo local es GMT,+ indica el tiempo de desfase mayor respecto al GMT(es mayor la hora local),- indica que tiempo es menor que GMT . hh' es el valor del desfase absoluto respecto al GMT en horas mm' es el valor del desfase absoluto respecto al GMT en minutos Este tipo es un tipo de "string". El tipo UTCTime se usa para tiempos asignados en PKCS #9's y atributos signing-time [10] y en los tipos Validity del X.509's para certificar períodos validados.[4]. El tipo de "tag" es "UNIVERSAL 23". 5.16.2.1 La notación ASN.1 La notación del ASN.1 para el tipo UTCTime es : UTCTime Ejemplo: NewTime ::= UTCTime entonces puede tomar los siguientes valores del tiempo local: "19991232235959" o "199912312359". 5.16.2.2 La codificación BER La codificación BER de un valor UTCTime puede ser primitive o constructed. En una codificación primitive, el contenido de los octetos da los caracteres en el string, cifrado en ASCII. En una codificación compuesta, el contenido de los octetos da la concatenación de subcadenas consecutivas de un "string" en la codificación BER. (La codificación compuesta no es particularmente interesante, porque aunque la codificación compuesta se permite, los valores que toma UTCTime son pequeños.) Por ejemplo, el tiempo en que se escribió esta frase era 4:45:40 postmeridiano Pacificif Daylight Time del 6 de mayo de 1991, que se puede representar con el valor UTCTime , entre otros: " 910506164540-0700" " 910506234540Z"
Estos valores tienen en BER las siguientes codificaciones, entre otras: 17 0d 39 31 30 35 30 36 32 33 34 35 34 30 5A 17 11 39 31 30 35 30 36 31 36 34 35 34 30 2D 30 37 30 30
5.16.2.3 La codificación DER
La codificación DER de un valor UTCTime siempre es primitive. El contenido de los octetos es como el de las primitives en la codificación en BER. 5.16.3 External.
Es un tipo definido en algún documento externo. Los valores de tipo "externos" que comunican tanto los datos como su interpretación. El tipo de dato "externo", no necesita ser un tipo de ASN.1. El tipo "externo" se usa por ejemplo en la "Association Control Service Element" (ACSE) que es común a todas las aplicaciones de OSI, como modelo un de variables cuyo tipo puede no ser especificado o especificado en otra parte. No hay ninguna restricción en la notación para especificar el tipo. En ISO 8824 contiene la definición del siguiente tipo "externo": EXTERNAL ::= [UNIVERSAL 8] IMPLICIT SEQUENCE { direct-reference OBJECT IDENTIFIER OPTIONAL, indirect-reference INTEGER OPTIONAL, data-value-descriptor ObjectDescriptor OPTIONAL encoding CHOICE { single-ASN1-type [0] ANY, octet-aligned [1] IMPLICIT OCTET STRING, arbitrary [2] IMPLICIT BIT STRING} }
La sintaxis de los nombres abstractos se transfieren como un nombre del tipo "OBJECT IDENTIFIER" y "Presentation Context Identifiers" (PCI) como un nombre del tipo "INTEGER" . La gestión de la capa de presentación hace al menos una referencia a "direct-reference" o "indirect-reference" obligatoriamente. Cada nombre de un identificador de una sintaxis abstracta puede ser dado por un P-usuario(sender). Se transfiere la sintaxis, luego se gestiona, se establece la conexión y se transifieren sus PCIs(para la interpretación de los valores de los datos). Cuando los valores de los datos son una instancia de tipos simples de ASN.1, se aplican a los tipos de datos, las reglas estándar de codificación. Sino el usuario tiene que elegir entre "octet-aligned" o "arbitrary" si el valor del dato es un número entero de octetos. Pero sólo puede utilizar "arbitrary" si el valor del tipo no es un múltiplo de octetos. Por ejemplo, suponemos que durante la gestión, el PCI de 7 está asignado a un tipo "string" por un estándar no ASN.1 y ese String ::= EXTERNAL está definido en ASN.1. Entonces una instancia de String es { indirect-reference 7, encoding arbitrary BIT STRING ' 27ABC63'H }
Donde "arbitrary" se elige para codificar y la cadena hexadecimal es la representación actual del "string" transmitido.
El tipo de "tag" es "UNIVERSAL 8".
6. RASGOS ADICIONALES.
ASN.1 también define una notación para subtipos y conjuntos de valores, y métodos para manejar la recursividad en los tipos de datos. Frecuentemente se usan subtipos y recursividad en las macros. 6.1 La notación de los subtipos y conjunto de valores. Frecuentemente nos encontramos situaciones donde sólo nos interesa una porción de un conjunto de valores o sólo nos interesa una parte de la secuencia. Por ejemplo, podemos estar interesados sólo en los divisores de 24, valores entre dos enteros, o las primeras 9 personas en una cola. ASN.1 permite subtipos que le permiten a un usuario que especifique valores dentro del rango de valores de un tipo. Un subtipo está derivado de un tipo padre con alguna restricción hacia el conjunto de valores del tipo padre. Esto es, el conjunto de valores para el subtipo es un subconjunto de valores del tipo padre. El proceso de crear subtipos puede extenderse a más de un nivel. Es decir, un subtipo puede ser al mismo tiempo, padre de otros subtipos y subtipo de otro. La notación del valor de un subtipo es como la del tipo del padre. 6.1.1 La notación ASN.1 La notación del tipo es la unión del conjunto de valores entre paréntesis separados por el símbolo "|" que tiene el significado de "or", como en BNF. ASN.1 definen seis formas de anotación para los conjuntos de valores. Ejemplos de cinco de ellos - SingleValue, ContainedSubtype, ValueRange, PermittedAlphabet, SizeConstraint y InnerType. 6.1.2 Single value: Un subtipo "valor simple" es una lista explícita de todos los valores que puede tomar el subtipo. Por ejemplo: Sucesion ::= INTEGER (2 | 5 | 7 | 11 | 13 | 17 | 19 | 23 | 29). En este caso Sucesion es un subtipo del tipo "INTEGER". Otro ejemplo: Meses ::= ENUMERATED ( enero (1),febrero (2), marzo (3),abril (4), mayo (5),junio (6), julio (7),agosto (8), septiembre (9),octubre (10), noviembre (11),diciembre (12) ) Primer-Trimestre ::= ( enero | febrero| marzo) Segundo-Trimestre ::= ( abril | mayo | junio ) Primer-trimestre y segundo trimestre son subtipo del tipo Meses.
6.1.3 Contained subtype
El "tipo contenido" se usa para nuevas formas de subtipos a partir fr subtipos ya existentes. El " tipo contenido" contiene todos los valores de los subtipos que contiene. Por ejemplo: Medio-Año :: = Meses ( INCLUDES Primer-Trimestre | INCLUDES Segundo-Trimestre) Un "tipo contenido" también puede incluir lista de valores explicitos: Mezcla ::= Meses (INCLUDES Primer-Trimestre | abril ) 6.1.4 Value range.
El subtipo "rango de valores" se aplica sólo a los tipos INTEGER y REAL. Especifica los valores numéricos dados entre los puntos finales del rango. Se pueden usar los valores especiales "PLUS-INFINITY" y MINUS-INFINITY" . Los valores especiales "MAX" y "MIN" pueden usarse para indicar los máximos y mínimos valores permitidos de los valores del padre. Los intervalos especificados pueden ser abiertos o cerrados. Cuando es abierto, la especificación del punto final es el símbolo "menor que" (<). Ejemplos: Las siguientes definiciones son equivalentes: EnterosPositivos ::= INTEGER (0< .. PLUS-INFINITY) EnterosPositivos ::= INTEGER (1 .. PLUS-INFINITY) EnterosPositivos ::= INTEGER (0< .. MAX) EnterosPositivos ::= INTEGER (1 .. MAX)
Las siguientes definiciones son equivalentes: EnterosNegativos ::= INTEGER (MINUS-INFINITY .. < 0) EnterosNegativos ::= INTEGER (MINUS-INFINITY .. -1) EnterosNegativos ::= INTEGER (MIN .. < 0) EnterosNegativos ::= INTEGER (MIN .. -1)
6.1.5 Permitted Alphabet.
El subtipo "alfabeto permitido" sólo puede ser aplicado al tipo "character string". Un "alfabeto permitido" se compone de todos los valores que pueden ser construídos usando un subalfabeto de tipo padre.
Ejemplo: TouchToneButtons ::= IA5String ( FROM ( "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "*" | "#" ) )
CadenaDigitos ::= IA5String ( FROM ( "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ) )
6.1.6 Size Constraint.
El subtipo "tamaño obligado" limita el número de elemento de un tipo. Puede ser aplicado solamente al tipo "string" (bit string, octet string, character string) y a los tipos "sequence of" y "set of" . El elemento que obliga, depende del tipo padre, como sigue. Tipo Unidad de medida bit string bit octet string octet character string character sequence-of valor del componente set-of valor del componente Un ejemplo de tipo "string", Recommendation X.121 especifica que los números internacionales de datos, están especificados por la dirección del sistema final de datos públicos en una network, incluyendo la X.25 network, que debería consistir en al menos 5 dígitos pero no más de 14 dígitos. Esto se puede especificar como sigue: ItlDataNumber ::= DigitString ( SIZE (5 ..14) ). Ahora consideremos un parámetro de una lista para mensajes que puede incluir 12 parámetros: ParameterList ::= SET SIZE (0 .. 12) OF Parameter
6.1.7 Inner subtyping Un "subtipo interno" sólo puede ser aplicado a los tipos "sequence", "sequence-of", "set" , " set-of" y "choice". Un subtipo interno incluye sólo algunos valores del tipo padre que cumplen una o más condiciones presentadas con los valores and/or de los componentes del tipo padre. Este es un subtipo muy complejo., y aqui sólo se dan unos pocos ejemplos. Consideremos una unidad de protocolo de datos(PDU) que puede tomar cuatro valores distintos, no en un orden particular: PDU ::= SET {alpha [0] INTEGER, beta [1] 2 IA5String, gamma [2] SEQUENCE OF Parameter, delta [3] BOOLEAN}
El siguiente código especificará un test que requiere el valor booleano para ser falso y el valor entero para ser negativo: TestPDU ::= PDU (WITH COMPONENTS {......... delta (false), alpha (MIN ... < 0 ) } ) Una nueva representación del parámetro beta se presenta en longitud cada 5 oó 12 caracteres, consideremos el siguiente código: FutherTestPDU ::= TestPDU (WITH COMPONENTS {....beta (SIZE (5 | 12) PRESENT} ) En otro ejemplo, consideramos el uso de un subtipo interno en una secuencia de constructores: Text-block ::= SEQUENCE OF VisibleString Address ::= Text-block ( SIZE (1..6) | WITH COMPONENT (SIZE (1..32) ) ) ) Estos indican que las dirección contiene desde 1 a 6 bloques de texto y que cada bloque de texto contiene de 1 a 32 caracteres de longitud.
6.2 La recursividad.
La recursividad, es un rasgo común de los lenguajes de alto nivel, y también es un rasgo en ASN.1 . Los tipos de datos, como un conjunto de conjuntos, registros con uno o más componentes siendo un registro, uniones de listas, y árboles, pueden ser mejor comprendidas cuando vemos una estructura recursivas. ASN.1 permite definiciones de esos emparentados tipos de datos y valores incluidos en la recursividad. Por ejemplo, las uniones de listas de valores de enteros, en cada nodo puede ser una unión de listas de valores de enteros, está especificada: LinkedList ::= SEQUENCE { label IASString, value CHOICE { nodevalue INTEGER OPTIONAL, node SEQUENCE OF LinkedList OPTIONAL } }
Asumir la "L", mostrada en la figura, como una instancia consistente en el tipo LinkedList de cuatro nodo etiquetados con A, B, C, D donde B es una unión de de listas de tres nodos B1, B2, B3 y B3 a su vez es una unión de dos nodos B31, B32. Los nodos cabecera no están incluídos en este ejemplo. Luego, la instancia puede ser representada: { label "L" value node { {label "A", value nodevalue 75}, {label "B", value node { {label "B1", value nodevalue 60}, {label "B2", value nodevalue 50}, {label "B3", value node { {label "B31", value nodevalue 48}, {label "B32", value nodevalue 46}, } } } {label "C", value nodevalue 35}, {label "D", value nodevalue 15},
}
6.3 MACROS
Esta notación permite al usuario extender la sintaxis de ASN.1 para definir nuevos tipos y sus valores. Consideramos lo siguientes puntos:
7. Ejemplo Esta sección da un ejemplo de la notación ASN.1 y codificación DER : el tipo Name[8] de X.501.
7.1 La notación abstracta Esta sección da la notación ASN.1 para el tipo Name de X.501. Name ::= CHOICE { RDNSequence }
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName RelativeDistinguishedName ::= SET OF AttributeValueAssertion AttributeValueAssertion ::= SEQUENCE { AttributeType, AttributeValue }
AttributeType ::= OBJECT IDENTIFIER AttributeValue ::= ANY El tipo Name identifica un objeto en un directorio de X.500 [15]. Name es un tipo CHOICE que consta de una alternativa: RDNSequence. El tipo RDNSequence da un path(direccion) a un directorio X.500 que empieza en el root(raiz). RDNSequence es un tipo SEQUENCE OF consistente en cero o más ocurrencias de RelativeDistinguishedName. El tipo RelativeDistinguishedName da un nombre único a un objeto relativo al objeto superior a él en el directorio del árbol. RelativeDistinguishedName es un tipo SET OF que consta de ceros o más ocurrencias de AttributeValueAssertion. El tipo AttributeValueAssertion le asigna a un valor a alguno de los atributos relativo nombre seleccionado, como un nombre country o como un nombre común. AttributeValueAssertion es un tipo SEQUENCE OF que consta de dos componentes, un tipo AttributeType y un tipo AttributeValue. El tipo AttributeType identifica un atributo por object identifier. El tipo AttributeValue da un valor a un atributo arbitrario. (El tipo actual de el valor del atributo es pensado para determinar por el tipo atributo , aunque ANY DEFINED BY no se emplea.) 7.2 DER codificación Esta sección da un ejemplo de la codificación DER de un valor de tipo Name , trabajando de abajo arriba. El nombre es ese de RSA Data Security, Inc's. "NOTARY" unidad para Internet Privacy-Enhaned Mail[ 16,17], que se representa por el path siguiente:
(root) | countryName = "US" | organizationName = "RSA Data Security, Inc." | organizationalUnitName = "NOTARY Cada nivel corresponde a un valor RelativeDistinguishedName , cada uno de los cuales, consta de un valor AttributeValueAssertion. El valor AttributeType esta antes del signo igual, y el valor AttributeValue (un printable string para los tipos de atributos) esta después del signo igual. AttributeType La codificación del valor del árbol AttributeType sigue la primitive, método definite-lenght, resultando el siguiente OCTET STRING: 06 03 55 04 06 countryName 06 03 55 04 0a organizationName 06 03 55 04 0b organizationalUnitName
Aquí 'countryName', 'organizationName', y 'organizationalUnitName' son tipos de atributos X.520 [14], que tienen las siguientes definiciones : AttributeType OBJECT IDENTIFIER::= { joint-iso-ccitt (2) ds (5) 4} countryName OBJECT IDENTIFIER::={attributeType 6} organizationName OBJECT IDENTIFIER::={attributeType 10} organitationUnitName OBJECT IDENTIFIER ::= {attributteType 11}
El identificador de octetos sigue la forma low-tags, como es una marca 6 para OBJECT IDENTIFIER. Los bits 7 y 8 tienen valor" 0", indicando la clase universal, y el bit 6 tiene valor" 0", que indica que la codificación es primitived. La longitud del octeto sigue la forma corta. El contenido de los octetos es el encadenamiento de arboles octet string derivados de los subidentificadores. subidentifiers: 85= 40+ 2+ 5; 4; y 6, 10, ó 11. AttributeValue La codificación DER de los valores del árbol AttributeValue siguen la primitive, método definite-lenght, resultando los siguientes octets strings: 13 02 55 53 "US" 13 17 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||