1# 2# This file is part of pyasn1 software. 3# 4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> 5# License: http://snmplabs.com/pyasn1/license.html 6# 7import sys 8 9try: 10 import platform 11 12 implementation = platform.python_implementation() 13 14except (ImportError, AttributeError): 15 implementation = 'CPython' 16 17from pyasn1.compat.octets import oct2int, null, ensureString 18 19if sys.version_info[0:2] < (3, 2) or implementation != 'CPython': 20 from binascii import a2b_hex, b2a_hex 21 22 if sys.version_info[0] > 2: 23 long = int 24 25 def from_bytes(octets, signed=False): 26 if not octets: 27 return 0 28 29 value = long(b2a_hex(ensureString(octets)), 16) 30 31 if signed and oct2int(octets[0]) & 0x80: 32 return value - (1 << len(octets) * 8) 33 34 return value 35 36 def to_bytes(value, signed=False, length=0): 37 if value < 0: 38 if signed: 39 bits = bitLength(value) 40 41 # two's complement form 42 maxValue = 1 << bits 43 valueToEncode = (value + maxValue) % maxValue 44 45 else: 46 raise OverflowError('can\'t convert negative int to unsigned') 47 elif value == 0 and length == 0: 48 return null 49 else: 50 bits = 0 51 valueToEncode = value 52 53 hexValue = hex(valueToEncode)[2:] 54 if hexValue.endswith('L'): 55 hexValue = hexValue[:-1] 56 57 if len(hexValue) & 1: 58 hexValue = '0' + hexValue 59 60 # padding may be needed for two's complement encoding 61 if value != valueToEncode or length: 62 hexLength = len(hexValue) * 4 63 64 padLength = max(length, bits) 65 66 if padLength > hexLength: 67 hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue 68 elif length and hexLength - length > 7: 69 raise OverflowError('int too big to convert') 70 71 firstOctet = int(hexValue[:2], 16) 72 73 if signed: 74 if firstOctet & 0x80: 75 if value >= 0: 76 hexValue = '00' + hexValue 77 elif value < 0: 78 hexValue = 'ff' + hexValue 79 80 octets_value = a2b_hex(hexValue) 81 82 return octets_value 83 84 def bitLength(number): 85 # bits in unsigned number 86 hexValue = hex(abs(number)) 87 bits = len(hexValue) - 2 88 if hexValue.endswith('L'): 89 bits -= 1 90 if bits & 1: 91 bits += 1 92 bits *= 4 93 # TODO: strip lhs zeros 94 return bits 95 96else: 97 98 def from_bytes(octets, signed=False): 99 return int.from_bytes(bytes(octets), 'big', signed=signed) 100 101 def to_bytes(value, signed=False, length=0): 102 length = max(value.bit_length(), length) 103 104 if signed and length % 8 == 0: 105 length += 1 106 107 return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed) 108 109 def bitLength(number): 110 return int(number).bit_length() 111