Domanda

Ho una stringa, una firma e una chiave pubblica e voglio verificare la firma sulla stringa.La chiave è simile a questa:

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

Sto leggendo la documentazione di Pycrypto da un po', ma non riesco a capire come creare un RSAobj con questo tipo di chiave.Se conosci PHP, sto provando a fare quanto segue:

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

Inoltre, se sono confuso riguardo alla terminologia, fatemelo sapere.

È stato utile?

Soluzione

I dati tra i marcatori è la codifica base64 del ASN.1 DER-codifica di un PKCS # 8 PublicKeyInfo contenente un PKCS # 1 RSAPublicKey.

Questo è un sacco di standard, e si saranno meglio tutelati con l'utilizzo di un cripto-libreria per decodificarlo (come M2Crypto come suggerito da joeforker ). Trattare le seguenti come un certo divertimento informazioni sul formato:

Se si desidera, è possibile decodificare in questo modo:

Base64 decodificare la stringa:

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

Questo è il DER-codifica:

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

Per una chiave RSA 1024 bit, è possibile trattare "30819f300d06092a864886f70d010101050003818d00308189028181" come intestazione costante, seguita da un 00-byte, seguita da 128 byte del modulo RSA. Dopo che il 95% del tempo si otterrà 0203010001, che significa un esponente pubblico RSA di 0x10001 = 65537.

È possibile utilizzare questi due valori come n e e in una tupla per costruire un RSAobj.

Altri suggerimenti

M2Crypto . Ecco come verificare per RSA e qualsiasi altro algoritmo supportato da 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

Una chiave pubblica contiene sia un modulo (numero molto lungo, può essere 1024bit, 2058bit, 4096bit) ed esponente chiave pubblica (numero molto più piccolo, di solito equivale a un più di un due per un po 'di potenza). Hai bisogno di trovare il modo di contempla quella chiave pubblica nelle due componenti prima di poter fare qualsiasi cosa con esso.

Non so molto di pycrypto ma per verificare una firma, prendo l'hash della stringa. Ora dobbiamo decifrare la firma. Leggi su elevamento a potenza modulare ; La formula per decifrare una firma è message^public exponent % modulus. L'ultimo passo è quello di verificare se l'hash hai fatto e la firma decifrati che hai sono gli stessi.

Penso ezPyCrypto potrebbe rendere questo un po 'più facile. I metodi di alto livello il tasto classe comprende questi due metodi che spero di risolvere il problema:

  • verifyString - verificare una stringa con un firma
  • importkey - import chiave pubblica (e la chiave privata possibilmente troppo)

Rasmus sottolinea nei commenti che verifyString è hard-coded per usare MD5, nel qual caso può ezPyCryto 't aiutare Andrew a meno che guada nel suo codice. Mi rimetto a :. considerare M2Crypto

Maggiori informazioni sulla decodifica DER.

La codifica DER segue sempre un formato tripletta TLV:(Tag, Lunghezza, Valore)

  • Il tag specifica il tipo (ad es.struttura dati) del valore
  • La lunghezza specifica il numero di byte occupati da questo campo valore
  • Il valore è il valore effettivo che potrebbe essere un'altra tripletta

Il tag indica fondamentalmente come interpretare i dati in byte nel campo Valore.ANS.1 ha un sistema di tipi, ad es.0x02 significa intero, 0x30 significa sequenza (una raccolta ordinata di una o più istanze di altro tipo)

La presentazione della lunghezza ha una logica speciale:

  • Se la lunghezza <127, il campo L utilizza solo un byte e codificato come valore del numero di lunghezza direttamente
  • Se la lunghezza> 127, quindi nel primo byte del campo L, il primo bit deve essere 1 e il resto 7 bit rappresenta il numero di byte seguenti utilizzati per specificare la lunghezza del campo Valore.Valore, i byte effettivamente del valore stesso.

Ad esempio, supponiamo che io voglia codificare un numero lungo 256 byte, allora sarebbe così

02  82  01  00  1F  2F  3F  4F  …   DE  AD  BE  EF
  • Tag, 0x02 significa che è un numero
  • Lunghezza, 0x82, presentazione bit di esso è 1000 0010, il che significa che i seguenti due byte specifica la lunghezza del valore, che il suo 0x0100 significa che il campo del valore è lungo 256 byte
  • Valore, da 1F a EF, i 256 byte effettivi.

Ora guardando il tuo esempio

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

Interpreta esattamente ciò che Rasmus Faber ha detto nella sua risposta

Forse questa non è la risposta che stai cercando, ma se tutto quello che serve è quello di girare la chiave in bit, sembra come se fosse codificato Base64. Guardate il modulo codecs (credo) nella libreria standard di Python.

Utilizzando M2Crypto, le risposte di cui sopra non funziona. Ecco un esempio testato.

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 che su di esso

cerco il codice data dal joeforker, ma non funziona. Qui è il mio codice di esempio e funziona bene.

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"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top