diff options
author | wbond <will@wbond.net> | 2019-09-28 07:05:11 -0400 |
---|---|---|
committer | wbond <will@wbond.net> | 2019-09-28 07:05:11 -0400 |
commit | 60136d7dce4b8ae89d5d000d249587806f3d5371 (patch) | |
tree | 00ca0bc78f5c398c2fffdf5f48a6ddab03050001 | |
parent | 3b330ff4d0fc59bacccc69972f3828286c18c97c (diff) | |
download | asn1crypto-60136d7dce4b8ae89d5d000d249587806f3d5371.tar.gz |
When copying a BER-encoded indefinite-length value, force it to be DER-encoded
-rw-r--r-- | asn1crypto/core.py | 30 | ||||
-rw-r--r-- | tests/test_core.py | 76 |
2 files changed, 104 insertions, 2 deletions
diff --git a/asn1crypto/core.py b/asn1crypto/core.py index 881620e..ebe2f5e 100644 --- a/asn1crypto/core.py +++ b/asn1crypto/core.py @@ -763,6 +763,20 @@ class Constructable(object): return self.contents + def _setable_native(self): + """ + Returns a native value that can be round-tripped into .set(), to + result in a DER encoding. This differs from .native in that .native + is designed for the end use, and may account for the fact that the + merged value is further parsed as ASN.1, such as in the case of + ParsableOctetString() and ParsableOctetBitString(). + + :return: + A python value that is valid to pass to .set() + """ + + return self.native + def _copy(self, other, copy_func): """ Copies the contents of another Constructable object to itself @@ -776,8 +790,10 @@ class Constructable(object): """ super(Constructable, self)._copy(other, copy_func) - self.method = other.method - self._indefinite = other._indefinite + # We really don't want to dump BER encodings, so if we see an + # indefinite encoding, let's re-encode it + if other._indefinite: + self.set(other._setable_native()) class Void(Asn1Value): @@ -2777,6 +2793,16 @@ class ParsableOctetString(Constructable, Castable, Primitive): self._bytes = self._merge_chunks() return self._bytes + def _setable_native(self): + """ + Returns a byte string that can be passed into .set() + + :return: + A python value that is valid to pass to .set() + """ + + return self.__bytes__() + def _copy(self, other, copy_func): """ Copies the contents of another ParsableOctetString object to itself diff --git a/tests/test_core.py b/tests/test_core.py index 5be2438..206a70a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -824,6 +824,82 @@ class CoreTests(unittest.TestCase): choice2.chosen['name'] = 'bar' self.assertNotEqual(choice2.chosen['name'], choice2_copy.chosen['name']) + def test_copy_indefinite(self): + v = core.BitString.load(b'\x23\x80\x03\x02\x00\x04\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(3, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual((0, 0, 0, 0, 0, 1, 0, 0), v2.native) + self.assertEqual(b'\x03\x02\x00\x04', v2.dump()) + + v = core.OctetBitString.load(b'\x23\x80\x03\x02\x00\x04\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(3, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(b'\x04', v2.native) + self.assertEqual(b'\x03\x02\x00\x04', v2.dump()) + + v = core.ParsableOctetBitString.load(b'\x23\x80\x03\x04\x00\x02\x01\x04\x00\x00') + self.assertEqual(4, v.parsed.native) + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(3, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(4, v2.parsed.native) + self.assertEqual(b'\x03\x04\x00\x02\x01\x04', v2.dump()) + + v = core.IntegerBitString.load(b'\x23\x80\x03\x02\x00\x04\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(3, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(4, v2.native) + self.assertEqual(b'\x03\x02\x00\x04', v2.dump()) + + v = core.OctetString.load(b'\x24\x80\x04\x03foo\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(4, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(b'foo', v2.native) + self.assertEqual(b'\x04\x03foo', v2.dump()) + + v = core.IntegerOctetString.load(b'\x24\x80\x04\x01\x04\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(4, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(4, v2.native) + self.assertEqual(b'\x04\x01\x04', v2.dump()) + + v = core.ParsableOctetString.load(b'\x24\x80\x04\x03\x02\x01\x04\x00\x00') + self.assertEqual(4, v.parsed.native) + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(4, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual(4, v2.parsed.native) + self.assertEqual(b'\x02\x01\x04', v2.__bytes__()) + self.assertEqual(b'\x04\x03\x02\x01\x04', v2.dump()) + + v = core.UTF8String.load(b'\x2C\x80\x0C\x03foo\x00\x00') + self.assertEqual(True, v._indefinite) + v2 = v.copy() + self.assertEqual(0, v2.method) + self.assertEqual(12, v2.tag) + self.assertEqual(False, v2._indefinite) + self.assertEqual('foo', v2.native) + self.assertEqual(b'\x0C\x03foo', v2.dump()) + def test_concat(self): child1 = Seq({ 'id': '1.2.3', |