Problemas para verificar un archivo firmado con python
google-app-engine openssl (1)
Finalmente encontré el problema. Estaba tan concentrado en encontrar un problema en el proceso de firma de openssl y no le presté atención al viejo problema de Ctrl + C / Ctrl + V.
Para fines de prueba, copié el ejemplo ''Leer de GCS'' de este tutorial .
Cuando cambié la prueba a la aplicación real, no volví a leer la página y no gcs_file.seek(-1024, os.SEEK_END)
.
Como dije en la pregunta original, no soy especialista en Python, pero esta línea solo leía parte del archivo GCS, por lo que la firma era realmente diferente de la original.
Solo corte esa línea de mis métodos de lectura y ahora todo funciona bien.
Intento crear un archivo firmado usando OpenSSL y Python, y no recibo ningún mensaje de error, pero el proceso no funciona correctamente y no puedo encontrar el motivo.
A continuación se muestra mi paso a paso para firmar el archivo y verificar la firma:
Primero creo el crt en línea de comando
openssl req -nodes -x509 -sha256 -newkey rsa:4096 -keyout "cert.key" -out "cert.crt" -subj "/C=BR/ST=SP/L=SP/O=Company/OU=IT Dept/CN=cert"
En este punto, tengo dos archivos: cert.key
y cert.crt
Firme el archivo use un script de Python como a continuación:
import os.path from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from base64 import b64encode, b64decode def __init__(self): folder = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(folder, ''../static/cert.key'') self.key = open(file_path, "r").read() def sign_data(self, my_file): rsakey = RSA.importKey(self.key) # I opened the cert.key in __init__ signer = PKCS1_v1_5.new(rsakey) digest = SHA256.new() digest.update(my_file) sign = signer.sign(digest) return sign, b64encode(sign)
Todo funciona bien y después de guardar los archivos, tengo otros tres archivos: my_file.csv
(el original), my_file.txt.sha256
y my_file.txt.sha256.base64
. En este punto, puedo decodificar el archivo base64 y compararlo con el firmado, y ambos están bien.
El problema es cuando intento verificar la firma con el siguiente comando:
`openssl dgst -sha256 -verify <(openssl x509 -in "cert.crt" -pubkey -noout) -signature my_file.txt.sha256 my_file.csv`
En este punto, siempre recibo el "Error de verificación" y no entiendo por qué.
Tal vez el problema es mi falta de conocimiento de Python, porque cuando firmo el archivo con el siguiente comando (después del paso 1 y antes de usar el script de Python descrito en 2), la misma verificación funciona bien.
openssl dgst -sha256 -sign "cert.key" -out my_file.txt.sha256 my_file.csv
¿Estoy haciendo algo mal?
ACTUALIZAR
En base a los comentarios, probé el script en un virtualv virtual con python 2.7 y funcionó, por lo que el problema debe estar en las operaciones de lectura / escritura.
Estoy actualizando esta consulta con el script completo, incluidas las operaciones de lectura / escritura porque puedo ejecutarlo localmente, pero todavía no aparece ningún error en el entorno de GAE y no puedo entender por qué.
El primer paso es la creación y el almacenamiento de CSV en Google Storage (Bucket) con el siguiente script
import logging
import string
import cloudstorage as gcs
from google.appengine.api import app_identity
def create_csv_file(self, filename, cursor=None):
filename = ''/'' + self.bucket_name + filename
try:
write_retry_params = gcs.RetryParams(backoff_factor=1.1)
# the cursor stores a MySQL result set
if cursor is not None:
gcs_file = gcs.open(filename,
''w'',
content_type=''text/csv'',
retry_params=write_retry_params)
for row in cursor:
gcs_file.write('',''.join(map(str, row)) + ''/n'')
gcs_file.close()
except Exception as ex:
logging.critical("Problem to write in th GC Storage with the exception:{}".format(ex))
raise ex
Funciona bien y almacena un archivo CSV en la ruta correcta dentro del almacenamiento de Google. Después de esa parte, la siguiente operación de lectura / escritura es la firma del archivo.
def cert_file(self, original_filename):
filename = ''/'' + self.bucket_name + original_filename
cert = Cert() # This class just has one method, that is that described in my original question and is used to sign the file.
with gcs.open(filename) as cloudstorage_file:
cloudstorage_file.seek(-1024, os.SEEK_END)
signed_file, encoded_signed_file = cert.sign_data(cloudstorage_file.read()) #the method to sign the file
signature_content = encoded_signed_file
signed_file_name = string.replace(original_filename, ''.csv'', ''.txt.sha256'')
encoded_signed_file_name = string.replace(signed_file_name, ''.txt.sha256'', ''.txt.sha256.base64'')
self.inner_upload_file(signed_file, signed_file_name)
self.inner_upload_file(encoded_signed_file, encoded_signed_file_name)
return signed_file_name, encoded_signed_file_name, signature_content
inner_upload_file
, solo guarde los nuevos archivos en el mismo contenedor:
def inner_upload_file(self, file_data, filename):
filename = ''/'' + self.bucket_name + filename
try:
write_retry_params = gcs.RetryParams(backoff_factor=1.1)
gcs_file = gcs.open(filename,
''w'',
content_type=''application/octet-stream'',
retry_params=write_retry_params)
gcs_file.write(file_data)
gcs_file.close()
except Exception as ex:
logging.critical("Problem to write in th GC Storage with the exception:{}".format(ex))
raise ex
Aquí está la aplicación.yaml para referencia. El cert.key y el cert.crt generados por la línea de comando se almacenan en una carpeta estática dentro de la carpeta de la aplicación (el mismo directorio donde está mi app.yaml).
ACTUALIZACIÓN 2
Después de los comentarios, intenté ejecutar el proceso de firma localmente y luego comparar los archivos. A continuación se muestra el paso por setp y los resultados.
Primero, python sign.py file_name
el proceso de firma para ejecutar como python sign.py file_name
.
#!/usr/bin/python
import sys
import os
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64encode, b64decode
file_path = ''static/cert.key''
key = open(file_path, "rb").read()
rsakey = RSA.importKey(key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
file_object = open(sys.argv[1], "r")
digest.update(file_object.read())
sign = signer.sign(digest)
signed_path = "signed"
f = open(signed_path + ''.txt.sha256'', ''w'')
f.write(sign)
f.close()
f2 = open(signed_path + ''.txt.sha256.base64'', ''w'')
f2.write(b64encode(sign))
f2.close()
Ejecuté el proceso automático que guardaba el archivo firmado en el cubo de GCS (junto con el archivo CSV original). Después de esto, descargo ambos archivos a través del panel web de Google para GCS.
python sign.py gcs_file_original.csv
el comando python sign.py gcs_file_original.csv
en un virtualenv con python 2.7.10 utilizando el archivo CSV que acabo de descargar.
Después de eso, cmp -b gcs_signed.txt.sha256 locally_signed.txt.sha256
los dos archivos firmados con cmp -b gcs_signed.txt.sha256 locally_signed.txt.sha256
da cmp -b gcs_signed.txt.sha256 locally_signed.txt.sha256
resultado:
gcs_signed.txt.sha256 locally_signed.txt.sha256 different: byte 1, line 1 is 24 ^ T 164 t
Usando VisualBinaryDiff , el resultado parece dos archivos totalmente diferentes.
Ahora, sé el problema, pero no tengo idea de cómo solucionarlo. Este problema está siendo muy divertido.