import base64 import asn1crypto #Task 1: int, bytes, bits, hex print("\nTask 1") byte_array1 = bytes([0x00, 0x01, 0x10, 0xff]) byte_array2 = bytearray([0, 1, 16, 255]) print(byte_array1 == byte_array2) print(byte_array1.hex()) int_little = int.from_bytes([0x01, 0x10],byteorder='little') int_big= int.from_bytes([0x01, 0x10], byteorder='big') print(int_little, bin(int_little)) print(int_big, bin(int_big)) #a) think about difference of little and big endian (int_little, int_big) #b) transform 123456 int to bytes (little endian) #c) transform hexadecimal string to bytes #d) write int_as_str as binary representation of int_ #e) transform int_as_str back to integer int_ = (512 + 256 + 128 + 1) int_as_str = '' #Task 2: base64 and padding print("\nTask 2") #When =, == are used as padding? print(base64.b64encode(b'\x00')) print(base64.b64encode(b'\x00\x01')) print(base64.b64encode(b'\x00\x02\x03')) print("") #Task 3: PEM vs DER # Read PEM as lines, strip armor (lines: ...BEGIN..., ...END...), decode to bytes and compare with DER print("\nTask 3") def compare_der_pem(path_pem, path_der): with open(path_pem, mode='r') as file: bytes_pem = bytes([]) with open(path_der, mode='rb') as file: bytes_der = file.read() if (bytes_pem == bytes_der): print("Data correctly converted to DER (bytes) - Well done!") else: print("PEM does not correspond to DER") # compare_der_pem(path_pem='RSApub.pem', path_der='RSApub.der') #Task 4: DER parsing print("\nTask 4") #implement get_length function types_verbose = \ { 0x02: 'INTEGER', 0x03: 'BIT STRING', 0x04: 'OCTET STRING', 0x05: 'NULL', 0x06: 'OBJECT', 0x13: 'PRINTABLESTRING', 0x14: 'T61STRING', 0x17: 'UTCTIME', 0x30: 'SEQUENCE', 0x31: 'SET' } def get_tag(byte_array, offset): '''returns tag and offset''' tag = byte_array[offset] if tag in types_verbose: return types_verbose[tag], offset + 1 else: return tag, offset + 1 # length is defined by byte or bytes on given offset - return tuple (length, new_offset) def get_length(byte_array, offset): '''returns length and new offset''' l = byte_array[offset] offset += 1 assert(l != 0x80), 'indefinite length' return 0, 0 #replace this line by block of code def get_value(byte_array, offset, length): '''returns value and offset''' return byte_array[offset: offset + length], offset + length def tlv(byte_array, offset=0, depth=0): offset_backup = offset # position where tlv starts t, offset = get_tag(byte_array, offset) l, offset = get_length(byte_array, offset) if (t in ['SEQUENCE', 'SET']) or not(t in types_verbose.values()): print('\t' * depth, f'offset={offset_backup}, tag={t}, length={l}') sequence_end = offset + l while (offset < sequence_end): offset = tlv(byte_array, offset, depth + 1) else: v, offset = get_value(byte_array, offset, l) integers = [int(b).to_bytes(length=1, byteorder='little').hex() for b in bytes(v)] print('\t' * depth, f'offset={offset_backup}, tag={t}, length={l} value={integers}') return offset # with open('RSApub.der', 'rb') as der_file: # byte_array = der_file.read() # tlv(byte_array)