2011-05-04 17 views

回答

3

從頭文件(openssl/evp.h和_hashopenssl.c)映射C結構很簡單,但並不總是可以跨不同版本移植。這是我的環境:

from ctypes import * 

PyObject_HEAD = [ 
    ('ob_refcnt', c_size_t), 
    ('ob_type', c_void_p), 
] 

class EVP_MD(Structure): 
    _fields_ = [ 
     ('type', c_int), 
     ('pkey_type', c_int), 
     ('md_size', c_int), 
     ('flags', c_ulong), 
     ('init', c_void_p), 
     ('update', c_void_p), 
     ('final', c_void_p), 
     ('copy', c_void_p), 
     ('cleanup', c_void_p), 
     ('sign', c_void_p), 
     ('verify', c_void_p), 
     ('required_pkey_type', c_int*5), 
     ('block_size', c_int), 
     ('ctx_size', c_int), 
    ] 

class EVP_MD_CTX(Structure): 
    _fields_ = [ 
     ('digest', POINTER(EVP_MD)), 
     ('engine', c_void_p), 
     ('flags', c_ulong), 
     ('md_data', POINTER(c_char)), 
    ] 

class EVPobject(Structure): 
    _fields_ = PyObject_HEAD + [ 
     ('name', py_object), 
     ('ctx', EVP_MD_CTX), 
    ] 

下面是關於如何用它來save and restore state of hash object一個例子:我需要

import hashlib 

hash = hashlib.md5('test') 
print hash.hexdigest() 

c_evp_obj = cast(c_void_p(id(hash)), POINTER(EVPobject)).contents 
ctx = c_evp_obj.ctx 
digest = ctx.digest.contents 
state = ctx.md_data[:digest.ctx_size] 

hash2 = hashlib.md5() 
c_evp_obj = cast(c_void_p(id(hash2)), POINTER(EVPobject)).contents 
ctx = c_evp_obj.ctx 
digest = ctx.digest.contents 
memmove(ctx.md_data, state, digest.ctx_size) 
print hash2.hexdigest() 
+0

究竟是什麼。非常感謝:) – est 2011-05-04 10:54:22

+1

@est,要小心:如果您仍然使用這個解決方案,您將不得不跟蹤openssl代碼:如果EVP_MD/EVP_MD_CTX在openssl代碼中發生變化,您的python代碼將會中斷。例如,上面的代碼在openssl-0.9.7之前不能用於任何openssl版本。 – abbot 2011-05-04 12:31:20

+0

感謝您發佈此信息。對於@ abbot來說,這段代碼需要Python 3.5+和2.7.13+('('ctx',EVP_MD_CTX)''變爲'('ctx',POINTER(EVP_MD_CTX))''的更新。我最終打包了一個基於這個和其他食譜的圖書館:https://github.com/kislyuk/rehash – weaver 2017-07-13 20:42:08