summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-07-16 03:28:46 +0000
committerGerrit Code Review <review@openstack.org>2015-07-16 03:28:46 +0000
commit15c83cf9e7c373c8a3dbbbee447b92152a0b24c1 (patch)
tree3e2ae009fef41b320e51e1145f57175ad265042a
parent7970a6cd0f2fc582fdd12a70683327dc7d1531a5 (diff)
parent1a31be6ee67d53b8078868460a7301402f5a0985 (diff)
downloadpython-barbicanclient-15c83cf9e7c373c8a3dbbbee447b92152a0b24c1.tar.gz
Merge "Added secret type command line option"
-rw-r--r--barbicanclient/barbican_cli/secrets.py7
-rw-r--r--barbicanclient/secrets.py28
-rw-r--r--barbicanclient/tests/test_secrets.py2
-rw-r--r--functionaltests/cli/v1/behaviors/secret_behaviors.py11
-rw-r--r--functionaltests/cli/v1/smoke/test_secret.py47
-rw-r--r--functionaltests/client/v1/functional/test_secrets.py104
-rw-r--r--functionaltests/client/v1/smoke/test_secrets.py46
-rw-r--r--functionaltests/common/keys.py404
8 files changed, 640 insertions, 9 deletions
diff --git a/barbicanclient/barbican_cli/secrets.py b/barbicanclient/barbican_cli/secrets.py
index 0accf1b..4daaabd 100644
--- a/barbicanclient/barbican_cli/secrets.py
+++ b/barbicanclient/barbican_cli/secrets.py
@@ -119,6 +119,10 @@ class StoreSecret(show.ShowOne):
help='the unencrypted secret; if provided, '
'you must also provide a '
'payload_content_type')
+ parser.add_argument('--secret-type', '-s', default='opaque',
+ help='the secret type; must be one of symmetric, '
+ 'public, private, certificate, passphrase, '
+ 'opaque (default)')
parser.add_argument('--payload-content-type', '-t',
help='the type/format of the provided '
'secret data; "text/plain" is assumed to be '
@@ -148,6 +152,7 @@ class StoreSecret(show.ShowOne):
payload_content_type=args.payload_content_type,
payload_content_encoding=args.payload_content_encoding,
algorithm=args.algorithm, bit_length=args.bit_length,
- mode=args.mode, expiration=args.expiration)
+ mode=args.mode, expiration=args.expiration,
+ secret_type=args.secret_type)
entity.store()
return entity._get_formatted_entity()
diff --git a/barbicanclient/secrets.py b/barbicanclient/secrets.py
index 4b07647..fe8dbfa 100644
--- a/barbicanclient/secrets.py
+++ b/barbicanclient/secrets.py
@@ -53,6 +53,7 @@ class SecretFormatter(formatter.EntityFormatter):
"Content types",
"Algorithm",
"Bit length",
+ "Secret type",
"Mode",
"Expiration",
)
@@ -65,6 +66,7 @@ class SecretFormatter(formatter.EntityFormatter):
self.content_types,
self.algorithm,
self.bit_length,
+ self.secret_type,
self.mode,
self.expiration,
)
@@ -96,6 +98,7 @@ class Secret(SecretFormatter):
expiration=expiration,
algorithm=algorithm,
bit_length=bit_length,
+ secret_type=secret_type,
mode=mode,
payload=payload,
payload_content_type=payload_content_type,
@@ -133,6 +136,11 @@ class Secret(SecretFormatter):
@property
@lazy
+ def secret_type(self):
+ return self._secret_type
+
+ @property
+ @lazy
def mode(self):
return self._mode
@@ -200,6 +208,11 @@ class Secret(SecretFormatter):
def bit_length(self, value):
self._bit_length = value
+ @secret_type.setter
+ @immutable_after_save
+ def secret_type(self, value):
+ self._secret_type = value
+
@mode.setter
@immutable_after_save
def mode(self, value):
@@ -262,6 +275,7 @@ class Secret(SecretFormatter):
'algorithm': self.algorithm,
'mode': self.mode,
'bit_length': self.bit_length,
+ 'secret_type': self.secret_type,
'expiration': self.expiration
}
@@ -319,8 +333,8 @@ class Secret(SecretFormatter):
raise LookupError("Secret is not yet stored.")
def _fill_from_data(self, name=None, expiration=None, algorithm=None,
- bit_length=None, mode=None, payload=None,
- payload_content_type=None,
+ bit_length=None, secret_type=None, mode=None,
+ payload=None, payload_content_type=None,
payload_content_encoding=None, created=None,
updated=None, content_types=None, status=None,
creator_id=None):
@@ -328,10 +342,13 @@ class Secret(SecretFormatter):
self._algorithm = algorithm
self._bit_length = bit_length
self._mode = mode
+ self._secret_type = secret_type
self._payload = payload
self._payload_content_encoding = payload_content_encoding
self._expiration = expiration
self._creator_id = creator_id
+ if not self._secret_type:
+ self._secret_type = "opaque"
if self._expiration:
self._expiration = parse_isotime(self._expiration)
if self._secret_ref:
@@ -363,6 +380,7 @@ class Secret(SecretFormatter):
expiration=result.get('expiration'),
algorithm=result.get('algorithm'),
bit_length=result.get('bit_length'),
+ secret_type=result.get('secret_type'),
mode=result.get('mode'),
payload_content_type=result.get('payload_content_type'),
payload_content_encoding=result.get(
@@ -410,7 +428,8 @@ class SecretManager(base.BaseEntityManager):
def create(self, name=None, payload=None,
payload_content_type=None, payload_content_encoding=None,
- algorithm=None, bit_length=None, mode=None, expiration=None):
+ algorithm=None, bit_length=None, secret_type=None,
+ mode=None, expiration=None):
"""
Factory method for creating new `Secret` objects
@@ -428,6 +447,7 @@ class SecretManager(base.BaseEntityManager):
:param algorithm: The algorithm associated with this secret key
:param bit_length: The bit length of this secret key
:param mode: The algorithm mode used with this secret key
+ :param secret_type: The secret type for this secret key
:param expiration: The expiration time of the secret in ISO 8601 format
:returns: A new Secret object
:rtype: :class:`barbicanclient.secrets.Secret`
@@ -439,7 +459,7 @@ class SecretManager(base.BaseEntityManager):
payload_content_type=payload_content_type,
payload_content_encoding=payload_content_encoding,
algorithm=algorithm, bit_length=bit_length, mode=mode,
- expiration=expiration)
+ secret_type=secret_type, expiration=expiration)
def delete(self, secret_ref):
"""
diff --git a/barbicanclient/tests/test_secrets.py b/barbicanclient/tests/test_secrets.py
index 3a8bbef..0bd3f4a 100644
--- a/barbicanclient/tests/test_secrets.py
+++ b/barbicanclient/tests/test_secrets.py
@@ -196,7 +196,7 @@ class WhenTestingSecrets(test_client.BaseEntityResource):
# Verify that attributes are immutable after store.
attributes = [
"name", "expiration", "algorithm", "bit_length", "mode", "payload",
- "payload_content_type", "payload_content_encoding"
+ "payload_content_type", "payload_content_encoding", "secret_type"
]
for attr in attributes:
try:
diff --git a/functionaltests/cli/v1/behaviors/secret_behaviors.py b/functionaltests/cli/v1/behaviors/secret_behaviors.py
index 0e289ff..778e1d0 100644
--- a/functionaltests/cli/v1/behaviors/secret_behaviors.py
+++ b/functionaltests/cli/v1/behaviors/secret_behaviors.py
@@ -38,15 +38,22 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
self.secret_hrefs_to_delete.remove(secret_href)
- def store_secret(self, payload="Payload for testing"):
+ def store_secret(self, payload="Payload for testing", store_argv=[]):
""" Store (aka create) a secret
- :param payload The payload to use when storing the secret.
+
+ The store_argv paramater allows additional command line parameters for
+ the store operation to be specified. This can be used to specify -a for
+ algorithm as an example.
+
+ :param payload The payload to use when storing the secret
+ :param store_argv The store command line parameters
:return: the href to the newly created secret
"""
argv = ['secret', 'store']
self.add_auth_and_endpoint(argv)
argv.extend(['--payload', payload])
+ argv.extend(store_argv)
stdout, stderr = self.issue_barbican_command(argv)
diff --git a/functionaltests/cli/v1/smoke/test_secret.py b/functionaltests/cli/v1/smoke/test_secret.py
index 1911458..416027f 100644
--- a/functionaltests/cli/v1/smoke/test_secret.py
+++ b/functionaltests/cli/v1/smoke/test_secret.py
@@ -13,11 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import base64
+
from functionaltests.cli.base import CmdLineTestCase
from functionaltests.cli.v1.behaviors.secret_behaviors import SecretBehaviors
+from functionaltests.common import keys
+from functionaltests import utils
from testtools import testcase
+@utils.parameterized_test_case
class SecretTestCase(CmdLineTestCase):
def setUp(self):
@@ -29,6 +34,48 @@ class SecretTestCase(CmdLineTestCase):
super(SecretTestCase, self).tearDown()
self.secret_behaviors.delete_all_created_secrets()
+ @utils.parameterized_dataset({
+ 'symmetric': ['symmetric',
+ 'aes',
+ '128',
+ ('\x00\x01\x02\x03\x04\x05\x06\x07'
+ '\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'private': ['private',
+ 'rsa',
+ '2048',
+ keys.get_private_key_pem()],
+ 'public': ['public',
+ 'rsa',
+ '2048',
+ keys.get_public_key_pem()],
+ 'certificate': ['certificate',
+ 'rsa',
+ '2048',
+ keys.get_certificate_pem()],
+ 'opaque': ['opaque',
+ None,
+ None,
+ (b'\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'passphrase': ['passphrase',
+ None,
+ None,
+ keys.get_passphrase_txt()],
+ })
+ @testcase.attr('positive')
+ def test_secret_store_with_secret_type(self, secret_type, algorithm,
+ bit_length, secret):
+ payload = base64.b64encode(secret)
+ secret_argv = ['--secret-type', secret_type]
+ if algorithm:
+ secret_argv.extend(['--algorithm', algorithm])
+ if bit_length:
+ secret_argv.extend(['--bit-length', bit_length])
+ secret_href = self.secret_behaviors.store_secret(payload, secret_argv)
+ self.assertIsNotNone(secret_href)
+
+ secret = self.secret_behaviors.get_secret(secret_href)
+ self.assertEqual(secret_href, secret['Secret href'])
+
@testcase.attr('positive')
def test_secret_store(self):
secret_href = self.secret_behaviors.store_secret()
diff --git a/functionaltests/client/v1/functional/test_secrets.py b/functionaltests/client/v1/functional/test_secrets.py
index 8d0961f..f02c156 100644
--- a/functionaltests/client/v1/functional/test_secrets.py
+++ b/functionaltests/client/v1/functional/test_secrets.py
@@ -18,6 +18,7 @@ import sys
from functionaltests.client import base
from functionaltests.client.v1.behaviors import secret_behaviors
+from functionaltests.common import keys
from functionaltests import utils
from testtools import testcase
@@ -320,6 +321,65 @@ class SecretsTestCase(base.TestCase):
self.assertEqual(e.status_code, 400)
@utils.parameterized_dataset({
+ 'symmetric': ['symmetric',
+ 'aes',
+ 128,
+ ('\x00\x01\x02\x03\x04\x05\x06\x07'
+ '\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'private': ['private',
+ 'rsa',
+ 2048,
+ keys.get_private_key_pem()],
+ 'public': ['public',
+ 'rsa',
+ 2048,
+ keys.get_public_key_pem()],
+ 'certificate': ['certificate',
+ 'rsa',
+ 2048,
+ keys.get_certificate_pem()],
+ 'opaque': ['opaque',
+ None,
+ None,
+ (b'\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'passphrase': ['passphrase',
+ None,
+ None,
+ keys.get_passphrase_txt()],
+ })
+ @testcase.attr('positive')
+ def test_secret_create_defaults_valid_secret_type(
+ self, secret_type, algorithm, bit_length, secret):
+ """Covers cases of creating secrets with valid secret types."""
+ test_model = self.behaviors.create_secret(
+ secret_create_defaults_data)
+ test_model.secret_type = secret_type
+ test_model.algorithm = algorithm
+ test_model.bit_length = bit_length
+ test_model.payload = base64.b64encode(secret)
+
+ secret_ref = self.behaviors.store_secret(test_model)
+ self.assertIsNotNone(secret_ref)
+
+ get_resp = self.behaviors.get_secret(secret_ref)
+ self.assertEqual(get_resp.secret_type, secret_type)
+
+ @testcase.attr('negative')
+ def test_secret_create_defaults_invalid_secret_type(self):
+ """Covers cases of creating secrets with invalid secret types."""
+ test_model = self.behaviors.create_secret(
+ secret_create_defaults_data)
+ test_model.secret_type = 'not a valid secret type'
+
+ e = self.assertRaises(
+ exceptions.HTTPClientError,
+ self.behaviors.store_secret,
+ test_model
+ )
+
+ self.assertEqual(e.status_code, 400)
+
+ @utils.parameterized_dataset({
'512': [512],
'sixteen': [16],
'fifteen': [15],
@@ -654,3 +714,47 @@ class SecretsTestCase(base.TestCase):
self.assertEqual(get_resp.mode, test_model.mode)
self.assertEqual(get_resp.algorithm, test_model.algorithm)
self.assertEqual(get_resp.bit_length, test_model.bit_length)
+
+ @utils.parameterized_dataset({
+ 'symmetric': ['symmetric',
+ 'aes',
+ 128,
+ ('\x00\x01\x02\x03\x04\x05\x06\x07'
+ '\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'private': ['private',
+ 'rsa',
+ 2048,
+ keys.get_private_key_pem()],
+ 'public': ['public',
+ 'rsa',
+ 2048,
+ keys.get_public_key_pem()],
+ 'certificate': ['certificate',
+ 'rsa',
+ 2048,
+ keys.get_certificate_pem()],
+ 'opaque': ['opaque',
+ None,
+ None,
+ (b'\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'passphrase': ['passphrase',
+ None,
+ None,
+ keys.get_passphrase_txt()],
+ })
+ @testcase.attr('positive')
+ def test_secret_get_defaults_secret_type(self, secret_type, algorithm,
+ bit_length, secret):
+ """Covers getting and checking a secret's metadata."""
+ test_model = self.behaviors.create_secret(secret_create_defaults_data)
+ test_model.secret_type = secret_type
+ test_model.algorithm = algorithm
+ test_model.bit_length = bit_length
+ test_model.payload = base64.b64encode(secret)
+
+ secret_ref = self.behaviors.store_secret(test_model)
+ self.assertIsNotNone(secret_ref)
+
+ get_resp = self.behaviors.get_secret(secret_ref)
+ self.assertEqual(get_resp.status, "ACTIVE")
+ self.assertEqual(get_resp.secret_type, secret_type)
diff --git a/functionaltests/client/v1/smoke/test_secrets.py b/functionaltests/client/v1/smoke/test_secrets.py
index e9387a6..8e1c764 100644
--- a/functionaltests/client/v1/smoke/test_secrets.py
+++ b/functionaltests/client/v1/smoke/test_secrets.py
@@ -12,9 +12,12 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import base64
+
from testtools import testcase
from functionaltests.client import base
from functionaltests.client.v1.behaviors import secret_behaviors
+from functionaltests.common import keys
from functionaltests import utils
secret_create_defaults_data = {
@@ -58,6 +61,47 @@ class SecretsTestCase(base.TestCase):
self.assertIsNotNone(secret_ref)
@testcase.attr('positive')
+ @utils.parameterized_dataset({
+ 'symmetric': ['symmetric',
+ 'aes',
+ 128,
+ ('\x00\x01\x02\x03\x04\x05\x06\x07'
+ '\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'private': ['private',
+ 'rsa',
+ 2048,
+ keys.get_private_key_pem()],
+ 'public': ['public',
+ 'rsa',
+ 2048,
+ keys.get_public_key_pem()],
+ 'certificate': ['certificate',
+ 'rsa',
+ 2048,
+ keys.get_certificate_pem()],
+ 'opaque': ['opaque',
+ None,
+ None,
+ (b'\x00\x01\x02\x03\x04\x05\x06\x07')],
+ 'passphrase': ['passphrase',
+ None,
+ None,
+ keys.get_passphrase_txt()],
+ })
+ def test_create_secret_with_type(self, secret_type, algorithm, bit_length,
+ secret):
+ """Creates a secret with default values"""
+ secret_data = secret_create_defaults_data
+ secret_data['secret_type'] = secret_type
+ secret_data['algorithm'] = algorithm
+ secret_data['bit_length'] = bit_length
+ secret_data['payload'] = base64.b64encode(secret)
+ test_model = self.behaviors.create_secret(secret_create_defaults_data)
+
+ secret_ref = self.behaviors.store_secret(test_model)
+ self.assertIsNotNone(secret_ref)
+
+ @testcase.attr('positive')
def test_secret_create_defaults_no_expiration(self):
"""Covers creating a secret without an expiration."""
test_model = self.behaviors.create_secret(secret_create_defaults_data)
@@ -95,7 +139,7 @@ class SecretsTestCase(base.TestCase):
get_resp = self.behaviors.get_secret(
secret_ref
- )
+ )
self.assertEqual(test_model.payload, get_resp.payload)
@testcase.attr('positive')
diff --git a/functionaltests/common/keys.py b/functionaltests/common/keys.py
new file mode 100644
index 0000000..44435b2
--- /dev/null
+++ b/functionaltests/common/keys.py
@@ -0,0 +1,404 @@
+# Copyright (c) 2015 Cisco Systems
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def get_private_key_pem():
+ """Returns a private key in PCKS#8 format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl pkcs8 -topk8 -nocrypt -in private.pem -out private.pk8
+
+ The byte string returned by this function is the contents
+ of the private.pk8 file.
+ """
+
+ return """-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCza2VoDXmBUMmw
+jFu9F6MM5q/AZ1WjnWA2YNdNy237TrGN/nobDDv8FBBpUPmHNZ04H1LyxFcP8ReF
+rcIXpifsReu2lAWaqRPxovu5CuAhfecKv+RhjLVLJ0I+MZIb72ROKpfZTmb7dhlF
+gGD3vkC51BCfhGVW35w52OY/23x5MeO4yvx5myPccnxMVQ42KuDrzKqjBlSjmBnc
+pGYx0JgCT+syFmHsl8rOkqCPPFLo24YQn+4/pr1AYwaZAbMTl9zoLtEQj6sxScuH
+cS9e8niptDxlsbLQgqGVaGdE117stC95QH7UvITbuYzdjZwBFc1Sgz8GZ/2hLSsH
+ujJiIQcvAgMBAAECggEAMOlUKbuSpigp85Ev6Sqqbnfs7Zy+Ae6DLg/UYgbVIq9f
+RABdtUXujFfD6ZIDlFKPW59ec4QG3/evm+e0g9HuDEE7cviDVphFMZhm2xkV5Mt3
+0rxhPB6pxaUcL+w/kpH+XDjMUJdJB8A4P3Qx+xfIeWBQb8wd/ELVSgfRLRNeqYL0
+0KXVs04/FOBEhqSiqi/oHYJ4gxNrSoINX71PHVbaEikIygzi4HZVyMut3LE6ceHz
+fSj71ftn+Ui0TzkLOb+NoBP31haHC/sfCrpKg7QtUP9q9dRq6dZcI17q5d7oEdET
+eDRKhT2vm7bx2bLGeF1w2H9B/V81upjiAah2RVnecQKBgQDsfHSjR1gd+SHw/2A9
+SaXS1k9LeXLt+UbDQdbjYOsh5LoT+EN/utO70RyDYqjlhzqJzciKTuAW5SVPC6gQ
+uCppA29Kntq7x1+Lw/4wG947poXb60tLdg3BK5mBFTORk5ATqAwVq7t+2NtS5S/J
+unzs5xrRolDFnSX4KnvVl6Jj3QKBgQDCOXZTVXRPEFhnqnqLErZe6EJkySwG8wgt
+OdCmr660bocY1i9vV+RaM1iARHX6u/suMhkz+3KRinzxIG5gQsyiWmTpFV298W9v
+kRtmsCQDn2my90yv4e6sLI0ng7l/N3r7CwLLNIV/CqeyaN40suzE8AjgEga5jTua
+6bP5m+x8ewKBgQCeuW3DxXfkLjnUumMK36qX11XDb5FvHjebiE5FsOBAkHdAPgp3
+6ZqBXfoISSjZXakxotft1MDdPRGMe2NjTWjRsQd6iyJ+lHORqIusGJhRaxQ/Ji8U
+R/k1ZSETnXpORD+YodrylKA0pDKY8dDgUfXVP8wlVg9mg3JfnYweMTdCVQKBgQCx
+133iNmgmkTfxzGci+wJkitVohdA7mMOO7daBGnKlImOvuUd784XTlhpecNF6wi/w
+D82GDKLOY3meLO0EVYYczxqBVqAccXtxM/RcJcMEUi6twcXFcuJhYvXpDbOHqlyA
+jIeFW9U1C6OcOGvm40Lr3UKzMa5Yrtq6MW4ri7uSCwKBgQDfdqVjT4uXmGwOh1z4
+Pzv6GCoc+6GobXg4DvvCUjP9MR+2+5sX0AY/f+aVCD05/Nj0RqpAwUc03zZU5ZtL
+2uNe6XDjEugfFtlzea6+rbD6KpFS+nxPJA8YyWYRpNhpRWGWQakHedr3BtMtGs0h
+pKNAQG72HKWtSfJQMXvn2RlicA==
+-----END PRIVATE KEY-----"""
+
+
+def get_private_key_der():
+ """Returns a private key in DER format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl pkcs8 -in private.pem -topk8 -nocrypt \
+ -outform DER -out private_pk8.der
+
+ The byte string returned by this function is the contents
+ of the private_pk8.der file.
+ """
+ key_der = (
+ '\x30\x82\x04\xbf\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86'
+ '\xf7\x0d\x01\x01\x01\x05\x00\x04\x82\x04\xa9\x30\x82\x04\xa5'
+ '\x02\x01\x00\x02\x82\x01\x01\x00\xb3\x6b\x65\x68\x0d\x79\x81'
+ '\x50\xc9\xb0\x8c\x5b\xbd\x17\xa3\x0c\xe6\xaf\xc0\x67\x55\xa3'
+ '\x9d\x60\x36\x60\xd7\x4d\xcb\x6d\xfb\x4e\xb1\x8d\xfe\x7a\x1b'
+ '\x0c\x3b\xfc\x14\x10\x69\x50\xf9\x87\x35\x9d\x38\x1f\x52\xf2'
+ '\xc4\x57\x0f\xf1\x17\x85\xad\xc2\x17\xa6\x27\xec\x45\xeb\xb6'
+ '\x94\x05\x9a\xa9\x13\xf1\xa2\xfb\xb9\x0a\xe0\x21\x7d\xe7\x0a'
+ '\xbf\xe4\x61\x8c\xb5\x4b\x27\x42\x3e\x31\x92\x1b\xef\x64\x4e'
+ '\x2a\x97\xd9\x4e\x66\xfb\x76\x19\x45\x80\x60\xf7\xbe\x40\xb9'
+ '\xd4\x10\x9f\x84\x65\x56\xdf\x9c\x39\xd8\xe6\x3f\xdb\x7c\x79'
+ '\x31\xe3\xb8\xca\xfc\x79\x9b\x23\xdc\x72\x7c\x4c\x55\x0e\x36'
+ '\x2a\xe0\xeb\xcc\xaa\xa3\x06\x54\xa3\x98\x19\xdc\xa4\x66\x31'
+ '\xd0\x98\x02\x4f\xeb\x32\x16\x61\xec\x97\xca\xce\x92\xa0\x8f'
+ '\x3c\x52\xe8\xdb\x86\x10\x9f\xee\x3f\xa6\xbd\x40\x63\x06\x99'
+ '\x01\xb3\x13\x97\xdc\xe8\x2e\xd1\x10\x8f\xab\x31\x49\xcb\x87'
+ '\x71\x2f\x5e\xf2\x78\xa9\xb4\x3c\x65\xb1\xb2\xd0\x82\xa1\x95'
+ '\x68\x67\x44\xd7\x5e\xec\xb4\x2f\x79\x40\x7e\xd4\xbc\x84\xdb'
+ '\xb9\x8c\xdd\x8d\x9c\x01\x15\xcd\x52\x83\x3f\x06\x67\xfd\xa1'
+ '\x2d\x2b\x07\xba\x32\x62\x21\x07\x2f\x02\x03\x01\x00\x01\x02'
+ '\x82\x01\x00\x30\xe9\x54\x29\xbb\x92\xa6\x28\x29\xf3\x91\x2f'
+ '\xe9\x2a\xaa\x6e\x77\xec\xed\x9c\xbe\x01\xee\x83\x2e\x0f\xd4'
+ '\x62\x06\xd5\x22\xaf\x5f\x44\x00\x5d\xb5\x45\xee\x8c\x57\xc3'
+ '\xe9\x92\x03\x94\x52\x8f\x5b\x9f\x5e\x73\x84\x06\xdf\xf7\xaf'
+ '\x9b\xe7\xb4\x83\xd1\xee\x0c\x41\x3b\x72\xf8\x83\x56\x98\x45'
+ '\x31\x98\x66\xdb\x19\x15\xe4\xcb\x77\xd2\xbc\x61\x3c\x1e\xa9'
+ '\xc5\xa5\x1c\x2f\xec\x3f\x92\x91\xfe\x5c\x38\xcc\x50\x97\x49'
+ '\x07\xc0\x38\x3f\x74\x31\xfb\x17\xc8\x79\x60\x50\x6f\xcc\x1d'
+ '\xfc\x42\xd5\x4a\x07\xd1\x2d\x13\x5e\xa9\x82\xf4\xd0\xa5\xd5'
+ '\xb3\x4e\x3f\x14\xe0\x44\x86\xa4\xa2\xaa\x2f\xe8\x1d\x82\x78'
+ '\x83\x13\x6b\x4a\x82\x0d\x5f\xbd\x4f\x1d\x56\xda\x12\x29\x08'
+ '\xca\x0c\xe2\xe0\x76\x55\xc8\xcb\xad\xdc\xb1\x3a\x71\xe1\xf3'
+ '\x7d\x28\xfb\xd5\xfb\x67\xf9\x48\xb4\x4f\x39\x0b\x39\xbf\x8d'
+ '\xa0\x13\xf7\xd6\x16\x87\x0b\xfb\x1f\x0a\xba\x4a\x83\xb4\x2d'
+ '\x50\xff\x6a\xf5\xd4\x6a\xe9\xd6\x5c\x23\x5e\xea\xe5\xde\xe8'
+ '\x11\xd1\x13\x78\x34\x4a\x85\x3d\xaf\x9b\xb6\xf1\xd9\xb2\xc6'
+ '\x78\x5d\x70\xd8\x7f\x41\xfd\x5f\x35\xba\x98\xe2\x01\xa8\x76'
+ '\x45\x59\xde\x71\x02\x81\x81\x00\xec\x7c\x74\xa3\x47\x58\x1d'
+ '\xf9\x21\xf0\xff\x60\x3d\x49\xa5\xd2\xd6\x4f\x4b\x79\x72\xed'
+ '\xf9\x46\xc3\x41\xd6\xe3\x60\xeb\x21\xe4\xba\x13\xf8\x43\x7f'
+ '\xba\xd3\xbb\xd1\x1c\x83\x62\xa8\xe5\x87\x3a\x89\xcd\xc8\x8a'
+ '\x4e\xe0\x16\xe5\x25\x4f\x0b\xa8\x10\xb8\x2a\x69\x03\x6f\x4a'
+ '\x9e\xda\xbb\xc7\x5f\x8b\xc3\xfe\x30\x1b\xde\x3b\xa6\x85\xdb'
+ '\xeb\x4b\x4b\x76\x0d\xc1\x2b\x99\x81\x15\x33\x91\x93\x90\x13'
+ '\xa8\x0c\x15\xab\xbb\x7e\xd8\xdb\x52\xe5\x2f\xc9\xba\x7c\xec'
+ '\xe7\x1a\xd1\xa2\x50\xc5\x9d\x25\xf8\x2a\x7b\xd5\x97\xa2\x63'
+ '\xdd\x02\x81\x81\x00\xc2\x39\x76\x53\x55\x74\x4f\x10\x58\x67'
+ '\xaa\x7a\x8b\x12\xb6\x5e\xe8\x42\x64\xc9\x2c\x06\xf3\x08\x2d'
+ '\x39\xd0\xa6\xaf\xae\xb4\x6e\x87\x18\xd6\x2f\x6f\x57\xe4\x5a'
+ '\x33\x58\x80\x44\x75\xfa\xbb\xfb\x2e\x32\x19\x33\xfb\x72\x91'
+ '\x8a\x7c\xf1\x20\x6e\x60\x42\xcc\xa2\x5a\x64\xe9\x15\x5d\xbd'
+ '\xf1\x6f\x6f\x91\x1b\x66\xb0\x24\x03\x9f\x69\xb2\xf7\x4c\xaf'
+ '\xe1\xee\xac\x2c\x8d\x27\x83\xb9\x7f\x37\x7a\xfb\x0b\x02\xcb'
+ '\x34\x85\x7f\x0a\xa7\xb2\x68\xde\x34\xb2\xec\xc4\xf0\x08\xe0'
+ '\x12\x06\xb9\x8d\x3b\x9a\xe9\xb3\xf9\x9b\xec\x7c\x7b\x02\x81'
+ '\x81\x00\x9e\xb9\x6d\xc3\xc5\x77\xe4\x2e\x39\xd4\xba\x63\x0a'
+ '\xdf\xaa\x97\xd7\x55\xc3\x6f\x91\x6f\x1e\x37\x9b\x88\x4e\x45'
+ '\xb0\xe0\x40\x90\x77\x40\x3e\x0a\x77\xe9\x9a\x81\x5d\xfa\x08'
+ '\x49\x28\xd9\x5d\xa9\x31\xa2\xd7\xed\xd4\xc0\xdd\x3d\x11\x8c'
+ '\x7b\x63\x63\x4d\x68\xd1\xb1\x07\x7a\x8b\x22\x7e\x94\x73\x91'
+ '\xa8\x8b\xac\x18\x98\x51\x6b\x14\x3f\x26\x2f\x14\x47\xf9\x35'
+ '\x65\x21\x13\x9d\x7a\x4e\x44\x3f\x98\xa1\xda\xf2\x94\xa0\x34'
+ '\xa4\x32\x98\xf1\xd0\xe0\x51\xf5\xd5\x3f\xcc\x25\x56\x0f\x66'
+ '\x83\x72\x5f\x9d\x8c\x1e\x31\x37\x42\x55\x02\x81\x81\x00\xb1'
+ '\xd7\x7d\xe2\x36\x68\x26\x91\x37\xf1\xcc\x67\x22\xfb\x02\x64'
+ '\x8a\xd5\x68\x85\xd0\x3b\x98\xc3\x8e\xed\xd6\x81\x1a\x72\xa5'
+ '\x22\x63\xaf\xb9\x47\x7b\xf3\x85\xd3\x96\x1a\x5e\x70\xd1\x7a'
+ '\xc2\x2f\xf0\x0f\xcd\x86\x0c\xa2\xce\x63\x79\x9e\x2c\xed\x04'
+ '\x55\x86\x1c\xcf\x1a\x81\x56\xa0\x1c\x71\x7b\x71\x33\xf4\x5c'
+ '\x25\xc3\x04\x52\x2e\xad\xc1\xc5\xc5\x72\xe2\x61\x62\xf5\xe9'
+ '\x0d\xb3\x87\xaa\x5c\x80\x8c\x87\x85\x5b\xd5\x35\x0b\xa3\x9c'
+ '\x38\x6b\xe6\xe3\x42\xeb\xdd\x42\xb3\x31\xae\x58\xae\xda\xba'
+ '\x31\x6e\x2b\x8b\xbb\x92\x0b\x02\x81\x81\x00\xdf\x76\xa5\x63'
+ '\x4f\x8b\x97\x98\x6c\x0e\x87\x5c\xf8\x3f\x3b\xfa\x18\x2a\x1c'
+ '\xfb\xa1\xa8\x6d\x78\x38\x0e\xfb\xc2\x52\x33\xfd\x31\x1f\xb6'
+ '\xfb\x9b\x17\xd0\x06\x3f\x7f\xe6\x95\x08\x3d\x39\xfc\xd8\xf4'
+ '\x46\xaa\x40\xc1\x47\x34\xdf\x36\x54\xe5\x9b\x4b\xda\xe3\x5e'
+ '\xe9\x70\xe3\x12\xe8\x1f\x16\xd9\x73\x79\xae\xbe\xad\xb0\xfa'
+ '\x2a\x91\x52\xfa\x7c\x4f\x24\x0f\x18\xc9\x66\x11\xa4\xd8\x69'
+ '\x45\x61\x96\x41\xa9\x07\x79\xda\xf7\x06\xd3\x2d\x1a\xcd\x21'
+ '\xa4\xa3\x40\x40\x6e\xf6\x1c\xa5\xad\x49\xf2\x50\x31\x7b\xe7'
+ '\xd9\x19\x62\x70')
+ return key_der
+
+
+def get_public_key_pem():
+ """Returns a public key in PEM format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl rsa -in private.pem -pubout > public.pem
+
+ The byte string returned by this function is the contents
+ of the public.pem file.
+ """
+
+ return """-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs2tlaA15gVDJsIxbvRej
+DOavwGdVo51gNmDXTctt+06xjf56Gww7/BQQaVD5hzWdOB9S8sRXD/EXha3CF6Yn
+7EXrtpQFmqkT8aL7uQrgIX3nCr/kYYy1SydCPjGSG+9kTiqX2U5m+3YZRYBg975A
+udQQn4RlVt+cOdjmP9t8eTHjuMr8eZsj3HJ8TFUONirg68yqowZUo5gZ3KRmMdCY
+Ak/rMhZh7JfKzpKgjzxS6NuGEJ/uP6a9QGMGmQGzE5fc6C7REI+rMUnLh3EvXvJ4
+qbQ8ZbGy0IKhlWhnRNde7LQveUB+1LyE27mM3Y2cARXNUoM/Bmf9oS0rB7oyYiEH
+LwIDAQAB
+-----END PUBLIC KEY-----"""
+
+
+def get_public_key_der():
+ """Returns a public key in DER format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl rsa -in private.pem -pubout > public.pem
+
+ The byte string returned by this function is the contents
+ of the public.der file.
+ """
+ key_der = (
+ '\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01'
+ '\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82'
+ '\x01\x01\x00\xb3\x6b\x65\x68\x0d\x79\x81\x50\xc9\xb0\x8c\x5b'
+ '\xbd\x17\xa3\x0c\xe6\xaf\xc0\x67\x55\xa3\x9d\x60\x36\x60\xd7'
+ '\x4d\xcb\x6d\xfb\x4e\xb1\x8d\xfe\x7a\x1b\x0c\x3b\xfc\x14\x10'
+ '\x69\x50\xf9\x87\x35\x9d\x38\x1f\x52\xf2\xc4\x57\x0f\xf1\x17'
+ '\x85\xad\xc2\x17\xa6\x27\xec\x45\xeb\xb6\x94\x05\x9a\xa9\x13'
+ '\xf1\xa2\xfb\xb9\x0a\xe0\x21\x7d\xe7\x0a\xbf\xe4\x61\x8c\xb5'
+ '\x4b\x27\x42\x3e\x31\x92\x1b\xef\x64\x4e\x2a\x97\xd9\x4e\x66'
+ '\xfb\x76\x19\x45\x80\x60\xf7\xbe\x40\xb9\xd4\x10\x9f\x84\x65'
+ '\x56\xdf\x9c\x39\xd8\xe6\x3f\xdb\x7c\x79\x31\xe3\xb8\xca\xfc'
+ '\x79\x9b\x23\xdc\x72\x7c\x4c\x55\x0e\x36\x2a\xe0\xeb\xcc\xaa'
+ '\xa3\x06\x54\xa3\x98\x19\xdc\xa4\x66\x31\xd0\x98\x02\x4f\xeb'
+ '\x32\x16\x61\xec\x97\xca\xce\x92\xa0\x8f\x3c\x52\xe8\xdb\x86'
+ '\x10\x9f\xee\x3f\xa6\xbd\x40\x63\x06\x99\x01\xb3\x13\x97\xdc'
+ '\xe8\x2e\xd1\x10\x8f\xab\x31\x49\xcb\x87\x71\x2f\x5e\xf2\x78'
+ '\xa9\xb4\x3c\x65\xb1\xb2\xd0\x82\xa1\x95\x68\x67\x44\xd7\x5e'
+ '\xec\xb4\x2f\x79\x40\x7e\xd4\xbc\x84\xdb\xb9\x8c\xdd\x8d\x9c'
+ '\x01\x15\xcd\x52\x83\x3f\x06\x67\xfd\xa1\x2d\x2b\x07\xba\x32'
+ '\x62\x21\x07\x2f\x02\x03\x01\x00\x01')
+ return key_der
+
+
+def get_encrypted_private_key_pem():
+ """Returns an encrypted private key in PKCS#8 format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ echo password > passphrase.txt
+ openssl pkcs8 -topk8 -passout file:passphrase.txt \
+ -in private.pem -out private_encrypted.pk8
+
+ The byte string returned by this function is the contents
+ of the private_encrypted.pk8 file.
+ """
+
+ return """-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQMwDgQIssadeQrYhhACAggABIIEyDNw3SV2b19yy4Q/
+kTbtJ/p2X2zKDqr7GgLeAowqqhcMfvprI7G8C0XtwxkR4SjMZUXNcmOwQB2kNKtK
+ZilCz6pSx81iUj4s1fU460XkhkIeV+F7aB2PsTG1oDfPCuzKFjT6EuSE6lFUH89r
+TRuHWMPseW7lrvEB5kNMFag5QxeKjsSCNkZWOT74o4fh3cEplgCEaA+nCclXU79m
+5rhaa9e1SUpPuPlhnAIDkBtHcC38B+SOYKQxLdZT1f72oZ1ozWJ4bEhKxvnNu5J+
+tCvgWOXMIEJVGgf8Cu58PoR18LyyAIk7zza+1LkCiyuLNgiz8a1sVw8uBcrVgD5R
+8f4XgI/Yjb16Bmpp/0iEjNcURaby9GnCCEc+W/ivSJTnG3o1Xn00FO98l2aggNpt
+S8gxK05NeCtdWoFFjTeIXxnb1ct0Iep8RwuO+FnupAf6aw12Uqj4qYNvNiY/kBhS
+P/Yd3KznasrolUZ9+PVTMUI45UTMN/XhNvXrozMq9nItWTV7wHyEL3mrYipvcxrm
+SnLlAp2zkmSu923cHN1teLE99/rV2jaBM03ROqvYWaxjfOjxfwz6PhdE8G//kWd0
+tf2Om+fyCkBRxo1sUcuiE79hJXgP5KJCMbPsDyG/aQk4oeS1nbn15AhthwiU7A13
+h9X6asgV2H+4Ljf+tr1b8p3qj3CSljfzoVErLqoHagjVB45WktHhrWbUSRpXSvPo
+Hh0LY62qxTa67gKjwarH5hYr5IaH39iR9bcyuvzE+u9TJWvWmeLJ7UmesfVPZtSf
+/JTpvr0zu4C95lXKt4FdxOhGcWwDN1Zp+lCsF5ruBGc+/pEggiXi1qvW9xUny1Of
+8NqdPxGPb4/zPHGaysypPsc6LiY3esI8wa7FnDsS4e79dWinD/BPWEa5N2jLm0Rr
+njkHTy0xtnw/a8Ofrtyy9V1tBBOCaswzGIZZj6oHyFCtAvjZuYa8TWVmSi6EqJKi
+lY5wSdQQXg3H0HnQYivtOY1YbfjtRkUB9e4xkSVhvYJpY1QWBtApdUGBsxsELkDC
+6cv/Kxnd9U7dz9+VhD0hAdrhFqbWqOEGTWt7xE44yzWokdKQWu5FsTs6gyXsGPen
+ZgZlR5pjPNGbMdftW0M473YyvtzjrCuSVgJspCzpA9uo6wfejaFb4RF/tcWtXglE
+Q5FzfsO1OZr6nONraShj9N1kxGBXUUOtAjZI/zoTWk3yndxw3IpvPtDTg9ByCp7F
+RFUtDyrki+YAIAiTgPq7qwc1upjU7R1Zlg4jIe0RI9A73NyLwa4QhgO+HmRBt7At
+LLuUeCFKuXMBHzlDaMYwq5ZPOb8VcMkhUoug2YJIc4YOOHh5O0mYnat0vaYO+A58
+DiuYgxKmO5+6+OMk2ovZgk1sFawR4rk9HUt8goUUptZ+hoHUVGtte5YcQniIOcds
+qY3ni/zwswHWQRaAu8Ej4qJKt1XwZo2K04xHhL90TMaY8NpLSMCfVqDDL409TqIj
+zHUfYl6N2Me4eKc8vl6Sm63g57NzLqTttD6KSn8v+OmUF5mOQwcLnr3nK7S+BQfI
+DLPY1Oh7Kec/M/d1080/Qv9YBAJhz50TLKoxXwVeH4OOvuaHVaotElMkr5QEkEXl
+gRgwkbMrQjg0II0O9g==
+-----END ENCRYPTED PRIVATE KEY-----"""
+
+
+def get_passphrase_txt():
+ """Returns the plain text string used to encrypt the private key
+
+ This key was created by issuing the following commands:
+
+ echo password > passphrase.txt
+
+ The byte string returned by this function is the contents
+ of the passphrase.txt file.
+ """
+
+ return """password"""
+
+
+def get_csr_pem():
+ """Returns a Certificate Signing Request (CSR) in PEM format
+
+ This key was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl req -new -key private.pem -out csr.pem -subj '/CN=example.com'
+
+ The byte string returned by this function is the contents
+ of the csr.pem file.
+ """
+
+ return """-----BEGIN CERTIFICATE REQUEST-----
+MIICWzCCAUMCAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCza2VoDXmBUMmwjFu9F6MM5q/AZ1WjnWA2YNdN
+y237TrGN/nobDDv8FBBpUPmHNZ04H1LyxFcP8ReFrcIXpifsReu2lAWaqRPxovu5
+CuAhfecKv+RhjLVLJ0I+MZIb72ROKpfZTmb7dhlFgGD3vkC51BCfhGVW35w52OY/
+23x5MeO4yvx5myPccnxMVQ42KuDrzKqjBlSjmBncpGYx0JgCT+syFmHsl8rOkqCP
+PFLo24YQn+4/pr1AYwaZAbMTl9zoLtEQj6sxScuHcS9e8niptDxlsbLQgqGVaGdE
+117stC95QH7UvITbuYzdjZwBFc1Sgz8GZ/2hLSsHujJiIQcvAgMBAAGgADANBgkq
+hkiG9w0BAQsFAAOCAQEAPJDIxzgtUDRgpfTbTOPDJYap+Lm4jYxsCuAFbYiQ43B+
+c7RyzEFOB2anrldTm3XzNytHZAkRTnN4dH09p1K1Pyepv+weSv8rvN9OohfYgpcj
+wQqw8ksdGb3Q6oPnTgGxmWvV4PbzHmDnOvOiQ+wuBHWXYks6tdgU7iCZ1djYibmL
+1j+XEvtstou8gu1lWhzH6tStwmA9udncg5rEvfDUDyvMN3T06QFqrlK9K1TXIlbM
+RvUDrBjINIOuEeZ/5czjBl1CX1Z1YqdunrPiCQM4+oUAtjyD6ZAsyAEXLKdSYtKZ
+hSZgIl7v+UAIM+9bhpVg15aTjRzfH2OsZodFIbsMDw==
+-----END CERTIFICATE REQUEST-----"""
+
+
+def get_certificate_pem():
+ """Returns an X509 certificate in PEM format
+
+ This certificate was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl req -new -x509 -key private.pem -out cert.pem \
+ -days 1000 -subj '/CN=example.com'
+
+ The byte string returned by this function is the contents
+ of the cert.pem file.
+ """
+
+ return """-----BEGIN CERTIFICATE-----
+MIIC/zCCAeegAwIBAgIJAOLqXKJ9q9/nMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV
+BAMMC2V4YW1wbGUuY29tMB4XDTE1MDQxMTAyMTUyOVoXDTE4MDEwNTAyMTUyOVow
+FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCza2VoDXmBUMmwjFu9F6MM5q/AZ1WjnWA2YNdNy237TrGN/nobDDv8
+FBBpUPmHNZ04H1LyxFcP8ReFrcIXpifsReu2lAWaqRPxovu5CuAhfecKv+RhjLVL
+J0I+MZIb72ROKpfZTmb7dhlFgGD3vkC51BCfhGVW35w52OY/23x5MeO4yvx5myPc
+cnxMVQ42KuDrzKqjBlSjmBncpGYx0JgCT+syFmHsl8rOkqCPPFLo24YQn+4/pr1A
+YwaZAbMTl9zoLtEQj6sxScuHcS9e8niptDxlsbLQgqGVaGdE117stC95QH7UvITb
+uYzdjZwBFc1Sgz8GZ/2hLSsHujJiIQcvAgMBAAGjUDBOMB0GA1UdDgQWBBSUq2A0
+b2Xo+sKvmKgN8Wq8l6j82jAfBgNVHSMEGDAWgBSUq2A0b2Xo+sKvmKgN8Wq8l6j8
+2jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBjiuqhlzNVOVLrHDQy
+Gr0fTACFJdDREnuhZp4d91++DmMCT+bcTG0+GCp3rfFOuEWpJLLLPdSOnIsnibsO
+syKPXuBBX5kmdYIojbdjUTSwnhcx9JTAfKSmxXWSC0rnKCefAf44Mm6fqvoTyTbe
+GSQP6nHzc7eLaK/efcrMvYdct+TeTkHjqR8Lu4pjZvRdUQadQHhDyN+ONKdKD9Tr
+jvfPim0b7Aq885PjSN6Qo4Z9HXR6+nK+bTz9HyUATMfDGNQt0L3vyfVxbNOxkCBc
+YI4hFtGfkOzd6B7r2sY1wGKdTLHkuT4m4/9A/SOzvnH+epnJqIS9jw+1iRj8xcDA
+6PNT
+-----END CERTIFICATE-----
+"""
+
+
+def get_certificate_der():
+ """Returns an X509 certificate in DER format
+
+ This certificate was created by issuing the following openssl commands:
+
+ openssl genrsa -out private.pem 2048
+ openssl req -new -x509 -key private.pem -out cert.pem \
+ -days 1000 -subj '/CN=example.com'
+ openssl x509 -outform der -in cert.pem -out cert.der
+
+ The byte string returned by this function is the contents
+ of the cert.der file.
+ """
+ cert_der = (
+ '\x30\x82\x02\xff\x30\x82\x01\xe7\xa0\x03\x02\x01\x02\x02\x09'
+ '\x00\xe2\xea\x5c\xa2\x7d\xab\xdf\xe7\x30\x0d\x06\x09\x2a\x86'
+ '\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x16\x31\x14\x30\x12'
+ '\x06\x03\x55\x04\x03\x0c\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e'
+ '\x63\x6f\x6d\x30\x1e\x17\x0d\x31\x35\x30\x34\x31\x31\x30\x32'
+ '\x31\x35\x32\x39\x5a\x17\x0d\x31\x38\x30\x31\x30\x35\x30\x32'
+ '\x31\x35\x32\x39\x5a\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04'
+ '\x03\x0c\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30'
+ '\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01'
+ '\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01'
+ '\x01\x00\xb3\x6b\x65\x68\x0d\x79\x81\x50\xc9\xb0\x8c\x5b\xbd'
+ '\x17\xa3\x0c\xe6\xaf\xc0\x67\x55\xa3\x9d\x60\x36\x60\xd7\x4d'
+ '\xcb\x6d\xfb\x4e\xb1\x8d\xfe\x7a\x1b\x0c\x3b\xfc\x14\x10\x69'
+ '\x50\xf9\x87\x35\x9d\x38\x1f\x52\xf2\xc4\x57\x0f\xf1\x17\x85'
+ '\xad\xc2\x17\xa6\x27\xec\x45\xeb\xb6\x94\x05\x9a\xa9\x13\xf1'
+ '\xa2\xfb\xb9\x0a\xe0\x21\x7d\xe7\x0a\xbf\xe4\x61\x8c\xb5\x4b'
+ '\x27\x42\x3e\x31\x92\x1b\xef\x64\x4e\x2a\x97\xd9\x4e\x66\xfb'
+ '\x76\x19\x45\x80\x60\xf7\xbe\x40\xb9\xd4\x10\x9f\x84\x65\x56'
+ '\xdf\x9c\x39\xd8\xe6\x3f\xdb\x7c\x79\x31\xe3\xb8\xca\xfc\x79'
+ '\x9b\x23\xdc\x72\x7c\x4c\x55\x0e\x36\x2a\xe0\xeb\xcc\xaa\xa3'
+ '\x06\x54\xa3\x98\x19\xdc\xa4\x66\x31\xd0\x98\x02\x4f\xeb\x32'
+ '\x16\x61\xec\x97\xca\xce\x92\xa0\x8f\x3c\x52\xe8\xdb\x86\x10'
+ '\x9f\xee\x3f\xa6\xbd\x40\x63\x06\x99\x01\xb3\x13\x97\xdc\xe8'
+ '\x2e\xd1\x10\x8f\xab\x31\x49\xcb\x87\x71\x2f\x5e\xf2\x78\xa9'
+ '\xb4\x3c\x65\xb1\xb2\xd0\x82\xa1\x95\x68\x67\x44\xd7\x5e\xec'
+ '\xb4\x2f\x79\x40\x7e\xd4\xbc\x84\xdb\xb9\x8c\xdd\x8d\x9c\x01'
+ '\x15\xcd\x52\x83\x3f\x06\x67\xfd\xa1\x2d\x2b\x07\xba\x32\x62'
+ '\x21\x07\x2f\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06'
+ '\x03\x55\x1d\x0e\x04\x16\x04\x14\x94\xab\x60\x34\x6f\x65\xe8'
+ '\xfa\xc2\xaf\x98\xa8\x0d\xf1\x6a\xbc\x97\xa8\xfc\xda\x30\x1f'
+ '\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x94\xab\x60\x34'
+ '\x6f\x65\xe8\xfa\xc2\xaf\x98\xa8\x0d\xf1\x6a\xbc\x97\xa8\xfc'
+ '\xda\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff'
+ '\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00'
+ '\x03\x82\x01\x01\x00\x63\x8a\xea\xa1\x97\x33\x55\x39\x52\xeb'
+ '\x1c\x34\x32\x1a\xbd\x1f\x4c\x00\x85\x25\xd0\xd1\x12\x7b\xa1'
+ '\x66\x9e\x1d\xf7\x5f\xbe\x0e\x63\x02\x4f\xe6\xdc\x4c\x6d\x3e'
+ '\x18\x2a\x77\xad\xf1\x4e\xb8\x45\xa9\x24\xb2\xcb\x3d\xd4\x8e'
+ '\x9c\x8b\x27\x89\xbb\x0e\xb3\x22\x8f\x5e\xe0\x41\x5f\x99\x26'
+ '\x75\x82\x28\x8d\xb7\x63\x51\x34\xb0\x9e\x17\x31\xf4\x94\xc0'
+ '\x7c\xa4\xa6\xc5\x75\x92\x0b\x4a\xe7\x28\x27\x9f\x01\xfe\x38'
+ '\x32\x6e\x9f\xaa\xfa\x13\xc9\x36\xde\x19\x24\x0f\xea\x71\xf3'
+ '\x73\xb7\x8b\x68\xaf\xde\x7d\xca\xcc\xbd\x87\x5c\xb7\xe4\xde'
+ '\x4e\x41\xe3\xa9\x1f\x0b\xbb\x8a\x63\x66\xf4\x5d\x51\x06\x9d'
+ '\x40\x78\x43\xc8\xdf\x8e\x34\xa7\x4a\x0f\xd4\xeb\x8e\xf7\xcf'
+ '\x8a\x6d\x1b\xec\x0a\xbc\xf3\x93\xe3\x48\xde\x90\xa3\x86\x7d'
+ '\x1d\x74\x7a\xfa\x72\xbe\x6d\x3c\xfd\x1f\x25\x00\x4c\xc7\xc3'
+ '\x18\xd4\x2d\xd0\xbd\xef\xc9\xf5\x71\x6c\xd3\xb1\x90\x20\x5c'
+ '\x60\x8e\x21\x16\xd1\x9f\x90\xec\xdd\xe8\x1e\xeb\xda\xc6\x35'
+ '\xc0\x62\x9d\x4c\xb1\xe4\xb9\x3e\x26\xe3\xff\x40\xfd\x23\xb3'
+ '\xbe\x71\xfe\x7a\x99\xc9\xa8\x84\xbd\x8f\x0f\xb5\x89\x18\xfc'
+ '\xc5\xc0\xc0\xe8\xf3\x53')
+ return cert_der