aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorDonald Stufft <donald@stufft.io>2013-10-18 19:21:27 -0700
committerDonald Stufft <donald@stufft.io>2013-10-18 19:21:27 -0700
commita3011beae965fde326d4977d850b2aaa9c7b216e (patch)
tree59095660e7061e238847c3e076d2d115ac716b2f /cryptography
parent90d2a77af90e9ed68125668e59b4d1f250938aec (diff)
parent3b7730cf90c6a5114391d2d5a2ccc1cdb448da9e (diff)
downloadcryptography-a3011beae965fde326d4977d850b2aaa9c7b216e.tar.gz
cryptography-a3011beae965fde326d4977d850b2aaa9c7b216e.tar.bz2
cryptography-a3011beae965fde326d4977d850b2aaa9c7b216e.zip
Merge pull request #123 from reaperhulk/hash-saga-sha1
Hash Saga Part 3 (API changes + SHA1)
Diffstat (limited to 'cryptography')
-rw-r--r--cryptography/bindings/openssl/api.py30
-rw-r--r--cryptography/primitives/hashes.py48
2 files changed, 78 insertions, 0 deletions
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py
index 2ad6c054..5eefcdb9 100644
--- a/cryptography/bindings/openssl/api.py
+++ b/cryptography/bindings/openssl/api.py
@@ -141,5 +141,35 @@ class API(object):
assert res != 0
return self.ffi.buffer(buf)[:outlen[0]]
+ def supports_hash(self, hash_cls):
+ return (self.ffi.NULL !=
+ self.lib.EVP_get_digestbyname(hash_cls.name.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