def der_pack(value, hint='no_hint', der_packer=None, cls=None): """Pack a Python value into a binary string holding a DER blob; see der_format() for a version that does not include the DER header. Since native types may have been produced from a variety of ASN.1 types, the hint can be used to signal the type name (though any STRING trailer is stripped). Alternatively, use cls to provide an ASN1Object subclass for packing or a der_packer instruction to apply. The latter could crash if not properly formatted -- at least make sure its DER_ENTER_ and DER_LEAVE nest properly and that the der_packer ends in DER_PACK_END. """ if der_packer is not None: if not type(value) == list: value = [value] if cls is not None: raise Exception('der_pack(...,der_packer=...,cls=...) is ambiguous') if hint != 'no_hint': raise Exception('der_pack(...,der_packer=...,hint=...) is ambiguous') return _quickder.der_pack(der_packer, value) elif cls is not None: if not issubclass(cls, classes.ASN1Object): raise Exception('der_pack(value,cls=...) requires cls to be a subclass of ASN1Object') if not type(value) == list: value = [value] if hint != 'no_hint': raise Exception('der_pack(...,cls=...,hint=...) is ambiguous') return _quickder.der_pack(cls._der_packer, value) elif isinstance(value, classes.ASN1Object): return value._der_pack() else: (tag, packfun) = _der_hintmapping(type(value), hint) return primitive.der_prefixhead(tag, packfun(value))
def der_format_OID(oidstr, hdr=False): oidvals = list(map(int, oidstr.split('.'))) oidvals[1] += 40 * oidvals[0] enc = '' for oidx in range(len(oidvals) - 1, 0, -1): oidval = oidvals[oidx] enc = chr(oidval & 0x7f) + enc while oidval > 127: oidval >>= 7 enc = chr(0x80 | (oidval & 0x7f)) + enc if hdr: enc = _quickder.der_pack('\x06\x00', [enc]) return enc
def der_format_INTEGER(ival, hdr=False): retval = '' byt = ival & 0xff while ival not in [0, -1]: ival = ival >> 8 retval = chr(byt) + retval if ival == 0: if len(retval) > 0 and byt & 0x80 == 0x80: retval = chr(0x00) + retval else: if len(retval) == 0 or byt & 0x80 == 0x00: retval = chr(0xff) + retval if hdr: retval = _quickder.der_pack('\x02\x00', [retval]) return retval
def der_format_INTEGER(ival, hdr=False): retval = '' byt = ival & 0xff while ival not in [0, -1]: byt = ival & 0xff ival = ival >> 8 retval = chr(byt) + retval if ival == 0: if len(retval) > 0 and byt & 0x80 == 0x80: retval = chr(0x00) + retval else: if len(retval) == 0 or byt & 0x80 == 0x00: retval = chr(0xff) + retval if hdr: retval = _quickder.der_pack('\x02\x00', [retval]) return retval
def _der_pack(self): """Pack the current ASN1ConstructedType using DER notation. Follow the syntax that was setup when this object was created, usually after a der_unpack() operation or a der_unpack(ClassName, derblob) or empty(ClassName) call. Return the bytes with the packed data. """ bindata = [] for bd in self._bindata[self._offset:self._offset + self._numcursori]: # TODO# set, list, atomic... print('bindata[] element is a {}'.format(type(bd))) if bd is not None and type(bd) != str: # Hope to map the value to DER without hints # TODO# Currently fails on ASN1Objects bd = format.der_format(bd) bindata.append(bd) return _quickder.der_pack(self._der_packer, bindata)
def _der_pack(self): """Pack the current ASN1ConstructedType using DER notation. Follow the syntax that was setup when this object was created, usually after a der_unpack() operation or a der_unpack(ClassName, derblob) or empty(ClassName) call. Return the bytes with the packed data. """ bindata = [] for bd in self._bindata[self._offset:self._offset + self._numcursori]: # TODO# set, list, atomic... print('bindata[] element is a {}'.format(type(bd))) if bd is not None and type(bd) != str: # Hope to map the value to DER without hints # TODO# Currently fails on ASN1Objects from quick_der import format bd = format.der_format(bd) bindata.append(bd) return _quickder.der_pack(self._der_packer, bindata)