diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py index 56dad181c..e0a503aa9 100644 --- a/src/OpenSSL/crypto.py +++ b/src/OpenSSL/crypto.py @@ -962,6 +962,33 @@ def verify(self, pkey): return result + def digest(self, digest_name): + """ + Return the digest of the X509Req object. + + :param digest_name: The name of the digest algorithm to use. + :type digest_name: :py:class:`bytes` + + :return: The digest of the object + """ + digest = _lib.EVP_get_digestbyname(_byte_string(digest_name)) + if digest == _ffi.NULL: + raise ValueError("No such digest method") + + result_buffer = _ffi.new("char[]", _lib.EVP_MAX_MD_SIZE) + result_length = _ffi.new("unsigned int[]", len(result_buffer)) + + digest_result = _lib.X509_REQ_digest( + self._req, digest, result_buffer, result_length) + + if not digest_result: + # TODO: This is untested. + _raise_current_error() + + return b":".join([ + b16encode(ch).upper() for ch + in _ffi.buffer(result_buffer, result_length[0])]) + X509ReqType = X509Req diff --git a/tests/test_crypto.py b/tests/test_crypto.py index 804777964..38b41fdd8 100644 --- a/tests/test_crypto.py +++ b/tests/test_crypto.py @@ -128,6 +128,18 @@ def normalize_privatekey_pem(pem): -----END RSA PRIVATE KEY----- """) +server_csr_pem = b("""-----BEGIN CERTIFICATE REQUEST----- +MIIBVzCBwQIBADAYMRYwFAYDVQQDDA1sb3ZlbHkgc2VydmVyMIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg +1U3u1eQ+U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5G +YGzVIx3QSBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2M +HQIDAQABoAAwDQYJKoZIhvcNAQEEBQADgYEAMRbqLdsXDEb4yR9KbuUqg9k90w0+ +8xPYgrNcTIrF2zTSZQKDfio6B7LBeD51fQabBNJo83+3M849Np8wN/h7ZFALiln6 +2ElkKCTQwmt/TbR3snakotqYUFw9//3PQCIq5cZfc32wim2IEyKOGBRvHqejpwbI +yT4P3uVSsYc35vY= +-----END CERTIFICATE REQUEST----- +""") + server_cert_pem = b("""-----BEGIN CERTIFICATE----- MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH @@ -1264,6 +1276,20 @@ def test_verify_success(self): request.sign(pkey, GOOD_DIGEST) self.assertEqual(True, request.verify(pkey)) + def test_digest(self): + """ + :py:obj:`X509Req.digest` returns a string giving ":"-separated + hex-encoded words of the digest of the certificate request. + """ + csr = load_certificate_request(FILETYPE_PEM, server_csr_pem) + + self.assertEqual( + # This is MD5 instead of GOOD_DIGEST because the digest algorithm + # actually matters to the assertion (ie, another arbitrary, good + # digest will not produce the same digest). + csr.digest("MD5"), + b("FB:D9:74:AB:24:A9:80:64:96:92:C0:1B:82:3C:36:C9")) + class X509Tests(TestCase, _PKeyInteractionTestsMixin): """