diff options
author | Cory Benfield <lukasaoz@gmail.com> | 2015-10-27 16:57:58 +0900 |
---|---|---|
committer | Cory Benfield <lukasaoz@gmail.com> | 2015-10-27 16:57:58 +0900 |
commit | 6492f7c129bf7ce60f83ac134571f31b31e2f842 (patch) | |
tree | 102aaf92595c9880d7697e0caa7afa93cbdbb6bc | |
parent | 3fffb7464cdf96ab4011d63929d41c3b26cbee68 (diff) | |
download | pyopenssl-6492f7c129bf7ce60f83ac134571f31b31e2f842.tar.gz |
Support for serializing/deserializing public keys
-rw-r--r-- | src/OpenSSL/crypto.py | 54 | ||||
-rw-r--r-- | tests/test_crypto.py | 31 |
2 files changed, 85 insertions, 0 deletions
diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py index 71b6c51..58e176d 100644 --- a/src/OpenSSL/crypto.py +++ b/src/OpenSSL/crypto.py @@ -1623,6 +1623,31 @@ def dump_certificate(type, cert): return _bio_to_string(bio) +def dump_publickey(type, pkey): + """ + Dump a public key to a buffer + + :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1). + :param pkey: The PKey to dump. + :return: The buffer with the dumped key in it. + :rtype: :py:data:`bytes` + """ + bio = _new_mem_buf() + if type == FILETYPE_PEM: + write_bio = _lib.PEM_write_bio_PUBKEY + elif type == FILETYPE_ASN1: + write_bio = _lib.i2d_PUBKEY_bio + else: + raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") + + result_code = write_bio(bio, pkey._pkey) + if result_code != 1: + # TODO: This is untested. + _raise_current_error() + + return _bio_to_string(bio) + + def dump_privatekey(type, pkey, cipher=None, passphrase=None): """ Dump a private key to a buffer @@ -2404,6 +2429,35 @@ class _PassphraseHelper(object): return 0 +def load_publickey(type, buffer): + """ + Load a public key from a buffer + + :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1) + :param buffer: The buffer the key is stored in + :return: The PKey object + """ + if isinstance(buffer, _text_type): + buffer = buffer.encode("ascii") + + bio = _new_mem_buf(buffer) + + if type == FILETYPE_PEM: + evp_pkey = _lib.PEM_read_bio_PUBKEY( + bio, _ffi.NULL, _ffi.NULL, _ffi.NULL) + elif type == FILETYPE_ASN1: + evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL) + else: + raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1") + + if evp_pkey == _ffi.NULL: + _raise_current_error() + + pkey = PKey.__new__(PKey) + pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free) + return pkey + + def load_privatekey(type, buffer, passphrase=None): """ Load a private key from a buffer diff --git a/tests/test_crypto.py b/tests/test_crypto.py index d9a9526..a3c540e 100644 --- a/tests/test_crypto.py +++ b/tests/test_crypto.py @@ -26,6 +26,7 @@ from OpenSSL.crypto import ( from OpenSSL.crypto import X509Req, X509ReqType from OpenSSL.crypto import X509Extension, X509ExtensionType from OpenSSL.crypto import load_certificate, load_privatekey +from OpenSSL.crypto import load_publickey, dump_publickey from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT from OpenSSL.crypto import dump_certificate, load_certificate_request from OpenSSL.crypto import dump_certificate_request, dump_privatekey @@ -300,6 +301,18 @@ MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh encryptedPrivateKeyPEMPassphrase = b("foobar") + +cleartextPublicKeyPEM = b("""-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxszlc+b71LvlLS0ypt/l +gT/JzSVJtnEqw9WUNGeiChywX2mmQLHEt7KP0JikqUFZOtPclNY823Q4pErMTSWC +90qlUxI47vNJbXGRfmO2q6Zfw6SE+E9iUb74xezbOJLjBuUIkQzEKEFV+8taiRV+ +ceg1v01yCT2+OjhQW3cxG42zxyRFmqesbQAUWgS3uhPrUQqYQUEiTmVhh4FBUKZ5 +XIneGUpX1S7mXRxTLH6YzRoGFqRoc9A0BBNcoXHTWnxV215k4TeHMFYE5RG0KYAS +8Xk5iKICEXwnZreIt3jyygqoOKsKZMK/Zl2VhMGhJR6HXRpQCyASzEG7bgtROLhL +ywIDAQAB +-----END PUBLIC KEY----- +""") + # Some PKCS#7 stuff. Generated with the openssl command line: # # openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl @@ -2562,6 +2575,24 @@ class FunctionTests(TestCase): good_text = _runopenssl(dumped_pem, b"rsa", b"-noout", b"-text") self.assertEqual(dumped_text, good_text) + def test_dump_publickey_pem(self): + """ + :py:obj:`dump_publickey` writes a PEM + """ + key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) + dumped_pem = dump_publickey(FILETYPE_PEM, key) + self.assertEqual(dumped_pem, cleartextPublicKeyPEM) + + def test_dump_publickey_asn1(self): + """ + :py:obj:`dump_publickey` writes a DER + """ + key = load_publickey(FILETYPE_PEM, cleartextPublicKeyPEM) + dumped_der = dump_publickey(FILETYPE_ASN1, key) + key2 = load_publickey(FILETYPE_ASN1, dumped_der) + dumped_pem2 = dump_publickey(FILETYPE_PEM, key2) + self.assertEqual(dumped_pem2, cleartextPublicKeyPEM) + def test_dump_certificate_request(self): """ :py:obj:`dump_certificate_request` writes a PEM, DER, and text. |