X509 serial numbers
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index 51be681..1329f93 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -97,6 +97,15 @@
         return _api.X509_get_version(self._x509)
 
 
+    def subject_name_hash(self):
+        """
+        Return the hash of the X509 subject.
+
+        :return: The hash of the subject.
+        """
+        return _api.X509_subject_name_hash(self._x509)
+
+
     def set_serial_number(self, serial):
         """
         Set serial number of the certificate
@@ -106,9 +115,37 @@
 
         :return: None
         """
-        if not isinstance(serial, int):
+        if not isinstance(serial, (int, long)):
             raise TypeError("serial must be an integer")
 
+        hex_serial = hex(serial)[2:]
+        if not isinstance(hex_serial, bytes):
+            hex_serial = hex_serial.encode('ascii')
+
+        bignum_serial = _api.new("BIGNUM**")
+
+        # BN_hex2bn stores the result in &bignum.  Unless it doesn't feel like
+        # it.  If bignum is still NULL after this call, then the return value is
+        # actually the result.  I hope.  -exarkun
+        small_serial = _api.BN_hex2bn(bignum_serial, hex_serial)
+
+        if bignum_serial[0] == _api.NULL:
+            set_result = ASN1_INTEGER_set(
+                _api.X509_get_serialNumber(self._x509), small_serial)
+            if set_result:
+                # TODO Not tested
+                _raise_current_error()
+        else:
+            asn1_serial = _api.BN_to_ASN1_INTEGER(bignum_serial[0], _api.NULL)
+            _api.BN_free(bignum_serial[0])
+            if asn1_serial == _api.NULL:
+                # TODO Not tested
+                _raise_current_error()
+            set_result = _api.X509_set_serialNumber(self._x509, asn1_serial)
+            if not set_result:
+                # TODO Not tested
+                _raise_current_error()
+
 
     def get_serial_number(self):
         """
@@ -116,6 +153,18 @@
 
         :return: Serial number as a Python integer
         """
+        asn1_serial = _api.X509_get_serialNumber(self._x509)
+        bignum_serial = _api.ASN1_INTEGER_to_BN(asn1_serial, _api.NULL)
+        try:
+            hex_serial = _api.BN_bn2hex(bignum_serial)
+            try:
+                hexstring_serial = _api.string(hex_serial)
+                serial = int(hexstring_serial, 16)
+                return serial
+            finally:
+                _api.OPENSSL_free(hex_serial)
+        finally:
+            _api.BN_free(bignum_serial)
 
 
     def gmtime_adj_notAfter(self, amount):