diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2013-10-18 18:08:49 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2013-10-18 18:08:49 -0500 |
commit | bde6fb52129909cf319157dba95d65fb557d5013 (patch) | |
tree | bf8b7f02ec9560fd5446239cc0bd27ac995e3a3f /cryptography | |
parent | 87cd0db396e157b3fb160b8b6fd770e2c661ace2 (diff) | |
download | cryptography-bde6fb52129909cf319157dba95d65fb557d5013.tar.gz cryptography-bde6fb52129909cf319157dba95d65fb557d5013.tar.bz2 cryptography-bde6fb52129909cf319157dba95d65fb557d5013.zip |
Hash Saga Part 3 - API changes + SHA1 support + tests
Diffstat (limited to 'cryptography')
-rw-r--r-- | cryptography/bindings/openssl/api.py | 30 | ||||
-rw-r--r-- | cryptography/primitives/hashes.py | 48 |
2 files changed, 78 insertions, 0 deletions
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 79ec5eea..548a9e66 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -139,5 +139,35 @@ class API(object): assert res != 0 return self.ffi.buffer(buf)[:outlen[0]] + def supports_hash(self, hashname): + return (self.ffi.NULL != + self.lib.EVP_get_digestbyname(hashname.encode("ascii"))) + + def create_hash_context(self, hashobject): + ctx = self.lib.EVP_MD_CTX_create() + ctx = self.ffi.gc(ctx, self.lib.EVP_MD_CTX_destroy) + evp_md = self.lib.EVP_get_digestbyname(hashobject.name.encode("ascii")) + assert evp_md != self.ffi.NULL + res = self.lib.EVP_DigestInit_ex(ctx, evp_md, self.ffi.NULL) + assert res != 0 + return ctx + + def update_hash_context(self, ctx, data): + res = self.lib.EVP_DigestUpdate(ctx, data, len(data)) + assert res != 0 + + def finalize_hash_context(self, ctx, digest_size): + buf = self.ffi.new("unsigned char[]", digest_size) + res = self.lib.EVP_DigestFinal_ex(ctx, buf, self.ffi.NULL) + assert res != 0 + return self.ffi.buffer(buf)[:digest_size] + + def copy_hash_context(self, ctx): + copied_ctx = self.lib.EVP_MD_CTX_create() + copied_ctx = self.ffi.gc(copied_ctx, self.lib.EVP_MD_CTX_destroy) + res = self.lib.EVP_MD_CTX_copy_ex(copied_ctx, ctx) + assert res != 0 + return copied_ctx + api = API() diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py new file mode 100644 index 00000000..d74287f9 --- /dev/null +++ b/cryptography/primitives/hashes.py @@ -0,0 +1,48 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import, division, print_function + +import binascii + +from cryptography.bindings import _default_api + + +class BaseHash(object): + def __init__(self, api=None, ctx=None): + if api is None: + api = _default_api + self._api = api + self._ctx = self._api.create_hash_context(self) if ctx is None else ctx + + def update(self, string): + self._api.update_hash_context(self._ctx, string) + + def copy(self): + return self.__class__(ctx=self._copy_ctx()) + + def digest(self): + return self._api.finalize_hash_context(self._copy_ctx(), + self.digest_size) + + def hexdigest(self): + return binascii.hexlify(self.digest()).decode("ascii") + + def _copy_ctx(self): + return self._api.copy_hash_context(self._ctx) + + +class SHA1(BaseHash): + name = "sha1" + digest_size = 20 + block_size = 64 |