NewProvisioningSession expects pkcs8 private key and SHA race fix
------------- Fix SHA hashing to remove race condition. This change fixes the implementation by passing in the digest buffer. ------------- The input to ProvisioningEngine::NewProvisioningSession should be pkcs8 private key instead of pkcs1 private key ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=151273394 Change-Id: Ibcdff7757b2ac2878ee8b1b88365083964bfa10a
This commit is contained in:
@@ -15,10 +15,19 @@ py_binary(
|
||||
srcs = ["oem_certificate.py"],
|
||||
)
|
||||
|
||||
py_library(
|
||||
name = "oem_certificate_generator_helper",
|
||||
srcs = ["oem_certificate_generator_helper.py"],
|
||||
deps = [
|
||||
":oem_certificate",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "oem_certificate_test",
|
||||
srcs = ["oem_certificate_test.py"],
|
||||
deps = [
|
||||
":oem_certificate",
|
||||
":oem_certificate_generator_helper",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -196,8 +196,8 @@ def _random_serial_number():
|
||||
return utils.int_from_bytes(os.urandom(16), byteorder='big')
|
||||
|
||||
|
||||
def _build_certificate(subject_name, issuer_name, system_id, not_valid_before,
|
||||
valid_duration, public_key, signing_key, ca):
|
||||
def build_certificate(subject_name, issuer_name, system_id, not_valid_before,
|
||||
valid_duration, public_key, signing_key, ca):
|
||||
"""Utility function to build certificate."""
|
||||
builder = x509.CertificateBuilder()
|
||||
builder = builder.subject_name(subject_name).issuer_name(issuer_name)
|
||||
@@ -237,10 +237,10 @@ def generate_intermediate_certificate(args):
|
||||
raise ValueError('Root certificate does not match with root private key')
|
||||
csr = x509.load_pem_x509_csr(args.csr_file.read(), backends.default_backend())
|
||||
|
||||
certificate = _build_certificate(csr.subject, root_cert.subject,
|
||||
args.system_id, args.not_valid_before,
|
||||
args.valid_duration,
|
||||
csr.public_key(), root_private_key, True)
|
||||
certificate = build_certificate(csr.subject, root_cert.subject,
|
||||
args.system_id, args.not_valid_before,
|
||||
args.valid_duration,
|
||||
csr.public_key(), root_private_key, True)
|
||||
args.output_certificate_file.write(
|
||||
certificate.public_bytes(serialization.Encoding.DER))
|
||||
|
||||
@@ -282,11 +282,11 @@ def generate_leaf_certificate(args):
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=_get_encryption_algorithm(args.passphrase)))
|
||||
|
||||
certificate = _build_certificate(subject_name, intermediate_cert.subject,
|
||||
system_id, args.not_valid_before,
|
||||
args.valid_duration,
|
||||
leaf_private_key.public_key(),
|
||||
intermediate_private_key, False)
|
||||
certificate = build_certificate(subject_name, intermediate_cert.subject,
|
||||
system_id, args.not_valid_before,
|
||||
args.valid_duration,
|
||||
leaf_private_key.public_key(),
|
||||
intermediate_private_key, False)
|
||||
args.output_certificate_file.write(
|
||||
X509CertificateChain([certificate, intermediate_cert]).der_bytes())
|
||||
|
||||
|
||||
154
oem_certificate_generator/oem_certificate_generator_helper.py
Normal file
154
oem_certificate_generator/oem_certificate_generator_helper.py
Normal file
@@ -0,0 +1,154 @@
|
||||
################################################################################
|
||||
# Copyright 2017 Google Inc.
|
||||
#
|
||||
# This software is licensed under the terms defined in the Widevine Master
|
||||
# License Agreement. For a copy of this agreement, please contact
|
||||
# widevine-licensing@google.com.
|
||||
################################################################################
|
||||
|
||||
"""Common utility functions for OEM certificate generation."""
|
||||
|
||||
import datetime
|
||||
import StringIO
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat import backends
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.x509 import oid
|
||||
|
||||
import oem_certificate
|
||||
|
||||
_COUNTRY_NAME = 'US'
|
||||
_STATE_OR_PROVINCE_NAME = 'WA'
|
||||
_LOCALITY_NAME = 'Kirkland'
|
||||
_ORGANIZATION_NAME = 'CompanyXYZ'
|
||||
_ORGANIZATIONAL_UNIT_NAME = 'ContentProtection'
|
||||
|
||||
|
||||
_NOT_VALID_BEFORE = datetime.datetime(2001, 8, 9)
|
||||
_VALID_DURATION = 100
|
||||
_LEAF_CERT_VALID_DURATION = 8000
|
||||
_SYSTEM_ID = 2001
|
||||
_ROOT_PRIVATE_KEY_PASSPHRASE = 'root_passphrase'
|
||||
|
||||
|
||||
class ArgParseObject(object):
|
||||
"""A convenient object to allow adding arbitrary attribute to it."""
|
||||
|
||||
|
||||
def create_root_certificate_and_key():
|
||||
"""Creates a root certificate and key."""
|
||||
key = rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=3072,
|
||||
backend=backends.default_backend())
|
||||
subject_name = x509.Name(
|
||||
[x509.NameAttribute(oid.NameOID.COMMON_NAME, u'root_cert')])
|
||||
certificate = oem_certificate.build_certificate(
|
||||
subject_name, subject_name, None,
|
||||
datetime.datetime(2001, 8, 9), 1000, key.public_key(), key, True)
|
||||
return (key, certificate)
|
||||
|
||||
|
||||
def setup_csr_rgs(country_name=_COUNTRY_NAME,
|
||||
state_or_province_name=_STATE_OR_PROVINCE_NAME,
|
||||
locality_name=_LOCALITY_NAME,
|
||||
organization_name=_ORGANIZATION_NAME,
|
||||
organizational_unit_name=_ORGANIZATIONAL_UNIT_NAME,
|
||||
key_size=4096,
|
||||
output_csr_file=None,
|
||||
output_private_key_file=None,
|
||||
passphrase=None):
|
||||
"""Sets up arguments to OEM Certificate generator for generating csr."""
|
||||
args = ArgParseObject()
|
||||
args.key_size = key_size
|
||||
args.country_name = country_name
|
||||
args.state_or_province_name = state_or_province_name
|
||||
args.locality_name = locality_name
|
||||
args.organization_name = organization_name
|
||||
args.organizational_unit_name = organizational_unit_name
|
||||
if output_csr_file:
|
||||
args.output_csr_file = output_csr_file
|
||||
else:
|
||||
args.output_csr_file = StringIO.StringIO()
|
||||
if output_private_key_file:
|
||||
args.output_private_key_file = output_private_key_file
|
||||
else:
|
||||
args.output_private_key_file = StringIO.StringIO()
|
||||
args.passphrase = passphrase
|
||||
return args
|
||||
|
||||
|
||||
def setup_intermediate_cert_args(
|
||||
csr_bytes, root_key, root_certificate, not_valid_before=_NOT_VALID_BEFORE,
|
||||
valid_duration=_VALID_DURATION, system_id=_SYSTEM_ID,
|
||||
root_private_key_passphrase=_ROOT_PRIVATE_KEY_PASSPHRASE,
|
||||
output_certificate_file=None):
|
||||
"""Sets up args to OEM Cert generator for generating intermediate cert."""
|
||||
args = ArgParseObject()
|
||||
args.not_valid_before = not_valid_before
|
||||
args.valid_duration = valid_duration
|
||||
args.system_id = system_id
|
||||
args.csr_file = StringIO.StringIO(csr_bytes)
|
||||
args.root_private_key_passphrase = root_private_key_passphrase
|
||||
if output_certificate_file:
|
||||
args.output_certificate_file = output_certificate_file
|
||||
else:
|
||||
args.output_certificate_file = StringIO.StringIO()
|
||||
|
||||
serialized_private_key = root_key.private_bytes(
|
||||
serialization.Encoding.DER,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.BestAvailableEncryption(
|
||||
args.root_private_key_passphrase))
|
||||
serialized_certificate = root_certificate.public_bytes(
|
||||
serialization.Encoding.DER)
|
||||
args.root_certificate_file = StringIO.StringIO(serialized_certificate)
|
||||
args.root_private_key_file = StringIO.StringIO(serialized_private_key)
|
||||
return args
|
||||
|
||||
|
||||
def setup_leaf_cert_args(intermediate_key_bytes,
|
||||
intermediate_certificate_bytes,
|
||||
key_size=1024,
|
||||
passphrase=None,
|
||||
not_valid_before=_NOT_VALID_BEFORE,
|
||||
valid_duration=_LEAF_CERT_VALID_DURATION,
|
||||
output_certificate_file=None,
|
||||
output_private_key_file=None):
|
||||
"""Sets up args to OEM Certificate generator for generating leaf cert."""
|
||||
args = ArgParseObject()
|
||||
args.key_size = key_size
|
||||
args.not_valid_before = not_valid_before
|
||||
args.valid_duration = valid_duration
|
||||
args.intermediate_private_key_passphrase = None
|
||||
if output_certificate_file:
|
||||
args.output_certificate_file = output_certificate_file
|
||||
else:
|
||||
args.output_certificate_file = StringIO.StringIO()
|
||||
if output_private_key_file:
|
||||
args.output_private_key_file = output_private_key_file
|
||||
else:
|
||||
args.output_private_key_file = StringIO.StringIO()
|
||||
args.passphrase = passphrase
|
||||
|
||||
args.intermediate_private_key_file = StringIO.StringIO(
|
||||
intermediate_key_bytes)
|
||||
args.intermediate_certificate_file = StringIO.StringIO(
|
||||
intermediate_certificate_bytes)
|
||||
return args
|
||||
|
||||
|
||||
def create_intermediate_certificate_and_key_bytes(key_size=4096,
|
||||
passphrase=None):
|
||||
"""Creates an intermediate certificate and key."""
|
||||
csr_args = setup_csr_rgs(key_size=key_size, passphrase=passphrase)
|
||||
oem_certificate.generate_csr(csr_args)
|
||||
csr_bytes = csr_args.output_csr_file.getvalue()
|
||||
|
||||
root_key, root_certificate = create_root_certificate_and_key()
|
||||
args = setup_intermediate_cert_args(csr_bytes, root_key, root_certificate)
|
||||
oem_certificate.generate_intermediate_certificate(args)
|
||||
return (csr_args.output_private_key_file.getvalue(),
|
||||
args.output_certificate_file.getvalue())
|
||||
@@ -18,10 +18,10 @@ from cryptography import x509
|
||||
from cryptography.hazmat import backends
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.x509 import oid
|
||||
|
||||
import oem_certificate
|
||||
import oem_certificate_generator_helper as oem_cert_gen_helper
|
||||
|
||||
|
||||
class ArgParseObject(object):
|
||||
@@ -31,19 +31,6 @@ class ArgParseObject(object):
|
||||
|
||||
class OemCertificateTest(unittest.TestCase):
|
||||
|
||||
def _setup_csr_args(self, key_size=4096, passphrase=None):
|
||||
args = ArgParseObject()
|
||||
args.key_size = key_size
|
||||
args.country_name = 'US'
|
||||
args.state_or_province_name = 'WA'
|
||||
args.locality_name = 'Kirkland'
|
||||
args.organization_name = 'CompanyXYZ'
|
||||
args.organizational_unit_name = 'ContentProtection'
|
||||
args.output_csr_file = StringIO.StringIO()
|
||||
args.output_private_key_file = StringIO.StringIO()
|
||||
args.passphrase = passphrase
|
||||
return args
|
||||
|
||||
def test_widevine_system_id(self):
|
||||
system_id = 1234567890123
|
||||
self.assertEqual(
|
||||
@@ -51,7 +38,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
system_id)
|
||||
|
||||
def test_generate_csr(self):
|
||||
args = self._setup_csr_args()
|
||||
args = oem_cert_gen_helper.setup_csr_rgs()
|
||||
oem_certificate.generate_csr(args)
|
||||
# Verify CSR.
|
||||
csr = x509.load_pem_x509_csr(args.output_csr_file.getvalue(),
|
||||
@@ -84,7 +71,8 @@ class OemCertificateTest(unittest.TestCase):
|
||||
private_key.public_key().public_numbers())
|
||||
|
||||
def test_generate_csr_with_keysize4096_and_passphrase(self):
|
||||
args = self._setup_csr_args(key_size=4096, passphrase='passphrase_4096')
|
||||
args = oem_cert_gen_helper.setup_csr_rgs(
|
||||
key_size=4096, passphrase='passphrase_4096')
|
||||
oem_certificate.generate_csr(args)
|
||||
private_key = serialization.load_der_private_key(
|
||||
args.output_private_key_file.getvalue(),
|
||||
@@ -98,49 +86,16 @@ class OemCertificateTest(unittest.TestCase):
|
||||
self.assertEqual(csr.public_key().public_numbers(),
|
||||
private_key.public_key().public_numbers())
|
||||
|
||||
def _create_root_certificate_and_key(self):
|
||||
key = rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=3072,
|
||||
backend=backends.default_backend())
|
||||
subject_name = x509.Name(
|
||||
[x509.NameAttribute(oid.NameOID.COMMON_NAME, u'root_cert')])
|
||||
certificate = oem_certificate._build_certificate(
|
||||
subject_name, subject_name, None,
|
||||
datetime.datetime(2001, 8, 9), 1000, key.public_key(), key, True)
|
||||
return (key, certificate)
|
||||
|
||||
def _setup_intermediate_cert_args(self, csr_bytes, root_key,
|
||||
root_certificate):
|
||||
args = ArgParseObject()
|
||||
args.not_valid_before = datetime.datetime(2001, 8, 9)
|
||||
args.valid_duration = 100
|
||||
args.system_id = 1234554321
|
||||
args.csr_file = StringIO.StringIO(csr_bytes)
|
||||
args.root_private_key_passphrase = 'root_passphrase'
|
||||
args.output_certificate_file = StringIO.StringIO()
|
||||
|
||||
serialized_private_key = root_key.private_bytes(
|
||||
serialization.Encoding.DER,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.BestAvailableEncryption(
|
||||
args.root_private_key_passphrase))
|
||||
serialized_certificate = root_certificate.public_bytes(
|
||||
serialization.Encoding.DER)
|
||||
|
||||
args.root_certificate_file = StringIO.StringIO(serialized_certificate)
|
||||
args.root_private_key_file = StringIO.StringIO(serialized_private_key)
|
||||
return args
|
||||
|
||||
def test_generate_intermediate_certificate(self):
|
||||
csr_args = self._setup_csr_args()
|
||||
csr_args = oem_cert_gen_helper.setup_csr_rgs()
|
||||
oem_certificate.generate_csr(csr_args)
|
||||
csr_bytes = csr_args.output_csr_file.getvalue()
|
||||
csr = x509.load_pem_x509_csr(csr_bytes, backends.default_backend())
|
||||
|
||||
root_key, root_certificate = self._create_root_certificate_and_key()
|
||||
args = self._setup_intermediate_cert_args(csr_bytes, root_key,
|
||||
root_certificate)
|
||||
root_key, root_certificate = (
|
||||
oem_cert_gen_helper.create_root_certificate_and_key())
|
||||
args = oem_cert_gen_helper.setup_intermediate_cert_args(
|
||||
csr_bytes, root_key, root_certificate)
|
||||
oem_certificate.generate_intermediate_certificate(args)
|
||||
|
||||
cert = x509.load_der_x509_certificate(
|
||||
@@ -162,53 +117,20 @@ class OemCertificateTest(unittest.TestCase):
|
||||
cert.signature_hash_algorithm)
|
||||
|
||||
def test_generate_intermediate_with_cert_mismatch_root_cert_and_key(self):
|
||||
root_key1, _ = self._create_root_certificate_and_key()
|
||||
_, root_certificate2 = self._create_root_certificate_and_key()
|
||||
args = self._setup_intermediate_cert_args('some csr data', root_key1,
|
||||
root_certificate2)
|
||||
root_key1, _ = (
|
||||
oem_cert_gen_helper.create_root_certificate_and_key())
|
||||
_, root_certificate2 = oem_cert_gen_helper.create_root_certificate_and_key()
|
||||
args = oem_cert_gen_helper.setup_intermediate_cert_args(
|
||||
'some csr data', root_key1, root_certificate2)
|
||||
with self.assertRaises(ValueError) as context:
|
||||
oem_certificate.generate_intermediate_certificate(args)
|
||||
self.assertTrue('certificate does not match' in str(context.exception))
|
||||
|
||||
def _setup_leaf_cert_args(self,
|
||||
intermediate_key_bytes,
|
||||
intermediate_certificate_bytes,
|
||||
key_size=1024,
|
||||
passphrase=None):
|
||||
args = ArgParseObject()
|
||||
args.key_size = key_size
|
||||
args.not_valid_before = datetime.datetime(2001, 8, 9)
|
||||
args.valid_duration = 8000
|
||||
args.intermediate_private_key_passphrase = None
|
||||
args.output_certificate_file = StringIO.StringIO()
|
||||
args.output_private_key_file = StringIO.StringIO()
|
||||
args.passphrase = passphrase
|
||||
|
||||
args.intermediate_private_key_file = StringIO.StringIO(
|
||||
intermediate_key_bytes)
|
||||
args.intermediate_certificate_file = StringIO.StringIO(
|
||||
intermediate_certificate_bytes)
|
||||
return args
|
||||
|
||||
def _create_intermediate_certificate_and_key_bytes(self,
|
||||
key_size=4096,
|
||||
passphrase=None):
|
||||
csr_args = self._setup_csr_args(key_size, passphrase)
|
||||
oem_certificate.generate_csr(csr_args)
|
||||
csr_bytes = csr_args.output_csr_file.getvalue()
|
||||
|
||||
root_key, root_certificate = self._create_root_certificate_and_key()
|
||||
args = self._setup_intermediate_cert_args(csr_bytes, root_key,
|
||||
root_certificate)
|
||||
oem_certificate.generate_intermediate_certificate(args)
|
||||
return (csr_args.output_private_key_file.getvalue(),
|
||||
args.output_certificate_file.getvalue())
|
||||
|
||||
def test_generate_leaf_certificate(self):
|
||||
intermediate_key_bytes, intermediate_certificate_bytes = (
|
||||
self._create_intermediate_certificate_and_key_bytes())
|
||||
args = self._setup_leaf_cert_args(intermediate_key_bytes,
|
||||
intermediate_certificate_bytes)
|
||||
oem_cert_gen_helper.create_intermediate_certificate_and_key_bytes())
|
||||
args = oem_cert_gen_helper.setup_leaf_cert_args(
|
||||
intermediate_key_bytes, intermediate_certificate_bytes)
|
||||
oem_certificate.generate_leaf_certificate(args)
|
||||
|
||||
certificate_chain = oem_certificate.X509CertificateChain.load_der(
|
||||
@@ -233,7 +155,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
oem_certificate.WidevineSystemId.oid).value.value
|
||||
self.assertEqual(
|
||||
oem_certificate.WidevineSystemId(system_id_raw_bytes).int_value(),
|
||||
1234554321)
|
||||
2001)
|
||||
|
||||
leaf_key = serialization.load_der_private_key(
|
||||
args.output_private_key_file.getvalue(),
|
||||
@@ -247,8 +169,8 @@ class OemCertificateTest(unittest.TestCase):
|
||||
|
||||
def test_generate_leaf_certificate_with_keysize4096_and_passphrase(self):
|
||||
intermediate_key_bytes, intermediate_certificate_bytes = (
|
||||
self._create_intermediate_certificate_and_key_bytes())
|
||||
args = self._setup_leaf_cert_args(
|
||||
oem_cert_gen_helper.create_intermediate_certificate_and_key_bytes())
|
||||
args = oem_cert_gen_helper.setup_leaf_cert_args(
|
||||
intermediate_key_bytes,
|
||||
intermediate_certificate_bytes,
|
||||
key_size=4096,
|
||||
@@ -261,7 +183,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
self.assertEqual(4096, args.key_size)
|
||||
|
||||
def test_get_csr_info(self):
|
||||
args = self._setup_csr_args()
|
||||
args = oem_cert_gen_helper.setup_csr_rgs()
|
||||
oem_certificate.generate_csr(args)
|
||||
args.file = StringIO.StringIO(args.output_csr_file.getvalue())
|
||||
output = StringIO.StringIO()
|
||||
@@ -278,7 +200,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
|
||||
def test_get_certificate_info(self):
|
||||
_, intermediate_certificate_bytes = (
|
||||
self._create_intermediate_certificate_and_key_bytes())
|
||||
oem_cert_gen_helper.create_intermediate_certificate_and_key_bytes())
|
||||
args = ArgParseObject()
|
||||
args.file = StringIO.StringIO(intermediate_certificate_bytes)
|
||||
output = StringIO.StringIO()
|
||||
@@ -293,23 +215,23 @@ class OemCertificateTest(unittest.TestCase):
|
||||
Issuer Name:
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
|
||||
Key Size: 4096
|
||||
Widevine System Id: 1234554321
|
||||
Widevine System Id: 2001
|
||||
Not valid before: 2001-08-09 00:00:00
|
||||
Not valid after: 2001-11-17 00:00:00"""
|
||||
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
|
||||
|
||||
def test_get_certificate_chain_info(self):
|
||||
intermediate_key_bytes, intermediate_certificate_bytes = (
|
||||
self._create_intermediate_certificate_and_key_bytes())
|
||||
args = self._setup_leaf_cert_args(intermediate_key_bytes,
|
||||
intermediate_certificate_bytes)
|
||||
oem_cert_gen_helper.create_intermediate_certificate_and_key_bytes())
|
||||
args = oem_cert_gen_helper.setup_leaf_cert_args(
|
||||
intermediate_key_bytes, intermediate_certificate_bytes)
|
||||
oem_certificate.generate_leaf_certificate(args)
|
||||
args.file = StringIO.StringIO(args.output_certificate_file.getvalue())
|
||||
output = StringIO.StringIO()
|
||||
oem_certificate.get_info(args, output)
|
||||
expected_info = """\
|
||||
Certificate Subject Name:
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'1234554321-leaf')>
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'2001-leaf')>
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
|
||||
@@ -322,7 +244,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
|
||||
Key Size: 1024
|
||||
Widevine System Id: 1234554321
|
||||
Widevine System Id: 2001
|
||||
Not valid before: 2001-08-09 00:00:00
|
||||
Not valid after: 2023-07-05 00:00:00
|
||||
|
||||
@@ -335,7 +257,7 @@ class OemCertificateTest(unittest.TestCase):
|
||||
Issuer Name:
|
||||
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
|
||||
Key Size: 4096
|
||||
Widevine System Id: 1234554321
|
||||
Widevine System Id: 2001
|
||||
Not valid before: 2001-08-09 00:00:00
|
||||
Not valid after: 2001-11-17 00:00:00"""
|
||||
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
|
||||
|
||||
Reference in New Issue
Block a user