aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-10-29 19:20:10 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-10-29 19:20:10 +0000
commitf647b415f656223003dfdac296da4d1393e5c200 (patch)
tree951b5e9d3a2406aacba331f73e047ea99d6704a5
parentd2e35bcae5e127a2df338ed99a53f47c2047d970 (diff)
parentb92eb88d3209fb2f0b7fe71c02b4d672c8f2d5e5 (diff)
downloadasn1crypto-f647b415f656223003dfdac296da4d1393e5c200.tar.gz
Upgrade python/asn1crypto to 1.4.0 am: 2b20719855 am: 47da9b5dc5 am: 84d95d24f2 am: b92eb88d32
Original change: https://android-review.googlesource.com/c/platform/external/python/asn1crypto/+/1479353 Change-Id: I5f64894cf60d21f316b6d1411c66794fede0fdf6
-rw-r--r--.circleci/config.yml17
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.travis.yml5
-rw-r--r--METADATA6
-rw-r--r--asn1crypto/core.py26
-rw-r--r--asn1crypto/keys.py2
-rw-r--r--asn1crypto/version.py4
-rw-r--r--asn1crypto/x509.py2
-rw-r--r--changelog.md11
-rw-r--r--codecov.json3
-rw-r--r--dev/deps.py287
-rw-r--r--readme.md13
-rw-r--r--setup.py2
-rw-r--r--tests/__init__.py4
-rw-r--r--tests/setup.py5
-rw-r--r--tests/test_core.py37
-rw-r--r--tests/test_keys.py10
17 files changed, 345 insertions, 91 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 874d959..e135408 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -14,16 +14,13 @@ jobs:
xcode: 10.3.0
steps:
- checkout
- - restore_cache:
- keys:
- - homebrew
- - run: brew install pypy
- - save_cache:
- key: homebrew
- paths:
- - /usr/local/Homebrew
- - run: pypy run.py deps
- - run: pypy run.py ci
+ - run: curl --location -O https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.3.1-osx64.tar.bz2
+ - run: tar xvf pypy2.7-v7.3.1-osx64.tar.bz2
+ - run: mv pypy2.7-v7.3.1-osx64 pypy
+ - run: xattr -rc pypy
+ - run: ./pypy/bin/pypy -m ensurepip
+ - run: ./pypy/bin/pypy run.py deps
+ - run: ./pypy/bin/pypy run.py ci
workflows:
version: 2
python-26:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8180e66..e91e6d6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,5 +1,5 @@
name: CI
-on: [push]
+on: [push, pull_request]
jobs:
build:
diff --git a/.travis.yml b/.travis.yml
index 93c1a7f..eb0ca1a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,11 @@ matrix:
language: python
python: "3.7"
- os: linux
+ arch: ppc64le
+ dist: bionic
+ language: python
+ python: "3.7"
+ - os: linux
dist: xenial
language: python
python: "pypy"
diff --git a/METADATA b/METADATA
index 4b41dcd..02bee43 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/wbond/asn1crypto"
}
- version: "1.3.0"
+ version: "1.4.0"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 1
- day: 4
+ month: 10
+ day: 28
}
}
diff --git a/asn1crypto/core.py b/asn1crypto/core.py
index 933f8ca..7133367 100644
--- a/asn1crypto/core.py
+++ b/asn1crypto/core.py
@@ -3104,6 +3104,21 @@ class ObjectIdentifier(Primitive, ValueMap):
first = part
continue
elif index == 1:
+ if first > 2:
+ raise ValueError(unwrap(
+ '''
+ First arc must be one of 0, 1 or 2, not %s
+ ''',
+ repr(first)
+ ))
+ elif first < 2 and part >= 40:
+ raise ValueError(unwrap(
+ '''
+ Second arc must be less than 40 if first arc is 0 or
+ 1, not %s
+ ''',
+ repr(part)
+ ))
part = (first * 40) + part
encoded_part = chr_cls(0x7F & part)
@@ -3145,8 +3160,15 @@ class ObjectIdentifier(Primitive, ValueMap):
# Last byte in subidentifier has the eighth bit set to 0
if byte & 0x80 == 0:
if len(output) == 0:
- output.append(str_cls(part // 40))
- output.append(str_cls(part % 40))
+ if part >= 80:
+ output.append(str_cls(2))
+ output.append(str_cls(part - 80))
+ elif part >= 40:
+ output.append(str_cls(1))
+ output.append(str_cls(part - 40))
+ else:
+ output.append(str_cls(0))
+ output.append(str_cls(part))
else:
output.append(str_cls(part))
part = 0
diff --git a/asn1crypto/keys.py b/asn1crypto/keys.py
index 599929f..96b763e 100644
--- a/asn1crypto/keys.py
+++ b/asn1crypto/keys.py
@@ -1216,7 +1216,7 @@ class PublicKeyInfo(Sequence):
if self._bit_size is None:
if self.algorithm == 'ec':
- self._bit_size = ((len(self['public_key'].native) - 1) / 2) * 8
+ self._bit_size = int(((len(self['public_key'].native) - 1) / 2) * 8)
else:
if self.algorithm == 'rsa':
prime = self['public_key'].parsed['modulus'].native
diff --git a/asn1crypto/version.py b/asn1crypto/version.py
index b7c352c..3cf4892 100644
--- a/asn1crypto/version.py
+++ b/asn1crypto/version.py
@@ -2,5 +2,5 @@
from __future__ import unicode_literals, division, absolute_import, print_function
-__version__ = '1.3.0'
-__version_info__ = (1, 3, 0)
+__version__ = '1.4.0'
+__version_info__ = (1, 4, 0)
diff --git a/asn1crypto/x509.py b/asn1crypto/x509.py
index 2cce9a5..16f7deb 100644
--- a/asn1crypto/x509.py
+++ b/asn1crypto/x509.py
@@ -1136,7 +1136,7 @@ class Name(Choice):
"""
if isinstance(value, list):
- return', '.join(
+ return ', '.join(
reversed([self._recursive_humanize(sub_value) for sub_value in value])
)
return value.native
diff --git a/changelog.md b/changelog.md
index 67d1766..46eb459 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,16 @@
# changelog
+## 1.4.0
+
+ - `core.ObjectIdentifier` and all derived classes now obey X.660 ยง7.6 and
+ thus restrict the first arc to 0 to 2, and the second arc to less than
+ 40 if the first arc is 0 or 1. This also fixes parsing of OIDs where the
+ first arc is 2 and the second arc is greater than 39.
+ - Fixed `keys.PublicKeyInfo.bit_size` to return an int rather than a float
+ on Python 3 when working with elliptic curve keys
+ - Fixed the `asn1crypto-tests` sdist on PyPi to work properly to generate a
+ .whl
+
## 1.3.0
- Added `encrypt_key_pref` (`1.2.840.113549.1.9.16.2.11`) to
diff --git a/codecov.json b/codecov.json
index 2bec947..ad045a7 100644
--- a/codecov.json
+++ b/codecov.json
@@ -1,4 +1,5 @@
{
"slug": "wbond/asn1crypto",
- "token": "98876f5e-6517-4def-85ce-c6e508eee35a"
+ "token": "98876f5e-6517-4def-85ce-c6e508eee35a",
+ "disabled": true
}
diff --git a/dev/deps.py b/dev/deps.py
index 7014172..8f52336 100644
--- a/dev/deps.py
+++ b/dev/deps.py
@@ -96,7 +96,78 @@ def _tuple_from_ver(version_string):
A tuple of integers
"""
- return tuple(map(int, version_string.split('.')))
+ match = re.search(
+ r'(\d+(?:\.\d+)*)'
+ r'([-._]?(?:alpha|a|beta|b|preview|pre|c|rc)\.?\d*)?'
+ r'(-\d+|(?:[-._]?(?:rev|r|post)\.?\d*))?'
+ r'([-._]?dev\.?\d*)?',
+ version_string
+ )
+ if not match:
+ return tuple()
+
+ nums = tuple(map(int, match.group(1).split('.')))
+
+ pre = match.group(2)
+ if pre:
+ pre = pre.replace('alpha', 'a')
+ pre = pre.replace('beta', 'b')
+ pre = pre.replace('preview', 'rc')
+ pre = pre.replace('pre', 'rc')
+ pre = re.sub(r'(?<!r)c', 'rc', pre)
+ pre = pre.lstrip('._-')
+ pre_dig_match = re.search(r'\d+', pre)
+ if pre_dig_match:
+ pre_dig = int(pre_dig_match.group(0))
+ else:
+ pre_dig = 0
+ pre = pre.rstrip('0123456789')
+
+ pre_num = {
+ 'a': -3,
+ 'b': -2,
+ 'rc': -1,
+ }[pre]
+
+ pre_tup = (pre_num, pre_dig)
+ else:
+ pre_tup = tuple()
+
+ post = match.group(3)
+ if post:
+ post_dig_match = re.search(r'\d+', post)
+ if post_dig_match:
+ post_dig = int(post_dig_match.group(0))
+ else:
+ post_dig = 0
+ post_tup = (1, post_dig)
+ else:
+ post_tup = tuple()
+
+ dev = match.group(4)
+ if dev:
+ dev_dig_match = re.search(r'\d+', dev)
+ if dev_dig_match:
+ dev_dig = int(dev_dig_match.group(0))
+ else:
+ dev_dig = 0
+ dev_tup = (-4, dev_dig)
+ else:
+ dev_tup = tuple()
+
+ normalized = [nums]
+ if pre_tup:
+ normalized.append(pre_tup)
+ if post_tup:
+ normalized.append(post_tup)
+ if dev_tup:
+ normalized.append(dev_tup)
+ # This ensures regular releases happen after dev and prerelease, but
+ # before post releases
+ if not pre_tup and not post_tup and not dev_tup:
+ normalized.append((0, 0))
+
+ return tuple(normalized)
def _open_archive(path):
@@ -309,17 +380,99 @@ def _extract_package(deps_dir, pkg_path, pkg_dir):
shutil.rmtree(staging_dir)
-def _stage_requirements(deps_dir, path):
+def _sort_pep440_versions(releases, include_prerelease):
"""
- Installs requirements without using Python to download, since
- different services are limiting to TLS 1.2, and older version of
- Python do not support that
+ :param releases:
+ A list of unicode string PEP 440 version numbers
- :param deps_dir:
- A unicode path to a temporary diretory to use for downloads
+ :param include_prerelease:
+ A boolean indicating if prerelease versions should be included
- :param path:
- A unicode filesystem path to a requirements file
+ :return:
+ A sorted generator of 2-element tuples:
+ 0: A unicode string containing a PEP 440 version number
+ 1: A tuple of tuples containing integers - this is the output of
+ _tuple_from_ver() for the PEP 440 version number and is intended
+ for comparing versions
+ """
+
+ parsed_versions = []
+ for v in releases:
+ t = _tuple_from_ver(v)
+ if not include_prerelease and t[1][0] < 0:
+ continue
+ parsed_versions.append((v, t))
+
+ return sorted(parsed_versions, key=lambda v: v[1])
+
+
+def _is_valid_python_version(python_version, requires_python):
+ """
+ Verifies the "python_version" and "requires_python" keys from a PyPi
+ download record are applicable to the current version of Python
+
+ :param python_version:
+ The "python_version" value from a PyPi download JSON structure. This
+ should be one of: "py2", "py3", "py2.py3" or "source".
+
+ :param requires_python:
+ The "requires_python" value from a PyPi download JSON structure. This
+ will be None, or a comma-separated list of conditions that must be
+ true. Ex: ">=3.5", "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+ """
+
+ if python_version == "py2" and sys.version_info >= (3,):
+ return False
+ if python_version == "py3" and sys.version_info < (3,):
+ return False
+
+ if requires_python is not None:
+
+ def _ver_tuples(ver_str):
+ ver_str = ver_str.strip()
+ if ver_str.endswith('.*'):
+ ver_str = ver_str[:-2]
+ cond_tup = tuple(map(int, ver_str.split('.')))
+ return (sys.version_info[:len(cond_tup)], cond_tup)
+
+ for part in map(str_cls.strip, requires_python.split(',')):
+ if part.startswith('!='):
+ sys_tup, cond_tup = _ver_tuples(part[2:])
+ if sys_tup == cond_tup:
+ return False
+ elif part.startswith('>='):
+ sys_tup, cond_tup = _ver_tuples(part[2:])
+ if sys_tup < cond_tup:
+ return False
+ elif part.startswith('>'):
+ sys_tup, cond_tup = _ver_tuples(part[1:])
+ if sys_tup <= cond_tup:
+ return False
+ elif part.startswith('<='):
+ sys_tup, cond_tup = _ver_tuples(part[2:])
+ if sys_tup > cond_tup:
+ return False
+ elif part.startswith('<'):
+ sys_tup, cond_tup = _ver_tuples(part[1:])
+ if sys_tup >= cond_tup:
+ return False
+ elif part.startswith('=='):
+ sys_tup, cond_tup = _ver_tuples(part[2:])
+ if sys_tup != cond_tup:
+ return False
+
+ return True
+
+
+def _locate_suitable_download(downloads):
+ """
+ :param downloads:
+ A list of dicts containing a key "url", "python_version" and
+ "requires_python"
+
+ :return:
+ A unicode string URL, or None if not a valid release for the current
+ version of Python
"""
valid_tags = _pep425tags()
@@ -330,8 +483,64 @@ def _stage_requirements(deps_dir, path):
version_info = sys.version_info
exe_suffix = '.%s-py%d.%d.exe' % (win_arch, version_info[0], version_info[1])
+ wheels = {}
+ whl = None
+ tar_bz2 = None
+ tar_gz = None
+ exe = None
+ for download in downloads:
+ if not _is_valid_python_version(download.get('python_version'), download.get('requires_python')):
+ continue
+
+ if exe_suffix and download['url'].endswith(exe_suffix):
+ exe = download['url']
+ if download['url'].endswith('.whl'):
+ parts = os.path.basename(download['url']).split('-')
+ tag_impl = parts[-3]
+ tag_abi = parts[-2]
+ tag_arch = parts[-1].split('.')[0]
+ wheels[(tag_impl, tag_abi, tag_arch)] = download['url']
+ if download['url'].endswith('.tar.bz2'):
+ tar_bz2 = download['url']
+ if download['url'].endswith('.tar.gz'):
+ tar_gz = download['url']
+
+ # Find the most-specific wheel possible
+ for tag in valid_tags:
+ if tag in wheels:
+ whl = wheels[tag]
+ break
+
+ if exe_suffix and exe:
+ url = exe
+ elif whl:
+ url = whl
+ elif tar_bz2:
+ url = tar_bz2
+ elif tar_gz:
+ url = tar_gz
+ else:
+ return None
+
+ return url
+
+
+def _stage_requirements(deps_dir, path):
+ """
+ Installs requirements without using Python to download, since
+ different services are limiting to TLS 1.2, and older version of
+ Python do not support that
+
+ :param deps_dir:
+ A unicode path to a temporary diretory to use for downloads
+
+ :param path:
+ A unicode filesystem path to a requirements file
+ """
+
packages = _parse_requires(path)
for p in packages:
+ url = None
pkg = p['pkg']
pkg_sub_dir = None
if p['type'] == 'url':
@@ -359,53 +568,25 @@ def _stage_requirements(deps_dir, path):
if os.path.exists(json_dest):
os.remove(json_dest)
- latest = pkg_info['info']['version']
- if p['type'] == '>=':
- if _tuple_from_ver(p['ver']) > _tuple_from_ver(latest):
- raise Exception('Unable to find version %s of %s, newest is %s' % (p['ver'], pkg, latest))
- version = latest
- elif p['type'] == '==':
+ if p['type'] == '==':
if p['ver'] not in pkg_info['releases']:
raise Exception('Unable to find version %s of %s' % (p['ver'], pkg))
- version = p['ver']
- else:
- version = latest
-
- wheels = {}
- whl = None
- tar_bz2 = None
- tar_gz = None
- exe = None
- for download in pkg_info['releases'][version]:
- if exe_suffix and download['url'].endswith(exe_suffix):
- exe = download['url']
- if download['url'].endswith('.whl'):
- parts = os.path.basename(download['url']).split('-')
- tag_impl = parts[-3]
- tag_abi = parts[-2]
- tag_arch = parts[-1].split('.')[0]
- wheels[(tag_impl, tag_abi, tag_arch)] = download['url']
- if download['url'].endswith('.tar.bz2'):
- tar_bz2 = download['url']
- if download['url'].endswith('.tar.gz'):
- tar_gz = download['url']
-
- # Find the most-specific wheel possible
- for tag in valid_tags:
- if tag in wheels:
- whl = wheels[tag]
- break
-
- if exe_suffix and exe:
- url = exe
- elif whl:
- url = whl
- elif tar_bz2:
- url = tar_bz2
- elif tar_gz:
- url = tar_gz
+ url = _locate_suitable_download(pkg_info['releases'][p['ver']])
+ if not url:
+ raise Exception('Unable to find a compatible download of %s == %s' % (pkg, p['ver']))
else:
- raise Exception('Unable to find suitable download for %s' % pkg)
+ p_ver_tup = _tuple_from_ver(p['ver'])
+ for ver_str, ver_tup in reversed(_sort_pep440_versions(pkg_info['releases'], False)):
+ if p['type'] == '>=' and ver_tup < p_ver_tup:
+ break
+ url = _locate_suitable_download(pkg_info['releases'][ver_str])
+ if url:
+ break
+ if not url:
+ if p['type'] == '>=':
+ raise Exception('Unable to find a compatible download of %s >= %s' % (pkg, p['ver']))
+ else:
+ raise Exception('Unable to find a compatible download of %s' % pkg)
local_path = _download(url, deps_dir)
diff --git a/readme.md b/readme.md
index 5f05a4e..62c070e 100644
--- a/readme.md
+++ b/readme.md
@@ -19,7 +19,6 @@ A fast, pure Python library for parsing and serializing ASN.1 structures.
[![Travis CI](https://api.travis-ci.org/wbond/asn1crypto.svg?branch=master)](https://travis-ci.org/wbond/asn1crypto)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/wbond/asn1crypto?branch=master&svg=true)](https://ci.appveyor.com/project/wbond/asn1crypto)
[![CircleCI](https://circleci.com/gh/wbond/asn1crypto.svg?style=shield)](https://circleci.com/gh/wbond/asn1crypto)
-[![Codecov](https://codecov.io/gh/wbond/asn1crypto/branch/master/graph/badge.svg)](https://codecov.io/gh/wbond/asn1crypto)
[![PyPI](https://img.shields.io/pypi/v/asn1crypto.svg)](https://pypi.org/project/asn1crypto/)
## Features
@@ -112,7 +111,7 @@ faster to an order of magnitude or more.
## Current Release
-1.3.0 - [changelog](changelog.md)
+1.4.0 - [changelog](changelog.md)
## Dependencies
@@ -156,10 +155,12 @@ links to the source for the various pre-defined type classes.
## Continuous Integration
- - [Windows](https://ci.appveyor.com/project/wbond/asn1crypto/history) via AppVeyor
- - [OS X](https://circleci.com/gh/wbond/asn1crypto) via CircleCI
- - [Linux](https://travis-ci.org/wbond/asn1crypto/builds) via Travis CI
- - [Test Coverage](https://codecov.io/gh/wbond/asn1crypto/commits) via Codecov
+Various combinations of platforms and versions of Python are tested via:
+
+ - [AppVeyor](https://ci.appveyor.com/project/wbond/asn1crypto/history)
+ - [CircleCI](https://circleci.com/gh/wbond/asn1crypto)
+ - [GitHub Actions](https://github.com/wbond/asn1crypto/actions)
+ - [Travis CI](https://travis-ci.org/wbond/asn1crypto/builds)
## Testing
diff --git a/setup.py b/setup.py
index ce6f2e2..991eb59 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ from setuptools.command.egg_info import egg_info
PACKAGE_NAME = 'asn1crypto'
-PACKAGE_VERSION = '1.3.0'
+PACKAGE_VERSION = '1.4.0'
PACKAGE_ROOT = os.path.dirname(os.path.abspath(__file__))
diff --git a/tests/__init__.py b/tests/__init__.py
index b669e5a..3b87410 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -6,8 +6,8 @@ import os
import unittest
-__version__ = '1.3.0'
-__version_info__ = (1, 3, 0)
+__version__ = '1.4.0'
+__version_info__ = (1, 4, 0)
def _import_from(mod, path, mod_dir=None):
diff --git a/tests/setup.py b/tests/setup.py
index fc20401..94aa438 100644
--- a/tests/setup.py
+++ b/tests/setup.py
@@ -10,10 +10,9 @@ from setuptools.command.egg_info import egg_info
PACKAGE_NAME = 'asn1crypto'
-PACKAGE_VERSION = '1.3.0'
+PACKAGE_VERSION = '1.4.0'
TEST_PACKAGE_NAME = '%s_tests' % PACKAGE_NAME
TESTS_ROOT = os.path.dirname(os.path.abspath(__file__))
-PACKAGE_ROOT = os.path.abspath(os.path.join(TESTS_ROOT, '..'))
# setuptools 38.6.0 and newer know about long_description_content_type, but
@@ -60,7 +59,7 @@ class EggInfoCommand(egg_info):
if not os.path.exists(egg_info_path):
os.mkdir(egg_info_path)
shutil.copy2(
- os.path.join(PACKAGE_ROOT, 'LICENSE'),
+ os.path.join(TESTS_ROOT, 'LICENSE'),
os.path.join(egg_info_path, 'LICENSE')
)
egg_info.run(self)
diff --git a/tests/test_core.py b/tests/test_core.py
index b9a7a82..9821c63 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -64,7 +64,7 @@ class NestSeqAny(core.Sequence):
_oid_pair = ('id', 'value')
_oid_specs = {
- '3.4.5': Seq,
+ '2.3.4.5': Seq,
}
@@ -76,7 +76,7 @@ class NestSeqExplicit(core.Sequence):
_oid_pair = ('id', 'value')
_oid_specs = {
- '3.4.5': Seq,
+ '2.3.4.5': Seq,
}
@@ -1314,14 +1314,14 @@ class CoreTests(unittest.TestCase):
def test_wrong_asn1value3(self):
with self.assertRaises(TypeError):
NestSeqAny({
- 'id': '3.4.5',
+ 'id': '2.3.4.5',
'value': core.Integer(1)
})
def test_wrong_asn1value4(self):
with self.assertRaises(TypeError):
NestSeqExplicit({
- 'id': '3.4.5',
+ 'id': '2.3.4.5',
'value': core.Integer(1)
})
@@ -1334,3 +1334,32 @@ class CoreTests(unittest.TestCase):
b.set_encoded_width(4)
self.assertEqual(1, b.native)
self.assertEqual(b'\x04\x04\x00\x00\x00\x01', b.dump())
+
+ @staticmethod
+ def object_identifier_info():
+ return (
+ ("0.0", b"\x06\x01\x00"),
+ ("0.39", b"\x06\x01\x27"),
+ ("1.0", b"\x06\x01\x28"),
+ ("1.39", b"\x06\x01\x4f"),
+ ("2.0", b"\x06\x01\x50"),
+ ("2.39", b"\x06\x01\x77"),
+ ("2.100.3", b"\x06\x03\x81\x34\x03"),
+ ("2.16.840.1.113730.1.1", b"\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01"),
+ )
+
+ @data('object_identifier_info')
+ def object_identifier(self, native, der_bytes):
+ oid = core.ObjectIdentifier(native)
+ self.assertEqual(der_bytes, oid.dump())
+ self.assertEqual(native, core.ObjectIdentifier.load(der_bytes).native)
+
+ def test_broken_object_identifier(self):
+ with self.assertRaisesRegex(ValueError, "First arc must be "):
+ core.ObjectIdentifier("3.4.5")
+
+ with self.assertRaisesRegex(ValueError, "Second arc must be "):
+ core.ObjectIdentifier("1.100.1000")
+
+ with self.assertRaisesRegex(ValueError, "Second arc must be "):
+ core.ObjectIdentifier("0.40")
diff --git a/tests/test_keys.py b/tests/test_keys.py
index 2f2856e..eefd48f 100644
--- a/tests/test_keys.py
+++ b/tests/test_keys.py
@@ -1,8 +1,9 @@
# coding: utf-8
from __future__ import unicode_literals, division, absolute_import, print_function
-import unittest
import os
+import sys
+import unittest
from asn1crypto import keys, core, util
@@ -11,6 +12,11 @@ from ._unittest_compat import patch
patch()
+if sys.version_info < (3,):
+ int_types = (int, long) # noqa
+else:
+ int_types = int
+
tests_root = os.path.dirname(__file__)
fixtures_dir = os.path.join(tests_root, 'fixtures')
@@ -481,7 +487,9 @@ class KeysTests(unittest.TestCase):
with open(os.path.join(fixtures_dir, public_key_file), 'rb') as f:
public_key = keys.PublicKeyInfo.load(f.read())
+ self.assertIsInstance(private_key.bit_size, int_types)
self.assertEqual(bit_size, private_key.bit_size)
+ self.assertIsInstance(public_key.bit_size, int_types)
self.assertEqual(bit_size, public_key.bit_size)
@staticmethod