sign and verify, for the most part
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index 9827098..0d96d79 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -1230,3 +1230,63 @@
     x509req = X509Req.__new__(X509Req)
     x509req._req = req
     return x509req
+
+
+
+def sign(pkey, data, digest):
+    """
+    Sign data with a digest
+
+    :param pkey: Pkey to sign with
+    :param data: data to be signed
+    :param digest: message digest to use
+    :return: signature
+    """
+    digest_obj = _api.EVP_get_digestbyname(digest)
+    if digest_obj == _api.NULL:
+        raise ValueError("No such digest method")
+
+    md_ctx = _api.new("EVP_MD_CTX*")
+
+    _api.EVP_SignInit(md_ctx, digest_obj)
+    _api.EVP_SignUpdate(md_ctx, data, len(data))
+
+    signature_buffer = _api.new("unsigned char[]", 512)
+    signature_length = _api.new("unsigned int*")
+    signature_length[0] = len(signature_buffer)
+    final_result = _api.EVP_SignFinal(
+        md_ctx, signature_buffer, signature_length, pkey._pkey)
+
+    if final_result != 1:
+        1/0
+
+    return _api.buffer(signature_buffer, signature_length[0])[:]
+
+
+
+def verify(cert, signature, data, digest):
+    """
+    Verify a signature
+
+    :param cert: signing certificate (X509 object)
+    :param signature: signature returned by sign function
+    :param data: data to be verified
+    :param digest: message digest to use
+    :return: None if the signature is correct, raise exception otherwise
+    """
+    digest_obj = _api.EVP_get_digestbyname(digest)
+    if digest_obj == _api.NULL:
+        raise ValueError("No such digest method")
+
+    pkey = _api.X509_get_pubkey(cert._x509)
+    if pkey == _api.NULL:
+        1/0
+
+    md_ctx = _api.new("EVP_MD_CTX*")
+
+    _api.EVP_VerifyInit(md_ctx, digest_obj)
+    _api.EVP_VerifyUpdate(md_ctx, data, len(data))
+    verify_result = _api.EVP_VerifyFinal(md_ctx, signature, len(signature), pkey)
+
+    if verify_result != 1:
+        _raise_current_error()