Jam*_*mes 8 python google-app-engine openssl cryptography google-cloud-storage
我正在尝试使用OpenSSL和Python创建一个签名文件,我没有收到任何错误消息,但是进程无法正常工作,我找不到原因.
下面是我逐步签署文件并检查签名:
首先,我在命令行中创建crt
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"
此时,我有两个文件:cert.key和cert.crt
使用如下所示的Python脚本对文件进行签名:
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)
Run Code Online (Sandbox Code Playgroud)一切正常,保存文件后,我还有其他三个文件:( my_file.csv原始文件),my_file.txt.sha256和my_file.txt.sha256.base64.此时,我可以解码base64文件并与签名的文件进行比较,两者都很好.
问题是当我尝试使用以下命令验证签名时:
`openssl dgst -sha256 -verify <(openssl x509 -in "cert.crt" -pubkey -noout) -signature my_file.txt.sha256 my_file.csv`
Run Code Online (Sandbox Code Playgroud)
在这一点上,我总是收到"验证失败",不明白为什么.
也许问题是我缺乏Python的知识,因为当我使用以下命令签署文件时(在步骤1之后和使用2中描述的Python脚本之前),相同的验证工作正常.
openssl dgst -sha256 -sign "cert.key" -out my_file.txt.sha256 my_file.csv
Run Code Online (Sandbox Code Playgroud)
我做错了吗?
UPDATE
基于这些评论,我在python 2.7的本地virtualnv中尝试了这个脚本并且它有效,所以问题必须在读/写操作中.
我正在用完整的脚本更新这个队列,包括读/写操作,因为我可以在本地运行它,但我仍然没有在GAE环境中得到任何错误,并且无法理解原因.
第一步是使用下面的脚本在Google Storage(Bucket)中创建和存储CSV
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
Run Code Online (Sandbox Code Playgroud)
它工作正常,并将CSV存储在Google存储空间内的正确路径中.在该部分之后,下一个读/写操作是文件的签名.
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
Run Code Online (Sandbox Code Playgroud)
的inner_upload_file,只是保存在同一个桶的新文件:
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
Run Code Online (Sandbox Code Playgroud)
这是app.yaml供参考.由命令行生成的cert.key和cert.crt存储在app文件夹内的静态文件夹中(与我的app.yaml相同的目录).
更新2
在评论之后,我尝试在本地运行签名过程,然后比较文件.以下是逐步和结果.
首先,我将签名过程改为运行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()
Run Code Online (Sandbox Code Playgroud)
我运行了自动进程,将已签名的文件保存在GCS的存储桶中(以及原始的CSV文件).之后我通过谷歌网页面板为GCS下载这两个文件.
我python sign.py gcs_file_original.csv使用我刚下载的CSV文件在带有python 2.7.10的virtualenv中运行命令.
在它之后,我比较了两个签名文件,cmp -b gcs_signed.txt.sha256 locally_signed.txt.sha256结果是:
gcs_signed.txt.sha256 local_signed.txt.sha256不同:字节1,第1行是24 ^ T 164 t
使用VisualBinaryDiff,结果看起来像两个完全不同的文件.
现在,我知道这个问题,但不知道如何修复它.这个问题非常棘手.
我终于找到了问题所在。我非常专注于寻找 openssl 签名过程中的问题,而没有注意到旧的 Ctrl+C/Ctrl+V 问题。
出于测试目的,我复制了本教程中的“从 GCS 读取”示例。
当我将测试转移到现实世界的应用程序时,我没有再次阅读该页面,也没有注意到gcs_file.seek(-1024, os.SEEK_END).
正如我在最初的问题中所说,我不是Python专家,但这一行只是读取了GCS文件的一部分,因此签名确实与原始签名不同。
只要剪掉我的阅读方法的那一行,现在一切都正常了。
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |