Pergunta

Eu tenho uma seqüência de caracteres, uma assinatura e uma chave pública, e quero verificar a assinatura na cadeia.A chave parece com isso:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----

Estive lendo o pycrypto docs por um tempo, mas eu não consigo descobrir como fazer um RSAobj com este tipo de chave.Se você conhece PHP, estou tentando fazer o seguinte:

openssl_verify($data, $signature, $public_key, OPENSSL_ALGO_SHA1);

Também, se eu estou confuso sobre qualquer terminologia, por favor, deixe-me saber.

Foi útil?

Solução

Os dados entre os marcadores são a codificação Base64 da codificação do ASN.1 Der de um PKCS#8 PublicKeyInfo contendo um PKCS#1 RsapublicKey.

São muitos padrões, e você será melhor servido usando uma biblioteca criptográfica para decodificá-lo (como m2crypto como sugerido por Joeforker). Trate o seguinte como algumas informações divertidas sobre o formato:

Se quiser, você pode decodificar assim:

Base64-decodificar a string:

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

Esta é a codificação de derrota de:

   0 30  159: SEQUENCE {
   3 30   13:   SEQUENCE {
   5 06    9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
  16 05    0:     NULL
            :     }
  18 03  141:   BIT STRING 0 unused bits, encapsulates {
  22 30  137:       SEQUENCE {
  25 02  129:         INTEGER
            :           00 DF 1B 82 2E 14 ED A1 FC B7 43 36 6A 27 C0 63
            :           70 E6 CA D6 9D 41 16 CE 80 6B 3D 11 75 34 CF 0B
            :           AA 93 8C 0F 8E 45 00 FB 59 D4 D9 8F B4 71 A8 D0
            :           10 12 D5 4B 32 24 41 97 C7 43 4F 27 C1 B0 D7 3F
            :           A1 B8 BA E5 5E 70 15 5F 90 78 79 CE 9C 25 F2 8A
            :           9A 92 FF 97 DE 16 84 FD AF F0 5D CE 19 6A E7 68
            :           45 F5 98 B3 28 C5 ED 76 E0 F7 1F 6A 6B 74 48 F0
            :           86 91 E6 A5 56 F5 F0 D7 73 CB 20 D1 3F 62 9B 63
            :           91
 157 02    3:         INTEGER 65537
            :         }
            :       }
            :   }

Para uma chave RSA de 1024 bits, você pode tratar "30819f300d06092a864886f70d010101050003818d00308189028181" Como cabeçalho constante, seguido por um 00-byte, seguido pelos 128 bytes do módulo RSA. Depois disso 95% do tempo, você receberá 0203010001, que significa um expoente público da RSA de 0x10001 = 65537.

Você pode usar esses dois valores como n e e em uma tupla para construir um rsaobj.

Outras dicas

Usar M2CRYPTO. Veja como verificar a RSA e qualquer outro algoritmo suportado pelo OpenSSL:

pem = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----""" # your example key

from M2Crypto import BIO, RSA, EVP
bio = BIO.MemoryBuffer(pem)
rsa = RSA.load_pub_key_bio(bio)
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)

# if you need a different digest than the default 'sha1':
pubkey.reset_context(md='sha1')
pubkey.verify_init()
pubkey.verify_update('test  message')
assert pubkey.verify_final(signature) == 1

Uma chave pública contém um módulo (número muito longo, pode ser 1024bit, 2058bit, 4096bit) e um expoente -chave público (número muito menor, geralmente é igual a um a mais que dois a algum poder). Você precisa descobrir como dividir essa chave pública nos dois componentes antes de poder fazer qualquer coisa com ela.

Não sei muito sobre Pycrypto, mas para verificar uma assinatura, pegue o hash da string. Agora devemos descriptografar a assinatura. Leia sobre exponenciação modular; A fórmula para descriptografar uma assinatura é message^public exponent % modulus. O último passo é verificar se o hash que você fez e a assinatura descriptografada que você recebe são iguais.

Eu penso ezpycrypto Pode tornar isso um pouco mais fácil. Os métodos de alto nível do chave A classe inclui estes dois métodos que espero resolver seu problema:

  • Verifystring - Verifique uma string contra uma assinatura
  • importação - importar chave pública (e possivelmente chave privada também)

Rasmus aponta nos comentários que verifyString é codificado para usar o MD5; nesse caso, o ezpycryto não pode ajudar Andrew a menos que ele entre em seu código. Eu adiar para Resposta do Joeforker: Considere M2CRYPTO.

Mais nos DER a decodificação.

Codificação DER segue sempre um TLV trio formato:(Marca, Tamanho, Valor)

  • Tag especifica o tipo (i.e.estrutura de dados) do valor
  • Comprimento especifica o número de bytes que este valor de campo ocupa
  • Valor é o valor real que poderia ser um outro trio

Tag basicamente diz como interpretar os bytes de dados no campo Valor.A ANS.1 tem um tipo de sistema, e.g.0x02 significa inteiro, 0x30 significa sequência (uma coleção ordenada de uma ou mais instâncias do tipo)

Comprimento da apresentação tem uma lógica especial:

  • Se o comprimento < 127, o L campo utiliza apenas um byte e codificado como o número de comprimento valor diretamente
  • Se o comprimento de > 127, em seguida, o primeiro byte de L campo, o primeiro bit deve ser 1, e o resto 7 bits que representa o número de seguir bytes usados para especifica o comprimento do campo de Valor.Valor, o na verdade bytes do valor em si.

Por exemplo, digamos que eu queira codificar um número de 256 bytes, em seguida, ele iria ser assim

02  82  01  00  1F  2F  3F  4F  …   DE  AD  BE  EF
  • Tag, 0x02 significa que é um número
  • Comprimento, 0x82, pouco a apresentação dele é 1000 0010, ou seja, o a seguir dois bytes especifica, na verdade, o comprimento do valor, que sua 0x0100 que significa o valor do campo é 256 bytes
  • Valor, a partir 1F para EF, o real 256 bytes.

Agora olhando para o seu exemplo

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

Ele interpreta como apenas o que Rasmus Faber colocar na sua resposta

Talvez essa não seja a resposta que você está procurando, mas se tudo o que você precisa é transformar a chave em bits, parece que a base64 é codificada. Olhe para a codecs Módulo (eu acho) na biblioteca Python padrão.

Usando o M2Crypto, as respostas acima não funcionam. Aqui está um exemplo testado.

import base64
import hashlib
import M2Crypto as m2

# detach the signature from the message if it's required in it (useful for url encoded data)
message_without_sign = message.split("&SIGN=")[0]
# decode base64 the signature
binary_signature = base64.b64decode(signature)
# create a pubkey object with the public key stored in a separate file
pubkey = m2.RSA.load_pub_key(os.path.join(os.path.dirname(__file__), 'pubkey.pem'))
# verify the key
assert pubkey.check_key(), 'Key Verification Failed'
# digest the message
sha1_hash = hashlib.sha1(message_without_sign).digest()
# and verify the signature
assert pubkey.verify(data=sha1_hash, signature=binary_signature), 'Certificate Verification Failed'

E isso é sobre isso

Eu tento o código fornecido pela Joeforker, mas não funciona. Aqui está o meu código de exemplo e funciona bem.

from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA 
from Crypto.Hash import SHA

pem = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----""" # your example key

key = RSA.importKey(pem)
h = SHA.new(self.populateSignStr(params))
verifier = PKCS1_v1_5.new(key)
if verifier.verify(h, signature):
  print "verified"
else:
  print "not verified"
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top