summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCory Benfield <lukasaoz@gmail.com>2015-10-27 16:57:58 +0900
committerCory Benfield <lukasaoz@gmail.com>2015-10-27 16:57:58 +0900
commit6492f7c129bf7ce60f83ac134571f31b31e2f842 (patch)
tree102aaf92595c9880d7697e0caa7afa93cbdbb6bc
parent3fffb7464cdf96ab4011d63929d41c3b26cbee68 (diff)
downloadpyopenssl-6492f7c129bf7ce60f83ac134571f31b31e2f842.tar.gz
Support for serializing/deserializing public keys
-rw-r--r--src/OpenSSL/crypto.py54
-rw-r--r--tests/test_crypto.py31
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.