primeiro módulo
Introdução, ASN.1
C2-2 Os padrões PKCS#1
e PKCS#8 para cifragem e assinatura
Detentora, até setembro de 2000, da patente do RSA, o primeiro algoritmo critpográfico assimétrico a resistir o critério de assimetria (controle do custo para se obter a chave privada a partir da chave pública com uma implementação sadia do algoritmo gerador do par de chaves), a RSADSI publicou, no início dos anos 90, uma série de recomendações contendo especificações visando padronizar os formatos e operações criptográficas baseadas neste algoritmo.Essa família de recomendações é conhecida pela sigla PKCS (Public Key Cryptographic Stantards) compreendendo os documentos PKCS #1, #3, #5, #7, #8, #9, #10 #11, #12, #13, #14 e #15 (repositório em ttp://www.rsasecurity.com/rsalabs/pkcs/). Devido a seu pioneirismo e simplicidade do algoritmo, tornaram-se padrão de fato em PKIs . Iremos abordar os padrões PKCS #1, que trata das primitivas critpográficas, dos esquemas de cifragem e assinatura digital e PKCS #8, que trata da sintaxe para armazenamento e uso de chaves privadas.
C2-2.1 PKCS#1: Primitivas e esquemas de cifragem
e assinatura com o RSA
O conteúdo das seções 1 a 5 foram cobertos
no curso C1 (pre-requisito para este curso), de forma que iremos nos ater,
neste módulo, a uma síntese das seções 6 a
9.
símbolo | significado |
c | inteiro entre 0 e n – 1 que representa internamente o criptograma |
C | criptograma codificado como cadeia de octetos |
d | inteiro positivo, expoente da chave privada RSA |
di | inteiro positivo satisfazendo e · di = 1 (mod (ri – 1)), i = 3,..., u, expoente do sistema de equações do resto chinês (CRT) correspondente ao fator primo ri do módulo aritmético n deum par de chaves RSA |
dP | inteiro positivo satisfazendo e · dP = 1 (mod (p – 1)), expoente do sistema CRT correspondente ao fator primo p |
dQ | inteiro positivo satisfazendo e · dQ = 1 (mod (q – 1)), expoente do sistema CRT correspondente ao fator primo q |
e | inteiro positivo, expoente da chave pública RSA |
EM | uma mensagem codificada em cadeia de octetos (Encoded Message) |
emBits | comprimento (presumido) em bits de uma mensagem codificada EM |
emLen | comprimento (presumido) em octetos de uma mensagem codificada EM |
GCD (. , .) | máximo divisor comum de dois inteiros não negativos (e não simultaneamente nulos) |
Hash | função de hash |
hLen | comprimento em octetos da saída da função de hash Hash |
k | comprimento em octetos do módulo aritmético n de um par de chaves RSA |
L | cadeia de octetos para rótulo adicional do esquema de cifragem RSAES-OAEP |
LCM (. ,..., .) | minimo múltiplo comum de uma lista de inteiros não negativos |
m | inteiro entre 1 e n-1 que representa internamente uma mensagem |
M | cadeia de octetos que forma uma mensagem |
mask | cadeia de octetos produzida como saída da função MGF |
maskLen | comprimento (presumido) em octetos de uma máscara mask |
MGF | função geradora de máscaras mask |
mgfSeed | cadeia de octetos de entrada (semente) para a função geradora de máscaras MGF |
mLen | comprimento em octetos de uma mensagem M |
n | módulo aritmético n = r1 · r2 · … · ru , u > 2 de um par de chaves RSA |
(n, e) | chave pública RSA |
p, q | primeiros dois fatores primos de um módulo aritmético n ( p = r1, q = r2 ) |
qInv | inteiro positivo que corresponde ao coeficiente CRT da equação q · qInv = 1 (mod p) |
ri | fator primo do módulo aritmético n de um par de chaves RSA, incluindo r1 = p, r2 = q |
s | inteiro entre 0 e n-1 que representa internamente uma assinatura digital (autenticador) |
S | assinatura digital representada como cadeia de octetos |
sLen | comprimento em octetos do complemento salt de uma assinatura no esquema EMSA-PSS |
ti | inteiros positivos correspondendo aos coeficientes dos fatores ri adicionais no sistema CRT onde r1 · r2 · … · ri-1 · ti = 1 (mod ri) , i = 3, …, u |
u | número de fatores primos (distintos) na decomposição do módulo aritmético n de um par de chaves RSA, u > 2 |
x | inteiro não negativo |
X | cadeia de octetos correspondendo a x |
xLen | comprimento (presumido) em octetos da cadeia de octetos X |
0x | indicador de representação hexadecimal para um octeto
ou cadeia de octetos;
“0x48” denota o octetp com valor hexadecimal 48; “(0x)48 09 0e” denota a cadeia de três consecutivos octetos com valores hexadecimais 48, 09, e 0e, respectivamente. |
phi(n) | LCM ( r1 – 1, r2 – 1, … , ru – 1) |
|| | operador de concatenação |
XOR | função lógica "Ou exclusivo" bit a bit |
CF( . ) | Ceiling function, retorna o menor inteiro maior ou igual ao argumento (número real) |
.
Chave Privada RSA (PKCS#1 v2.1)
.
A chave privada RSA tem dois formatos possíveis
.
a.1. o par (n, d), onde
1. If x > 256xLen , output
“integer too large” and stop.
2. Write the integer x in its unique xLen-digit
representation in base 256:
3. Let the octet Xi have the integer value xxLen–i for 1 < i < xLen. Output the octet string X = X1 X2 … XxLen. |
1. Let X1 X2 … XxLen
be the octets of X from first to last, and let xxLen–i be the
integer value of the octet Xi for 1 < i <
xLen
2. Let x = xxLen–1 256 xLen-1 + xxLen–2 256 xLen-2 + … + x1 256 + x0. 3. Output x. |
1. If m is not between 0 and n – 1, output
“message representative out of range” and stop.
2. Let c = me mod n. 3. Output c. |
b) RSADP primitiva de decriptação RSA
RSADP (K, c)
1. If c is not between 0 and n – 1, output
“ciphertext representative out of range” and stop.
2. The message representative m is computed as follows. a. If the first form (n, d) of K is used, let m = cd mod n.3. Output m. |
1. If m is not between 0 and n – 1, output
“message representative out of range” and stop.
2. The signature representative s is computed as follows. a. If the first form (n, d) of K is used, let s = md mod n.3. Output s. |
RSAVP1 ((n, e), s)
1. If s is not between 0 and n – 1, output “signature
representative out of range” and stop.
2. Let m = se mod n. 3. Output m. |
C2-2.1.5 Esquemas (protocolos) de cifragem: RSAES-OAEP e RSAES-PKCSI v1_5
a) RSAES-OAEP (Rogaway's “Optimal Asymmetric Encryption Padding.”)
RSAES-OAEP-ENCRYPT ((n, e), M, L)
1. Length checking:
b. If mLen > k – 2·hLen – 2, output “message too long” and stop.
b. Generate an octet string PS consisting of k – mLen – 2·hLen – 2 zero octets. The length of PS may be zero. c. Concatenate lHash, PS, a single octet with hexadecimal value 0x01, and the message M to form a data block DB of length k – hLen – 1 octets as DB = lHash || PS || 0x01 || M . d. Generate a random octet string seed of length hLen. e. Let dbMask = MGF(seed, k – hLen – 1) f. Let maskedDB = DB XOR dbMask. g. Let seedMask = MGF(maskedDB, hLen). h. Let maskedSeed = seed XOR seedMask. i. Concatenate a single octet with hexadecimal value 0x00, maskedSeed, and maskedDB to form an encoded message EM of length k octets as EM = 0x00 || maskedSeed || maskedDB.
b. Apply the RSAEP encryption primitive (Section 5.1.1) to the RSA public key (n, e) and the message representative m to produce an integer ciphertext representative c: c = RSAEP ((n, e), m) . c. Convert the ciphertext representative c to a ciphertext C of length k octets (2.1.3, ref [4] Section 4.1); C = I2OSP(c, k) . |
1. Length checking:
b. If the length of the ciphertext C is not k octets, output “decryption error” and stop. c. If k < 2hLen + 2, output “decryption error” and stop.
b. Apply the RSADP decryption primitive (2.1.4, ref [4] Section 5.1.2) to the RSA private key K and the ciphertext representative c to produce an integer message representative m: m = RSADP(K, c) If RSADP outputs “ciphertext representative out of range” (meaning that c > n), output “decryption error” and stop. c. Convert the message representative m to an encoded message EM of length k octets (2.1.3, ref [4] Section 4.2): EM = I2OSP(m, k) .
b. Separate the encoded message EM into a single octet Y, an octet string maskedSeed of length hLen, and an octet string maskedDB of length k - hLen - 1 as EM = Y || maskedSeed || maskedDB. c. Let seedMask = MGF(maskedDB, hLen). d. Let seed = maskedSeed XOR seedMask. e. Let dbMask = MGF(seed, k – hLen – 1). f. Let DB = maskedDB XOR dbMask. g. Separate DB into an octet string lHash’ of length hLen, a (possibly empty) padding string PS consisting of octets with hexadecimal value 0x00, and a message M as DB = lHash’ || PS || 0x01 || M . If there is no octet with hexadecimal value 0x01 to separate PS from M, if lHash does not equal lHash’, or if Y is nonzero, output “decryption error” and stop. (See the note below.) |
Nota: ref [4] pag 21 explica porque as mensagens de erro dos diferentes passos do esquema acima devem ser indistinguiveis.
RSAES-PKCSIv1_5-ENCRYPT ((n, e), M)
1. Length checking: If mLen > k – 11, output
“message too long” and stop.
2. EME-PKCS1-v1_5 encoding:
b. Concatenate PS, the message M, and other padding to form an encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M .
b. Apply the RSAEP encryption primitive (Section 5.1.1) to the RSA public key (n, e) and the message representative m to produce an integer ciphertext representative c: c = RSAEP((n, e), m) . c. Convert the ciphertext representative c to a ciphertext C of length k octets: C = I2OSP(c, k) . |
1. Length checking: If the length of C is not
k octets (or if k < 11), output “decryption error” and stop.
2. RSA decryption:
b. Apply the RSADP decryption primitive (2.1.4 ref. [4] Section 5.1.2) to the RSA private key (n, d) and the ciphertext representative c to produce an integer message representative m: m = RSADP((n, d), c) . If RSADP outputs “ciphertext representative out of range” (meaning that c > n), output “decryption error” and stop. c. Convert the message representative m to an encoded message EM of length k octets: EM = I2OSP(m, k) . If the first octet of EM does not have hexadecimal value 0x00, if the second octet of EM does not have hexadecimal value 0x02, if there is no octet with hexadecimal value 0x00 to separate PS from M, or if the length of PS is less than 8 octets, output “decryption error” and stop. (See the note below.) 4. Output M. |
Nota: ref [4] pag 21 explica porque as mensagens
de erro dos diferentes passos do esquema acima devem ser indistinguiveis.
Um dos motivos para a escolha desse método, baseado
no padrão IEEE 1363-2000, é a possibilidade dos esquemas
de assinatura digital nele modelados se integrarem a protocolos mais complexos
que procuram suprir as premissas do conceito de assinatura digital de forma
escalável em redes abertas, como em PKIs baseadas no padrão
X.509. Este método, porém, apresenta características
de segurança (vistas no curso C.1) que indicam a sua atomização
(single pass). Em situações onde o cálculo
do hash da mensagem precisa ser separado do processo critpográfico
sobre os autenticadores apensáveis, deve-se buscar outro padrão
para o esquema de assinatura, como o atual PKCS#7.
O esquema RSASSA-PSS opera com mensagens autenticáveis de comprimento
irrestrito ou restrito por um número muito grande, dependendo da
função de hash implementada pela codificação
EMSA-PSS. O método de codificação EMSA-PSS é
recomendado como alternativa ao método usado no padrão PKCS#1v1.5,
contra possíveis desenvolvimentos futuros da criptoanálise
de chaves públicas. Para uma justificativa, são citadas referencias
e estudos em ref [4] pag 30.
1. EMSA-PSS encoding: Apply the EMSA-PSS encoding
operation ( ref [4] Section 9.1.1) to the message M to produce an encoded
message EM of length CF( (modBits – 1)/8 ) octets such that the bit length
of the integer OS2IP(EM) (see ref [4] Section 4.2) is at most modBits –
1, where modBits is the length in bits of the RSA modulus n: EM = EMSA-PSS-ENCODE(M,
modBits – 1) .
Note that the octet length of EM will be one less than k if modBits – 1 is divisible by 8 and equal to k otherwise. If the encoding operation outputs “message too long,” output “message too long” and stop. If the encoding operation outputs “encoding error,” output “encoding error” and stop. 2. RSA signature: a. Convert the encoded message EM to an integer message representative m (2.1.3 ref [4] Section 4.2): m = OS2IP(EM) .3. Output the signature S. |
1. Length checking: If the length of the signature
S is not k octets, output “invalid signature” and stop.
2. RSA verification: a. Convert the signature S to an integer signature representative s (2.1.3 ref [4] Section 4.2): s = OS2IP(S) .3. EMSA-PSS verification: Apply the EMSA-PSS verification operation ( ref [4] Section 9.1.2) to the message M and the encoded message EM to determine whether they are consistent: Result = EMSA-PSS-VERIFY(M, EM, modBits – 1) . 4. If Result = “consistent,” output “valid signature.” Otherwise, output “invalid signature.” |
O esquema RSASSA-PKCS1-v1_5 opera com mensagens autenticáveis
de comprimento irrestrito ou restrito por um número muito grande,
dependendo da função de hash implementada pela codificação
EMSA. Enquanto nenhum ataque é conhecido na literatura científica
contra o método de codificação EMSA-PKCS-v1_5, uma
transição gradual para o método EMSA-PSS é
recomendada como precaução, contra os possíveis desenvolvimentos
futuros da criptoanálise de chaves públicas. Para uma justificativa,
são citadas referencias e estudos em ref [4] pag 30.
1. EMSA-PKCS1-v1_5 encoding:
Apply the EMSA-PKCS1-v1_5 encoding operation (see ref. [4] Section 9.2) to the message M to produce an encoded message EM of length k octets: EM = EMSA-PKCS1-V1_5-ENCODE(M, k) . If the encoding operation outputs “message too long,” output “message too long” and stop. If the encoding operation outputs “intended encoded message length too short,” output “RSA modulus too short” and stop. 2. RSA signature: a. Convert the encoded message EM to an integer message representative m (2.1.3 ref. [4] Section 4.2): m = OS2IP (EM) .3. Output the signature S. |
1. Length checking:
If the length of the signature S is not k octets, output “invalid signature” and stop. 2. RSA verification: a. Convert the signature S to an integer signature representative s (2.1.3 ref.[4] Section 4.2):
4. Compare the encoded message EM and the second encoded message EM’. If they are the same, output “valid signature”; otherwise, output “invalid signature.”.. |
c.1 EMSA-PSS
1. If the length of M is greater
than the input limitation for the hash function (261
– 1 octets for SHA-1), output “message too long” and stop.
2. Let mHash = Hash (M), an octet string of length hLen. 3. If emLen < hLen + sLen + 2, output “encoding error” and stop. 4. Generate a random octet string salt of length sLen; if sLen = 0, then salt is the empty string. 5. Let M’ = (0x)00 00 00 00
00 00 00 00 || mHash || salt;
6. Let H = Hash (M’), an octet string of length hLen. 7. Generate an octet string PS consisting
of emLen – sLen – hLen – 2 zero octets.
8. Let DB = PS || 0x01 || salt; DB is an octet string of length emLen – hLen – 1. 9. Let dbMask = MGF (H, emLen – hLen – 1). 10. Let maskedDB = DB XOR dbMask. 11. Set the leftmost 8 emLen – emBits bits of the leftmost octet in maskedDB to zero. 12. Let EM = maskedDB || H || (0x)bc. 13. Output EM. |
1. If the length of M is greater
than the input limitation for the hash function (261
– 1octets for SHA-1), output “inconsistent” and stop.
2. Let mHash = Hash (M), an octet string of length hLen. 3. If emLen < hLen + sLen + 2, output “inconsistent” and stop. 4. If the rightmost octet of EM does not have hexadecimal value 0xbc, output “inconsistent” and stop. 5. Let maskedDB be the leftmost emLen – hLen – 1 octets of EM, and let H be the next hLen octets. 6. If the leftmost 8emLen – emBits bits of the leftmost octet in maskedDB are not all equal to zero, output “inconsistent” and stop. 7. Let dbMask = MGF (H, emLen – hLen – 1). 8. Let DB = maskedDB XOR dbMask. 9. Set the leftmost 8emLen – emBits bits of the leftmost octet in DB to zero. 10. If the emLen – hLen – sLen – 2 leftmost octets of DB are not zero or if the octet at position emLen – hLen – sLen – 1 (the leftmost position is “position 1”) does not have hexadecimal value 0x01, output “inconsistent” and stop. 11. Let salt be the last sLen octets of DB. 12. Let M’ = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; M’ is an octet string of length 8 + hLen + sLen with eight initial zero octets. 13. Let H’ = Hash (M’), an octet string of length hLen. 14. If H = H’, output “consistent.” Otherwise, output “inconsistent.” |
1. Apply the hash function to the
message M to produce a hash value H: H = Hash (M) .
If the hash function outputs “message too long,” output “message too long” and stop. 2. Encode the algorithm ID for the
hash function and the hash value into an ASN.1 value of type DigestInfo
(see Appendix A.2.4) with the Distinguished Encoding Rules (DER), where
the type DigestInfo has the syntax
3. If emLen < tLen + 11, output “intended encoded message length too short” and stop. 4. Generate an octet string PS consisting of emLen – tLen – 3 octets with hexadecimal value 0xff. The length of PS will be at least 8 octets. 5. Concatenate PS, the DER encoding
T, and other padding to form the encoded message EM as
6. Output EM. |
Notes.
1. For the six hash functions mentioned in Appendix
B.1, the DER encoding T of the DigestInfo value is
2. In version 1.5 of this document, T was defined as the BER encoding, rather than the DER encoding, of the DigestInfo value. In particular, it is possible – at least in theory – that the verification operation defined in this document (as well as in version 2.0) rejects a signature that is valid with respect to the specification given in PKCS #1 v1.5. This occurs if other rules than DER are applied to DigestInfo (e.g., an indefinite length encoding of the underlying SEQUENCE type). While this is unlikely to be a concern in practice, a cautious implementer may choose to employ a verification operation based on a BER decoding operation as specified in PKCS #1 v1.5. In this manner, compatibility with any valid implementation based on PKCS #1 v1.5 is obtained. Such a verification operation should indicate whether the underlying BER encoding is a DER encoding and hence whether the signature is valid with respect to the specification given in this document. |
O apêndice A da ref [4] descreve, entre as páginas 39 a 46, os tipos ASN-1 de todas as estruturas de dados utilizadas nos algoritmos aqui descritosC2-2.2 O padrão PKCS#8 para representação de chaves privadas RSA
Esse padrão, cuja versão aqui resumida teve sua última revisão em novembro de 1993 [5], descreve a sintaxe para representação de chaves privadas do algoritmo RSA e informações pertinentes. Essas informações incluem aquelas relativas ao processo de cifragem para armazenamento (processo descrito no padrão PKCS#5) e um conjunto de atributos representando as premissas de confiança para o uso da chave, incluindo nome do titular e nome distinguido da entidade certificadora do par público da chave privada.C2-2.2.1 Sintaxe de informação sobre chaves privadasUma lista não exaustiva desses atributos pode ser encontrada no documento que descreve o padrão PKCS#9
A definição do tipo ASN.1 para informação sobre chaves privadas deve ser
type PrivateKeyInfo PrivateKeyInfo ::= SEQUENCE
{
version Version,
privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
privateKey PrivateKey,
attributes [0] IMPLICIT Attributes OPTIONAL
}
Version ::= INTEGER
PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
PrivateKey ::= OCTET STRING
Attributes ::= SET OF AttributeA semântica dos campos desse tipo corresponde a:
- version é o número de versão da sintaxe, para compatibilidade com versões futuras deste padrão. Deve ser 0 para esta versão deste padrão.
- privateKeyAlgorithm identifica o algoritmo para o qual foi gerada a chave privada, conforme descritos no padrão PKCS #1. Um exemplo de valor para este campo seria rsaEncryption.
- privateKey é a cadeia de octetos cujo conteúdo constitui os valores da chave privada. A interpretação desse conteúdo é definida no registro do algoritmo. Para uma dada chave privada RSA, corresponde ao valor codificado segundo as regras BER para o tipo RSAPrivateKey, descritos no apêndice A do padrão PKCS#1 (ref [4]).
- attributes Conjunto de valores que informam sobre o uso pretendido para tal chave privada, encriptados junto com a respectiva chave privada.
C2-2.2.2 Sintaxe de informação
sobre chaves privadas encriptadas
EncryptedPrivateKeyInfo ::= SEQUENCE
{ encryptionAlgorithm EncryptionAlgorithmIdentifier, encryptedData EncryptedData } EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier EncryptedData ::= OCTET STRING |
A semântica dos campos desse tipo corresponde a:O processo de encriptação envolve dois passos:
- encryptionAlgorithm identifica o algoritmo sob o qual a informação sobre uma chave privada foi encriptada. Dois exemplos, descritos no documento que estabelece o padrão PKCS#5 são pbeWithMD2AndDES-CBC e pbeWithMD5AndDES-CBC.p
- encryptedData é a informação sobre uma chave privada devidamente encriptada
- 1. A informação sobre uma chave privada é codificada segundo as regras BER, resultando numa cadeia de octetos.
- 2. A cadeia de octetos resultante do passo 1 é encriptada com uma chave secreta (normalmente derivada de uma "senha de acesso")
Material de referência
Texto de Referência
Material de consulta
Os textos abaixo aprofundam o material abordado no curso.