def rs_fix(data): # data=data+bytearray([0]*elen) data = data + ([0] * elen) r = range(len(data) - elen, len(data)) try: (cmsg, crs) = reedsolo.rs_correct_msg(data, nsym, fcr, generator, r) except: return (False, None, None) return (True, cmsg, crs)
def rs_fix(data): # data=data+bytearray([0]*elen) data=data+([0]*elen) r=list(range(len(data)-elen,len(data))) try: (cmsg,crs)=reedsolo.rs_correct_msg(data,nsym+elen,fcr,generator,erase_pos=r) except reedsolo.ReedSolomonError: return (False,None,None) except ZeroDivisionError: return (False,None,None) return (True,cmsg,crs[:nsym])
def hread(tout): start = time.time() while tout <= 0 or (time.time() - start) < tout: if ser.inWaiting() >= 3: try: header = reedsolo.rs_correct_msg(ser.read(3), 2)[0] return ord(header) except reedsolo.ReedSolomonError as e: return 'Error' ser.flushInput return None
def decode(blocks, nsym=DEFAULT_NSYM): last_chunk = end_of_stream(BLOCK_SIZE - nsym - 1) for block in blocks: assert len(block) == BLOCK_SIZE chunk = bytearray(rs_correct_msg(block, nsym)) if chunk == last_chunk: log.info('EOF encountered') return # end of stream size = chunk[0] payload = chunk[1:] if size > len(payload): raise ValueError('Invalid chunk', size, len(payload), payload) yield payload[:size]
def main(): # Reed message from file and encode msg = open('data/input.txt', 'r').read().encode() msgs = split_str(msg, n - 2 * t) # Open timer file in append mode encode_time = open('data/encode_time_python.csv', 'a') decode_time = open('data/decode_time_python.csv', 'a') # Generate table and generater polynomial # prim = rs.find_prime_polys(c_exp=m, fast_primes=True, single=True) # rs.init_tables(c_exp=m, prim=prim) rs.init_tables(0x14d) gen = rs.rs_generator_poly_all(n) for i in range(runs): # Encode msg msgeccs = [] t1 = time.perf_counter() for m in msgs: msgeccs.append(rs.rs_encode_msg(m, 2 * t, gen=gen[2 * t])) t2 = time.perf_counter() encode_time.write(str(t2 - t1) + '\n') # Error for msgecc in msgeccs: error_inject(msgecc) # Decode corrections = [] t1 = time.perf_counter() for msgecc in msgeccs: corrections.append(rs.rs_correct_msg(msgecc, 2 * t)) t2 = time.perf_counter() decode_time.write(str(t2 - t1) + '\n') rmsg = b'' for c in corrections: rmsg += c[0] # Check result if (msg.decode() == rmsg.decode()): print("True") else: print("False")
def decode_im(im): print im out = bytearray([0] * 24) for i in range(0, 24, 3): res = 0 for j in range(8): res |= (im[i / 3 * 8 + j] << ((7 - j) * 3)) out[i] = res >> 16 out[i + 1] = (res >> 8) & 0xff out[i + 2] = res & 0xff input = out[:] mes, ecc = reedsolo.rs_correct_msg(input, 8) err = 0 for x, y in zip((mes + ecc), input): err += sum(map(int, '{:08b}'.format(x ^ y))) print "%d errors" % err return mes
def hread(tout): start = time.time() while tout <= 0 or (time.time() - start) < tout: if ser.inWaiting() >= 3: try: #sim r = ser.read(3) if ord(r[0]) > 9: print("Received header: %s\n" % repr(r)) else: print("Received response: %s\n" % repr(r)) header = reedsolo.rs_correct_msg(r, 2)[0] return ord(header) except reedsolo.ReedSolomonError as e: return 'Error' ser.flushInput return None
rs.init_tables(c_exp=12, prim=prim) n = 255 nsym = 12 mes = "a" * (n-nsym) #mesbytarray=[elem.encode(decimal.Decimal) for elem in mes] gen = rs.rs_generator_poly_all(n) print(len(gen)) enc = rs.rs_encode_msg(mes, nsym, gen=gen[nsym]) enc[1] = 0 enc[2]=0 enc[4]=0 enc[8]=0 enc[32] = 0 enc[33]=0 rmes, recc = rs.rs_correct_msg(enc, nsym, erase_pos=None) # print("msg= ", mes) # print("enc= ", enc) # print("dec= ", rmes) mesbytarray="".join(chr(i) for i in rmes) #print("mesba= ",mesbytarray) #print(type(mes),type(mesbytarray)) if mes == mesbytarray: print("Sucess") else: print("FAIL") # i=10 # #rs=RSCodec(nsym=i,c_exp=10) # rs=RSCodec(i) # msg=bytearray(randomString(20), "latin1")
# Channel simulation for x, y in enumerate(en): # Add errors based on probability to be tested if random.random() < pe[i]: # Avoid writing a symbol that is the same as the original if en[x] != 1: en[x] = 1 else: en[x] = 0 if en[:-nk] == packet[:-nk]: ndec[i] += 1 # Test if decodable try: de = reedsolo.rs_correct_msg(en, nk)[0] # Correct decoding? if de == packet[:-nk]: dec[i] += 1 else: idec[i] += 1 except reedsolo.ReedSolomonError: continue # Get theoretical values # Probabilities of decoding pt = [PDP(m, l, nk) for y, m in enumerate(pe)] # Multiply by packets dect = [a * n for y, a in enumerate(pt)] + [0] # ndec - Uncoded number
if en[x] != 1: en[x] = 1 else: en[x] = 0 if len(en) > 2: todec = en[:] else: todec += en[:] # Decode try: #FEC rs_packet = todec + ''.join('0' for x in range(18 - nk)) de = reedsolo.rs_correct_msg( rs_packet, 18, 0, 2, [rs for rs in range(len(todec), (len(todec) + (18 - nk)))])[0] # Correct decoding? if de == p[:-18]: dec[i] += 1 else: idec[i] += 1 break except (reedsolo.ReedSolomonError, ZeroDivisionError): nsym[i] += 5 nak_count += 1 if (nki + nak_count * 2) > 18: terr[i] += 1 break
print u'\n総コード語数: {0}'.format(len(blocks)) print u'データブロック: {0}'.format(repr(blocks)) reedsolo.init_tables(0x11d) # from writeup: https://www.robertxiao.ca/hacking/ctf-writeup/mma2015-qrcode/ b = bytearray() erasures = [] for i, bits in enumerate(blocks): if '?' in bits: erasures.append(i) b.append(0) else: b.append(int(bits, 2)) mes, ecc = reedsolo.rs_correct_msg(b, 22, erase_pos=erasures) for i, c in enumerate(mes): blocks[i] = '{:08b}'.format(c) #RSブロックに分割する RS_blocks = [] block_num = RS_block_num_table[version - 1][error_correction_level] offset = data_code_num_table[version - 1][error_correction_level] for i in range(block_num): t = [] for j in range(offset // block_num): #データ部 t.append(blocks[j * block_num + i]) if offset % block_num != 0: #端数のある場合 remain = offset % block_num if (block_num - remain) <= i: t.append(blocks[(offset // block_num) * block_num +
def error_correction(raw_bit_array, version, ecc_level): ''' Extracts the error-corrected data out of a raw bit array Keyword arguments: raw_bit_array -- the list of booleans being extracted from the data matrix version -- the version of the qr code (1-40) ecc_level -- the level of the error correction (0-3) Returns: A list of booleans, which have been corrected with the error-correction algorithm (This will contain less elements than the raw_bit_array) ''' CODEWORD_COUNT_LOOKUP = [[19, 16, 13, 9], [34, 28, 22, 16], [55, 44, 34, 26], [80, 64, 48, 36], [108, 86, 62, 46], [136, 108, 76, 60], [156, 124, 88, 66], [194, 154, 110, 86], [232, 182, 132, 100], [274, 216, 154, 122], [324, 254, 180, 140], [370, 290, 206, 158], [428, 334, 244, 180], [461, 365, 261, 197], [523, 415, 295, 223], [589, 453, 325, 253], [647, 507, 367, 283], [721, 563, 397, 313], [795, 627, 445, 341], [861, 669, 485, 385], [932, 714, 512, 406], [1006, 782, 568, 442], [1094, 860, 614, 464], [1174, 914, 664, 514], [1276, 1000, 718, 538], [1370, 1062, 754, 596], [1468, 1128, 808, 628], [1531, 1193, 871, 661], [1631, 1267, 911, 701], [1735, 1373, 985, 745], [1843, 1455, 1033, 793], [1955, 1541, 1115, 845], [2071, 1631, 1171, 901], [2191, 1725, 1231, 961], [2306, 1812, 1286, 986], [2434, 1914, 1354, 1054], [2566, 1992, 1426, 1096], [2702, 2102, 1502, 1142], [2812, 2216, 1582, 1222], [2956, 2334, 1666, 1276]] BLOCK_COUNT_LOOKUP = [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 2, 2], [1, 2, 2, 4], [1, 2, 4, 4], [2, 4, 4, 4], [2, 4, 6, 5], [2, 4, 6, 6], [2, 5, 8, 8], [4, 5, 8, 8], [4, 5, 8, 11], [4, 8, 10, 11], [4, 9, 12, 16], [4, 9, 16, 16], [6, 10, 12, 18], [6, 10, 17, 16], [6, 11, 16, 19], [6, 13, 18, 21], [7, 14, 21, 25], [8, 16, 20, 25], [8, 17, 23, 25], [9, 17, 23, 34], [9, 18, 25, 30], [10, 20, 27, 32], [12, 21, 29, 35], [12, 23, 34, 37], [12, 25, 34, 40], [13, 26, 35, 42], [14, 28, 38, 45], [15, 29, 40, 48], [16, 31, 43, 51], [17, 33, 45, 54], [18, 35, 48, 57], [19, 37, 51, 60], [19, 38, 53, 63], [20, 40, 56, 66], [21, 43, 59, 70], [22, 45, 62, 74], [24, 47, 65, 77], [25, 49, 68, 81]] # the amount of blocks being interwoven block_count = BLOCK_COUNT_LOOKUP[version - 1][ecc_level] # the sum of data bytes without error-correction overhead being contained in all blocks codeword_count = CODEWORD_COUNT_LOOKUP[version - 1][ecc_level] bytes_count = raw_bit_array.size // 8 # the amount of entire bytes contained in the bit array # the amount of data bytes without error-correction overhead contained in a short block short_codeword_block_bytes_count = codeword_count // block_count #long_codeword_block_bytes_count = short_block_bytes_count + 1 # not required. The amount of bytes in long blocks is 1 greater than the short blocks # the amount of bytes in the error-correction part of each block errorcorrection_block_bytes_count = (bytes_count - codeword_count) // block_count # The amount of long data blocks long_codeword_block_count = codeword_count % block_count # The amount of short data blocks short_codeword_block_count = block_count - long_codeword_block_count # generators of indices for the data block. # The indices of the short blocks are completely regular and always have the # distance block_count # The indices of the long blocks are regularly exceptional the last index. # The last index only has the distance long_codeword_block_count instead of # block_count from the next to the last # Therefor two different generators are generated and chained short_codeword_block_index_list_gen = (range( block, short_codeword_block_bytes_count * block_count, block_count) for block in range(short_codeword_block_count)) long_codeword_block_index_list_gen = (itertools.chain( range(block, short_codeword_block_bytes_count * block_count, block_count), [short_codeword_block_bytes_count * block_count + block ]) for block in range(short_codeword_block_count, block_count)) codeword_block_index_list_gen = itertools.chain( short_codeword_block_index_list_gen, long_codeword_block_index_list_gen) # The error-correction blocks are all of the same size, have a regular # distance and start after all the data blocks errorcorrection_block_index_list_gen = (range(codeword_count + block, bytes_count, block_count) for block in range(block_count)) # extracting the data and the correction data for each block codeword_errorcorrection_block_index_list_gen = (list( itertools.chain(block, correction_data)) for block, correction_data in zip( codeword_block_index_list_gen, errorcorrection_block_index_list_gen)) raw_byte_array = np.packbits( raw_bit_array) # converting the array of bits to arrays of bytes # applying reed Solomon error-correction to all blocks # the result is a generator of np arrays of corrected bytes corrected_byte_list_gen = (reedsolo.rs_correct_msg( raw_byte_array[codeword_errorcorrection_block_index_list], errorcorrection_block_bytes_count) for codeword_errorcorrection_block_index_list in codeword_errorcorrection_block_index_list_gen) # concatenating the bytes of each block to one array corrected_byte_array = np.fromiter( itertools.chain.from_iterable(corrected_byte_list_gen), dtype=np.uint8, count=codeword_count) # extracting the bits from the bytes corrected_bit_array = np.unpackbits(corrected_byte_array) return corrected_bit_array
def get_data(header): seq_last = int(100) # Random number different from 1 buffer = [] retr_seq = 0 # Retransmission sequence while True: if header == 'Error': ser.flushInput() ser.write(nak_pack) header = hread(TOUT_recv) continue elif 6 < header < 9: # It is an ACK or a NAK print("In function get_data: Expected data, ARQ response found") logging.critical( "In function get_data: Expected data, ARQ response found") return None else: break while True: temp = pread(header) if temp == None: print("In function get_data: Expected packet") logging.critical("In function get_data: Expected packet") return None # Check if it's a retransmission if 2 <= header <= 3: # It's a retransmission if retr_seq != header: # Append the FEC symbols only if the sequence is different from the last one packet += temp header = len(packet) else: packet = temp # Calculate N-K based on packet length if header >= 237: # 236+1 packet dlength = 237 elif 65 <= header < 237: # 64+1 packet dlength = 65 else: # 8+1 packet dlength = 9 nk = header - dlength # header = data + current FEC # dlength = data # nk = FEC # dlength + 18 = max packet try: # Parse sequence number and data if nk > 0: rs_packet = packet + ''.join('0' for x in range(18 - nk)) p = reedsolo.rs_correct_msg( rs_packet, 18, 0, 2, [i for i in range(header, (dlength + 18))])[0] seq = p[0] data = p[1:] else: seq = ord(packet[0]) data = packet[1:] if seq != seq_last: # Remove zeros padded for last packet if 0 < seq <= 7: data = data[:-seq] buffer.append(data.decode('utf-8')) seq_last = seq if seq <= 7: return b"".join(buffer) # Reset retransmission sequence retr_seq = 0 # Send ACK ser.write(ack_pack) except (reedsolo.ReedSolomonError, ZeroDivisionError): # Send NAK ser.write(nak_pack) if nk == 18: # Maximum FEC bytes reached print("In function get_data: Maximum NAK reached") logging.critical("In function get_data: Maximum NAK reached") terminator( 0 ) # Respond to communication attempts by sending out a NAK return None # Read header while True: header = hread(TOUT_recv) if header == None: print("In function get_data: Connection timed out") logging.critical("In function get_data: Connection timed out") return None elif header == 'Error': ser.flushInput() ser.write(nak_pack) continue elif 6 < header < 9: # It is an ACK or a NAK print( "In function get_data: Expected data, ARQ response found") logging.critical( "In function get_data: Expected data, ARQ response found") return None else: break
11000011 10000000 10101100 00010000 11100100 10101010 10011001 01100110 ???????? ???????? ?????0?0 00000000 ???????? ???????? ???????? ???????? ????????'''.split() b = bytearray() erasures = [] for i, bits in enumerate(qr_bytes): if '?' in bits: erasures.append(i) b.append(0) else: b.append(int(bits, 2)) mes, ecc = reedsolo.rs_correct_msg(b, 22, erase_pos=erasures) for c in mes: print '{:08b}'.format(c)